Coverage for sparkle/platform/output/structures.py: 84%

43 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-07 15:22 +0000

1#!/usr/bin/env python3 

2"""Sparkle output structures.""" 

3from __future__ import annotations 

4import sys 

5from pathlib import Path 

6 

7from runrunner.base import Status 

8 

9from sparkle.solver import Solver 

10from sparkle.types import SolverStatus, SparkleObjective 

11from sparkle.instance import InstanceSet 

12from sparkle.structures import PerformanceDataFrame 

13 

14 

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. 

21 

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 

34 

35 

36class SelectionSolverData: 

37 """Class that stores solver information.""" 

38 def __init__(self: SelectionSolverData, 

39 solver_performance_ranking: list[tuple[str, float]], 

40 num_solvers: int) -> None: 

41 """Initalize SelectionSolverData. 

42 

43 Args: 

44 solver_performance_ranking: list with solvers ranked by avg. performance 

45 num_solvers: The number of solvers 

46 """ 

47 self.solver_performance_ranking = solver_performance_ranking 

48 self.single_best_solver = solver_performance_ranking[0][0] 

49 self.num_solvers = num_solvers 

50 

51 

52class SelectionPerformance: 

53 """Class that stores selection performance results.""" 

54 def __init__(self: SelectionSolverData, 

55 performance_path: Path, 

56 vbs_performance: float, 

57 objective: SparkleObjective) -> None: 

58 """Initalize SelectionPerformance. 

59 

60 Args: 

61 performance_path: Path to portfolio selector performance 

62 vbs_performance: The performance of the virtual best selector 

63 objective: The objective (Performance type) 

64 """ 

65 if not performance_path.exists(): 

66 print(f"ERROR: {performance_path} does not exist.") 

67 sys.exit(-1) 

68 actual_performance_data = PerformanceDataFrame(performance_path) 

69 self.vbs_performance = vbs_performance 

70 self.actual_performance = actual_performance_data.mean( 

71 objective=objective.name) 

72 self.metric = objective.name 

73 

74 

75class ParallelPortfolioResults: 

76 """Class that stores parallel portfolio results.""" 

77 def __init__(self: ParallelPortfolioResults, 

78 unsolved_instances: int, 

79 sbs: str, 

80 runtime_solvers: dict[str, float], 

81 instance_results: dict[str, list]) -> None: 

82 """Initalize SelectionSolverData. 

83 

84 Args: 

85 unsolved_instances: Number of unsolved instances 

86 sbs: Name of the single best solver 

87 runtime_solvers: Dictionary containing penalised average runtime per solver 

88 instance_results: Dictionary containing 

89 """ 

90 self.unsolved_instances = unsolved_instances 

91 self.sbs = sbs 

92 self.runtime_solvers = runtime_solvers 

93 self.instance_results = instance_results 

94 

95 self.solver_performance = {} 

96 # Iterate over each instance and aggregate the results 

97 for _, results in self.instance_results.items(): 

98 for solver_result in results: 

99 solver_name = solver_result[0] 

100 outcome = solver_result[1] 

101 # Initialize the solver's record in solver_performance if not present 

102 if solver_name not in self.solver_performance: 

103 self.solver_performance[solver_name] = { 

104 status: 0 for status in SolverStatus 

105 } 

106 # Increment the appropriate outcome count 

107 self.solver_performance[solver_name][outcome] += 1