Skip to content

Replace hardcoded canonical rule examples with ILPSolver calls#774

Closed
isPANN wants to merge 28 commits intomainfrom
replace-hardcoded-ilp-examples-772
Closed

Replace hardcoded canonical rule examples with ILPSolver calls#774
isPANN wants to merge 28 commits intomainfrom
replace-hardcoded-ilp-examples-772

Conversation

@isPANN
Copy link
Copy Markdown
Collaborator

@isPANN isPANN commented Mar 26, 2026

Summary

  • Convert 46 ILP reduction rules from hardcoded SolutionPair to dynamic ILPSolver::new().solve() calls in canonical_rule_example_specs()
  • Add z upper bound constraint in MinMaxMulticenter ILP formulation to prevent HiGHS stalling
  • Update constraint count assertion in minmaxmulticenter test
  • Relax exact-value assertion in IntegralFlowBundles example-db test (solver may return different valid solutions)

Details

ILP<bool> (36 rules): Mechanical replacement — reduce source, solve ILP, extract solution, pass into SolutionPair.

ILP<i32> (10 rules): Same pattern. MinMaxMulticenter additionally needed an explicit z upper bound (max weighted distance) so HiGHS doesn't see [0, 2^31) and hang.

All 3530 tests pass (3383 lib + 66 integration + 81 doc).

Test plan

  • cargo build --features example-db,ilp compiles cleanly
  • cargo test --features example-db,ilp — all tests pass
  • rule_specs_solution_pairs_are_consistent validates all canonical examples

Closes #772

🤖 Generated with Claude Code

isPANN and others added 28 commits March 25, 2026 12:26
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Min<usize>)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…::Sum>)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…<i64>)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…to optimization (Min<i64>)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… (Min<i64>) + ILP rewrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…<f64>) + ILP rewrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…<i64>) + ILP rewrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Max<usize>) + ILP rewrite + config redesign

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…n (Min<usize>) + config redesign

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove bound parameter from 8 model constructor calls in CLI create
- Remove associated bound parsing/validation code and CLI tests
- Fix SumOfSquaresPartition canonical example (optimal is 226, not 230)
- Fix StackerCrane example-db test assertion (no longer has bound field)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…(Min<W::Sum>)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ion (Min<N::Sum>) + ILP rewrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…28>) + ILP rewrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Sum>) + minimax ILP rewrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… (Max<usize>) + config redesign

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ptimization-765

# Conflicts:
#	docs/paper/reductions.typ
… merge

- Convert 10 ILP rules from feasibility to optimization (remove bound, add objective)
- Fix SCS ILP: add contiguous padding constraint, fix alphabet_size field
- Mark OLA ILP<i32> tests as ignored (ILP solver too slow for integer variables)
- Fix sequencing ILP test to use ILPSolver instead of brute-force on ILP<i32>

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nces

- model_specs_are_optimal now tries brute-force first for instances with
  search space ≤ 2^20, avoiding HiGHS hangs on ILP<i32> reductions
- Hardcode OLA and Sequencing ILP canonical example solutions (avoid
  calling ILPSolver at example-db build time for ILP<i32> targets)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: ILP<i32> variables default to domain [0, 2^31], causing HiGHS
to hang on even tiny instances. Two fixes:

1. ILP solver: derive tighter per-variable upper bounds from single-variable
   ≤ constraints before passing to HiGHS (covers x and p variables)
2. OLA ILP: add z_e ≤ n-1 bound (max position difference)
3. Sequencing ILP: add z ≤ Σ|costs| bound (max cumulative cost)

Restores ILPSolver calls in canonical rule examples (removes hardcoded
solutions) and reverts model_specs_are_optimal to ILP-first strategy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lver test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…verage

- Remove #[ignore] from OLA ILP tests (HiGHS is fast now with z bounds)
- Add rural_postman tests: wrong config length, is_weighted, solver aggregate
- Add SWCP test: weight bound exceeded
- Covers codecov gaps in rural_postman, shortest_weight_constrained_path,
  and optimallineararrangement_ilp

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix CustomizedSolver for MinimumCardinalityKey to guarantee minimum
  cardinality using iterative deepening by subset size, not just any
  minimal key (critical correctness fix for optimization upgrade)
- Remove stale --bound references from CLI help and usage strings for
  LongestCircuit, MixedChinesePostman, RuralPostman, StackerCrane,
  LCS, SCS, MinimumCardinalityKey, MultipleCopyFileAllocation, and
  SequencingToMinimizeMaximumCumulativeCost
- Remove stale --num-paths-required from LengthBoundedDisjointPaths help
- Remove stale --k from MinimumCardinalityKey help
- Remove --length-bound from SWCP example in docs/src/cli.md
- Fix OLA->ILP overhead num_constraints (add num_edges for z_e bounds)
- Fix LongestCircuit->ILP overhead (n-1 commodities, not n)
- Allow LCS max_length == 0 for empty input strings instead of panicking
- Strengthen LCS brute-force test assertion to check exact optimal value
- Add optimality assertions to CustomizedSolver MCK tests
- Update cli_tests to reflect removed --bound flags

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert 46 ILP reduction rules from hardcoded SolutionPair to dynamic
ILPSolver::new().solve() calls, ensuring canonical examples actually
verify the ILP solver can solve the reduction.

Also adds a z upper bound constraint in MinMaxMulticenter ILP formulation
to prevent HiGHS from stalling on unbounded [0, 2^31) domain.

Closes #772

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…plate

Add `rule_example_via_ilp<S, V>()` to `example_db::specs` that performs
reduce → ILP solve → extract → assemble in one call. This replaces
the 8-line block that was copy-pasted across 60 ILP rule files, and
also eliminates the double `reduce_to()` call (once explicit, once
inside `rule_example_with_witness`).

Also fixes stale docstring on `build_example_db()` which incorrectly
claimed no solver is called.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@isPANN
Copy link
Copy Markdown
Collaborator Author

isPANN commented Mar 26, 2026

Canonical rule example convention change

After this PR, the standard pattern for canonical_rule_example_specs() in *_ilp.rs files is:

#[cfg(feature = "example-db")]
pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
    vec![crate::example_db::specs::RuleExampleSpec {
        id: "<source>_to_ilp",
        build: || {
            let source = /* construct instance */;
            crate::example_db::specs::rule_example_via_ilp::<_, bool>(source)  // or i32
        },
    }]
}

What changed:

  • rule_example_via_ilp<S, V>(source) replaces the old pattern of hardcoding SolutionPair { source_config: vec![...], target_config: vec![...] }
  • Internally it does: reduce_to()ILPSolver::new().solve()extract_solution() → assemble — in one call, with no double reduction
  • The use crate::export::SolutionPair import is no longer needed for ILP rules
  • rule_example_with_witness() still exists for non-ILP target rules that need a manually specified solution pair

For new ILP rules: just use rule_example_via_ilp. If the ILP solver hangs, it means the formulation needs tighter variable bounds (see minmaxmulticenter_ilp.rs for an example of adding a z upper bound).

@isPANN isPANN changed the base branch from upgrade-decision-to-optimization-765 to main March 26, 2026 03:21
@isPANN isPANN closed this Mar 26, 2026
@GiggleLiu GiggleLiu deleted the replace-hardcoded-ilp-examples-772 branch April 12, 2026 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace hardcoded canonical rule examples with ILPSolver calls

2 participants