Skip to content

Commit e7ea0c1

Browse files
isPANNclaudeGiggleLiu
authored
Fix #140: Add MinimumFeedbackVertexSet model (#596)
* Add plan for #140: [Model] MinimumFeedbackVertexSet Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(topology): add DirectedGraph for directed problem infrastructure Add DirectedGraph struct (wrapping petgraph DiGraph) with full API: new/empty constructors, num_vertices/num_arcs, arcs, has_arc, successors, predecessors, is_dag (via toposort), and induced_subgraph with contiguous vertex remapping. Implements PartialEq/Eq (normalized arc sort) and VariantParam. Includes 19 unit tests covering all methods, DAG detection, serialization round-trip, and invalid-arc panic. This is Batch 1 infrastructure for MinimumFeedbackVertexSet (#140). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add MinimumFeedbackVertexSet model (#140) Implements the Minimum Feedback Vertex Set problem on directed graphs. Includes evaluate logic via induced subgraph DAG check, unit weight and weighted variants, BruteForce solver compatibility, and full unit test coverage (7 tests, including solver finding 18 optimal solutions). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: register MinimumFeedbackVertexSet in CLI (dispatch, create, aliases) Adds CLI support for MinimumFeedbackVertexSet: - dispatch.rs: load/serialize via deser_opt/try_ser for MinimumFeedbackVertexSet<i32> - create.rs: new --arcs flag parses directed arc lists ("0>1,1>2,2>0"), constructs DirectedGraph + MinimumFeedbackVertexSet - problem_name.rs: FVS alias and lowercase minimumfeedbackvertexset -> MinimumFeedbackVertexSet - cli.rs: --arcs flag on CreateArgs, all_data_flags_empty check, help table entry and example Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Implement #140: Add MinimumFeedbackVertexSet model - Add DirectedGraph topology type (wraps petgraph DiGraph) - Methods: new, num_vertices, num_arcs, arcs, has_arc, successors, predecessors, is_dag, induced_subgraph - 19 unit tests covering all methods - Add MinimumFeedbackVertexSet<W> problem model - Evaluate: check induced subgraph on unremoved vertices is DAG - Direction: Minimize (sum of weights of removed vertices) - Complexity: O*(1.8638^n) per Razgon (2007) - 7 unit tests including brute-force solver verification - Register in CLI with FVS alias and --arcs flag Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove plan file after implementation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address Copilot review comments for MinimumFeedbackVertexSet - Fix doc reference: FeedbackVertexSet -> MinimumFeedbackVertexSet - Add config length checks in is_valid_solution() and evaluate() to return false/Invalid instead of panicking on malformed input - Add CLI validation for --num-vertices vs arc indices to return a structured error instead of panicking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add coverage tests for MinimumFeedbackVertexSet accessors and guards Cover set_weights, is_weighted, num_vertices, num_arcs, variant, is_valid_solution (including wrong-length guard), and evaluate wrong-length guard. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: GiggleLiu <cacate0129@gmail.com>
1 parent 064d7dd commit e7ea0c1

19 files changed

Lines changed: 931 additions & 43 deletions

