From 9944c51525ccd19579efe6ac8a666d1afffc278e Mon Sep 17 00:00:00 2001
From: Christian Doh Dinga <cdohdinga@tudelft.nl>
Date: Sun, 23 Jun 2024 20:28:11 +0200
Subject: [PATCH] implement ADMM subroutine: update and solve optimization
 problems

---
 .../implement_admm_subroutine.py              | 136 ++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 src/demoses_distibuted_optimization/implement_admm_subroutine.py

diff --git a/src/demoses_distibuted_optimization/implement_admm_subroutine.py b/src/demoses_distibuted_optimization/implement_admm_subroutine.py
new file mode 100644
index 0000000..6864eb2
--- /dev/null
+++ b/src/demoses_distibuted_optimization/implement_admm_subroutine.py
@@ -0,0 +1,136 @@
+import timeit
+import numpy as np
+import pyomo.environ as pyo
+from typing import Dict
+from solve_consumer_agent import solve_consumer_agent
+from solve_generator_agent import solve_generator_agent
+
+
+def implement_admm_subroutine(
+    agent: str, 
+    agents: Dict, 
+    primal_var_and_λ_EOM: Dict, 
+    admm_parameters: Dict, 
+    EOM: Dict, 
+    model: pyo.ConcreteModel,
+    data: Dict,
+) -> Dict:
+    """This function implements the first step of ADMM which is the admm_subroutine.
+    
+    admm_subroutine obtains the latest values of ADMM paramters (λ_EOM, g_bar, ρ_EOM) from the previous optimization round,
+    and updates them to new_λ_EOM, new_g_bar, and new_ρ_EOM respectively. Next, it then calls the solve_generator_agent and 
+    solve_consumer_agent functions, which instantiates new optimization problems for each agents by updating ADMM paramters
+    to their new values. Finally, it runs all optimization problems again and appends results to the respective dictionaries.
+    """
+    # Initialize total run time
+    total_time = 0
+    start_time = timeit.default_timer()
+    # Get current ADMM parameters and update to latest values for next optimization round (common to all agents)
+    new_λ_EOM = primal_var_and_λ_EOM['λ']['EOM'][-1]
+    new_g_bar = primal_var_and_λ_EOM['g'][agent][-1] - (1 / (EOM['nAgents'] + 1)) * admm_parameters['Imbalances']['EOM'][-1]
+    new_ρ_EOM = admm_parameters['ρ']['EOM'][-1]
+
+    # Prepare updated data in right format for instantiating agent optimization problems
+    instance_data = {
+        None: {
+            'λ_EOM': dict(enumerate(new_λ_EOM)), # Convert time-indexed parameters to dict for declaration in pyomo
+            'g_bar': dict(enumerate(new_g_bar)),
+            'ρ_EOM': {None: new_ρ_EOM},
+        }
+    }
+    update_time = timeit.default_timer() - start_time
+    total_time += update_time
+    start_time = timeit.default_timer()
+    # Instantiate and solve agent new optimization problems
+    if agent in agents['Gen']:
+        # print(f'############ solve optimization problem for generator agent {agent} in subroutine: start #################')
+        instance_model = solve_generator_agent(model=model, data=data, instance_data=instance_data)
+        # print(f'############ solve optimization problem for generator agent {agent} in subroutine: done ##################')
+    elif agent in agents['Cons']:
+        # print(f'############ solve optimization problem for consumer agent {agent} in subroutine: start ##################')
+        instance_model = solve_consumer_agent(model=model, data=data, instance_data=instance_data)
+        # print(f'############ solve optimization problem for consumer agent {agent} in subroutine: done ###################')
+    else:
+        print(f'Agent {agent} is not part of the game')
+        return 0
+
+    solve_time = timeit.default_timer() - start_time
+    total_time += solve_time
+
+    # Query results
+    start_time = timeit.default_timer()
+    optimal_decision_variable = np.array([pyo.value(instance_model.var_g[t]) for t in instance_model.time]) # get values of decision variables
+    primal_var_and_λ_EOM['g'][agent].append(optimal_decision_variable)
+    query_time = timeit.default_timer() - start_time
+    total_time += query_time
+    # print(f'################ print primal decision variables for agent {agent} in subroutine: start #####################')
+    # print(optimal_decision_variable)
+    # print(f'################ print primal decision variables for agent {agent} in subroutine: done ######################')
+
+    # Record the total time in the TO dictionary
+    TO = dict()
+    TO['total_time'] = TO.get('total_time', 0) + total_time
+    return TO
+
+
+# # Example usage
+# import yaml
+# import pandas as pd
+# from define_EOM_parameters import define_EOM_parameters
+# from define_common_parameters import define_common_parameters
+# from define_consumer_parameters import define_consumer_parameters
+# from define_generator_parameters import define_generator_parameters
+# from define_results import define_results
+
+
+# def read_config(config_file):
+#     with open(config_file, 'r') as file:
+#         config = yaml.safe_load(file)
+#     return config
+# data = read_config('config.yaml')
+# ts = pd.read_csv('timeseries.csv', delimiter=';')
+# scenario_number = 1
+# scenario_overview_row = pd.read_csv('overview_scenarios.csv', delimiter=';').iloc[scenario_number-1, :]
+
+# agents = {}
+# agents['Gen'] = [id for id in data['Generators'].keys()]
+# agents['Cons'] = [id for id in data['Consumers'].keys()]
+# agents['eom'] = agents['Gen'] + agents['Cons']
+
+# generator_agent = agents['Gen'][0]
+# generator_agent_model = define_common_parameters(agent=generator_agent, data=data)
+# define_generator_parameters(agent=generator_agent, model=generator_agent_model, data=data, ts=ts)
+
+# consumer_agent = agents['Cons'][0]
+# consumer_agent_model = define_common_parameters(agent=consumer_agent, data=data)
+# define_consumer_parameters(agent=consumer_agent, model=consumer_agent_model, data=data, ts=ts)
+
+# EOM = define_EOM_parameters(ts=ts)
+# EOM["nAgents"] = len(agents['eom'])
+
+# primal_var_and_λ_EOM, admm_parameters = define_results(data=data, agents=agents)
+
+# TO_generator_agent = implement_admm_subroutine(
+#     agent=generator_agent, 
+#     agents=agents, 
+#     primal_var_and_λ_EOM=primal_var_and_λ_EOM, 
+#     admm_parameters=admm_parameters,
+#     EOM=EOM, 
+#     model=generator_agent_model,
+#     data=data,
+# )
+
+# print(TO_generator_agent)
+
+# print()
+
+# TO_consumer_agent = implement_admm_subroutine(
+#     agent=consumer_agent, 
+#     agents=agents, 
+#     primal_var_and_λ_EOM=primal_var_and_λ_EOM, 
+#     admm_parameters=admm_parameters, 
+#     EOM=EOM, 
+#     model=consumer_agent_model,
+#     data=data,
+# )
+# print(TO_consumer_agent)
-- 
GitLab