Coverage for sparkle/platform/output/configuration_output.py: 92%
52 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-07 15:22 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-07 15:22 +0000
1"""Sparkle class to organise configuration output."""
2from __future__ import annotations
3import ast
4import json
5from pathlib import Path
7from sparkle.solver import Solver
8from sparkle.structures import PerformanceDataFrame
9from sparkle.instance import InstanceSet, Instance_Set
10from sparkle.configurator.configurator import Configurator, ConfigurationScenario
13class ConfigurationOutput:
14 """Class that collects configuration data and outputs it a JSON format."""
16 def __init__(self: ConfigurationOutput,
17 path: Path,
18 configurator: Configurator,
19 config_scenario: ConfigurationScenario,
20 performance_data: PerformanceDataFrame,
21 instance_set_test: InstanceSet,
22 output: Path) -> None:
23 """Initialize Configurator Output class.
25 Args:
26 path: Path to configuration output directory
27 configurator: The configurator that was used
28 config_scenario: The scenario to output
29 performance_data: Performance data
30 instance_set_test: Instance set used for testing
31 output: Path to the output directory
32 """
33 self.solver = config_scenario.solver
34 self.configurator = configurator
35 self.instance_set_train = config_scenario.instance_set
36 self.instance_set_test = instance_set_test
37 self.directory = path
38 self.config_scenario = config_scenario
39 self.output = output / "configuration.json" if not output.is_file() else output
41 # Fix relative path
42 if Path.cwd() in self.solver.directory.parents:
43 self.solver = Solver(
44 self.solver.directory.relative_to(Path.cwd()),
45 )
46 if Path.cwd() in self.instance_set_train.directory.parents:
47 self.instance_set_train = Instance_Set(
48 self.instance_set_train.directory.relative_to(Path.cwd())
49 )
50 if (self.instance_set_test
51 and Path.cwd() in self.instance_set_test.directory.parents):
52 self.instance_set_test = Instance_Set(
53 self.instance_set_test.directory.relative_to(Path.cwd())
54 )
55 # Retrieve all configurations
56 solver_key = str(self.solver.directory)
57 all_configurations = performance_data.get_value(
58 solver_key, None,
59 objective=self.config_scenario.sparkle_objective.name,
60 solver_fields=[PerformanceDataFrame.column_configuration])
62 # Turn in to dictionary and unique
63 self.configurations_performances = []
64 for config in all_configurations:
65 try:
66 config = ast.literal_eval(config)
67 if config not in self.configurations_performances:
68 self.configurations_performances.append(config)
69 except Exception:
70 if isinstance(config, str):
71 print("Failed to parse configuration:\n", config)
72 # Retrieve configuration performances
73 train_instances = [str(p) for p in self.instance_set_train.instance_paths]
74 # Retrieve Default (No configuration) performance
75 _, self.default_performance_train = performance_data.configuration_performance(
76 solver_key, PerformanceDataFrame.missing_value,
77 objective=self.config_scenario.sparkle_objective,
78 instances=train_instances)
80 _, self.default_performance_per_instance_train =\
81 performance_data.configuration_performance(
82 solver_key, PerformanceDataFrame.missing_value,
83 objective=self.config_scenario.sparkle_objective,
84 instances=train_instances,
85 per_instance=True)
87 self.configurations_performances = [performance_data.configuration_performance(
88 solver_key, config,
89 objective=self.config_scenario.sparkle_objective,
90 instances=train_instances) for config in self.configurations_performances]
92 # Retrieve best found configuration
93 self.best_configuration, self.best_performance_train =\
94 performance_data.best_configuration(
95 solver_key,
96 objective=self.config_scenario.sparkle_objective,
97 instances=train_instances)
99 # Retrieve best configuration per instance performances
100 _, self.best_conf_performance_per_instance_train =\
101 performance_data.configuration_performance(
102 solver_key, self.best_configuration,
103 objective=self.config_scenario.sparkle_objective,
104 instances=train_instances,
105 per_instance=True)
107 if instance_set_test:
108 test_instances = [str(p) for p in self.instance_set_test.instance_paths]
109 # Retrieve default performance on the test set
110 _, self.default_performance_test =\
111 performance_data.configuration_performance(
112 solver_key, PerformanceDataFrame.missing_value,
113 objective=self.config_scenario.sparkle_objective,
114 instances=test_instances)
115 _, self.default_performance_per_instance_test =\
116 performance_data.configuration_performance(
117 solver_key, PerformanceDataFrame.missing_value,
118 objective=self.config_scenario.sparkle_objective,
119 instances=test_instances,
120 per_instance=True)
121 # Retrieve the best configuration test set performance
122 _, self.best_performance_test = performance_data.configuration_performance(
123 solver_key, self.best_configuration,
124 objective=self.config_scenario.sparkle_objective,
125 instances=test_instances,
126 )
127 _, self.best_conf_performance_per_instance_test =\
128 performance_data.configuration_performance(
129 solver_key, self.best_configuration,
130 objective=self.config_scenario.sparkle_objective,
131 instances=test_instances,
132 per_instance=True)
133 self.performance_data = performance_data
135 def write_output(self: ConfigurationOutput) -> None:
136 """Write data into a JSON file."""
137 output_data = {
138 "solver": self.solver.name,
139 "configurator": self.configurator.name,
140 "best_configuration": self.best_configuration,
141 "best_performance_train": self.best_performance_train,
142 "scenario": self.config_scenario.serialize()
143 if self.configurator.scenario else None,
144 "train_set_results": self.performance_data[self.performance_data.index.isin(
145 [str(p) for p in self.instance_set_train.instance_paths],
146 level=PerformanceDataFrame.index_instance)].to_json(),
147 "test_set_results": (self.performance_data[self.performance_data.index.isin(
148 [str(p) for p in self.instance_set_test.instance_paths],
149 level=PerformanceDataFrame.index_instance)].to_json()
150 if self.instance_set_test else None),
151 }
152 self.output.parent.mkdir(parents=True, exist_ok=True)
153 with self.output.open("w") as f:
154 json.dump(output_data, f, indent=4)