File tree

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ Before any implementation, collect all required information. If called from `iss
2525
| 8 | **Objective function** | How to compute the metric | "Sum of weights of selected vertices" |
2626
| 9 | **Best known exact algorithm** | Complexity with variable definitions | "O(1.1996^n) by Xiao & Nagamochi (2017), where n = \|V\|" |
2727
| 10 | **Solving strategy** | How it can be solved | "BruteForce works; ILP reduction available" |
28-
| 11 | **Category** | Which sub-module under `src/models/` | `graph`, `optimization`, `satisfiability`, `set`, `specialized` |
28+
| 11 | **Category** | Which sub-module under `src/models/` | `graph`, `formula`, `set`, `algebraic`, `misc` |
2929

3030
If any item is missing, ask the user to provide it. Do NOT proceed until the checklist is complete.
3131

3232
## Reference Implementations
3333

3434
Read these first to understand the patterns:
3535
- **Optimization problem:** `src/models/graph/maximum_independent_set.rs`
36-
- **Satisfaction problem:** `src/models/satisfiability/sat.rs`
36+
- **Satisfaction problem:** `src/models/formula/sat.rs`
3737
- **Model tests:** `src/unit_tests/models/graph/maximum_independent_set.rs`
3838
- **Trait definitions:** `src/traits.rs` (`Problem`, `OptimizationProblem`, `SatisfactionProblem`)
3939
- **CLI dispatch:** `problemreductions-cli/src/dispatch.rs`
@@ -42,11 +42,11 @@ Read these first to understand the patterns:
4242
## Step 1: Determine the category
4343

4444
Choose the appropriate sub-module under `src/models/`:
45-
- `graph/` -- problems defined on graphs (vertex/edge selection)
46-
- `optimization/` -- generic optimization formulations (QUBO, ILP, SpinGlass)
47-
- `satisfiability/` -- boolean satisfaction problems (SAT, k-SAT)
45+
- `graph/` -- problems defined on graphs (vertex/edge selection, SpinGlass, etc.)
46+
- `formula/` -- logical formulas and circuits (SAT, k-SAT, CircuitSAT)
4847
- `set/` -- set-based problems (set packing, set cover)
49-
- `specialized/` -- problems that don't fit other categories (factoring, circuit, paintshop)
48+
- `algebraic/` -- matrices, linear systems, lattices (QUBO, ILP, CVP, BMF)
49+
- `misc/` -- unique input structures that don't fit other categories (BinPacking, PaintShop, Factoring)
5050

5151
## Step 1.5: Infer problem size getters
5252

.claude/skills/review-implementation/SKILL.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,14 @@ if [ -n "$PR_NUM" ]; then
6363
ISSUE_NUM=$(gh pr view $PR_NUM --json body -q .body | grep -oE '#[0-9]+' | head -1 | tr -d '#')
6464
fi
6565

66-
# Fetch the issue body if found
66+
# Fetch the issue body and comments if found
6767
if [ -n "$ISSUE_NUM" ]; then
6868
ISSUE_BODY=$(gh issue view $ISSUE_NUM --json title,body -q '"# " + .title + "\n\n" + .body')
69+
ISSUE_COMMENTS=$(gh issue view $ISSUE_NUM --json comments -q '.comments[] | "**" + .author.login + "** (" + .createdAt + "):\n" + .body + "\n"')
6970
fi
7071
```
7172

72-
If an issue is found, pass it as `{ISSUE_CONTEXT}` to both subagents. If not, set `{ISSUE_CONTEXT}` to "No linked issue found."
73+
If an issue is found, pass `{ISSUE_CONTEXT}` (title + body + comments) to both subagents. If not, set `{ISSUE_CONTEXT}` to "No linked issue found." Comments often contain clarifications, corrections, or additional requirements from maintainers.
7374

7475
## Step 3: Dispatch Subagents in Parallel
7576

@@ -83,7 +84,7 @@ Dispatch using `Agent` tool with `subagent_type="superpowers:code-reviewer"`:
8384
- `{REVIEW_PARAMS}` -> summary of what's being reviewed
8485
- `{PROBLEM_NAME}`, `{CATEGORY}`, `{FILE_STEM}` -> for model reviews
8586
- `{SOURCE}`, `{TARGET}`, `{RULE_STEM}`, `{EXAMPLE_STEM}` -> for rule reviews
86-
- `{ISSUE_CONTEXT}` -> full issue title + body (or "No linked issue found.")
87+
- `{ISSUE_CONTEXT}` -> full issue title + body + comments (or "No linked issue found.")
8788
- Prompt = filled template
8889

