Gecode 6.4.0
Numerical LP observations, basis, evidence and sensitivity

These explicit workflows use ordinary Continuous linear models and numerical HiGHS semantics. They do not automatically relax a MIP or replace unsupported indicators/globals. Historical artifacts own their source model and original slot mapping. Available zero values, unavailable data and unrequested data have different states; read those states before optional payloads.

Operation Delivered data Boundary
Gecode::Optimize::solve_lp_observed Original row activity/slack, checked duals/reduced costs and basis statuses Accepted duals require timely optimal primal/dual data and independent KKT checks. Basis data is not a proof.
Gecode::Optimize::make_lp_basis and Gecode::Optimize::solve_lp_with_basis Immutable original basis input and explicit accepted/repaired/rejected submission Exact owner/revision/content checks; no simultaneous primal start, silent cold fallback or faster-solve guarantee.
Gecode::Optimize::analyze_lp_evidence Independently checked numerical primal rays or Farkas multipliers using explicit private auxiliary solves Original and auxiliary coordinates/statuses remain distinct; no exact infeasibility certificate claim.
Gecode::Optimize::analyze_lp_sensitivity One-parameter objective-coefficient or common equality-RHS interval for a selected optimal basis Additional private factorization/system solves, zero optimization runs; numerical intervals only.

Selected-basis sensitivity

LpSensitivityOptions requests unique LpObjectiveParameter or LpEqualityRhsParameter entries from an owning LpObservedResult. The analyzer checks original feasibility, dual/KKT evidence, complete basis statuses and reconstructed reference point before interval publication. It neither repairs nor chooses another basis. A degenerate optimum can have different intervals for different selected bases/statuses.

namespace O = Gecode::Optimize;
O::Model model;
const auto x = model.add_continuous();
const auto y = model.add_continuous();
const auto balance = model.add_row({{x, 1}, {y, 1}}, 3, 3);
model.minimize({{x, 2}, {y, 1}}, 7);
const auto observed = O::solve_lp_observed(model);
O::LpSensitivityOptions options;
options.parameters = {O::LpObjectiveParameter{x},
O::LpEqualityRhsParameter{balance}};
const auto analysis = O::analyze_lp_sensitivity(observed, options);
if (analysis.sensitivity) {
const auto* entry = analysis.sensitivity->objective(x);
if (entry && entry->group.state == O::LpSensitivityState::Available) {
// Read entry->interval: tagged endpoints, slope and checks.
}
}
Optional sparse optimization models, backends and owning results.

Each interval varies one original parameter alone with the selected basis and nonbasic statuses fixed. Equality RHS varies both equal sides together. Endpoints are absolute parameter values; infinity is tagged, not a finite double. A singleton is an available interval. The optional objective_slope describes slope*(parameter-anchor), without adding the original offset again. Variable-bound, inequality-side, matrix-entry and simultaneous perturbation ranges are not supported. There is no CPLEX/Gurobi ranging equivalence claim.

Complete means every requested interval passed; Partial allows per-request rejection. Whole-call stop, resource, allocation or cleanup failure clears every interval's availability, including earlier results. Source history and completed diagnostics can remain. Lookups perform no solver work and survive model/session destruction. Size/work/factor-solve caps and one cooperative deadline cover admission through backend cleanup.