Skip to main content

converge_optimization/
types.rs

1//! Common types used across optimization modules
2
3use serde::{Deserialize, Serialize};
4
5/// Cost type for optimization problems (signed to allow negative costs)
6pub type Cost = i64;
7
8/// Weight type for capacity constraints
9pub type Weight = i64;
10
11/// Value type for objective functions
12pub type Value = i64;
13
14/// Index type for nodes/variables
15pub type Index = usize;
16
17/// Solver status after optimization
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
19pub enum SolverStatus {
20    /// Optimal solution found
21    Optimal,
22    /// Feasible solution found (may not be optimal)
23    Feasible,
24    /// Problem is infeasible
25    Infeasible,
26    /// Problem is unbounded
27    Unbounded,
28    /// Solver timed out
29    Timeout,
30    /// Solver hit iteration limit
31    IterationLimit,
32    /// Unknown status
33    Unknown,
34}
35
36impl SolverStatus {
37    /// Returns true if a solution was found
38    pub fn has_solution(self) -> bool {
39        matches!(self, Self::Optimal | Self::Feasible)
40    }
41
42    /// Returns true if the solution is proven optimal
43    pub fn is_optimal(self) -> bool {
44        matches!(self, Self::Optimal)
45    }
46}
47
48/// Statistics from a solver run
49#[derive(Debug, Clone, Default, Serialize, Deserialize)]
50pub struct SolverStats {
51    /// Time spent solving (seconds)
52    pub solve_time_seconds: f64,
53    /// Number of iterations
54    pub iterations: usize,
55    /// Number of nodes explored (for tree search)
56    pub nodes_explored: usize,
57    /// Best objective value found
58    pub objective_value: Option<f64>,
59    /// Best bound (for MIP)
60    pub best_bound: Option<f64>,
61    /// Gap between objective and bound
62    pub gap: Option<f64>,
63}
64
65/// Common solver parameters
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct SolverParams {
68    /// Maximum solve time in seconds (0 = unlimited)
69    pub time_limit_seconds: f64,
70    /// Maximum iterations (0 = unlimited)
71    pub iteration_limit: usize,
72    /// Number of threads to use (0 = auto)
73    pub num_threads: usize,
74    /// Random seed for reproducibility
75    pub random_seed: u64,
76    /// Verbosity level (0 = silent)
77    pub verbosity: u32,
78}
79
80impl Default for SolverParams {
81    fn default() -> Self {
82        Self {
83            time_limit_seconds: 0.0,
84            iteration_limit: 0,
85            num_threads: 0,
86            random_seed: 0,
87            verbosity: 0,
88        }
89    }
90}
91
92impl SolverParams {
93    /// Create params with a time limit
94    pub fn with_time_limit(seconds: f64) -> Self {
95        Self {
96            time_limit_seconds: seconds,
97            ..Default::default()
98        }
99    }
100
101    /// Check if time limit is set
102    pub fn has_time_limit(&self) -> bool {
103        self.time_limit_seconds > 0.0
104    }
105
106    /// Check if iteration limit is set
107    pub fn has_iteration_limit(&self) -> bool {
108        self.iteration_limit > 0
109    }
110}