8990
### Quality Reviewer (always)
@@ -96,7 +97,7 @@ Dispatch using `Agent` tool with `subagent_type="superpowers:code-reviewer"`:
9697
- `{CHANGED_FILES}` -> list of changed files
9798
- `{PLAN_STEP}` -> description of what was implemented (or "standalone review")
9899
- `{BASE_SHA}`, `{HEAD_SHA}` -> git range
99-
- `{ISSUE_CONTEXT}` -> full issue title + body (or "No linked issue found.")
100+
- `{ISSUE_CONTEXT}` -> full issue title + body + comments (or "No linked issue found.")
100101
- Prompt = filled template
101102

102103
**Both subagents must be dispatched in parallel** (single message with two Agent tool calls — use `run_in_background: true` on one, foreground on the other, then read the background result with `TaskOutput`).
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# pred-sym-prof-yuki-tanaka
2+
3+
## Target
4+
pred-sym (symbolic expression CLI)
5+
6+
## Use Case
7+
Three combined scenarios:
8+
1. **Complexity comparison** — Compare algorithm complexity expressions to determine asymptotic equivalence (e.g., O(n^2 + n) == O(n^2), O(n log n) != O(n^2)).
9+
2. **Reduction overhead audit** — Parse and simplify overhead expressions from reduction rules to verify they match expected growth (e.g., '3*num_vertices + num_edges^2').
10+
3. **Teaching complexity notation** — Use pred-sym as a learning/demonstration tool to explore how expressions simplify, evaluate at concrete sizes, and compare growth rates.
11+
12+
## Expected Outcome
13+
All subcommands (parse, canon, big-o, eval, compare) produce mathematically correct, clear output. Canonical and Big-O forms are rigorous. Edge cases (zero exponents, nested functions, multi-variable expressions) are handled gracefully with precise error messages.
14+
15+
## Agent
16+
17+
### Background
18+
Prof. Yuki Tanaka is a theoretical computer science professor at a research university, specializing in computational complexity and approximation algorithms. She regularly teaches graduate courses on NP-hard problems and writes textbooks. She evaluates tools against textbook definitions and mathematical rigor standards.
19+
20+
### Experience Level
21+
Expert
22+
23+
### Decision Tendencies
24+
Stress-tests edge cases systematically — zero, negative, nested, degenerate inputs. Expects mathematically rigorous output and will flag any algebraically incorrect simplification. Compares results against textbook definitions of canonical forms and asymptotic notation. Tests all subcommands in sequence, then tries to compose them in shell pipelines.
25+
26+
### Quirks
27+
Will try expressions with Unicode math symbols to see what happens. Tests the boundary between polynomial and exponential complexity deliberately. Expects `--help` to be precise and well-organized — gets annoyed by imprecise language like "simplify" when "canonicalize" is meant. Will attempt to pipe output of one subcommand into another.

docs/paper/reductions.typ

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"BinPacking": [Bin Packing],
5555
"ClosestVectorProblem": [Closest Vector Problem],
5656
"SubsetSum": [Subset Sum],
57+
"MinimumFeedbackVertexSet": [Minimum Feedback Vertex Set],
5758
)
5859

5960
// Definition label: "def:<ProblemName>" — each definition block must have a matching label
@@ -537,6 +538,37 @@ caption: [Path $P_5$ with maximal IS $S = {v_1, v_3}$ (blue, $w(S) = 2$). $S$ is
537538
) <fig:path-maximal-is>
538539
]
539540

