Skip to content

Commit 88c1635

Browse files
GiggleLiuclaude
andauthored
Fix complexity inconsistencies, enforce overhead, add missing variants (#112)
* Fix complexity inconsistencies, enforce overhead, add missing variants - Make overhead mandatory in #[reduction] proc macro (compile error instead of silent default) - Fix 11 complexity strings to match paper ground truth (best known algorithms) - Add declare_variants! to BicliqueCover, BMF, and PaintShop Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix MIS complexity for geometric graph variants to 2^sqrt(n) KingsSubgraph, TriangularSubgraph, and UnitDiskGraph variants use subexponential algorithms exploiting planar/geometric structure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Note subexponential MIS complexity on geometric graphs in paper Cite Alber & Fiala (2004) for O*(c^sqrt(n)) algorithms on unit disk, King's subgraph, and triangular subgraph variants. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix bugs in skills: wrong tool name, broken regex, missing steps - review-implementation: "Task tool" → "Agent tool" (tool doesn't exist) - review-implementation: Remove narrow HEAD~1 detection, use main..HEAD only - review-implementation: Add run_in_background guidance for parallel dispatch - structural-reviewer-prompt: Fix grep-style \| to ripgrep | alternation - fix-pr: Add $REPO resolution, replace {owner}/{repo} placeholders - fix-pr: Clarify --jq warning scope (gh api only, not gh pr view) - add-rule: Add export_schemas to Step 6, fix section title - add-model: Add Step 2.5 for declare_variants! macro registration - add-model: Add declare_variants! to Common Mistakes table Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix remaining skill gaps: variant docs, branch guards, prerequisites - add-model: Document variant_params! macro usage for variant() implementation - issue-to-pr: Add pre-flight checks (clean tree, existing branch) before branch creation; add retry/dirty-tree to Common Mistakes - write-model-in-paper: Fix wrong make rust-export → use make paper (which auto-runs export_graph + export_schemas) - write-rule-in-paper: Fix wrong make rust-export → correct export commands Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add meta-power skill for batch issue resolution Orchestrates end-to-end pipeline: issue-to-pr -> make run-plan -> copilot-review -> fix-pr loop (3 retries) -> merge. Processes all open [Model] issues first, then [Rule] issues. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * save makefile update * Harden meta-power skill against fragile patterns - Replace fixed sleep with CI poll loop (30s intervals, 15min max) - Use gh pr merge --auto to avoid CI/merge race condition - Detect existing PRs from previous runs and resume instead of re-plan - Clean stale branches before starting a new issue - Add batch-mode note: auto-approve sub-skill confirmation prompts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * update CLAUDE.md * Add compiled eval functions for overhead and complexity expressions - Add overhead_eval_fn to ReductionEntry (calls getter methods directly) - Add complexity_eval_fn to VariantEntry (same pattern) - Convert declare_variants! from macro_rules to proc macro with compile-time getter validation - Make overhead attribute required in #[reduction] macro - Add Expr::parse() runtime parser for cross-check tests - Fix complexity strings: use concrete values only (no epsilon/omega) - Fix getter mismatches: SpinGlass num_spins, CircuitSAT num_variables - Add comprehensive parser tests and cross-check tests - Update CLAUDE.md and skills to document new patterns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix Copilot review comments: regenerate JSON, improve docs - Regenerate reduction_graph.json to fix stale complexity strings (Factoring num_bits → m+n, MaxCut omega → 2.372) - Clarify Box::leak memory note in Expr::parse doc comment - Fix regex alternation consistency in structural-reviewer-prompt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9ad1678 commit 88c1635

42 files changed

Lines changed: 1484 additions & 235 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/CLAUDE.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Rust library for NP-hard problem reductions. Implements computational problems w
1212
- [write-model-in-paper](skills/write-model-in-paper/SKILL.md) -- Write or improve a problem-def entry in the Typst paper. Covers formal definition, background, example with visualization, and algorithm list.
1313
- [write-rule-in-paper](skills/write-rule-in-paper/SKILL.md) -- Write or improve a reduction-rule entry in the Typst paper. Covers complexity citation, self-contained proof, detailed example, and verification.
1414
- [release](skills/release/SKILL.md) -- Create a new crate release. Determines version bump from diff, verifies tests/clippy, then runs `make release`.
15+
- [meta-power](skills/meta-power/SKILL.md) -- Batch-resolve all open `[Model]` and `[Rule]` issues autonomously: plan, implement, review, fix CI, merge — in dependency order (models first).
1516

1617
## Commands
1718
```bash
@@ -26,7 +27,7 @@ make mdbook # Build and serve mdBook with live reload
2627
make paper # Build Typst paper (runs examples + exports first)
2728
make coverage # Generate coverage report (>95% required)
2829
make check # Quick pre-commit check (fmt + clippy + test)
29-
make rust-export # Generate Rust mapping JSON exports
30+
make rust-export # Generate Julia parity test data (mapping stages)
3031
make export-schemas # Regenerate problem schemas JSON
3132
make qubo-testdata # Regenerate QUBO ground truth JSON
3233
make clean # Clean build artifacts
@@ -90,6 +91,8 @@ enum Direction { Maximize, Minimize }
9091
```
9192

9293
### Key Patterns
94+
- `variant_params!` macro implements `Problem::variant()` — e.g., `crate::variant_params![G, W]` for two type params, `crate::variant_params![]` for none (see `src/variant.rs`)
95+
- `declare_variants!` proc macro registers concrete type instantiations with best-known complexity — must appear in every model file (see `src/models/graph/maximum_independent_set.rs`). Variable names in complexity strings are validated at compile time against actual getter methods.
9396
- Problems parameterized by graph type `G` and optionally weight type `W` (problem-dependent)
9497
- `ReductionResult` provides `target_problem()` and `extract_solution()`
9598
- `Solver::find_best()``Option<Vec<usize>>` for optimization problems; `Solver::find_satisfying()``Option<Vec<usize>>` for `Metric = bool`
@@ -101,7 +104,7 @@ enum Direction { Maximize, Minimize }
101104
- `NumericSize` supertrait bundles common numeric bounds (`Clone + Default + PartialOrd + Num + Zero + Bounded + AddAssign + 'static`)
102105

103106
### Overhead System
104-
Reduction overhead is expressed using `Expr` AST (in `src/expr.rs`) with the `#[reduction]` macro:
107+
Reduction overhead is expressed using `Expr` AST (in `src/expr.rs`) with the `#[reduction]` macro. The `overhead` attribute is **required** — omitting it is a compile error:
105108
```rust
106109
#[reduction(overhead = {
107110
num_vertices = "num_vertices + num_clauses",
@@ -110,9 +113,14 @@ Reduction overhead is expressed using `Expr` AST (in `src/expr.rs`) with the `#[
110113
impl ReduceTo<Target> for Source { ... }
111114
```
112115
- Expression strings are parsed at compile time by a Pratt parser in the proc macro crate
116+
- Variable names are validated against actual getter methods on the source type — typos cause compile errors
113117
- Each problem type provides inherent getter methods (e.g., `num_vertices()`, `num_edges()`) that the overhead expressions reference
114118
- `ReductionOverhead` stores `Vec<(&'static str, Expr)>` — field name to symbolic expression mappings
115-
- Expressions support: constants, variables, `+`, `*`, `^`, `exp()`, `log()`, `sqrt()`
119+
- `ReductionEntry` has both symbolic (`overhead_fn`) and compiled (`overhead_eval_fn`) evaluation — the compiled version calls getters directly
120+
- `VariantEntry` has both a complexity string and compiled `complexity_eval_fn` — same pattern
121+
- Expressions support: constants, variables, `+`, `-`, `*`, `/`, `^`, `exp()`, `log()`, `sqrt()`
122+
- Complexity strings must use **concrete numeric values only** (e.g., `"2^(2.372 * num_vertices / 3)"`, not `"2^(omega * num_vertices / 3)"`)
123+
- `Expr::parse()` provides runtime parsing for cross-check tests that compare compiled vs symbolic evaluation
116124

117125
### Problem Names
118126
Problem types use explicit optimization prefixes:
@@ -216,6 +224,8 @@ The complexity string represents the **worst-case time complexity of the best kn
216224
2. Confirm the worst-case time bound from the original paper or a survey
217225
3. Check that polynomial-time problems (e.g., MaximumMatching, 2-SAT, 2-Coloring) are NOT declared with exponential complexity
218226
4. For NP-hard problems, verify the base of the exponential matches the literature (e.g., 1.1996^n for MIS, not 2^n)
227+
5. Use only concrete numeric values — no symbolic constants (epsilon, omega); inline the actual numbers with citations
228+
6. Variable names must match getter methods on the problem type (enforced at compile time)
219229

220230
### Reduction Overhead (`#[reduction(overhead = {...})]`)
221231
Overhead expressions describe how target problem size relates to source problem size. To verify correctness:

.claude/skills/add-model/SKILL.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,25 @@ Key decisions:
8484
- **Weight management:** use inherent methods (`weights()`, `set_weights()`, `is_weighted()`), NOT traits
8585
- **`dims()`:** returns the configuration space dimensions (e.g., `vec![2; n]` for binary variables)
8686
- **`evaluate()`:** must check feasibility first, then compute objective
87+
- **`variant()`:** use the `variant_params!` macro — e.g., `crate::variant_params![G, W]` for `Problem<G, W>`, or `crate::variant_params![]` for problems with no type parameters. Each type parameter must implement `VariantParam` (already done for standard types like `SimpleGraph`, `i32`, `One`). See `src/variant.rs`.
88+
89+
## Step 2.5: Register variant complexity
90+
91+
Add `declare_variants!` at the bottom of the model file (after the trait impls, before the test link). Each line declares a concrete type instantiation with its best-known worst-case complexity:
92+
93+
```rust
94+
crate::declare_variants! {
95+
ProblemName<SimpleGraph, i32> => "1.1996^num_vertices",
96+
ProblemName<SimpleGraph, One> => "1.1996^num_vertices",
97+
}
98+
```
99+
100+
- The complexity string references the getter method names from Step 1.5 (e.g., `num_vertices`) — variable names are validated at compile time against actual getters, so typos cause compile errors
101+
- One entry per supported `(graph, weight)` combination
102+
- The string is parsed as an `Expr` AST — supports `+`, `-`, `*`, `/`, `^`, `exp()`, `log()`, `sqrt()`
103+
- Use only concrete numeric values (e.g., `"1.1996^num_vertices"`, not `"(2-epsilon)^num_vertices"`)
104+
- A compiled `complexity_eval_fn` is auto-generated alongside the symbolic expression
105+
- See `src/models/graph/maximum_independent_set.rs` for the reference pattern
87106

88107
## Step 3: Register the model
89108

@@ -146,5 +165,6 @@ Then run the [review-implementation](../review-implementation/SKILL.md) skill to
146165
| Missing `#[path]` test link | Add `#[cfg(test)] #[path = "..."] mod tests;` at file bottom |
147166
| Wrong `dims()` | Must match the actual configuration space (e.g., `vec![2; n]` for binary) |
148167
| Not registering in `mod.rs` | Must update both `<category>/mod.rs` and `models/mod.rs` |
168+
| Forgetting `declare_variants!` | Required for variant complexity metadata used by the paper's auto-generated table |
149169
| Forgetting CLI dispatch | Must add match arms in `dispatch.rs` (`load_problem` + `serialize_any_problem`) |
150170
| Forgetting CLI alias | Must add lowercase entry in `problem_name.rs` `resolve_alias()` |

.claude/skills/add-rule/SKILL.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl ReductionResult for ReductionXToY {
7373
}
7474
```
7575

76-
**ReduceTo with `#[reduction]` macro:**
76+
**ReduceTo with `#[reduction]` macro** (overhead is **required**):
7777
```rust
7878
#[reduction(overhead = {
7979
field_name = "source_field",
@@ -131,11 +131,12 @@ example_fn!(test_<source>_to_<target>, reduction_<source>_to_<target>);
131131

132132
Invoke the `/write-rule-in-paper` skill to write the reduction-rule entry in `docs/paper/reductions.typ`. That skill covers the full authoring process: complexity citation, self-contained proof, detailed worked example, and verification checklist.
133133

134-
## Step 6: Regenerate graph and verify
134+
## Step 6: Regenerate exports and verify
135135

136136
```bash
137-
cargo run --example export_graph # Update reduction_graph.json
138-
make test clippy # Must pass
137+
cargo run --example export_graph # Update reduction_graph.json
138+
cargo run --example export_schemas # Update problem schemas
139+
make test clippy # Must pass
139140
```
140141

141142
Then run the [review-implementation](../review-implementation/SKILL.md) skill to verify all structural and semantic checks pass.

.claude/skills/fix-pr/SKILL.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@ Resolve PR review comments, fix CI failures, and address codecov coverage gaps f
1111

1212
**IMPORTANT:** Do NOT use `gh api --jq` for extracting data — it uses a built-in jq that
1313
chokes on response bodies containing backslashes (common in Copilot code suggestions).
14-
Always pipe to `python3 -c` instead.
14+
Always pipe to `python3 -c` instead. (`gh pr view --jq` is fine — only `gh api --jq` is affected.)
1515

1616
```bash
17+
# Get repo identifiers
18+
REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner) # e.g., "owner/repo"
19+
1720
# Get PR number
1821
PR=$(gh pr view --json number --jq .number)
1922

2023
# Get PR head SHA (on remote)
21-
HEAD_SHA=$(gh api repos/{owner}/{repo}/pulls/$PR | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])")
24+
HEAD_SHA=$(gh api repos/$REPO/pulls/$PR | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])")
2225
```
2326

2427
### 1a. Fetch Review Comments
@@ -27,23 +30,23 @@ Three sources of feedback to check:
2730

2831
```bash
2932
# Copilot and user inline review comments (on code lines)
30-
gh api repos/{owner}/{repo}/pulls/$PR/comments | python3 -c "
33+
gh api repos/$REPO/pulls/$PR/comments | python3 -c "
3134
import sys,json
3235
for c in json.load(sys.stdin):
3336
line = c.get('line') or c.get('original_line') or '?'
3437
print(f'[{c[\"user\"][\"login\"]}] {c[\"path\"]}:{line} — {c[\"body\"]}')
3538
"
3639

