Repository navigation
Tighten ILP num_nonzeros bounds to per-constraint counts - #1222
Conversation
Each ILP rule's num_nonzeros upper bound was num_constraints * num_vars, a dense-matrix bound that the corpus measured at under half of its prediction on 55 rules. Derive the bound from each reduce_to's constraint families instead, summing the terms each family contributes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agentic Review ReportScope: 46 Structural
Semantic: hand derivation of every formulaI traced each Data-dependent loops checked:
Exact matches (derivation equals the formula on the dense worst case): COS, Steiner, STMMCC, STMTTW, STMWT, SMWCT, FSS, MTS (both), DHP, OCST, SubIso, MinMaxMulticenter, MGB, OLA, LongestPath, SWCP, MLST, U2CIF, UFLB, and the others with linear families. Loose but valid (≤ 1.2× slack):
Spot measurement with Quality
Feature test
FindingsCritical: none. Important: none. Minor
Verdict: correct. All 46 |
Canonical examples are sparse, so a constraint family missing from a per-family nonzero count can go unnoticed. Reduce dense instances of five rules with the most constraint families and require the measured count to stay within the declared bound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bound K counts selected columns, but try_new accepted any negative value. Such an instance panicked in parameters(), whose bound must fit u64, and its ILP reduction cast the bound with `as usize`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The corpus measured 81 non-trivial upper-bound fields at exactly their prediction on every instance. Of those, 46 fields in 30 rules are exact by construction: every row family and variable block is emitted unconditionally, the source invariants (simple graphs, exactly-K clauses, n divisible by 3, 1 <= k <= n) rule out merged or dropped terms, and no early return builds a different target. The rest stay upper bounds: degenerate-input shortcuts, data-dependent zero coefficients or cancelled literals, and QUBO entries where penalty and objective terms can cancel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KSatisfiability<K3>::new_allow_less admits clauses with fewer than three literals, so 3SAT -> KClique num_vertices and 3SAT -> DecisionMVC num_edges shrink below their formulas. Return both to upper_bound, pin the relations with short-clause instances, and lay out the transform declarations by nesting depth. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The exact claims for HamiltonianCircuit, MaximalIS, MinimumDominatingSet, MaximumMatching, Kernel, PartitionIntoPathsOfLength2, PartitionIntoPerfectMatchings and PartitionIntoCliques were checked only on canonical examples. Pin them on empty, path and complete graphs with up to three vertices, k = 1 and k = n, and antiparallel arcs. Also promote MinimumVertexCover -> EnsembleComputation num_subsets, one subset per edge, and convert the ConsecutiveOnesSubmatrix bound with try_from now that construction keeps it nonnegative. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxCut<SimpleGraph, i64> accepts negative weights, but the rule rejected
them, so every planned path through it (for example Max2SAT -> MaxCut ->
MinimumMatrixCover) failed on ordinary inputs. Replace each negative edge
{u, v} by an auxiliary vertex joined to v with |w| + 1 and to u with |w|:
every maximum cut separates the auxiliary vertex from v, so the gadget
shifts the cut by the constant 2|w| + 1 and preserves maximum cuts.
Extraction drops the auxiliary bits; num_rows becomes an upper bound.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ConsecutiveOnesSubmatrix stores its column-count bound as usize, so serde and the CLI reject negatives by type and the model and ILP rule drop their conversions. - The MaxCut -> MinimumMatrixCover gadget computes |w| + 1 as 1 - w with one checked subtraction; module docs and the paper's duplicate extraction paragraph now describe the auxiliary vertices. - The PartitionIntoPathsOfLength2 comment states why its counts are exact. - The degenerate-graph test covers every valid k; transform layouts are consistent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KSatisfiability<KN> was Satisfiability under another name: it checked no clause width and its only edges were identity casts into and out of it. Every path from K2 or K3 paid an extra hop through it. - Drop the KN variant; K2 and K3 now reduce directly to Satisfiability and K3 is the default variant. - Remove new_allow_less/try_new_allow_less. K2 and K3 always hold exactly K literals per clause, matching what serde and the CLI already enforced. - Delete the short- and empty-clause branches these constructors forced on 3-SAT rules, and declare 3SAT -> KClique num_vertices and 3SAT -> DecisionMVC num_edges exact again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e text SAT -> NAE turns every three-literal clause into a four-literal one, so the MonochromaticTriangle vertex, edge and triangle counts are equalities and its two-literal branch was dead. Also remove leftover short- and empty-clause wording and dead padding in OneInThree, QuadraticCongruences and Kernel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add a FixedK sub-trait implemented by K1..K5, and bound KSatisfiability and the SAT/K-SAT results by it, so KSatisfiability<KN> no longer type-checks instead of failing at construction. - Register each K-SAT aggregate mapping inside the macro that registers its witness edge, and take the SAT -> K-SAT clause width from the type. - Allocate CyclicOrdering's fresh padding variables with allocate_many. - Drop leftover braces in two tests and a stale QuadraticCongruences note. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removing the KSatisfiability KN variant does not need a new variant trait. Keep KSatisfiability bounded by KValue with the runtime width check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GiggleLiu
left a comment
There was a problem hiding this comment.
Agentic Review Report
PR #1222: Tighten ILP num_nonzeros bounds to per-constraint counts
Review date: 2026-10-29. Fresh-context read-only review of 0daa9a8265aefe40983beeba0464f8feea8c3316...f95447ad2f1de5d37c020ad6ffc119460adebaff. Used the PR's own stack base, not origin/main. Local implementation evidence is diff-1222.patch; GitHub context is context-1222.txt in this directory.
Verdict: No new blocking finding in this diff. Hold stack integration until prerequisite fixes land.
Structural and semantic review
Reviewed all 46 changed ILP num_nonzeros declarations and their reduce_to construction bodies, the dense-source regression, and affected manual text against exact #1218. Each expression is an upper bound, so coefficient normalization may merge duplicates or drop zeros without invalidating it. No change to the optimization semantics is introduced.
Independent representative term counts: BinPacking has n² assignment terms plus n(n+1) capacity terms, giving 2n²+n. DirectedHamiltonianPath contributes 3n² plus 2n²(n−1), giving n²+2n³. Directed two-commodity paths contribute 4km flow terms plus 2km shared-capacity terms. Kernel/Clique-like and domination formulas count graph degrees before adding per-vertex terms. Scheduling formulas count one-hot rows, period capacities, and ordered precedence contributions separately rather than multiplying all rows by all variables. ResourceConstrainedScheduling uses the compressed horizon D <= n. SteinerTree's n−1 term is safe because construction requires a nonempty terminal set and thus n >= 1.
Checked degenerate zero-variable or empty-edge cases and early infeasible targets; each bound remains nonnegative or safely overestimates the constructed target. The changed multiway, flow, longest-path/circuit, tree, matching, assignment, scheduling, and subgraph-isomorphism bounds were traced to actual add_constraint calls. No undercount was identified.
Quality review
The new dense-source regression complements existing canonical sparse examples; a sparse canonical instance alone would not justify a tighter worst-case formula. Hand counts were used to assess all changed formulas. Material examples include 6km for directed commodity paths, 22m for undirected two-commodity flow, n+2precedences for partially ordered knapsack, and pattern_verticeshost_vertices plus 2pattern_edgeshost_vertices² for subgraph isomorphism. Normalization only decreases these upper bounds.
Feature tests and verification limits
No native exact #1222 metadata test or full build was run by this reviewer. The shared build slot was used for #1218 tests/CLI, then the exact #1224 numeric probe. That probe compiles the #1224 descendant, which includes these declarations, but compilation does not validate their counts. The author-reported tightness corpus and parameter regression results were read and are not counted as reviewer execution.
Executed own-base git diff --check successfully. Source/target optimization behavior is unchanged by this PR. Current GitHub CI results were not visible in the collected stack metadata. Parent should run current integrated parameter tests before merge.
Findings (severity order)
No new blocking finding. All changed count expressions were independently checked as upper bounds. The inherited #1214 reduction panic is outside this diff and should be resolved before integrating its dependency chain.
GitHub PR Audit — #1222
GATE: PASS
Harm signals (blocking)
- harm.secrets (
security.no-secrets): OK — inspected added text; no credential/key/token or private-data additions found. - harm.dangerous-files (
git.harm-signals): OK — changed files are scoped source, tests, and manual material; no conflict markers, unexplained binaries/archives, scratch files, or local configuration. - harm.generated-artifacts (
code.generated-artifacts): OK — no generated example/schema/reduction-graph exports or build/dependency outputs are committed. - harm.cache (
code.generated-cache): OK — no cache directories added. - harm.debug-leftovers (
code.debug-leftovers): OK — no debugger, debug print, temporary probe, or WIP instrumentation in added production code.
PR legibility (advisory)
- pr.description-quality (
github.pr-description-quality): OK — body describes scope, purpose, validation, and limits; comments and reviews were read withgh-axi pr view --full --comments --reviews. - pr.traceable (
github.prs-traceable): OK — purpose and validation are stated and the series/issue context is identifiable.
Harm gate PASS does not clear correctness findings. No tracked file, commit, remote branch, PR comment, review, or merge was modified by this reviewer.
[Critical] Remove KSatisfiability KN variant and short-clause constructors
Declare exact parameter counts that constructions always produce
GiggleLiu
left a comment
There was a problem hiding this comment.
Agentic Review Report: stack consolidation
Approved current head 5cab940eee60588875f3b21162df8881a0ff10e2 for merging into feat/binary-ilp-to-sat only. This contains the previously reviewed changes and, where applicable, the preceding recorded backend merges. The numeric blockers in #1214 and #1224 are fixed and reviewed at 2226ebec4 and 52bd171a0.
Rechecked inline comments, submitted reviews, PR conversation, linked-issue comments, and Codecov comments. No new unaddressed material issue. Harm gate remains PASS from the independent reviews. The old roadmap draft/hold instructions predate the user's current authorization; deferred rules and #1219/#1220/#1221 remain excluded.
The repaired aggregate passed 7,194 native tests, formatting, all-target/all-feature Clippy, and make paper at d96e7c8b8; the final website gate subsequently passed all 336 browser cases at 77774797e. These are aggregate gates, including the separately reviewed integration fixtures, not a claim that this branch head was independently retested unchanged. Required main-branch CI remains pending. This feature-branch merge preserves the individual PR record.
Summary
46 ILP rules declared
num_nonzeros <= num_constraints * num_vars, which is the bound for a dense matrix. Againstpred-validation-corpus, 55 rules never reached even half of that prediction. Each rule now sums the terms contributed by each constraint family in itsreduce_to.Verification
scripts/verify_parameters.py(corpus) re-run on those 55 rules, 100 instances each: 0 violations. 47 fields now reach 0.83–1.0 of their prediction (before: ≤ 0.48).cargo test --workspace,cargo fmt --checkand clippy all pass. The one clippy warning, inksatisfiability_bicliquecover.rs, was already there.Still loose, and not changed here: MinimumHittingSet (its parameters can't express the incidence count), CircuitSAT, HighlyConnectedDeletion, MinimumCodeGenerationUnlimitedRegisters, SequencingWithReleaseTimesAndDeadlines, SequencingWithinIntervals, TwoDimensionalConsecutiveSets.
Stacked on #1218 (
feat/binary-ilp-to-sat).🤖 Generated with Claude Code