Coverage for sparkle/platform/output/structures.py: 96%
47 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-05 14:48 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-05 14:48 +0000
1#!/usr/bin/env python3
2"""Sparkle output structures."""
3from __future__ import annotations
4import sys
5from pathlib import Path
7from runrunner.base import Status
9from sparkle.solver import Solver
10from sparkle.types import SolverStatus, SparkleObjective
11from sparkle.instance import InstanceSet
12from sparkle.structures import PerformanceDataFrame
15class ValidationResults:
16 """Class that stores validation information and results."""
17 def __init__(self: ValidationResults, solver: Solver,
18 configuration: dict, instance_set: InstanceSet,
19 results: list[list[str, Status, float, float]]) -> None:
20 """Initalize ValidationResults.
22 Args:
23 solver: The name of the solver
24 configuration: The configuration being used
25 instance_set: The set of instances
26 results: Validation results in the format:
27 [["instance", "status", "quality", "runtime"]]
28 """
29 self.solver = solver
30 self.configuration = configuration
31 self.instance_set = instance_set
32 self.result_header = ["instance", "status", "quality", "runtime"]
33 self.result_vals = results
36class ConfigurationResults:
37 """Class that aggregates configuration results."""
38 def __init__(self: ConfigurationResults, metrics: float,
39 results: ValidationResults) -> None:
40 """Initalize ConfigurationResults.
42 Args:
43 metrics: The performance of a configured solver
44 results: The results for one configuration
45 """
46 self.performance = metrics
47 self.results = results
50class SelectionSolverData:
51 """Class that stores solver information."""
52 def __init__(self: SelectionSolverData,
53 solver_performance_ranking: list[tuple[str, float]],
54 num_solvers: int) -> None:
55 """Initalize SelectionSolverData.
57 Args:
58 solver_performance_ranking: list with solvers ranked by avg. performance
59 num_solvers: The number of solvers
60 """
61 self.solver_performance_ranking = solver_performance_ranking
62 self.single_best_solver = solver_performance_ranking[0][0]
63 self.num_solvers = num_solvers
66class SelectionPerformance:
67 """Class that stores selection performance results."""
68 def __init__(self: SelectionSolverData,
69 performance_path: Path,
70 vbs_performance: float,
71 objective: SparkleObjective) -> None:
72 """Initalize SelectionPerformance.
74 Args:
75 performance_path: Path to portfolio selector performance
76 vbs_performance: The performance of the virtual best selector
77 objective: The objective (Performance type)
78 """
79 if not performance_path.exists():
80 print(f"ERROR: {performance_path} does not exist.")
81 sys.exit(-1)
82 actual_performance_data = PerformanceDataFrame(performance_path)
83 self.vbs_performance = vbs_performance
84 self.actual_performance = actual_performance_data.mean(
85 objective=objective.name)
86 self.metric = objective.name
89class ParallelPortfolioResults:
90 """Class that stores parallel portfolio results."""
91 def __init__(self: ParallelPortfolioResults,
92 unsolved_instances: int,
93 sbs: str,
94 runtime_solvers: dict[str, float],
95 instance_results: dict[str, list]) -> None:
96 """Initalize SelectionSolverData.
98 Args:
99 unsolved_instances: Number of unsolved instances
100 sbs: Name of the single best solver
101 runtime_solvers: Dictionary containing penalised average runtime per solver
102 instance_results: Dictionary containing
103 """
104 self.unsolved_instances = unsolved_instances
105 self.sbs = sbs
106 self.runtime_solvers = runtime_solvers
107 self.instance_results = instance_results
109 self.solver_performance = {}
110 # Iterate over each instance and aggregate the results
111 for _, results in self.instance_results.items():
112 for solver_result in results:
113 solver_name = solver_result[0]
114 outcome = solver_result[1]
115 # Initialize the solver's record in solver_performance if not present
116 if solver_name not in self.solver_performance:
117 self.solver_performance[solver_name] = {
118 status: 0 for status in SolverStatus
119 }
120 # Increment the appropriate outcome count
121 self.solver_performance[solver_name][outcome] += 1