541+
#problem-def("MinimumFeedbackVertexSet")[
542+
Given a directed graph $G = (V, A)$ with vertex weights $w: V -> RR$, find $S subset.eq V$ minimizing $sum_(v in S) w(v)$ such that the induced subgraph $G[V backslash S]$ is a directed acyclic graph (DAG).
543+
][
544+
One of Karp's 21 NP-complete problems ("Feedback Node Set") @karp1972. Applications include deadlock detection in operating systems, loop breaking in circuit design, and Bayesian network structure learning. The directed version is strictly harder than undirected FVS: the best known exact algorithm runs in $O^*(1.9977^n)$ @razgon2007, compared to $O^*(1.7548^n)$ for undirected graphs. An $O(log n dot log log n)$-approximation exists @even1998.
545+
546+
*Example.* Consider the directed graph $G$ with $n = 5$ vertices, $|A| = 7$ arcs, and unit weights. The arcs form two overlapping directed cycles: $C_1 = v_0 -> v_1 -> v_2 -> v_0$ and $C_2 = v_0 -> v_3 -> v_4 -> v_1$. The set $S = {v_0}$ with $w(S) = 1$ is a minimum feedback vertex set: removing $v_0$ breaks both cycles, leaving a DAG with topological order $(v_3, v_4, v_1, v_2)$. No 0-vertex set suffices since $C_1$ and $C_2$ overlap only at $v_0$ and $v_1$, and removing $v_1$ alone leaves $C_1' = v_0 -> v_3 -> v_4 -> v_1 -> v_2 -> v_0$.
547+
548+
#figure({
549+
// Directed graph: 5 vertices, 7 arcs, two overlapping cycles
550+
let verts = ((0, 1), (2, 1), (1, 0), (-0.5, -0.2), (0.8, -0.5))
551+
let arcs = ((0, 1), (1, 2), (2, 0), (0, 3), (3, 4), (4, 1), (2, 4))
552+
let highlights = (0,) // FVS = {v_0}
553+
canvas(length: 1cm, {
554+
// Draw directed arcs with arrows
555+
for (u, v) in arcs {
556+
draw.line(verts.at(u), verts.at(v),
557+
stroke: 1pt + black,
558+
mark: (end: "straight", scale: 0.4))
559+
}
560+
// Draw nodes on top
561+
for (k, pos) in verts.enumerate() {
562+
let s = highlights.contains(k)
563+
g-node(pos, name: "v" + str(k),
564+
fill: if s { graph-colors.at(0) } else { white },
565+
label: if s { text(fill: white)[$v_#k$] } else { [$v_#k$] })
566+
}
567+
})
568+
},
569+
caption: [A directed graph with FVS $S = {v_0}$ (blue, $w(S) = 1$). Removing $v_0$ breaks both directed cycles $v_0 -> v_1 -> v_2 -> v_0$ and $v_0 -> v_3 -> v_4 -> v_1$, leaving a DAG.],
570+
) <fig:fvs-example>
571+
]
540572

541573
== Set Problems
542574

docs/paper/references.bib

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,25 @@ @inproceedings{aggarwal2015
344344
doi = {10.1109/FOCS.2015.41}
345345
}
346346

347+
@inproceedings{razgon2007,
348+
author = {Igor Razgon},
349+
title = {Computing Minimum Directed Feedback Vertex Set in {$O^*(1.9977^n)$}},
350+
booktitle = {Proceedings of the 10th Italian Conference on Theoretical Computer Science (ICTCS)},
351+
pages = {70--81},
352+
year = {2007}
353+
}
354+
355+
@article{even1998,
356+
author = {Guy Even and Joseph Naor and Baruch Schieber and Madhu Sudan},
357+
title = {Approximating Minimum Feedback Sets and Multicuts in Directed Graphs},
358+
journal = {Algorithmica},
359+
volume = {20},
360+
number = {2},
361+
pages = {151--174},
362+
year = {1998},
363+
doi = {10.1007/PL00009191}
364+
}
365+
347366
@article{shannon1956,
348367
author = {Claude E. Shannon},
349368
title = {The zero error capacity of a noisy channel},

docs/src/reductions/problem_schemas.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,22 @@
307307
}
308308
]
309309
},
310+
{
311+
"name": "MinimumFeedbackVertexSet",
312+
"description": "Find minimum weight feedback vertex set in a directed graph",
313+
"fields": [
314+
{
315+
"name": "graph",
316+
"type_name": "DirectedGraph",
317+
"description": "The directed graph G=(V,A)"
318+
},
319+
{
320+
"name": "weights",
321+
"type_name": "Vec<W>",
322+
"description": "Vertex weights w: V -> R"
323+
}
324+
]
325+
},
310326
{
311327
"name": "MinimumSetCovering",
312328
"description": "Find minimum weight collection covering the universe",

0 commit comments

Comments
 (0)