diff --git a/src/orchestration_config.json b/src/orchestration_config.json index 160dd2af5bf3b2f222cc8dc48b3f21ea2c02cd48..b93e40bbe9098aadb21fc8e8077e36657189ccd5 100644 --- a/src/orchestration_config.json +++ b/src/orchestration_config.json @@ -4,23 +4,27 @@ "MODEL_FILE": "ITSystem.mo", "MODEL_NAME": "ITSystem", "SIMULATION_TIME": 100, - "START_TIME": 8, - "END_TIME": 13, - "TIME_UNIT": "hour", - "OPTIMIZATION_PARAMETERS": { - "activeCores": { - "bounds": [1, 4], - "type": "int" - }, - "cpuFrequency": { - "bounds": [1.0, 3.0], - "type": "float" - } + "TIME_CONFIG": { + "START_TIME": 8, + "END_TIME": 13, + "TIME_UNIT": "hour" }, - "EVALUATION_PARAMETERS": { - "performance": "performance", - "remaining_energy": "remainingEnergy", - "energy_consumption": "energyConsumption" + "OBJECTIVES": [ + {"name": "remainingEnergy", "maximize": true}, + {"name": "performance", "maximize": true} + ], + "TUNABLE_PARAMETERS": { + "PARAMETERS": ["activeCores", "cpuFrequency"], + "PARAM_BOUNDS": { + "activeCores": { + "bounds": [1, 4], + "type": "int" + }, + "cpuFrequency": { + "bounds": [1.0, 3.0], + "type": "float" + } + } }, "INPUT_PARAMETERS": { "available_energy": "availableEnergy", @@ -28,5 +32,12 @@ }, "CRITERIA": { "GOAL_EXPRESSION": "evaluation_results['performance'] >= simulation_inputs['user_demand']" - } + }, + "PLOT_CONFIG": { + "PLOT_X": "", + "PLOT_Y": "", + "PLOT_TITLE": "", + "ENABLE_PLOT": false + }, + "N_JOBS": -1 } \ No newline at end of file diff --git a/src/orchestration_configurator.py b/src/orchestration_configurator.py index 21949ee7e4b05fd0e68b12ba05a3ca6c222c356d..f496ab91163d069b7910205d9b2e1e06ebe464ca 100644 --- a/src/orchestration_configurator.py +++ b/src/orchestration_configurator.py @@ -18,17 +18,18 @@ def build_model(omc, model_name): build_result = omc.sendExpression(f'buildModel({model_name})') return build_result -def simulate_and_evaluate(parameters, simulation_time, simulation_inputs, global_config): +def simulate_and_evaluate(parameters, simulation_time, simulation_inputs, orchestration_config): # General setup and configuration - model_file = global_config['MODEL_FILE'] - model_name = global_config['MODEL_NAME'] - param_types = {param: details['type'] for param, details in global_config['OPTIMIZATION_PARAMETERS'].items()} + model_file = orchestration_config['MODEL_FILE'] + model_name = orchestration_config['MODEL_NAME'] + param_types = {param: details['type'] for param, details in orchestration_config['TUNABLE_PARAMETERS']['PARAM_BOUNDS'].items()} + # Create a temporary directory to avoid GUID mismatch issues temp_dir = tempfile.mkdtemp() - evaluation_parameters = global_config['EVALUATION_PARAMETERS'] - input_parameters = global_config['INPUT_PARAMETERS'] - goal_expression = global_config['CRITERIA']['GOAL_EXPRESSION'] + evaluation_parameters = {obj['name']: obj['name'] for obj in orchestration_config['OBJECTIVES']} + input_parameters = orchestration_config['INPUT_PARAMETERS'] + goal_expression = orchestration_config['CRITERIA']['GOAL_EXPRESSION'] try: omc = init_omc_session(temp_dir, model_file) @@ -80,17 +81,17 @@ def read_data_from_file(filename): data.append((time_value, *map(int, values))) # Combine time value with other data return data -def adaptive_control_loop(data, moo_wrapper, global_config): - start_time = global_config['START_TIME'] - end_time = global_config['END_TIME'] - simulation_time = global_config['SIMULATION_TIME'] - input_keys = list(global_config['INPUT_PARAMETERS'].keys()) # List of input parameter keys +def adaptive_control_loop(data, moo_wrapper, orchestration_config): + start_time = orchestration_config['TIME_CONFIG']['START_TIME'] + end_time = orchestration_config['TIME_CONFIG']['END_TIME'] + simulation_time = orchestration_config['SIMULATION_TIME'] + input_keys = list(orchestration_config['INPUT_PARAMETERS'].keys()) # List of input parameter keys report = [] for entry in data: time_value, *input_values = entry if start_time <= time_value < end_time: - print(f"Processing {global_config['TIME_UNIT']} {time_value}") + print(f"Processing {orchestration_config['TIME_CONFIG']['TIME_UNIT']} {time_value}") # Create a dictionary of inputs simulation_inputs = dict(zip(input_keys, input_values)) @@ -109,7 +110,7 @@ def adaptive_control_loop(data, moo_wrapper, global_config): for best_parameters in parameter_list: try: evaluation_results, goal_satisfied, parameters, depletion_time = simulate_and_evaluate( - best_parameters, simulation_time, simulation_inputs, global_config) + best_parameters, simulation_time, simulation_inputs, orchestration_config) except Exception as e: print(f"Simulation error: {e}") continue @@ -119,25 +120,11 @@ def adaptive_control_loop(data, moo_wrapper, global_config): # Generate the report for each hour if goal_satisfied: - report.append(f"{global_config['TIME_UNIT'].capitalize()} {time_value}: Goal satisfid with configuration {parameters}. Simulation ran for {depletion_time} seconds out of {simulation_time} seconds.") + report.append(f"{orchestration_config['TIME_CONFIG']['TIME_UNIT'].capitalize()} {time_value}: Goal satisfid with configuration {parameters}. Simulation ran for {depletion_time} seconds out of {simulation_time} seconds.") else: - report.append(f"{global_config['TIME_UNIT'].capitalize()} {time_value}: No sufficient configuration found. Simulation ran for {depletion_time} seconds out of {simulation_time} seconds.") + report.append(f"{orchestration_config['TIME_CONFIG']['TIME_UNIT'].capitalize()} {time_value}: No sufficient configuration found. Simulation ran for {depletion_time} seconds out of {simulation_time} seconds.") # Print the final report print("\nFinal Report:") for line in report: - print(line) - -if __name__ == "__main__": - # Load the orchestration configuration from orchestration_config.json - with open(orchestration_config_path, 'r') as f: - orchestration_config = json.load(f) - - # Read data from the specified data file - data = read_data_from_file(orchestration_config['DATA_FILE_PATH']) - - # Initialize the MOO4ModelicaWrapper with the path to the MOO4Modelica config and the orchestration configuration - moo_wrapper = MOO4ModelicaWrapper(config_path=orchestration_config['CONFIG_PATH'], global_config=orchestration_config) - - # Run the adaptive control loop with the loaded data and configuration - adaptive_control_loop(data, moo_wrapper, orchestration_config) \ No newline at end of file + print(line) \ No newline at end of file diff --git a/src/orchestration_wrapper.py b/src/orchestration_wrapper.py index 07c97f1243a6812f9951d1c8f976668ab70d832b..095075c420b5d484233e2001c9547eaca29fc58b 100644 --- a/src/orchestration_wrapper.py +++ b/src/orchestration_wrapper.py @@ -5,25 +5,43 @@ import json import os from optimize_main import run_optimization +import json +import os +from optimize_main import run_optimization + class MOO4ModelicaWrapper: - def __init__(self, config_path, global_config): + def __init__(self, orchestration_config_path, config_path): + self.orchestration_config_path = orchestration_config_path self.config_path = config_path - self.global_config = global_config - self.load_config() - self.model_file = global_config['MODEL_FILE'] - self.model_name = global_config['MODEL_NAME'] + self.load_configs() + self.update_config_file() + + def load_configs(self): + with open(self.orchestration_config_path, 'r') as f: + self.orchestration_config = json.load(f) - def load_config(self): with open(self.config_path, 'r') as f: self.config = json.load(f) + def update_config_file(self): + # Update config with orchestration config + self.config['MODEL_NAME'] = self.orchestration_config['MODEL_NAME'] + self.config['MODEL_FILE'] = self.orchestration_config['MODEL_FILE'] + self.config['SIMULATION_STOP_TIME'] = self.orchestration_config['SIMULATION_TIME'] + self.config['PARAMETERS'] = self.orchestration_config['TUNABLE_PARAMETERS']['PARAMETERS'] + self.config['PARAM_BOUNDS'] = self.orchestration_config['TUNABLE_PARAMETERS']['PARAM_BOUNDS'] + self.config['OBJECTIVES'] = self.orchestration_config['OBJECTIVES'] + self.config['PLOT_CONFIG'] = self.orchestration_config['PLOT_CONFIG'] + self.config['N_JOBS'] = self.orchestration_config['N_JOBS'] + + with open(self.config_path, 'w') as f: + json.dump(self.config, f, indent=4) + def update_config(self, simulation_inputs, simulation_time): - # Modify the configuration with new parameters - self.config['PARAMETERS'] = list(self.global_config['OPTIMIZATION_PARAMETERS'].keys()) - self.config['PARAM_BOUNDS'] = self.global_config['OPTIMIZATION_PARAMETERS'] + # Update only the simulation-specific parameters self.config['SIMULATION_STOP_TIME'] = simulation_time for input_param, value in simulation_inputs.items(): - self.config[self.global_config['INPUT_PARAMETERS'][input_param]] = value + self.config[self.orchestration_config['INPUT_PARAMETERS'][input_param]] = value # Save the updated configuration to a file with open(self.config_path, 'w') as f: diff --git a/src/orchestrator.py b/src/orchestrator.py index f229fce4bf900313a85c52f9e55fa405f2ddd038..7c067e482cd8a545e7c5fb9fecee65c5c0d90f98 100644 --- a/src/orchestrator.py +++ b/src/orchestrator.py @@ -3,7 +3,6 @@ import json import os -from optimize_main import run_optimization from orchestration_wrapper import MOO4ModelicaWrapper from orchestration_configurator import adaptive_control_loop, read_data_from_file @@ -13,20 +12,20 @@ orchestration_config_path = os.path.join(base_path, 'orchestration_config.json') def main(): # Load the orchestration configuration with open(orchestration_config_path, 'r') as f: - global_config = json.load(f) + orchestration_config = json.load(f) # Get paths from the orchestration configuration - data_file_path = os.path.join(base_path, global_config['DATA_FILE_PATH']) - config_path = os.path.join(base_path, global_config['CONFIG_PATH']) + data_file_path = os.path.join(base_path, orchestration_config['DATA_FILE_PATH']) + config_path = os.path.join(base_path, orchestration_config['CONFIG_PATH']) # Read data from the specified data file data = read_data_from_file(data_file_path) # Initialize the MOO4ModelicaWrapper with the path to the MOO4Modelica config and the orchestration configuration - moo_wrapper = MOO4ModelicaWrapper(config_path=config_path, global_config=global_config) + moo_wrapper = MOO4ModelicaWrapper(orchestration_config_path=orchestration_config_path, config_path=config_path) # Run the adaptive control loop with the loaded data and configuration - adaptive_control_loop(data, moo_wrapper, global_config) + adaptive_control_loop(data, moo_wrapper, orchestration_config) if __name__ == "__main__": main() \ No newline at end of file