Skip to main content

SolverInterface

Trait SolverInterface 

Source
pub trait SolverInterface: Send {
    // Required methods
    fn load_model(&mut self, template: &StageTemplate);
    fn add_rows(&mut self, cuts: &RowBatch);
    fn set_row_bounds(
        &mut self,
        indices: &[usize],
        lower: &[f64],
        upper: &[f64],
    );
    fn set_col_bounds(
        &mut self,
        indices: &[usize],
        lower: &[f64],
        upper: &[f64],
    );
    fn solve(&mut self) -> Result<SolutionView<'_>, SolverError>;
    fn reset(&mut self);
    fn get_basis(&mut self, out: &mut Basis);
    fn solve_with_basis(
        &mut self,
        basis: &Basis,
    ) -> Result<SolutionView<'_>, SolverError>;
    fn statistics(&self) -> SolverStatistics;
    fn name(&self) -> &'static str;
}
Expand description

Backend-agnostic interface for LP solver instances.

§Design

The trait is resolved as a generic type parameter at compile time (compile-time monomorphization for FFI-wrapping trait; see docs/adr/003-compile-time-solver.md), not as dyn SolverInterface. This monomorphization approach eliminates virtual dispatch overhead on the hot path, where tens of millions of LP solves occur during a single training run. The training loop is parameterized as fn train<S: SolverInterface>(solver_factory: impl Fn() -> S, ...).

§Thread Safety

The trait requires Send but not Sync. Send allows solver instances to be transferred to worker threads during thread pool initialization. The absence of Sync prevents concurrent access, which matches the reality of C-library solver handles (HiGHS, CLP): they maintain mutable internal state (factorization workspace, working arrays) that is not thread-safe. Each worker thread owns exactly one solver instance for the duration of the training run, following the thread-local workspace pattern described in Solver Workspaces SS1.1.

§Mutability Convention

  • Mutating methods (load_model, add_rows, set_row_bounds, set_col_bounds, solve, solve_with_basis, reset) take &mut self.
  • Methods that write to internal scratch buffers (get_basis) take &mut self.
  • Read-only query methods (statistics, name) take &self.

§Error Recovery Contract

When solve or solve_with_basis returns Err, the solver’s internal state is unspecified. The caller is responsible for calling reset() before reusing the instance for another solve sequence. Failing to call reset() after an error may produce incorrect results or panics.

§Usage as a Generic Bound

use cobre_solver::{SolverInterface, SolutionView, SolverError};

fn run_solve<S: SolverInterface>(solver: &mut S) -> Result<SolutionView<'_>, SolverError> {
    solver.solve()
}

See Solver Interface Trait SS1 and Solver Interface Trait SS5 for the dispatch mechanism rationale.

Required Methods§

Source

fn load_model(&mut self, template: &StageTemplate)

Bulk-loads a pre-assembled structural LP (first step of rebuild sequence).

Replaces any previous model. Validates template is a valid CSC matrix with num_cols > 0 and num_rows > 0 (panic on violation).

See Solver Interface Trait SS2.1.

Source

fn add_rows(&mut self, cuts: &RowBatch)

Appends constraint rows to the dynamic constraint region (step 2 of rebuild).

Requires load_model called first and cuts to have valid CSR data with column indices in [0, num_cols) (panic on violation).

See Solver Interface Trait SS2.2.

Source

fn set_row_bounds(&mut self, indices: &[usize], lower: &[f64], upper: &[f64])

Updates row bounds (step 3 of rebuild; patching for scenario realization).

indices, lower, and upper must have equal length, with all indices referencing valid rows and bounds finite. For equality constraints, set lower[i] == upper[i]. Panics if lengths differ or indices are out-of-bounds.

See Solver Interface Trait SS2.3.

Source

fn set_col_bounds(&mut self, indices: &[usize], lower: &[f64], upper: &[f64])

Updates column bounds (per-scenario variable bound patching).

indices, lower, and upper must have equal length, with all indices referencing valid columns and bounds finite. Panics if lengths differ or indices are out-of-bounds.

See Solver Interface Trait SS2.3a.

Source

fn solve(&mut self) -> Result<SolutionView<'_>, SolverError>

Solves the LP, returning a zero-copy view or terminal error after retry exhaustion.

Hot-path method encapsulating internal retry logic. Requires Self::load_model called first and scenario patches applied. On error, caller must call Self::reset before reusing. The returned SolutionView borrows solver-internal buffers and is valid until the next &mut self call. Call SolutionView::to_owned when the solution must outlive the borrow.

§Errors

Returns Err(SolverError) when all internal retry attempts exhausted. Possible variants: SolverError::Infeasible, SolverError::Unbounded, SolverError::NumericalDifficulty, SolverError::TimeLimitExceeded, SolverError::IterationLimit, or SolverError::InternalError.

See Solver Interface Trait SS2.4.

Source

fn reset(&mut self)

Clears internal solver state for error recovery or LP structure change.

Requires Self::load_model before next solve. Preserves SolverStatistics counters; does not zero them.

See Solver Interface Trait SS2.6.

Source

fn get_basis(&mut self, out: &mut Basis)

Writes solver-native i32 status codes into a caller-owned Basis buffer.

The caller pre-allocates a Basis with Basis::new and reuses it across iterations, eliminating per-element enum translation overhead.

The buffer is not resized by this method. The implementation writes into the first num_cols entries of out.col_status and the first num_rows entries of out.row_status. Panics if no model is loaded.

See Solver Interface Trait SS2.7.

Source

fn solve_with_basis( &mut self, basis: &Basis, ) -> Result<SolutionView<'_>, SolverError>

Injects a basis and solves, returning a zero-copy SolutionView.

Status codes in basis are injected directly without per-element enum translation. On success the returned view borrows solver-internal buffers and is valid until the next &mut self call. Call SolutionView::to_owned when the solution must outlive the borrow.

§Errors

Same error contract as solve.

See Solver Interface Trait SS2.5.

Source

fn statistics(&self) -> SolverStatistics

Returns accumulated solve metrics (snapshot of monotonically increasing counters).

Statistics accumulate since construction; Self::reset does not zero them. All fields non-negative.

See Solver Interface Trait SS2.8.

Source

fn name(&self) -> &'static str

Returns a static string identifying the solver backend (e.g., "HiGHS").

Used for logging, diagnostics, and checkpoint metadata.

See Solver Interface Trait SS2.9.

Implementors§