Conversation
| /// Add solving method using gurobi syntax | ||
| pub fn with_algorithm(&self, algorithm: u32) -> GurobiSolver { |
There was a problem hiding this comment.
algorithm: u32 is obscure. This should probably be an enum, or at least very clearly documented.
There was a problem hiding this comment.
I could just rename it to method: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#method I don't quite remember why I called it like that, probably for it to be consistent with other APIs
| /// Tell gurobi to use crossover | ||
| pub fn with_crossover(&self, crossover: u32) -> GurobiSolver { |
There was a problem hiding this comment.
Same here, crossover: u32 does not make sense to me. And the doc comment is way too short
There was a problem hiding this comment.
Should we add these as links to the docstrings? https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#crossover
There was a problem hiding this comment.
I think we should expose it as native rust types, not mirror the C interface, and have our own documentation for our own types. In this case, it might look like this
/// Controls whether and how the solver converts an interior-point solution into
/// a basic solution.
///
/// Barrier and PDHG algorithms usually produce an *interior* solution: a solution
/// that satisfies the model well, but is not necessarily positioned on a clear
/// set of active variable bounds and constraints.
///
/// Some users need a *basic* solution instead. A basic solution is the kind of
/// corner-point solution typically produced by simplex methods. It is often more
/// useful when inspecting basis status, reduced costs, shadow prices, or when
/// passing the solution into later simplex-based work.
///
/// Crossover is the post-processing step that performs this conversion. It first
/// tries to move selected primal or dual quantities to their bounds, then uses a
/// simplex cleanup phase to repair any remaining infeasibility.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Crossover {
/// Let the solver choose the crossover behavior automatically.
///
/// This is usually the best choice unless there is a specific reason to
/// control the crossover sequence. The solver may choose based on model
/// structure, numerical behavior, and the algorithm used to solve the
/// relaxation.
#[default]
Auto,
/// Do not run crossover.
///
/// With this setting, the solver returns the interior solution produced by
/// barrier or PDHG directly. This may be faster when a basic solution is not
/// needed, but the returned solution can be less suitable for workflows that
/// rely on basis information or simplex-style post-processing.
///
/// Disabling crossover is not available for every model type or algorithm
/// combination. Those compatibility rules should be checked when the
/// parameter is applied to a model.
Disabled,
/// Run crossover using an explicit push order and cleanup method.
///
/// This gives callers control over two decisions:
///
/// - whether primal or dual quantities are pushed to bounds first;
/// - whether the final cleanup is performed with primal or dual simplex.
///
/// Most users should prefer [`Crossover::Auto`]. This option is useful when
/// reproducing solver behavior, comparing strategies, or tuning difficult
/// models.
Strategy {
/// The order in which crossover performs its two push phases.
///
/// A push phase tries to move either primal or dual quantities onto
/// bounds so that the interior solution becomes closer to a basic
/// solution before simplex cleanup begins.
push_order: PushPhaseOrder,
/// The simplex algorithm used for the final cleanup phase.
///
/// Cleanup removes any remaining primal or dual infeasibilities after
/// the push phases have finished.
cleanup: CrossoverCleanup,
},
}
/// Specifies which crossover push phase runs first.
///
/// Crossover has two push phases:
///
/// - a *primal* push, which works on the model variables directly;
/// - a *dual* push, which works on dual information associated with constraints
/// and bounds.
///
/// The order can affect performance and numerical behavior, but it does not
/// change the mathematical model being solved.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PushPhaseOrder {
/// Run the dual push phase first, followed by the primal push phase.
///
/// This prioritizes making the dual side of the solution more basis-like
/// before pushing primal variables to bounds.
DualThenPrimal,
/// Run the primal push phase first, followed by the dual push phase.
///
/// This prioritizes moving model variables toward bounds before working on
/// the dual side of the solution.
PrimalThenDual,
}
/// Specifies which simplex method is used during crossover cleanup.
///
/// After the push phases, the solution may still have small primal or dual
/// infeasibilities. The cleanup phase uses simplex to finish the conversion to a
/// basic solution.
///
/// Primal and dual simplex are closely related algorithms. Either can be a good
/// choice depending on the model and the state of the solution after the push
/// phases.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CrossoverCleanup {
/// Use primal simplex for the cleanup phase.
///
/// Primal simplex focuses on maintaining primal feasibility while improving
/// the remaining basis structure. It can be preferable when the post-push
/// solution is already close to primal feasible.
PrimalSimplex,
/// Use dual simplex for the cleanup phase.
///
/// Dual simplex focuses on maintaining dual feasibility while repairing the
/// remaining primal side. It can be preferable when the post-push solution is
/// already close to dual feasible.
DualSimplex,
}| } | ||
|
|
||
| /// Toggle verbose | ||
| pub fn set_verbose(&self, verbose: u32) -> GurobiSolver { |
There was a problem hiding this comment.
There was a problem hiding this comment.
same as above, we want to provide a rust interface, documented in its own right
There was a problem hiding this comment.
for logging, we probably want a bool that defaults to false
| } | ||
|
|
||
| /// Toggle predual | ||
| pub fn set_predual(&self, predual: u32) -> GurobiSolver { |
There was a problem hiding this comment.
| } | ||
|
|
||
| /// Toggle predual | ||
| pub fn with_barconvtol(&self, barconvtol: f32) -> GurobiSolver { |
There was a problem hiding this comment.
|
I think we need better docs and better types. |
Hi, I had these features of the Gurobi solver laying around for a while and I thought it wouldn't be bad to have them in the main repo. Let me know if you need some changes.