Skip to content

Commit 6649410

Browse files
GiggleLiuclaude
andauthored
Implement 6 problem-to-QUBO reductions (Issue #18) (#29)
* Add QUBO test data generation script and ground truth datasets - Add scripts/generate_qubo_tests.py using qubogen to generate QUBO ground truth for 7 problem types: MaxCut, VertexCovering, IndependentSet, Coloring, SetPacking, KSatisfiability (2-SAT), and ILP - Add scripts/ Python project managed by uv (pyproject.toml, uv.lock) - Add tests/data/qubo/*.json with brute-force optimal solutions - Add `make qubo-testdata` target to regenerate test data - Update .gitignore for .venv/ Ref #18 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add related projects section to README Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * update * feat: add IndependentSet, VertexCovering, and MaxCut → QUBO reductions Implement three problem-to-QUBO reductions with closed-loop unit tests: - IndependentSet → QUBO: penalty formulation with P = 1 + Σw_i - VertexCovering → QUBO: constraint penalty for uncovered edges - MaxCut → QUBO: unconstrained cut maximization Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add KColoring, SetPacking, and KSatisfiability → QUBO reductions Implement three more problem-to-QUBO reductions with closed-loop tests: - KColoring → QUBO: one-hot encoding with n*K variables - SetPacking → QUBO: IS on intersection graph structure - KSatisfiability(K=2) → QUBO: Max-2-SAT penalty formulation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add ILP (binary) → QUBO reduction Implement binary ILP to QUBO reduction with slack variables for inequality constraints. Feature-gated behind `ilp`. Supports Maximize, Minimize, and equality/inequality constraints. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add integration tests for QUBO reductions against ground truth Add 7 integration tests comparing Rust QUBO reductions against Python-generated ground truth JSON datasets for IS, VC, MaxCut, KColoring, SetPacking, KSatisfiability, and ILP. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add QUBO reductions example program Demonstrate all 7 problem-to-QUBO reductions with practical stories: wireless towers (IS), security cameras (VC), network partitioning (MaxCut), map coloring, delivery zones (SP), switch config (2-SAT), and project selection (ILP). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add QUBO reduction theorems to paper, acknowledge references - Add 7 QUBO reduction theorems with step-by-step mathematical proofs (IS, VC, MaxCut, KColoring, SetPacking, 2-SAT, ILP → QUBO) - Update QUBO definition to clarify upper-triangular matrix convention - Update problem definitions with "Reduces to: QUBO" cross-references - Add 7 rows to the summary table - Add Acknowledgments section to README crediting ProblemReductions.jl, UnitDiskMapping.jl, and qubogen - Fix graph path-finding tests for new QUBO reduction edges - Update .gitignore for pkgref/ reference packages directory Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: fix ILP slack variables, remove redundant MaxCut→QUBO, add coverage tests - Fix ILP→QUBO slack variable signs (Le→+1, Ge→-1) and count formula (ceil(log2(range+1)) to represent all valid slack values) - Remove redundant MaxCut→QUBO reduction (reachable via MaxCut→SpinGlass→QUBO) - Add round-trip tests covering ILP Ge/Le slack branches, KColoring reversed edge ordering, and KSat reversed variable ordering Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add references for QUBO reductions (Glover 2019, Lucas 2014) Add Glover, Kochenberger & Du (2019) "Quantum Bridge Analytics I" as primary reference for QUBO formulations. Cite Lucas (2014) for IS, VC, KColoring, and ILP reductions. Update summary table citations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: reclassify QUBO reductions into penalty-method section Move 6 QUBO reductions from "Trivial" to new "Penalty-Method QUBO Reductions" section. Add introductory paragraph explaining the penalty method with label for cross-referencing. Each proof now references the shared penalty-method description. Remove gray fill from summary table for QUBO rows. Trivial: complement/isomorphism (IS↔VC, IS↔SP, VC→SC, Matching→SP, SG↔QUBO) Penalty-method: IS→QUBO, VC→QUBO, KColoring→QUBO, SP→QUBO, 2SAT→QUBO, ILP→QUBO Non-trivial: gadget-based (SAT→IS, SAT→3-Coloring, etc.) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address Copilot review - generic SetPacking, ILP slack bounds - Make SetPacking→QUBO reduction generic over weight type W: Into<f64> (supports both i32 and f64 weights, removing the f64→i32 truncation) - Fix ILP slack range to use min_lhs/max_lhs for negative coefficients - Fix duplicate variable accumulation (= → +=) in ILP constraint matrix - Remove unused import and variable in Python test generator - Update test comments to match corrected formulas Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e27ef70 commit 6649410

36 files changed

Lines changed: 2976 additions & 67 deletions

.claude/CLAUDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ make clippy # Lint
1010
make export-graph # Regenerate reduction graph
1111
make paper # Build Typst paper
1212
make coverage # Generate coverage report (>95% required)
13+
make qubo-testdata # Regenerate QUBO ground truth JSON
1314
```
1415

1516
## Verify Changes
@@ -28,6 +29,9 @@ make test clippy export-graph # Must pass before PR
2829
- `src/registry/` - Compile-time reduction metadata collection
2930
- `src/unit_tests/` - Unit test files (mirroring `src/` structure, referenced via `#[path]`)
3031
- `tests/main.rs` - Integration tests (modules in `tests/suites/`)
32+
- `tests/data/` - Ground truth JSON for integration tests
33+
- `scripts/` - Python test data generation scripts (managed with `uv`)
34+
- `docs/plans/` - Implementation plans
3135

3236
### Trait Hierarchy
3337

.claude/rules/adding-reductions.md

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,59 @@ paths:
55

66
# Adding a Reduction Rule (A → B)
77

8+
## 0. Brainstorm & Generate Test Data First
9+
10+
Before writing any Rust code, follow this workflow:
11+
12+
1. **Brainstorm the reduction** — use `superpowers:brainstorming` to discuss with the user:
13+
- Research the mathematical formulation (paper, textbook, or derive it)
14+
- Understand the variable mapping and constraint encoding
15+
- Discuss implementation approach: penalty values, matrix construction, solution extraction
16+
- Read reference implementations in the codebase (e.g., `src/rules/spinglass_qubo.rs`) to understand conventions
17+
- Agree on scope (weighted vs unweighted, specific graph types, const generics)
18+
2. **Generate ground truth test data** — use an existing library (e.g., Python with qubogen, qubovert, or networkx) to create small instances, reduce them, brute-force solve both sides, and export as JSON to `tests/data/<target>/`. It is recommended to download the relevant package and check the existing tests to understand how to construct tests. To generate the test data, you can use the following command:
19+
```bash
20+
# Example: generate QUBO test data
21+
cd scripts && uv run python generate_qubo_tests.py
22+
```
23+
3. **Create a practical example** — design a small, explainable instance for `examples/` (e.g., "wireless tower placement" for IndependentSet, "map coloring" for Coloring). This example will also appear in the `docs/paper/reductions.typ`.
24+
4. **Write the implementation plan** — save to `docs/plans/` using `superpowers:writing-plans`. The plan must include implementation details from the brainstorming session (formulas, penalty terms, matrix construction, variable indexing).
25+
826
## 1. Implementation
9-
Create `src/rules/<source>_<target>.rs`:
27+
28+
Create `src/rules/<source>_<target>.rs` following the pattern in `src/rules/spinglass_qubo.rs`:
1029

1130
```rust
12-
use problemreductions::reduction;
31+
use crate::reduction;
32+
33+
#[derive(Debug, Clone)]
34+
pub struct ReductionSourceToTarget {
35+
target: TargetProblem<...>,
36+
source_size: ProblemSize,
37+
// + any metadata needed for extract_solution
38+
}
39+
40+
impl ReductionResult for ReductionSourceToTarget {
41+
type Source = SourceProblem<...>;
42+
type Target = TargetProblem<...>;
43+
44+
fn target_problem(&self) -> &Self::Target { &self.target }
45+
fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> { ... }
46+
fn source_size(&self) -> ProblemSize { self.source_size.clone() }
47+
fn target_size(&self) -> ProblemSize { self.target.problem_size() }
48+
}
1349

1450
#[reduction(
1551
overhead = { ReductionOverhead::new(vec![...]) }
1652
)]
17-
impl ReduceTo<TargetProblem<Unweighted>> for SourceProblem<Unweighted> {
53+
impl ReduceTo<TargetProblem<...>> for SourceProblem<...> {
1854
type Result = ReductionSourceToTarget;
1955
fn reduce_to(&self) -> Self::Result { ... }
2056
}
57+
58+
#[cfg(test)]
59+
#[path = "../unit_tests/rules/<source>_<target>.rs"]
60+
mod tests;
2161
```
2262

2363
The `#[reduction]` macro auto-generates the `inventory::submit!` call. Optional attributes: `source_graph`, `target_graph`, `source_weighted`, `target_weighted`.
@@ -28,25 +68,39 @@ mod source_target;
2868
pub use source_target::ReductionSourceToTarget;
2969
```
3070

31-
## 2. Closed-Loop Test (Required)
71+
## 2. Tests (Required)
72+
73+
- **Unit tests** in `src/unit_tests/rules/<source>_<target>.rs` — closed-loop + edge cases. See `rules/testing.md`.
74+
- **Integration tests** in `tests/suites/reductions.rs` — compare against JSON ground truth from step 0.
75+
- Test name: `test_<source>_to_<target>_closed_loop`
3276

33-
See `rules/testing.md` for the full pattern. Test name: `test_<source>_to_<target>_closed_loop`.
77+
## 3. Example Program
78+
79+
Add a round-trip demo to `examples/` showing a practical, explainable instance:
80+
1. Create source problem with a real-world story
81+
2. Reduce to target, solve, extract solution
82+
3. Print human-readable explanation
83+
84+
## 4. Documentation
3485

35-
## 3. Documentation
3686
Update `docs/paper/reductions.typ` (see `rules/documentation.md` for the pattern):
3787
- Add theorem + proof sketch
38-
- Add code example
88+
- Add Rust code example from the example program
3989
- Add to summary table with overhead and citation
4090

91+
The goal is to 1. prove the correctness of the reduction to human beings. 2. provide a minimal working example to the readers.
92+
4193
Citations must be verifiable. Use `[Folklore]` or `` for trivial reductions.
4294

43-
## 4. Regenerate Reduction Graph
95+
## 5. Regenerate Reduction Graph
4496
```bash
4597
make export-graph
4698
```
4799

48100
## Anti-patterns
101+
- Don't write Rust code before understanding the math and having test data
49102
- Don't create reductions without closed-loop tests
50103
- Don't forget `inventory::submit!` registration (reduction graph won't update)
51104
- Don't hardcode weights - use generic `W` parameter
52105
- Don't skip overhead polynomial specification
106+
- Don't skip the example program — every reduction needs an explainable demo

.claude/skills/issue-to-pr.md

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ Convert a GitHub issue into an actionable PR with a plan that auto-triggers Clau
1919
digraph issue_to_pr {
2020
"Receive issue number" [shape=box];
2121
"Fetch issue with gh" [shape=box];
22+
"Check the rules to follow" [shape=box];
2223
"Brainstorm with user" [shape=box];
2324
"Write plan file" [shape=box];
2425
"Create branch and PR" [shape=box];
2526
"PR triggers [action]" [shape=doublecircle];
2627
2728
"Receive issue number" -> "Fetch issue with gh";
28-
"Fetch issue with gh" -> "Brainstorm with user";
29+
"Fetch issue with gh" -> "Check the rules to follow";
30+
"Check the rules to follow" -> "Brainstorm with user";
2931
"Brainstorm with user" -> "Write plan file";
3032
"Write plan file" -> "Create branch and PR";
3133
"Create branch and PR" -> "PR triggers [action]";
@@ -53,45 +55,27 @@ Present issue summary to user.
5355

5456
**REQUIRED:** Invoke `superpowers:brainstorming` skill with the issue context (if superpowers plugin is available). Otherwise, conduct a manual brainstorming discussion with the user.
5557

56-
This ensures:
57-
- User intent is clarified
58-
- Multiple approaches are explored
59-
- Requirements are understood before planning
58+
Brainstorming must cover:
59+
- **User intent** — clarify what the issue is asking for
60+
- **Multiple approaches** — explore 2-3 different implementation strategies
61+
- **Implementation details** — discuss the mathematical formulation, data structures, variable mappings, constraint encodings, and any non-obvious design choices
62+
- **Existing patterns** — read reference implementations in the codebase (e.g., `spinglass_qubo.rs` for reductions) to understand the conventions
63+
- **Scope** — agree on which variants to implement (e.g., unweighted only, specific K values)
6064

6165
Do NOT skip brainstorming. Do NOT write a plan without user discussion.
6266

6367
### 4. Write Plan
6468

65-
After brainstorming concludes, write plan to `issue-<number>-<slug>.md` in the repo root:
66-
67-
```markdown
68-
# <Title from brainstorming>
69-
70-
Issue: #<number>
71-
72-
## Context
73-
<Brief problem statement>
74-
75-
## Approach
76-
<Chosen approach from brainstorming>
77-
78-
## Tasks
79-
1. <Specific implementation task>
80-
2. <Another task>
81-
...
82-
83-
## Acceptance Criteria
84-
- <Criteria from issue/brainstorming>
85-
```
69+
After brainstorming concludes, write plan to `docs/plans/YYYY-MM-DD-<slug>.md` using `superpowers:writing-plans`:
8670

8771
### 5. Create PR
8872

8973
```bash
9074
# Create branch
9175
git checkout -b issue-<number>-<slug>
9276

93-
# Stage only the plan file
94-
git add issue-<number>-<slug>.md
77+
# Stage the plan file
78+
git add docs/plans/<plan-file>.md
9579

9680
# Commit
9781
git commit -m "Add plan for #<number>: <title>"
@@ -117,19 +101,19 @@ User: /issue-to-pr 42
117101
118102
Claude: Let me fetch issue #42...
119103
120-
[Fetches issue: "Add dark mode support"]
104+
[Fetches issue: "Add IndependentSet → QUBO reduction"]
121105
122-
I'll use superpowers:brainstorming to explore this with you.
106+
I'll read the rules to follow in .claude/rules/adding-reductions.md and use superpowers:brainstorming to explore this with you.
123107
124108
[Invokes brainstorming - discusses approaches, user preferences, scope]
125109
126-
Based on our discussion, I'll create the plan...
110+
Based on our discussion, I'll create the plan with superpowers:writing-plans...
127111
128-
[Writes docs/plans/issue-42-dark-mode.md]
112+
[Writes docs/plans/2026-02-09-independentset-to-qubo.md]
129113
[Creates branch, commits, pushes]
130114
[Creates PR with body starting with "[action]"]
131115
132-
Created PR #45: Fix #42: Add dark mode support
116+
Created PR #45: Fix #42: Add IndependentSet → QUBO reduction
133117
The [action] trigger will automatically execute the plan.
134118
```
135119

@@ -139,5 +123,5 @@ The [action] trigger will automatically execute the plan.
139123
|---------|-----|
140124
| Skipping brainstorming | Always use superpowers:brainstorming (or manual discussion) first |
141125
| `[action]` not at start | PR body must BEGIN with `[action]` |
142-
| Including code in PR | Only commit the plan file |
126+
| Including implementation code in initial PR | First PR: plan only |
143127
| Generic plan | Use specifics from brainstorming |

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ quickcheck-tests.json
3838
/dist/
3939
/build/
4040

41-
# Python (for pre-commit)
41+
# Python
4242
__pycache__/
4343
*.py[cod]
4444
*$py.class
4545
.Python
46+
.venv/
4647
venv/
4748
env/
4849
ENV/
@@ -67,3 +68,6 @@ tarpaulin-report.html
6768

6869
# Generated documents
6970
*.pdf
71+
72+
# Reference packages (downloaded for comparison)
73+
pkgref/

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Makefile for problemreductions
22

3-
.PHONY: help build test fmt clippy doc mdbook paper clean coverage rust-export compare
3+
.PHONY: help build test fmt clippy doc mdbook paper clean coverage rust-export compare qubo-testdata
44

55
# Default target
66
help:
@@ -18,6 +18,7 @@ help:
1818
@echo " check - Quick check (fmt + clippy + test)"
1919
@echo " rust-export - Generate Rust mapping JSON exports"
2020
@echo " compare - Generate and compare Rust mapping exports"
21+
@echo " qubo-testdata - Regenerate QUBO test data (requires uv)"
2122

2223
# Build the project
2324
build:
@@ -65,6 +66,10 @@ clean:
6566
check: fmt-check clippy test
6667
@echo "✅ All checks passed!"
6768

69+
# Regenerate QUBO test data from Python (requires uv)
70+
qubo-testdata:
71+
cd scripts && uv run python generate_qubo_tests.py
72+
6873
# Generate Rust mapping JSON exports for all graphs and modes
6974
GRAPHS := diamond bull house petersen
7075
MODES := unweighted weighted triangular

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,21 @@ make check # Quick check before commit (fmt + clippy + test)
7272
```
7373

7474

75+
## Acknowledgments
76+
77+
This project draws inspiration from the following packages:
78+
79+
- **[ProblemReductions.jl](https://github.com/GiggleLiu/ProblemReductions.jl)** — Julia library for computational problem reductions. Our problem trait hierarchy, reduction interface (`ReduceTo`/`ReductionResult`), and graph-based reduction registry are directly inspired by this package.
80+
- **[UnitDiskMapping.jl](https://github.com/QuEraComputing/UnitDiskMapping.jl)** — Julia package for mapping problems to unit disk graphs. Our unit disk graph (King's subgraph / triangular lattice) reductions and the copy-line method are based on this implementation.
81+
- **[qubogen](https://github.com/tamuhey/qubogen)** — Python library for generating QUBO matrices from combinatorial problems. Our QUBO reduction formulas (Vertex Cover, Graph Coloring, Set Packing, Max-2-SAT, binary ILP) reference the implementations in this package.
82+
83+
## Related Projects
84+
85+
- **[Karp](https://github.com/REA1/karp)** — A DSL (built on Racket) for writing and testing Karp reductions between NP-complete problems ([PLDI 2022 paper](https://dl.acm.org/doi/abs/10.1145/3519939.3523732)). Focused on education and proof verification rather than a solver pipeline.
86+
- **[Complexity Zoo](https://complexityzoo.net/)** — Comprehensive catalog of 550+ computational complexity classes (Scott Aaronson).
87+
- **[A Compendium of NP Optimization Problems](https://www.csc.kth.se/tcs/compendium/)** — Online catalog of NP optimization problems with approximability results (Crescenzi & Kann).
88+
- **Computers and Intractability** (Garey & Johnson, 1979) — The classic reference cataloging 300+ NP-complete problems with reductions. The most cited book in computer science.
89+
7590
## License
7691

7792
MIT License - see [LICENSE](LICENSE) for details.

0 commit comments

Comments
 (0)