3740
# Review-level comments (top-level review body)
38-
gh api repos/{owner}/{repo}/pulls/$PR/reviews | python3 -c "
41+
gh api repos/$REPO/pulls/$PR/reviews | python3 -c "
3942
import sys,json
4043
for r in json.load(sys.stdin):
4144
if r.get('body'):
4245
print(f'[{r[\"user\"][\"login\"]}] {r[\"state\"]}: {r[\"body\"]}')
4346
"
4447

4548
# Issue-level comments (general discussion, excluding bots)
46-
gh api repos/{owner}/{repo}/issues/$PR/comments | python3 -c "
49+
gh api repos/$REPO/issues/$PR/comments | python3 -c "
4750
import sys,json
4851
for c in json.load(sys.stdin):
4952
login = c['user']['login']
@@ -56,7 +59,7 @@ for c in json.load(sys.stdin):
5659

5760
```bash
5861
# All check runs on the PR head
59-
gh api repos/{owner}/{repo}/commits/$HEAD_SHA/check-runs | python3 -c "
62+
gh api repos/$REPO/commits/$HEAD_SHA/check-runs | python3 -c "
6063
import sys,json
6164
for cr in json.load(sys.stdin)['check_runs']:
6265
print(f'{cr[\"name\"]}: {cr.get(\"conclusion\") or cr[\"status\"]}')
@@ -67,7 +70,7 @@ for cr in json.load(sys.stdin)['check_runs']:
6770

6871
```bash
6972
# Codecov bot comment with coverage diff
70-
gh api repos/{owner}/{repo}/issues/$PR/comments | python3 -c "
73+
gh api repos/$REPO/issues/$PR/comments | python3 -c "
7174
import sys,json
7275
for c in json.load(sys.stdin):
7376
if c['user']['login'] == 'codecov[bot]':
@@ -129,7 +132,7 @@ For detailed line-by-line coverage, use the Codecov API:
129132

