diff --git a/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py b/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py index bdda72911..f4df84859 100644 --- a/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py +++ b/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py @@ -9,9 +9,18 @@ import logging import os from typing import List, Optional, Set, cast +from discopop_library.discopop_optimizer.DataTransfers.NewDataTransfers import new_calculate_data_transfers +from discopop_library.discopop_optimizer.DataTransfers.calculate_configuration_data_movement import ( + calculate_data_movement, +) from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments +from discopop_library.discopop_optimizer.UpdateOptimization.main import optimize_updates from discopop_library.discopop_optimizer.Variables.Experiment import Experiment -from discopop_library.discopop_optimizer.Variables.ExperimentUtils import restore_session +from discopop_library.discopop_optimizer.Variables.ExperimentUtils import ( + export_patterns_to_json, + export_to_json, + restore_session, +) from discopop_library.discopop_optimizer.utilities.MOGUtilities import show from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern @@ -39,12 +48,12 @@ def run_interactive_optimizer(arguments: OptimizerArguments): print() print("Options: list, add []+, rm []+, exit, export, showdiff, clear") input1 = input() - logger.debug("Got input: ", input1) - got_continue = parse_input(input1, experiment, applied_suggestions) + logger.debug("Got input: " + input1) + got_continue = parse_input(input1, experiment, applied_suggestions, arguments) logger.info("Closing interactive optimizer..") -def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int]): +def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): """Return True if the interactive session should be kept alive. Return False if the main loop should be exited.""" if input.startswith("list"): @@ -59,7 +68,7 @@ def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int pattern_ids1.append(id) except: pass - logger.info("Adding ids: " + str(pattern_ids1)) + logger.debug("Adding ids: " + str(pattern_ids1)) applied_suggestions.update(pattern_ids1) elif input.startswith("rm "): split_input = input.split(" ") @@ -70,7 +79,7 @@ def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int pattern_ids2.append(id) except: pass - logger.info("Removing ids: " + str(pattern_ids2)) + logger.debug("Removing ids: " + str(pattern_ids2)) for i in pattern_ids2: if i in applied_suggestions: applied_suggestions.remove(i) @@ -79,7 +88,7 @@ def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int elif input.startswith("exit"): return False elif input.startswith("export"): - export_configuration(experiment, applied_suggestions) + export_configuration(experiment, applied_suggestions, arguments) elif input.startswith("showdiff"): show_configuration_diff(experiment, applied_suggestions) else: @@ -92,32 +101,63 @@ def show_configuration_diff(experiment: Experiment, applied_suggestions: Set[int logger.info("Not yet implemented") -def export_configuration(experiment: Experiment, applied_suggestions: Set[int]): +def export_configuration(experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): logger.info("Exporting the current configuration..") - logger.warning("Not yet implemented!") - - -# __create_optimizer_output_pattern(experiment, applied_suggestions) - -# def __create_optimizer_output_pattern(experiment: Experiment, applied_suggestions: List[int]) -> Optional[OptimizerOutputPattern]: -# if len(applied_suggestions) == 0: -# return None -# output_pattern: Optional[OptimizerOutputPattern] = None -# -# for suggestion_id in applied_suggestions: -# if output_pattern is None: -# # get suggestion object -# first_suggestion = experiment.detection_result.patterns.get_pattern_from_id(suggestion_id) -# -# output_pattern = OptimizerOutputPattern(first_suggestion._node, experiment.suggestion_to_node_ids_dict[first_suggestion.pattern_id], experiment.get_system().get_host_device_id()) -# logger.info("Initialized OptimizerOutputPattern based on " + str(suggestion_id)) -# else: -# pattern_obj = experiment.detection_result.patterns.get_pattern_from_id(suggestion_id) -# if type(pattern_obj) == OptimizerOutputPattern: -# target_device_id = cast(OptimizerOutputPattern, pattern_obj). -# else: -# experiment.get_system().get_host_device_id() -# -# output_pattern.add_pattern(suggestion_id, target_device_id, experiment.get_system().get_device(target_device_id).get_device_type()) -# logger.info("Added pattern : " + str(suggestion_id)) -# return output_pattern + configured_pattern = __create_optimizer_output_pattern(experiment, applied_suggestions) + if configured_pattern is None: + logger.info("Nothing to export.") + return + logger.info("Calculating necessary data movement") + logger.debug("Decisions: " + str(configured_pattern.decisions)) + data_transfer = new_calculate_data_transfers( + experiment.optimization_graph, configured_pattern.decisions, experiment + ) + for update in data_transfer: + configured_pattern.add_data_movement(update) + logger.info("Calculating necessary data movement") + configured_pattern = optimize_updates(experiment, configured_pattern, arguments) + # append the configuration to the list of patterns + experiment.detection_result.patterns.optimizer_output.append(configured_pattern) + # save updated patterns.json to disk + export_patterns_to_json(experiment, os.path.join("optimizer", "patterns.json")) + logger.info("Saved patterns.") + # save updated experiment + export_to_json(experiment, "optimizer") + logger.info("Saved experiment.") + + +def __create_optimizer_output_pattern( + experiment: Experiment, applied_suggestions: Set[int] +) -> Optional[OptimizerOutputPattern]: + if len(applied_suggestions) == 0: + return None + output_pattern: Optional[OptimizerOutputPattern] = None + + for suggestion_id in applied_suggestions: + if output_pattern is None: + # Initialize output_pattern + first_suggestion = experiment.detection_result.patterns.get_pattern_from_id(suggestion_id) + output_pattern = OptimizerOutputPattern( + first_suggestion._node, + experiment.pattern_id_to_decisions_dict[first_suggestion.pattern_id], + experiment.get_system().get_host_device_id(), + experiment, + ) + logger.debug("Initialized OptimizerOutputPattern based on " + str(suggestion_id)) + + pattern_obj = experiment.detection_result.patterns.get_pattern_from_id(suggestion_id) + if "device_id" in pattern_obj.__dict__: + device_id = pattern_obj.__dict__["device_id"] + else: + device_id = experiment.get_system().get_host_device_id() + output_pattern.add_pattern( + pattern_obj.pattern_id, device_id, experiment.get_system().get_device(device_id).get_device_type() + ) + logger.debug("Added pattern : " + str(suggestion_id)) + + if output_pattern is None: + return None + # collect decisions + output_pattern.decisions = output_pattern.get_contained_decisions(experiment) + logger.info("Created new pattern: " + str(output_pattern.pattern_id)) + return output_pattern diff --git a/discopop_library/result_classes/OptimizerOutputPattern.py b/discopop_library/result_classes/OptimizerOutputPattern.py index 315e2e737..351f3f9a0 100644 --- a/discopop_library/result_classes/OptimizerOutputPattern.py +++ b/discopop_library/result_classes/OptimizerOutputPattern.py @@ -64,3 +64,14 @@ def add_pattern(self, pattern_id: SuggestionId, target_device_id: DeviceID, devi def add_data_movement(self, update: Update): self.data_movement.append(update) + + def get_contained_decisions(self, experiment: Experiment) -> List[int]: + decision_list: List[int] = [] + for d in self.decisions: + if d not in decision_list: + decision_list.append(d) + for tmp_dict in self.applied_patterns: + for d in experiment.pattern_id_to_decisions_dict[tmp_dict["pattern_id"]]: + if d not in decision_list: + decision_list.append(d) + return decision_list diff --git a/discopop_library/result_classes/PatternStorage.py b/discopop_library/result_classes/PatternStorage.py index fa7ab61c7..eaaf1a09a 100644 --- a/discopop_library/result_classes/PatternStorage.py +++ b/discopop_library/result_classes/PatternStorage.py @@ -31,9 +31,7 @@ def __init__(self): def get_pattern_from_id(self, pattern_id: int) -> PatternBase: for type in self.__dict__: - print("type: ", type) for suggestion in self.__dict__[type]: if suggestion.pattern_id == pattern_id: - print("FOUND") return cast(PatternBase, suggestion) raise ValueError("Pattern not found: " + str(pattern_id))