Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ make clippy # Lint
make export-graph # Regenerate reduction graph
make paper # Build Typst paper
make coverage # Generate coverage report (>95% required)
make qubo-testdata # Regenerate QUBO ground truth JSON
```

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

### Trait Hierarchy

Expand Down
70 changes: 62 additions & 8 deletions .claude/rules/adding-reductions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,59 @@ paths:

# Adding a Reduction Rule (A → B)

## 0. Brainstorm & Generate Test Data First

Before writing any Rust code, follow this workflow:

1. **Brainstorm the reduction** — use `superpowers:brainstorming` to discuss with the user:
- Research the mathematical formulation (paper, textbook, or derive it)
- Understand the variable mapping and constraint encoding
- Discuss implementation approach: penalty values, matrix construction, solution extraction
- Read reference implementations in the codebase (e.g., `src/rules/spinglass_qubo.rs`) to understand conventions
- Agree on scope (weighted vs unweighted, specific graph types, const generics)
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:
```bash
# Example: generate QUBO test data
cd scripts && uv run python generate_qubo_tests.py
```
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`.
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).

## 1. Implementation
Create `src/rules/<source>_<target>.rs`:

Create `src/rules/<source>_<target>.rs` following the pattern in `src/rules/spinglass_qubo.rs`:

```rust
use problemreductions::reduction;
use crate::reduction;

#[derive(Debug, Clone)]
pub struct ReductionSourceToTarget {
target: TargetProblem<...>,
source_size: ProblemSize,
// + any metadata needed for extract_solution
}

impl ReductionResult for ReductionSourceToTarget {
type Source = SourceProblem<...>;
type Target = TargetProblem<...>;

fn target_problem(&self) -> &Self::Target { &self.target }
fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> { ... }
fn source_size(&self) -> ProblemSize { self.source_size.clone() }
fn target_size(&self) -> ProblemSize { self.target.problem_size() }
}

#[reduction(
overhead = { ReductionOverhead::new(vec![...]) }
)]
impl ReduceTo<TargetProblem<Unweighted>> for SourceProblem<Unweighted> {
impl ReduceTo<TargetProblem<...>> for SourceProblem<...> {
type Result = ReductionSourceToTarget;
fn reduce_to(&self) -> Self::Result { ... }
}

#[cfg(test)]
#[path = "../unit_tests/rules/<source>_<target>.rs"]
mod tests;
```

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

## 2. Closed-Loop Test (Required)
## 2. Tests (Required)

- **Unit tests** in `src/unit_tests/rules/<source>_<target>.rs` — closed-loop + edge cases. See `rules/testing.md`.
- **Integration tests** in `tests/suites/reductions.rs` — compare against JSON ground truth from step 0.
- Test name: `test_<source>_to_<target>_closed_loop`

See `rules/testing.md` for the full pattern. Test name: `test_<source>_to_<target>_closed_loop`.
## 3. Example Program

Add a round-trip demo to `examples/` showing a practical, explainable instance:
1. Create source problem with a real-world story
2. Reduce to target, solve, extract solution
3. Print human-readable explanation

## 4. Documentation

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

The goal is to 1. prove the correctness of the reduction to human beings. 2. provide a minimal working example to the readers.

Citations must be verifiable. Use `[Folklore]` or `—` for trivial reductions.

## 4. Regenerate Reduction Graph
## 5. Regenerate Reduction Graph
```bash
make export-graph
```

## Anti-patterns
- Don't write Rust code before understanding the math and having test data
- Don't create reductions without closed-loop tests
- Don't forget `inventory::submit!` registration (reduction graph won't update)
- Don't hardcode weights - use generic `W` parameter
- Don't skip overhead polynomial specification
- Don't skip the example program — every reduction needs an explainable demo
52 changes: 18 additions & 34 deletions .claude/skills/issue-to-pr.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ Convert a GitHub issue into an actionable PR with a plan that auto-triggers Clau
digraph issue_to_pr {
"Receive issue number" [shape=box];
"Fetch issue with gh" [shape=box];
"Check the rules to follow" [shape=box];
"Brainstorm with user" [shape=box];
"Write plan file" [shape=box];
"Create branch and PR" [shape=box];
"PR triggers [action]" [shape=doublecircle];

"Receive issue number" -> "Fetch issue with gh";
"Fetch issue with gh" -> "Brainstorm with user";
"Fetch issue with gh" -> "Check the rules to follow";
"Check the rules to follow" -> "Brainstorm with user";
"Brainstorm with user" -> "Write plan file";
"Write plan file" -> "Create branch and PR";
"Create branch and PR" -> "PR triggers [action]";
Expand Down Expand Up @@ -53,45 +55,27 @@ Present issue summary to user.

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

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

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

### 4. Write Plan

After brainstorming concludes, write plan to `issue-<number>-<slug>.md` in the repo root:

```markdown
# <Title from brainstorming>

Issue: #<number>

## Context
<Brief problem statement>

## Approach
<Chosen approach from brainstorming>

## Tasks
1. <Specific implementation task>
2. <Another task>
...

## Acceptance Criteria
- <Criteria from issue/brainstorming>
```
After brainstorming concludes, write plan to `docs/plans/YYYY-MM-DD-<slug>.md` using `superpowers:writing-plans`:

### 5. Create PR

```bash
# Create branch
git checkout -b issue-<number>-<slug>

# Stage only the plan file
git add issue-<number>-<slug>.md
# Stage the plan file
git add docs/plans/<plan-file>.md

# Commit
git commit -m "Add plan for #<number>: <title>"
Expand All @@ -117,19 +101,19 @@ User: /issue-to-pr 42

Claude: Let me fetch issue #42...

[Fetches issue: "Add dark mode support"]
[Fetches issue: "Add IndependentSet → QUBO reduction"]

I'll use superpowers:brainstorming to explore this with you.
I'll read the rules to follow in .claude/rules/adding-reductions.md and use superpowers:brainstorming to explore this with you.

[Invokes brainstorming - discusses approaches, user preferences, scope]

Based on our discussion, I'll create the plan...
Based on our discussion, I'll create the plan with superpowers:writing-plans...

[Writes docs/plans/issue-42-dark-mode.md]
[Writes docs/plans/2026-02-09-independentset-to-qubo.md]
[Creates branch, commits, pushes]
[Creates PR with body starting with "[action]"]

Created PR #45: Fix #42: Add dark mode support
Created PR #45: Fix #42: Add IndependentSet → QUBO reduction
The [action] trigger will automatically execute the plan.
```

Expand All @@ -139,5 +123,5 @@ The [action] trigger will automatically execute the plan.
|---------|-----|
| Skipping brainstorming | Always use superpowers:brainstorming (or manual discussion) first |
| `[action]` not at start | PR body must BEGIN with `[action]` |
| Including code in PR | Only commit the plan file |
| Including implementation code in initial PR | First PR: plan only |
| Generic plan | Use specifics from brainstorming |
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ quickcheck-tests.json
/dist/
/build/

# Python (for pre-commit)
# Python
__pycache__/
*.py[cod]
*$py.class
.Python
.venv/
venv/
env/
ENV/
Expand All @@ -67,3 +68,6 @@ tarpaulin-report.html

# Generated documents
*.pdf

# Reference packages (downloaded for comparison)
pkgref/
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Makefile for problemreductions

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

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

# Build the project
build:
Expand Down Expand Up @@ -65,6 +66,10 @@ clean:
check: fmt-check clippy test
@echo "✅ All checks passed!"

# Regenerate QUBO test data from Python (requires uv)
qubo-testdata:
cd scripts && uv run python generate_qubo_tests.py

# Generate Rust mapping JSON exports for all graphs and modes
GRAPHS := diamond bull house petersen
MODES := unweighted weighted triangular
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ make check # Quick check before commit (fmt + clippy + test)
```


## Acknowledgments

This project draws inspiration from the following packages:

- **[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.
- **[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.
- **[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.

## Related Projects

- **[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.
- **[Complexity Zoo](https://complexityzoo.net/)** — Comprehensive catalog of 550+ computational complexity classes (Scott Aaronson).
- **[A Compendium of NP Optimization Problems](https://www.csc.kth.se/tcs/compendium/)** — Online catalog of NP optimization problems with approximability results (Crescenzi & Kann).
- **Computers and Intractability** (Garey & Johnson, 1979) — The classic reference cataloging 300+ NP-complete problems with reductions. The most cited book in computer science.

## License

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