130133
```bash
131134
# Get file-level coverage for the PR
132-
gh api repos/{owner}/{repo}/issues/$PR/comments | python3 -c "
135+
gh api repos/$REPO/issues/$PR/comments | python3 -c "
133136
import sys,json,re
134137
for c in json.load(sys.stdin):
135138
if c['user']['login'] == 'codecov[bot]':

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,14 @@ Include the concrete details from the issue (problem definition, reduction algor
8181

8282
Create a pull request with only the plan file.
8383

84+
**Pre-flight checks** (before creating the branch):
85+
1. Verify clean working tree: `git status --porcelain` must be empty. If not, STOP and ask user to stash or commit.
86+
2. Check if branch already exists: `git rev-parse --verify issue-<number>-<slug> 2>/dev/null`. If it exists, switch to it with `git checkout` (no `-b`) instead of creating a new one.
87+
8488
```bash
85-
# Create branch
86-
git checkout -b issue-<number>-<slug>
89+
# Create branch (from main)
90+
git checkout main
91+
git rev-parse --verify issue-<number>-<slug> 2>/dev/null && git checkout issue-<number>-<slug> || git checkout -b issue-<number>-<slug>
8792

8893
# Stage the plan file
8994
git add docs/plans/<plan-file>.md
@@ -131,3 +136,5 @@ Created PR #45: Fix #42: Add IndependentSet -> QUBO reduction
131136
| Generic plan | Use specifics from the issue, mapped to add-model/add-rule steps |
132137
| Skipping CLI registration in plan | add-model requires CLI dispatch updates -- include in plan |
133138
| Not verifying facts from issue | Use WebSearch/WebFetch to cross-check claims |
139+
| Branch already exists on retry | Check with `git rev-parse --verify` before `git checkout -b` |
140+
| Dirty working tree | Verify `git status --porcelain` is empty before branching |

0 commit comments

Comments
 (0)