Skip to content

[Bug] QAP→ILP extract_solution produces invalid permutation + non-deterministic reduction path selection #780

@zazabap

Description

@zazabap

Summary

Two related bugs cause intermittent CI failures when solving HamiltonianCircuit via ILP:

  1. Non-deterministic path selection in the reduction graph (HashMap iteration order)
  2. QAP→ILP extract_solution bug producing invalid permutations for certain instances

Bug 1: Non-deterministic path selection

src/rules/graph.rs uses HashMap for node_index and name_to_nodes. Rust's default hasher uses a random seed per process, so the reduction path finder may select different paths across runs:

  • Run A: HC → TSP → ILP (correct)
  • Run B: HC → QAP → ILP (triggers Bug 2)

Both paths have similar overhead, so which is chosen depends on HashMap iteration order.

Fix options:

  • Replace HashMap with BTreeMap for deterministic iteration
  • Add path selection tiebreaking (prefer shorter/simpler paths)

Bug 2: QAP→ILP extraction produces invalid permutation

When the reduction graph selects HC → QAP → ILP for the prism graph (6 vertices, 9 edges), the QAP→ILP extract_solution (src/rules/quadraticassignment_ilp.rs:37-46) returns permutation [1, 2, 3, 0, 5, 4]. This represents tour 1→2→3→0→5→4→1, but edge (2,3) does not exist in the prism graph — so this is NOT a valid Hamiltonian circuit.

The QAP→ILP reduction uses McCormick linearization for z_{ijpq} = x_{ip} * x_{jq}. While McCormick is theoretically exact for binary variables, the resulting ILP has 1332 variables (36 x-vars + 1296 z-vars) for n=6. HiGHS may encounter numerical issues in branch-and-bound that lead to an incorrect extraction.

Specific investigation needed:

  • Does HiGHS return a truly optimal ILP solution, or does it return a solution that violates integrality tolerances?
  • Are the McCormick constraints properly tightened? (e.g., missing z >= 0 lower bound?)
  • Does the QAP evaluate() confirm the extracted permutation is suboptimal?

Reproduction

# The test passes locally but fails on some HashMap seeds.
# To reproduce, run repeatedly — it depends on HashMap random seed:
cargo test --features "ilp-highs example-db" -- model_specs_are_optimal

The failure is intermittent locally but was consistent on CI during PR #779.

Workaround applied

PR #779 changed the HC model example from the prism graph to K4 (complete graph on 4 vertices), where every permutation is a valid HC. This makes the test pass regardless of which reduction path is selected or what permutation the solver extracts.

Files involved

  • src/rules/graph.rs — HashMap-based reduction graph (Bug 1)
  • src/rules/quadraticassignment_ilp.rs — QAP→ILP reduction + extraction (Bug 2)
  • src/rules/ilp_helpers.rsmccormick_product helper
  • src/models/graph/hamiltonian_circuit.rs — model example spec (workaround applied)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions