Commit 015b1c6
Fix ILP i32->bool cast overhead: use size-field name num_vars, not getter alias (#1080)
Root cause of the `pred path MinimumFeedbackVertexSet ILP` bug (asymptotic `num_vars`
composed to `O(num_variables)` instead of `O(num_vertices)`): the `ILP<i32> → ILP<bool>`
binary-encoding cast declared its overhead as `num_vars = "31 * num_variables"`. ILP's
size field is named `num_vars`; `num_variables()` is only a getter *alias* for it. The
`#[reduction]` macro validates overhead variables against getter *methods*, so the alias
compiled, and both instance-mode sizing (`evaluate_output_size` calls the getter) and
raw-overhead Big-O rendering resolve it — the mistake was invisible there.
But asymptotic growth composition (`GrowthLabel::extend`) threads size-field *names*: the
label key at the ILP node is `num_vars`, so the variable `num_variables` was unmapped and
leaked through unchanged as `num_vars = O(num_variables)`. The path's arrow display had
also masked this by collapsing the hidden `ILP/i32 → ILP/bool` cast step.
Fix: `31 * num_variables` → `31 * num_vars` (semantically identical — 31 bits per integer
variable — and numerically unchanged, since both getters return `num_vars`).
Effects: `MFVS → ILP` now composes `num_vars = O(num_vertices)`. `MVC → ILP` drops from 3
to 2 front paths — the corrected feedback-vertex-set route
(`num_constraints = O(num_edges + num_vertices), num_vars = O(num_vertices)`) is now
correctly Pareto-dominated by the direct route and pruned.
Test: `test_asymptotic_front_uses_only_source_variables_mfvs_ilp` pins
`num_vars = O(num_vertices)` and asserts every composed field's growth references only
MinimumFeedbackVertexSet's own size variables — a general "source-variables-only"
invariant on the front label.
Note: this is one instance of a getter-alias-vs-field-name mismatch. A separate, broader
class of leaks remains in other reductions (e.g. `ClosestVectorProblem`'s `num_encoding_bits`
and `CircuitSAT`'s `tseitin_num_vars`/`tseitin_num_clauses`, which surface in KSat→QUBO);
those are genuine field-name inconsistencies between a node's incoming and outgoing
reductions, outside the growth-composition logic, and are left for separate scoping.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EgxSbn5gwizTBkC22eyWXR1 parent ad2c050 commit 015b1c6
2 files changed
Lines changed: 72 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
264 | 264 | | |
265 | 265 | | |
266 | 266 | | |
267 | | - | |
| 267 | + | |
268 | 268 | | |
269 | 269 | | |
270 | 270 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
714 | 714 | | |
715 | 715 | | |
716 | 716 | | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
0 commit comments