| """Data models for solver benchmarking.""" |
|
|
| from __future__ import annotations |
|
|
| from dataclasses import asdict, dataclass, field |
| from typing import Any |
|
|
|
|
| @dataclass |
| class InstanceFeatures: |
| n_variables: int = 0 |
| n_constraints: int = 0 |
| density: float = 0.0 |
| symmetry: float = 0.0 |
| pct_integer: float = 0.0 |
| graph_sparsity: float = 0.0 |
| constraint_tightness: float = 0.0 |
|
|
| def to_dict(self) -> dict[str, float | int]: |
| return asdict(self) |
|
|
| def vector(self) -> list[float]: |
| return [ |
| float(self.n_variables), |
| float(self.n_constraints), |
| self.density, |
| self.symmetry, |
| self.pct_integer, |
| self.graph_sparsity, |
| self.constraint_tightness, |
| ] |
|
|
|
|
| @dataclass |
| class ProblemInstance: |
| problem_type: str |
| instance_id: str |
| label: str |
| size: str |
| seed: int |
| data: dict[str, Any] |
| features: InstanceFeatures |
| known_optimum: float | None = None |
|
|
| def to_dict(self) -> dict[str, Any]: |
| return { |
| "problem_type": self.problem_type, |
| "instance_id": self.instance_id, |
| "label": self.label, |
| "size": self.size, |
| "seed": self.seed, |
| "data": self.data, |
| "features": self.features.to_dict(), |
| "known_optimum": self.known_optimum, |
| } |
|
|
|
|
| @dataclass |
| class SolverMetrics: |
| solution_quality: float = 0.0 |
| optimality_gap: float = 0.0 |
| time_to_first_feasible: float = 0.0 |
| time_to_best: float = 0.0 |
| total_solving_time: float = 0.0 |
| memory_usage_mb: float = 0.0 |
| branch_and_bound_nodes: int = 0 |
| stability_score: float = 1.0 |
| scalability_score: float = 1.0 |
| status: str = "unknown" |
| objective_value: float = 0.0 |
| feasible: bool = False |
|
|
| def to_dict(self) -> dict[str, Any]: |
| return asdict(self) |
|
|
|
|
| @dataclass |
| class SolverResult: |
| solver_id: str |
| solver_config: dict[str, Any] |
| instance_id: str |
| problem_type: str |
| metrics: SolverMetrics |
| solution: dict[str, Any] = field(default_factory=dict) |
|
|
| def to_dict(self) -> dict[str, Any]: |
| return { |
| "solver_id": self.solver_id, |
| "solver_config": self.solver_config, |
| "instance_id": self.instance_id, |
| "problem_type": self.problem_type, |
| "metrics": self.metrics.to_dict(), |
| "solution": self.solution, |
| } |
|
|
|
|
| @dataclass |
| class MetaModelPrediction: |
| recommended_solver: str |
| recommended_config: dict[str, Any] |
| confidence: float |
| rankings: list[dict[str, Any]] |
| rationale: str |
|
|
| def to_dict(self) -> dict[str, Any]: |
| return asdict(self) |
|
|
|
|
| @dataclass |
| class BenchmarkRun: |
| instance: ProblemInstance |
| results: list[SolverResult] |
| winner: str |
| winner_gap_pct: float |
|
|
| def to_dict(self) -> dict[str, Any]: |
| return { |
| "instance": self.instance.to_dict(), |
| "results": [r.to_dict() for r in self.results], |
| "winner": self.winner, |
| "winner_gap_pct": self.winner_gap_pct, |
| } |
|
|