Skip to content

feat: add 11 Tier 1a + 1b medium-confidence reduction rules (#770)#804

Merged
isPANN merged 19 commits intomainfrom
feat/770-tier1a-tier1b-medium-batch
Mar 30, 2026
Merged

feat: add 11 Tier 1a + 1b medium-confidence reduction rules (#770)#804
isPANN merged 19 commits intomainfrom
feat/770-tier1a-tier1b-medium-batch

Conversation

@zazabap
Copy link
Copy Markdown
Collaborator

@zazabap zazabap commented Mar 28, 2026

Summary

Add 11 reduction rules from #770 (Tier 1a + Tier 1b medium-confidence). Each rule includes: implementation, unit tests, example_db entry, and paper entry.

# Rule Issue
1 MinimumVertexCover → MinimumHittingSet #200
2 PartitionIntoPathsOfLength2 → BoundedComponentSpanningForest #241
3 HamiltonianCircuit → LongestCircuit #358
4 Partition → SubsetSum #387
5 RootedTreeArrangement → RootedTreeStorageAssignment #424
6 SubsetSum → CapacityAssignment #426
7 LongestCommonSubsequence → MaximumIndependentSet #109
8 MinimumVertexCover → EnsembleComputation #204
9 KClique → BalancedCompleteBipartiteSubgraph #231
10 KColoring(K3) → TwoDimensionalConsecutiveSets #437
11 PaintShop → QUBO #649

Fixes #200
Fixes #241
Fixes #358
Fixes #387
Fixes #424
Fixes #426
Fixes #109
Fixes #204
Fixes #231
Fixes #437
Fixes #649


Agentic Review

Structural Check

# Rule File Tests Mod.rs Example_db Paper Overhead Correctness
1 HC → LongestCircuit 4 ✅
2 KClique → BCBS 6 ✅
3 KColoring → 2DCS 6 ✅
4 LCS → MIS 9 ✅ ✅ (worst-case)
5 MVC → EnsembleComp 6 ✅
6 MVC → HittingSet 6 ✅
7 PaintShop → QUBO 6 ✅
8 Partition → SubsetSum 4 ✅
9 PIPL2 → BCSF 4 ✅
10 RTA → RTSA 6 ✅
11 SubsetSum → CapAssign 5 ✅

Build: PASS — fmt, clippy, 3655+ tests all pass

Feature Tests

All 11 rules: fully discoverable, reducible, and solvable (where ILP path exists).

# Rule pred list pred show pred create pred reduce pred solve Status
1 MVC → MinimumHittingSet ✅ Min(2) PASS
2 PIPL2 → BCSF ✅ Or(true) PASS
3 HC → LongestCircuit ✅ Or(true) PASS
4 Partition → SubsetSum ✅ Or(true) PASS
5 RTA → RTSA ✅ Or(true) PASS
6 SubsetSum → CapAssign ✅ Min(11) PASS
7 LCS → MIS ✅ Max(2) PASS
8 MVC → EnsembleComp N/A PASS
9 KClique → BCBS ✅ Or(true) PASS
10 KColoring → 2DCS N/A PASS
11 PaintShop → QUBO ✅ Min(2) PASS

Review Comments Resolution

# File Issue Status
1 rootedtreearrangement_rootedtreestorageassignment.rs:69 saturating_sub unsound when K < |E| Fixedchecked_sub + infeasible gadget; test added
2 partitionintopathsoflength2_boundedcomponentspanningforest.rs:62 Panic when n=0 Fixed — clamp max_components to ≥1
3 paintshop_qubo.rs:49 Underflow when seq_len == 0 Fixedsaturating_sub(1); test added
4 kcoloring_twodimensionalconsecutivesets.rs:67 Colors > 2 in extract_solution Fixed — HashMap label compression with % 3
5 longestcommonsubsequence_maximumindependentset.rs:209 Mislabeled vertex indices Fixed — corrected comments
6 subsetsum_capacityassignment.rs:74 u64 underflow when target > sum Fixedsaturating_sub; test added
7 subsetsum_capacityassignment.rs:58 BigUint→u64 panic on large instances Acknowledged — needs model-level change

Quality issues noted (low severity, deferred)

  • MVC→EnsembleComp reduces from weighted i32 variant but discards weights
  • LCS→MIS edge overhead bound is loose (worst-case, not tight)
  • Partition→SubsetSum has only 4 tests
  • HC→LongestCircuit non-Hamiltonian test has weak assertion

zazabap and others added 12 commits March 28, 2026 09:35
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…st reduction (#241)

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

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

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

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zazabap zazabap requested a review from Copilot March 28, 2026 09:51
@zazabap zazabap moved this to Review pool in Good issues Mar 28, 2026
@zazabap zazabap moved this from Review pool to Under review in Good issues Mar 28, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 28, 2026

Codecov Report

❌ Patch coverage is 98.86707% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.91%. Comparing base (a70b132) to head (b322ef9).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/models/misc/ensemble_computation.rs 74.19% 8 Missing ⚠️
...t_tests/rules/hamiltoniancircuit_longestcircuit.rs 90.90% 4 Missing ⚠️
.../longestcommonsubsequence_maximumindependentset.rs 99.06% 1 Missing ⚠️
...ts/rules/minimumvertexcover_ensemblecomputation.rs 98.78% 1 Missing ⚠️
...c/unit_tests/rules/subsetsum_capacityassignment.rs 98.38% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #804      +/-   ##
==========================================
+ Coverage   97.89%   97.91%   +0.02%     
==========================================
  Files         651      673      +22     
  Lines       71463    72756    +1293     
==========================================
+ Hits        69959    71240    +1281     
- Misses       1504     1516      +12     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a batch of new Tier 1a/1b reduction rules (with tests, canonical examples, and paper entries) to expand the reduction graph and documented proof corpus across graph, set, and misc/algebraic models.

Changes:

  • Implement 11 new reduction rules and register them in the rules module + canonical example spec aggregator.
  • Add unit tests for each new rule (closed-loop/structure/extraction checks).
  • Extend a few models with new public getters / variant declarations needed for overhead and reductions, and update the Typst paper with new reduction entries.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/rules/subsetsum_capacityassignment.rs Implements SubsetSum → CapacityAssignment reduction + canonical example + tests hook.
src/unit_tests/rules/subsetsum_capacityassignment.rs Adds closed-loop, structure, NO-instance, and monotonicity tests for SubsetSum → CapacityAssignment.
src/rules/rootedtreearrangement_rootedtreestorageassignment.rs Implements RootedTreeArrangement → RootedTreeStorageAssignment reduction + canonical example + tests hook.
src/unit_tests/rules/rootedtreearrangement_rootedtreestorageassignment.rs Adds closed-loop, structure, UNSAT, and extraction tests for RTA → RTSA.
src/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs Implements PPL2 → BCSF reduction + canonical example + tests hook.
src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs Adds closed-loop, UNSAT, and extraction tests for PPL2 → BCSF.
src/rules/partition_subsetsum.rs Implements Partition → SubsetSum reduction + canonical example + tests hook.
src/unit_tests/rules/partition_subsetsum.rs Adds closed-loop, structure, odd-sum, and equal-elements tests for Partition → SubsetSum.
src/rules/paintshop_qubo.rs Implements PaintShop → QUBO reduction + canonical example + tests hook.
src/unit_tests/rules/paintshop_qubo.rs Adds closed-loop, matrix-structure, and optimal-value tests for PaintShop → QUBO (+ example-db spec check).
src/rules/minimumvertexcover_minimumhittingset.rs Implements MVC(One) → MinimumHittingSet reduction + canonical example + tests hook.
src/unit_tests/rules/minimumvertexcover_minimumhittingset.rs Adds closed-loop, structure, and extraction tests for MVC → HS.
src/rules/minimumvertexcover_ensemblecomputation.rs Implements MVC → EnsembleComputation reduction + canonical example + tests hook.
src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs Adds structure and extraction-focused tests for MVC → EC.
src/rules/longestcommonsubsequence_maximumindependentset.rs Implements LCS → MIS reduction + canonical example + tests hook.
src/unit_tests/rules/longestcommonsubsequence_maximumindependentset.rs Adds closed-loop, structure, and extraction tests for LCS → MIS (k=2..4).
src/rules/kclique_balancedcompletebipartitesubgraph.rs Implements KClique → BCBS reduction + canonical example + tests hook.
src/unit_tests/rules/kclique_balancedcompletebipartitesubgraph.rs Adds closed-loop and several parameter-edge-case tests for KClique → BCBS.
src/rules/kcoloring_twodimensionalconsecutivesets.rs Implements K3-Coloring → TDCS reduction + canonical example + tests hook.
src/unit_tests/rules/kcoloring_twodimensionalconsecutivesets.rs Adds closed-loop and extraction-validity tests for K3-Coloring → TDCS.
src/rules/hamiltoniancircuit_longestcircuit.rs Implements HamiltonianCircuit → LongestCircuit reduction + canonical example + tests hook.
src/unit_tests/rules/hamiltoniancircuit_longestcircuit.rs Adds closed-loop, structure, and extraction tests for HC → LongestCircuit.
src/rules/mod.rs Registers the new rule modules and adds their canonical example specs into the aggregator.
src/unit_tests/rules/analysis.rs Updates dominated-rules expectation set to account for the new KClique → BCBS path.
src/models/misc/paintshop.rs Adds public getters needed by the PaintShop → QUBO reduction (sequence indices + parity).
src/models/misc/longest_common_subsequence.rs Adds cross_frequency_product() getter for LCS → MIS overhead accounting.
src/models/graph/minimum_vertex_cover.rs Adds One weight variant support + declares MVC<SimpleGraph,One> variant.
docs/paper/reductions.typ Adds Typst paper entries/examples for the newly introduced reductions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +67 to +69
// Bound K' = K - |E|; saturate at 0 to avoid underflow
let bound = self.bound().saturating_sub(num_edges);

Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saturating_sub(num_edges) makes the reduction unsound when K < |E|: the source is always infeasible (each edge contributes distance ≥ 1) but the target can become feasible with bound = 0 (e.g., a tree graph with K = |E| - 1). Use checked_sub; on underflow, return a target instance guaranteed unsatisfiable (e.g., a small fixed gadget with minimum extension cost ≥ 1) rather than clamping to 0.

Suggested change
// Bound K' = K - |E|; saturate at 0 to avoid underflow
let bound = self.bound().saturating_sub(num_edges);
// Bound K' = K - |E|. If this underflows (K < |E|), the source instance
// is infeasible (each edge contributes at least 1 to the arrangement
// cost). In that case, return a fixed gadget instance that is
// guaranteed infeasible for the target problem as well.
let bound = match self.bound().checked_sub(num_edges) {
Some(b) => b,
None => {
// Gadget: universe {0,1,2} with all 2-element subsets and bound 0.
// For any rooted tree on three vertices, at least one pair has
// distance 2, so at least one subset has extension cost >= 1.
// Thus the minimum total extension cost is >= 1, making this
// instance infeasible for bound 0.
let gadget_n = 3;
let gadget_subsets = vec![vec![0, 1], vec![1, 2], vec![0, 2]];
let target = RootedTreeStorageAssignment::new(gadget_n, gadget_subsets, 0);
return ReductionRootedTreeArrangementToRootedTreeStorageAssignment {
target,
num_vertices: gadget_n,
};
}
};

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +62
let n = self.num_vertices();
let q = n / 3;

let target = BoundedComponentSpanningForest::new(
SimpleGraph::new(n, self.graph().edges()),
vec![1i32; n], // unit weights
q, // K = |V|/3
3, // B = 3
);
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the source has n = 0 vertices, q = n/3 becomes 0 and BoundedComponentSpanningForest::new(..., max_components = 0, ...) will panic because it requires max_components >= 1. Handle the empty-graph case explicitly (e.g., set max_components = 1 with an empty graph/weights) so the reduction is total and preserves satisfiability.

Copilot uses AI. Check for mistakes.
let mut matrix = vec![vec![0.0f64; n]; n];

// For each adjacent pair in the sequence
for pos in 0..(seq_len - 1) {
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for pos in 0..(seq_len - 1) will underflow when seq_len == 0 (PaintShop currently allows an empty sequence with 0 cars). Use 0..seq_len.saturating_sub(1) or an early-return for seq_len < 2 to avoid panics and keep the reduction defined on edge cases.

Suggested change
for pos in 0..(seq_len - 1) {
for pos in 0..seq_len.saturating_sub(1) {

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +67
let vertex_groups: Vec<usize> = target_solution[..self.num_vertices].to_vec();

// Collect all distinct group indices used by all symbols and compress to 0..k-1
let mut used_groups: Vec<usize> = target_solution.to_vec();
used_groups.sort();
used_groups.dedup();

let mut group_to_color = vec![0usize; self.num_vertices + self.edges.len()];
for (color, &group) in used_groups.iter().enumerate() {
if group < group_to_color.len() {
group_to_color[group] = color;
}
}

vertex_groups.iter().map(|&g| group_to_color[g]).collect()
}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract_solution can output colors > 2 when the TDCS witness assigns graph vertices to more than 3 distinct groups (which is possible even when the source is 3-colorable). Since the source expects exactly 3 colors, this breaks witness extraction for some valid target witnesses. Consider mirroring TDCS’s internal label-compression and then mapping vertex dense labels modulo 3 (or otherwise deriving a 3-coloring) so every satisfying target witness extracts to a satisfying K3-coloring.

Copilot uses AI. Check for mistakes.
Comment on lines +204 to +209
// Issue example: MIS solution {v2, v3, v5} gives LCS "BAC" (length 3).
// Match nodes (ordered by character):
// c=A(0): v0=(0,1), v1=(0,3), v3=(2,1), v4=(2,3)
// c=B(1): v2=(1,0)
// c=C(2): v5=(3,2)
// MIS {v2, v3, v5} => positions B@(1,0), A@(2,1), C@(3,2)
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The canonical example comments mislabel the selected vertices: with the tuple-generation order in this file, index 2 is an A-node (2,1) and index 4 is the B-node (1,0), but the comment says otherwise. This makes it hard to audit the example/witness mapping; please update the comment so indices/tuples match the actual construction.

Suggested change
// Issue example: MIS solution {v2, v3, v5} gives LCS "BAC" (length 3).
// Match nodes (ordered by character):
// c=A(0): v0=(0,1), v1=(0,3), v3=(2,1), v4=(2,3)
// c=B(1): v2=(1,0)
// c=C(2): v5=(3,2)
// MIS {v2, v3, v5} => positions B@(1,0), A@(2,1), C@(3,2)
// Issue example: MIS solution {v2, v4, v5} gives LCS "BAC" (length 3).
// Match nodes (ordered by character):
// c=A(0): v0=(0,1), v1=(0,3), v2=(2,1), v3=(2,3)
// c=B(1): v4=(1,0)
// c=C(2): v5=(3,2)
// MIS {v2, v4, v5} => positions B@(1,0), A@(2,1), C@(3,2)

Copilot uses AI. Check for mistakes.
.target()
.try_into()
.expect("SubsetSum target must fit in u64 for CapacityAssignment reduction");
let delay_budget = total_sum - target_val;
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delay_budget is computed as total_sum - target_val on u64, which will underflow/panic (debug) or wrap (release) when target_val > total_sum (a valid unsatisfiable SubsetSum instance). Use checked_sub/saturating_sub and pick semantics that keep the reduction sound for B > S (e.g., treat negative budgets as 0 so the optimal cost cannot equal B).

Suggested change
let delay_budget = total_sum - target_val;
// Use saturating subtraction to avoid underflow when target_val > total_sum.
// In that case, treat the delay budget as 0 so the reduction remains sound.
let delay_budget = total_sum.saturating_sub(target_val);

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +58
for size in self.sizes() {
let a_i: u64 = size
.try_into()
.expect("SubsetSum element must fit in u64 for CapacityAssignment reduction");
cost.push(vec![0, a_i]);
delay.push(vec![a_i, 0]);
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reduction converts BigUint sizes/target to u64 via try_into().expect(...). Since SubsetSum is explicitly arbitrary-precision, this makes the reduction panic on perfectly valid instances. Consider either (a) changing the target model to support larger integers for this rule, or (b) explicitly rejecting/encoding out-of-range instances in a way that preserves correctness (instead of panicking).

Copilot uses AI. Check for mistakes.
@zazabap zazabap moved this from Under review to Final review in Good issues Mar 28, 2026
zazabap and others added 3 commits March 29, 2026 14:26
- RTA→RTSA: use checked_sub with infeasible gadget instead of saturating_sub
- PIPL2→BCSF: handle n=0 empty graph (max_components must be >= 1)
- PaintShop→QUBO: use saturating_sub to prevent underflow on empty sequence
- KColoring→TDCS: use HashMap for group_to_color mapping, remove unused edges field
- LCS→MIS: fix mislabeled match-node indices in example comments
- SubsetSum→CapAssign: use saturating_sub for delay_budget underflow
- Paper: fix #n-vertex Typst variable error (escape hyphen)
- Add edge-case tests for RTA underflow, empty PaintShop, SubsetSum target>sum
- Merge main to resolve conflicts with CosineProductIntegration/ProductionPlanning

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@isPANN isPANN moved this from Final review to OnHold in Good issues Mar 30, 2026
zazabap and others added 2 commits March 30, 2026 02:36
Merge main branch to pick up new models (IntegerKnapsack, FeasibleBasisExtension,
QuadraticDiophantineEquations, etc.). Resolved conflict in references.bib by
keeping entries from both branches. Applied rustfmt to fix formatting.

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

isPANN commented Mar 30, 2026

Design issue: MVC → EnsembleComputation (#204)

This rule has two fundamental problems that need to be addressed before it can be merged:

1. Trivial upper-bound budget makes the reduction vacuous.
The GJ proof establishes: G has a vertex cover of size ≤ K iff EC with budget J = K + |E| is satisfiable. But since MinimumVertexCover is a pure optimization problem with no explicit K parameter, the implementation uses J = |V| + |E| (trivial upper bound). This means the EC instance is always satisfiable for any graph — the reduction becomes trivial in one direction and the extracted cover is valid but not necessarily minimum.

2. Source variant is weighted i32, but weights are discarded.
The implementation is ReduceTo<EnsembleComputation> for MinimumVertexCover<SimpleGraph, i32>, but EC has no weight field. Vertex weights are silently dropped. If this reduction must exist, the source should be MinimumVertexCover<SimpleGraph, One> (like MVC → MinimumHittingSet in this same PR).

Recommendation: Remove MVC → EnsembleComputation from this batch PR. The remaining 10 rules are sound and ready to merge. File a separate issue for redesigning this reduction (e.g., by adding an explicit K parameter to the source, or by implementing an aggregate-only edge that binary-searches on K).

@isPANN
Copy link
Copy Markdown
Collaborator

isPANN commented Mar 30, 2026

Design issue: MVC → EnsembleComputation (#204) — recommend removing from this batch

After reviewing the 11 rules in this PR, I found that the MinimumVertexCover → EnsembleComputation reduction has two fundamental design problems. The other 10 rules are sound.

Problem 1: Trivial upper-bound budget makes the reduction vacuous

The Garey & Johnson proof (PO9) establishes a tight equivalence:

G has a vertex cover of size ≤ K if and only if the EC instance with budget J = K + |E| is satisfiable.

The key insight is that J depends on K — the vertex cover budget. However, MinimumVertexCover in this codebase is a pure optimization problem (Value = Min<W::Sum>) with no explicit K parameter. The implementation works around this by using the trivial upper bound J = |V| + |E| (since any vertex cover has size ≤ |V|).

This makes the EC instance always satisfiable for any graph with edges. The reduction becomes one-directional: you can always find a satisfying EC sequence, but the extracted vertex cover is just "some valid cover" — potentially all vertices. You cannot recover the minimum cover through this path, because the budget constraint that encodes optimality has been relaxed away.

For comparison, the other feasibility-to-feasibility reductions in this PR (e.g., KClique → BCBS, Partition → SubsetSum) correctly propagate the budget parameter, so the target is satisfiable iff the source is.

Problem 2: Source variant is weighted i32, but weights are discarded

The implementation registers:

impl ReduceTo<EnsembleComputation> for MinimumVertexCover<SimpleGraph, i32>

But EnsembleComputation has no weight field — the reduction only uses graph structure and silently drops vertex weights. This means even if the budget issue were fixed, the reduction could not preserve weighted optimality.

For reference, MVC → MinimumHittingSet in this same PR correctly uses MinimumVertexCover<SimpleGraph, One> as the source variant.

Suggested fix direction

Change EnsembleComputation to an optimization formulation (Value = Min<usize>, minimize sequence length, remove the budget parameter). Then register the reduction as:

impl ReduceTo<EnsembleComputationOpt> for MinimumVertexCover<SimpleGraph, One>

Both sides are Min, no weights are discarded (unit-weight is just counting), and the optimal value relationship J* = K* + |E| is tight — no trivial upper bound needed.

This requires modifying the EnsembleComputation model, which is out of scope for this batch PR.

Recommendation

Remove this rule from the batch and file a separate issue for redesigning it. The remaining 10 rules are all correct and ready to merge.

…MVC→EC reduction

- EnsembleComputation: Value changed from Or (feasibility) to Min<usize>
  (minimize sequence length). The budget parameter remains as a search-space
  bound, but evaluate() now returns the number of steps used rather than
  just true/false.

- MVC→EC reduction: source changed from MinimumVertexCover<SimpleGraph, i32>
  to MinimumVertexCover<SimpleGraph, One>. The weighted variant was unsound
  because EC has no weight field. With both sides as Min, the optimal value
  relationship J* = K* + |E| is tight — no trivial upper bound needed.

- Updated paper entries, model tests, and rule tests accordingly.

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

isPANN commented Mar 30, 2026

Update: MVC → EnsembleComputation issue has been fixed in the latest push.

Changes made:

  1. EnsembleComputation model changed from feasibility (Value = Or) to optimization (Value = Min<usize>, minimize sequence length). Budget remains as a search-space bound.
  2. Reduction source changed from MinimumVertexCover<SimpleGraph, i32> to MinimumVertexCover<SimpleGraph, One> — no more weight discarding.
  3. The optimal value relationship J* = K* + |E| is now tight. Both sides are Min, so the reduction correctly preserves optimality.

All tests pass, paper builds clean.

- Add `with_default_budget()` and `default_budget()` methods. Default is
  sum of subset sizes (worst-case without reuse), clamped to at least 1.
- CLI: --budget is now optional; omitting it uses the default.
- Paper: remove J from problem definition (it's a search-space bound,
  not a mathematical parameter).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@isPANN isPANN merged commit 0f51be6 into main Mar 30, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment