Skip to content

Wrong optimal objective reported with presolve enabled #3452

Closed

Description

@hodangkhoinguyen

What version of HiGHS and what language are you using?
Release 1.15.1 and branch latest (95bd9c8).
Using the standalone C++ command-line executable.

Which solver are you using (e.g. LP, MIP, QP)
MIP

What operating system (Linux, Windows, ...) and version?
Debian GNU/Linux 12, x86-64

What did you do?
Ran the attached model test.mps.txt

highs test.mps --threads 1 --time_limit 120

What did you expect to see
Optimal, objective ≈ 8104.99914

What did you see instead?
Optimal, objective 12924.9999939 (primal and dual bound both 12924.9999939, gap 0%)

Disabling presolve returns an optimal solution with objective approximately 8104.99914364:

highs test.mps --threads 1 --time_limit 120 --presolve off

The attached witness.txt lists a verified feasible solution with objective approximately 8104.99914364, disproving the reported optimality claim. Variables not listed are zero.

Anything else we should know about your project / environment
On 95bd9c8, turning off only the DualFixing presolve rule (presolve_rule_off = 131072) also gives 8104.99914364; on 1.15.1 it does not.

Activity

  1. fwesselm commented on Oct 22, 2026

    @fwesselm
    Collaborator

    I will have a look.

  2. self-assigned this
    on Oct 22, 2026
  3. fwesselm commented on Oct 22, 2026

    @fwesselm
    Collaborator

    @Opt-Mucca, I think I need your help here, our friend "analytic center computation" is back:

    1. At the root, HighsMipSolverData::startAnalyticCenterComputation solves the presolved LP with zero costs using IPX with run_centring = true and run_crossover = off.
    2. On this model IPX makes no progress (status_ipm = IPX_STATUS_no_progress), so it never attempts the centring steps.
    3. IpxWrapper returns model status kUnknown.
    4. lpKktCheck then upgrades the status to kOptimal, because the point is primal and dual feasible (zero objective).
    5. HighsMipSolverData::finishAnalyticCenterComputation only checks analyticCenterStatus == HighsModelStatus::kOptimal. Column x2365 is at its upper bound 293000 (a bound set by presolve), and the code sets its lower bound to 293000. The global domain becomes infeasible, the root node is pruned, and the incumbent found earlier by a heuristic (with objective 12924.99999) is reported as optimal.

    I think losing the status IPX_STATUS_no_progress is the culprit here.

  4. Opt-Mucca commented on Oct 22, 2026

    @Opt-Mucca
    Collaborator

    @fwesselm I was just exploring the same bug in the other issue! Nice to know we got to the same conclusion

    Edit: Agree on losing the status being the likely culprit.

  5. odow commented on Oct 29, 2026

    @odow
    Collaborator

    Closed by #3456

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions