Skip to content

Commit f5de907

Browse files
GiggleLiuclaude
andcommitted
docs: merge .claude/rules/ into CLAUDE.md for upfront context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 346fddd commit f5de907

1 file changed

Lines changed: 189 additions & 6 deletions

File tree

.claude/CLAUDE.md

Lines changed: 189 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,193 @@ Reduction graph nodes use variant IDs: `ProblemName[/GraphType][/Weighted]`
112112
- `display-name` dict maps `ProblemName` to display text
113113

114114
## Contributing
115-
See `.claude/rules/` for detailed guides:
116-
- `adding-reductions.md` - How to add reduction rules
117-
- `adding-models.md` - How to add problem types
118-
- `testing.md` - Testing requirements and patterns
119-
- `documentation.md` - Paper documentation patterns
120-
115+
See the sections below for detailed guides on adding reductions, models, tests, and documentation.
121116
Also see GitHub Issue #3 for coding rules.
117+
118+
## Adding a Reduction Rule (A -> B)
119+
120+
**Reference implementations — read these first:**
121+
- **Reduction rule:** `src/rules/minimumvertexcover_maximumindependentset.rs``ReductionResult` + `ReduceTo` + `#[reduction]` macro
122+
- **Unit test:** `src/unit_tests/rules/minimumvertexcover_maximumindependentset.rs` — closed-loop + edge cases
123+
- **Example program:** `examples/reduction_minimumvertexcover_to_maximumindependentset.rs` — create, reduce, solve, extract, verify, export
124+
- **Paper entry:** `docs/paper/reductions.typ` (search for `MinimumVertexCover` `MaximumIndependentSet`)
125+
- **Traits:** `src/rules/traits.rs``ReductionResult` and `ReduceTo` trait definitions
126+
127+
### 0. Before Writing Code
128+
129+
1. **Brainstorm** — use `superpowers:brainstorming` to discuss with the user:
130+
- The math (variable mapping, constraint encoding, penalty terms)
131+
- Which example instance to use in `examples/` (must be small, human-explainable, and agreed with the user)
132+
2. **Generate ground truth** — use Python scripts in `scripts/` (run with `uv`) to create test data in `tests/data/<target>/`.
133+
3. **Write plan** — save to `docs/plans/` using `superpowers:writing-plans`.
134+
135+
### 1. Implement
136+
137+
Create `src/rules/<source>_<target>.rs` following the reference. Key pieces:
138+
139+
- **`ReductionResult` struct + impl**`target_problem()` + `extract_solution()` (see reference)
140+
- **`ReduceTo` impl with `#[reduction(...)]` macro** — auto-generates `inventory::submit!`; only `overhead` attribute needed (graph/weight types are inferred, defaulting to `SimpleGraph`/`Unweighted`)
141+
- **`#[cfg(test)] #[path = ...]`** linking to unit tests
142+
143+
Register in `src/rules/mod.rs`.
144+
145+
### 2. Test
146+
147+
- **Unit tests** in `src/unit_tests/rules/<source>_<target>.rs` — closed-loop + edge cases (see reference test).
148+
- **Integration tests** in `tests/suites/reductions.rs` — compare against JSON ground truth.
149+
150+
### 3. Example Program
151+
152+
Add `examples/reduction_<source>_to_<target>.rs` — create, reduce, solve, extract, verify, export JSON (see reference example).
153+
154+
Examples must expose `pub fn run()` with `fn main() { run() }` so they can be tested directly via `include!` (no subprocess). Use regular comments (`//`) not inner doc comments (`//!`), and hardcode the example name instead of using `env!("CARGO_BIN_NAME")`.
155+
156+
Register the example in `tests/suites/examples.rs` by adding:
157+
```rust
158+
example_test!(reduction_<source>_to_<target>);
159+
example_fn!(test_<source>_to_<target>, reduction_<source>_to_<target>);
160+
```
161+
162+
### 4. Document
163+
164+
Update `docs/paper/reductions.typ` — add `reduction-rule("Source", "Target", ...)` with proof sketch (see `rules/documentation.md`).
165+
166+
### 5. Regenerate Graph
167+
168+
```bash
169+
cargo run --example export_graph
170+
```
171+
172+
## Adding a Model (Problem Type)
173+
174+
**Reference implementations — read these first:**
175+
- **Optimization problem:** `src/models/graph/maximum_independent_set.rs``Problem` + `OptimizationProblem` with `Metric = SolutionSize<W>`
176+
- **Satisfaction problem:** `src/models/satisfiability/sat.rs``Problem` with `Metric = bool`
177+
- **Reference test:** `src/unit_tests/models/graph/maximum_independent_set.rs`
178+
179+
### Steps
180+
181+
1. **Create** `src/models/<category>/<name>.rs` — follow the reference for struct definition, `Problem` impl, and `OptimizationProblem` impl (if applicable).
182+
2. **Register** in `src/models/<category>/mod.rs`.
183+
3. **Add tests** in `src/unit_tests/models/<category>/<name>.rs` (linked via `#[path]`).
184+
4. **Document** in `docs/paper/reductions.typ`: add `display-name` entry and `#problem-def("Name")[definition...]`.
185+
186+
### Trait Implementations
187+
188+
Every problem must implement `Problem` (see `src/traits.rs`). Key points:
189+
190+
- **`type Metric`**`SolutionSize<W>` for optimization, `bool` for satisfaction
191+
- **`fn dims()`** — configuration space dimensions (e.g., `vec![2; n]` for n binary variables)
192+
- **`fn evaluate()`** — return `SolutionSize::Valid(value)` / `SolutionSize::Invalid` for optimization, or `bool` for satisfaction
193+
- **`fn variant()`** — graph and weight type metadata for the reduction registry
194+
195+
Optimization problems additionally implement `OptimizationProblem` (see `src/traits.rs`):
196+
- **`type Value`** — the inner objective type (e.g., `i32`, `f64`, `W`)
197+
- **`fn direction()`**`Direction::Maximize` or `Direction::Minimize`
198+
199+
The supertrait `Problem<Metric = SolutionSize<Self::Value>>` ensures the solver can call `metric.is_valid()` and `metric.is_better()` directly — no per-problem customization needed.
200+
201+
Weight management (`weights()`, `set_weights()`, `is_weighted()`) goes on inherent `impl` blocks, not traits. See the reference implementation for the pattern.
202+
203+
### Categories
204+
205+
- `src/models/satisfiability/` — Satisfiability, KSatisfiability, CircuitSAT
206+
- `src/models/graph/` — MaximumIndependentSet, MinimumVertexCover, KColoring, etc.
207+
- `src/models/set/` — MinimumSetCovering, MaximumSetPacking
208+
- `src/models/optimization/` — SpinGlass, QUBO, ILP
209+
- `src/models/specialized/` — CircuitSAT, Factoring, PaintShop, BicliqueCover, BMF
210+
211+
### Naming
212+
213+
Use explicit optimization prefixes: `Maximum` for maximization, `Minimum` for minimization (e.g., `MaximumIndependentSet`, `MinimumVertexCover`).
214+
215+
## Testing Requirements
216+
217+
**Reference implementations — read these first:**
218+
- **Reduction test:** `src/unit_tests/rules/minimumvertexcover_maximumindependentset.rs` — closed-loop pattern
219+
- **Model test:** `src/unit_tests/models/graph/maximum_independent_set.rs` — evaluation, serialization
220+
- **Solver test:** `src/unit_tests/solvers/brute_force.rs``find_best` + `find_satisfying`
221+
- **Trait definitions:** `src/traits.rs` (`Problem`, `OptimizationProblem`), `src/solvers/mod.rs` (`Solver`)
222+
223+
### Coverage
224+
225+
New code must have >95% test coverage. Run `make coverage` to check.
226+
227+
### Naming
228+
229+
- Reduction tests: `test_<source>_to_<target>_closed_loop`
230+
- Model tests: `test_<model>_basic`, `test_<model>_serialization`
231+
- Solver tests: `test_<solver>_<problem>`
232+
233+
### Key Testing Patterns
234+
235+
Follow the reference files above for exact API usage. Summary:
236+
237+
- `solver.find_best(&problem)``Option<Vec<usize>>` — one optimal solution for optimization problems
238+
- `solver.find_satisfying(&problem)``Option<Vec<usize>>` — one satisfying assignment
239+
- `solver.find_all_best(&problem)``Vec<Vec<usize>>` — all optimal solutions (BruteForce only)
240+
- `solver.find_all_satisfying(&problem)``Vec<Vec<usize>>` — all satisfying assignments (BruteForce only)
241+
- `problem.evaluate(&config)` — returns `SolutionSize::Valid(value)` / `SolutionSize::Invalid` for optimization, `bool` for satisfaction
242+
243+
### File Organization
244+
245+
Unit tests live in `src/unit_tests/`, mirroring `src/` structure. Source files reference them via `#[path]`:
246+
247+
```rust
248+
// In src/rules/foo_bar.rs:
249+
#[cfg(test)]
250+
#[path = "../unit_tests/rules/foo_bar.rs"]
251+
mod tests;
252+
```
253+
254+
Integration tests are in `tests/suites/`, consolidated through `tests/main.rs`.
255+
256+
### Example Tests
257+
258+
**Reference:** `tests/suites/examples.rs` — macro-based test harness
259+
260+
Example programs (`examples/reduction_*.rs`) are tested via `include!` in `tests/suites/examples.rs` — each example is compiled directly into the test binary (no subprocess overhead). Each example must expose a `pub fn run()` entry point. See any existing example (e.g., `examples/reduction_minimumvertexcover_to_maximumindependentset.rs`) for the pattern:
261+
262+
- `pub fn run()` with logic + `fn main() { run() }`
263+
- Regular comments (`//`) not inner doc comments (`//!`)
264+
- Hardcoded example name, not `env!("CARGO_BIN_NAME")`
265+
266+
The test harness auto-registers each example as a separate `#[test]`, so `cargo test` runs them in parallel.
267+
268+
### Before PR
269+
270+
```bash
271+
make test clippy
272+
```
273+
274+
## Documentation Requirements
275+
276+
**Reference:** search `docs/paper/reductions.typ` for `MinimumVertexCover` `MaximumIndependentSet` to see a complete problem-def + reduction-rule example.
277+
278+
### Adding a Problem Definition
279+
280+
```typst
281+
#problem-def("ProblemName")[
282+
Mathematical definition...
283+
]
284+
```
285+
286+
Also add to the `display-name` dictionary:
287+
```typst
288+
"ProblemName": [Problem Name],
289+
```
290+
291+
### Adding a Reduction Theorem
292+
293+
```typst
294+
#reduction-rule("Source", "Target",
295+
example: true,
296+
example-caption: [caption text],
297+
)[
298+
Rule statement...
299+
][
300+
Proof sketch...
301+
]
302+
```
303+
304+
Every directed reduction in the graph needs its own `reduction-rule` entry. The paper auto-checks completeness against `reduction_graph.json`.

0 commit comments

Comments
 (0)