JSON schema export & interactive reduction diagram (#33, #34)#36
JSON schema export & interactive reduction diagram (#33, #34)#36
Conversation
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
The diagram moves to an interactive web visualization in mdBook. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #36 +/- ##
=======================================
Coverage 97.29% 97.30%
=======================================
Files 174 176 +2
Lines 25994 26080 +86
=======================================
+ Hits 25292 25378 +86
Misses 702 702 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Show reduction graph on introduction/index page - Double-click nodes to navigate to problem documentation - Add collapsible interaction hints - Simplify reductions/graph.md to reference the index diagram Co-Authored-By: Claude Opus 4.6 <[email protected]>
API page now redirects to rustdoc output. No manual link maintenance needed — `make doc` generates everything. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Replace folded details with a single-line hint - Add window.scrollX/Y to tooltip positioning for correct placement Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR adds an auto-generated problem schema export (JSON) to drive Typst struct renderings, and replaces the static reduction diagram with an interactive Cytoscape.js visualization in the mdBook docs.
Changes:
- Introduce
inventory-based registration of problem schemas and export them todocs/paper/problem_schemas.json. - Update the Typst paper to render Rust struct definitions from the exported JSON and remove the embedded reduction diagram.
- Add an interactive reduction graph (Cytoscape.js) to the mdBook introduction and adjust doc build targets accordingly.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/registry/schema.rs | Adds inventory collection + JSON-serializable schema types and a collector. |
| src/registry/mod.rs | Exposes schema collection/types and re-exports FieldInfo. |
| src/registry/info.rs | Adds FieldInfo and a new fields member on ProblemInfo. |
| src/models/specialized/paintshop.rs | Registers PaintShop schema via inventory::submit!. |
| src/models/specialized/factoring.rs | Registers Factoring schema via inventory::submit!. |
| src/models/specialized/circuit.rs | Registers CircuitSAT schema via inventory::submit!. |
| src/models/specialized/bmf.rs | Registers BMF schema via inventory::submit!. |
| src/models/specialized/biclique_cover.rs | Registers BicliqueCover schema via inventory::submit!. |
| src/models/set/set_packing.rs | Registers SetPacking schema via inventory::submit!. |
| src/models/set/set_covering.rs | Registers SetCovering schema via inventory::submit!. |
| src/models/satisfiability/sat.rs | Registers Satisfiability schema via inventory::submit!. |
| src/models/satisfiability/ksat.rs | Registers KSatisfiability schema via inventory::submit!. |
| src/models/optimization/spin_glass.rs | Registers SpinGlass schema via inventory::submit!. |
| src/models/optimization/qubo.rs | Registers QUBO schema via inventory::submit!. |
| src/models/optimization/ilp.rs | Registers ILP schema via inventory::submit!. |
| src/models/graph/vertex_covering.rs | Registers VertexCovering schema via inventory::submit!. |
| src/models/graph/maximal_is.rs | Registers MaximalIS schema via inventory::submit!. |
| src/models/graph/max_cut.rs | Registers MaxCut schema via inventory::submit!. |
| src/models/graph/matching.rs | Registers Matching schema via inventory::submit!. |
| src/models/graph/kcoloring.rs | Registers KColoring schema via inventory::submit!. |
| src/models/graph/independent_set.rs | Registers IndependentSet schema via inventory::submit!. |
| src/models/graph/dominating_set.rs | Registers DominatingSet schema via inventory::submit!. |
| src/models/graph/clique.rs | Registers Clique schema via inventory::submit!. |
| examples/export_schemas.rs | Adds an example binary to export collected schemas to JSON. |
| docs/src/reductions/graph.md | Removes Mermaid diagram and points to the interactive graph. |
| docs/src/introduction.md | Adds Cytoscape.js interactive reduction graph UI + path highlighting. |
| docs/src/api.md | Replaces prior content with a redirect/link to locally generated rustdoc. |
| docs/paper/reductions.typ | Switches struct blocks to JSON-driven #render-struct and removes embedded diagram figure. |
| docs/paper/reduction-diagram.typ | Removes the Typst reduction diagram implementation. |
| docs/paper/problem_schemas.json | Adds the generated schema JSON consumed by Typst. |
| README.md | Moves developer make commands pointer to .claude/CLAUDE.md. |
| Makefile | Adds export-schemas and updates doc/paper build steps to generate/copy required artifacts. |
| .claude/CLAUDE.md | Centralizes and expands developer make command documentation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| mdbook: | ||
| cargo run --example export_graph | ||
| cp docs/paper/reduction_graph.json docs/src/reductions/ | ||
| cargo doc --all-features --no-deps |
There was a problem hiding this comment.
The mdbook target runs cargo doc but does not copy target/doc into docs/book/api, so the API redirect/link in docs/src/api.md may be broken when serving locally unless the user ran make doc beforehand. Consider mirroring the copy step here (and ensuring it won’t be wiped by mdBook rebuilds).
| cargo doc --all-features --no-deps | |
| cargo doc --all-features --no-deps | |
| cp -r target/doc docs/book/api |
docs/src/api.md
Outdated
| # API Reference | ||
|
|
||
| Full API documentation is available at [docs.rs/problemreductions](https://docs.rs/problemreductions) or in the generated rustdoc. | ||
| <meta http-equiv="refresh" content="0; url=../api/problemreductions/index.html"> |
There was a problem hiding this comment.
The <meta http-equiv="refresh"> tag is emitted into the page body by mdBook, but meta refresh is only valid/reliable in the HTML <head>; some browsers and tooling ignore it. Consider replacing this with a small inline JS redirect or just rely on the explicit link below so navigation works consistently.
| <meta http-equiv="refresh" content="0; url=../api/problemreductions/index.html"> | |
| <script> | |
| window.location.replace("../api/problemreductions/index.html"); | |
| </script> |
docs/paper/reductions.typ
Outdated
| ``` | ||
| #render-struct("KColoring") | ||
|
|
||
| Where `num_colors` is the number of colors $k$, and `graph` represents $G = (V, E)$ with vertices indexed $0..n-1$. The solution is a color assignment $c: V -> {0, ..., k-1}$ represented as a `Vec<usize>` indexed by vertex. |
There was a problem hiding this comment.
This section still refers to a num_colors field, but #render-struct("KColoring") renders only a graph field (the Rust type uses a const generic K and a phantom field). Please update the explanation to describe how k is represented in the actual KColoring type so the definition matches the exported schema.
| Where `num_colors` is the number of colors $k$, and `graph` represents $G = (V, E)$ with vertices indexed $0..n-1$. The solution is a color assignment $c: V -> {0, ..., k-1}$ represented as a `Vec<usize>` indexed by vertex. | |
| Where `graph` represents $G = (V, E)$ with vertices indexed $0..n-1$. The number of colors $k$ is encoded in the Rust type as a const generic parameter in `KColoring<K>` rather than as a struct field, so it does not appear in the rendered definition above. The solution is a color assignment $c: V -> {0, ..., k-1}$ represented as a `Vec<usize>` indexed by vertex. |
| /// Struct field descriptions for schema export. | ||
| pub fields: &'static [FieldInfo], | ||
| } |
There was a problem hiding this comment.
ProblemInfo is a public struct; adding a new public field (fields) is a semver-breaking change for downstream users that construct/destructure ProblemInfo. Consider making this field private with an accessor, or marking ProblemInfo as #[non_exhaustive] (and providing builder/accessor APIs) to allow adding fields without breaking consumers.
examples/export_schemas.rs
Outdated
| let json = serde_json::to_string(&schemas).expect("Failed to serialize"); | ||
| std::fs::write(output_path, &json).expect("Failed to write file"); |
There was a problem hiding this comment.
The schema export writes a minified JSON string. Since docs/paper/problem_schemas.json is committed, this makes diffs hard to review and tends to churn. Consider using a pretty writer (e.g., to_writer_pretty) and ensuring the file ends with a newline for more stable, readable output.
| fetch('reductions/reduction_graph.json') | ||
| .then(function(r) { return r.json(); }) | ||
| .then(function(data) { | ||
| var baseNodes = data.nodes.filter(function(n) { | ||
| return !n.variant || Object.keys(n.variant).length === 0; |
There was a problem hiding this comment.
The fetch('reductions/reduction_graph.json') chain has no error handling. If the JSON can’t be loaded or parsed, the page will fail silently and the UI remains in an unusable state. Add a .catch(...) to show a user-visible error (and potentially disable the instructions/button) so failures are diagnosable.
docs/paper/reductions.typ
Outdated
| ``` | ||
| #render-struct("MaxCut") | ||
|
|
||
| Where `graph` represents $G = (V, E)$ with edge weights $w: E -> RR$ stored in graph edge data. The solution is a partition $(S, overline(S))$ represented as a binary assignment `Vec<usize>` where 0/1 indicates partition membership. |
There was a problem hiding this comment.
The description says edge weights are stored in graph edge data, but MaxCut is rendered from problem_schemas.json as { graph: G, edge_weights: Vec<W> } (and the Rust struct also has an edge_weights field). Update the prose to match the actual representation so the paper isn't misleading.
| Where `graph` represents $G = (V, E)$ with edge weights $w: E -> RR$ stored in graph edge data. The solution is a partition $(S, overline(S))$ represented as a binary assignment `Vec<usize>` where 0/1 indicates partition membership. | |
| Where `graph` represents $G = (V, E)$ with vertices indexed $0..n-1$, and `edge_weights` stores edge weights $w: E -> RR$ in the same order as the edges of `graph`. The solution is a partition $(S, overline(S))$ represented as a binary assignment `Vec<usize>` where 0/1 indicates partition membership. |
docs/paper/reductions.typ
Outdated
| ``` | ||
| #render-struct("SpinGlass") | ||
|
|
||
| Where `num_spins` is $n$, `interactions` stores pairwise couplings $J_(i j)$ as `Vec<((usize, usize), W)>`, and `fields` stores external fields $h_i$ as `Vec<W>` indexed by spin. The solution is a spin assignment $bold(s) in {-1, +1}^n$ encoded as `Vec<usize>` where 0 maps to $s=-1$ and 1 maps to $s=+1$. |
There was a problem hiding this comment.
The prose still describes SpinGlass in terms of num_spins and interactions, but the exported schema (and Rust struct) use { graph: G, couplings: Vec<W>, fields: Vec<W> }. Please update the text to match these fields (including how couplings align with graph.edges()), otherwise the paper's definition diverges from the code.
| Where `num_spins` is $n$, `interactions` stores pairwise couplings $J_(i j)$ as `Vec<((usize, usize), W)>`, and `fields` stores external fields $h_i$ as `Vec<W>` indexed by spin. The solution is a spin assignment $bold(s) in {-1, +1}^n$ encoded as `Vec<usize>` where 0 maps to $s=-1$ and 1 maps to $s=+1$. | |
| Here `graph` is a graph on $n$ vertices, whose vertices index the spins $s_1, dots, s_n$. The vector `couplings` stores the edge couplings $J_(i j)$ as `Vec<W>` in the same order as `graph.edges()`, so the $k$-th entry of `couplings` corresponds to the $k$-th edge returned by `graph.edges()`. The vector `fields` stores the external fields $h_i$ as `Vec<W>` indexed by vertex/spin. The solution is a spin assignment $bold(s) in {-1, +1}^n$ encoded as `Vec<usize>` where 0 maps to $s=-1$ and 1 maps to $s=+1$. |
docs/paper/reductions.typ
Outdated
| ``` | ||
| #render-struct("Matching") | ||
|
|
||
| Where `num_vertices` is $|V|$, `graph` represents $G = (V, E)$ with edge weights, and `edge_weights` stores weights $w: E -> RR$ indexed by edge index. The solution is a subset $M subset.eq E$ represented as a `Vec<usize>` of edge indices. |
There was a problem hiding this comment.
This paragraph mentions a num_vertices field, but #render-struct("Matching") (and the Rust struct) only have graph and edge_weights. Update the description to remove/replace num_vertices so the paper matches the exported schema.
| Where `num_vertices` is $|V|$, `graph` represents $G = (V, E)$ with edge weights, and `edge_weights` stores weights $w: E -> RR$ indexed by edge index. The solution is a subset $M subset.eq E$ represented as a `Vec<usize>` of edge indices. | |
| Where `graph` represents $G = (V, E)$ with vertices indexed $0..n-1$, and `edge_weights` stores weights $w: E -> RR$ indexed by edge index. The solution is a subset $M subset.eq E$ represented as a `Vec<usize>` of edge indices. |
docs/paper/problem_schemas.json
Outdated
| @@ -0,0 +1 @@ | |||
| [{"name":"BMF","category":"specialized","description":"Boolean matrix factorization","fields":[{"name":"matrix","type_name":"Vec<Vec<bool>>","description":"Target boolean matrix A"},{"name":"m","type_name":"usize","description":"Number of rows"},{"name":"n","type_name":"usize","description":"Number of columns"},{"name":"k","type_name":"usize","description":"Factorization rank"}]},{"name":"BicliqueCover","category":"specialized","description":"Cover bipartite edges with k bicliques","fields":[{"name":"left_size","type_name":"usize","description":"Vertices in left partition"},{"name":"right_size","type_name":"usize","description":"Vertices in right partition"},{"name":"edges","type_name":"Vec<(usize, usize)>","description":"Bipartite edges"},{"name":"k","type_name":"usize","description":"Number of bicliques"}]},{"name":"CircuitSAT","category":"satisfiability","description":"Find satisfying input to a boolean circuit","fields":[{"name":"circuit","type_name":"Circuit","description":"The boolean circuit"},{"name":"variables","type_name":"Vec<String>","description":"Circuit variable names"},{"name":"weights","type_name":"Vec<W>","description":"Assignment weights"}]},{"name":"Clique","category":"graph","description":"Find maximum weight clique in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"DominatingSet","category":"graph","description":"Find minimum weight dominating set in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"Factoring","category":"specialized","description":"Factor a composite integer into two factors","fields":[{"name":"m","type_name":"usize","description":"Bits for first factor"},{"name":"n","type_name":"usize","description":"Bits for second factor"},{"name":"target","type_name":"u64","description":"Number to factor"}]},{"name":"ILP","category":"optimization","description":"Optimize linear objective subject to linear constraints","fields":[{"name":"num_vars","type_name":"usize","description":"Number of integer variables"},{"name":"bounds","type_name":"Vec<VarBounds>","description":"Variable bounds"},{"name":"constraints","type_name":"Vec<LinearConstraint>","description":"Linear constraints"},{"name":"objective","type_name":"Vec<(usize, f64)>","description":"Sparse objective coefficients"},{"name":"sense","type_name":"ObjectiveSense","description":"Optimization direction"}]},{"name":"IndependentSet","category":"graph","description":"Find maximum weight independent set in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"KColoring","category":"graph","description":"Find valid k-coloring of a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"}]},{"name":"KSatisfiability","category":"satisfiability","description":"SAT with exactly k literals per clause","fields":[{"name":"num_vars","type_name":"usize","description":"Number of Boolean variables"},{"name":"clauses","type_name":"Vec<CNFClause>","description":"Clauses each with exactly K literals"},{"name":"weights","type_name":"Vec<W>","description":"Clause weights for MAX-K-SAT"}]},{"name":"Matching","category":"graph","description":"Find maximum weight matching in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"edge_weights","type_name":"Vec<W>","description":"Edge weights w: E -> R"}]},{"name":"MaxCut","category":"graph","description":"Find maximum weight cut in a graph","fields":[{"name":"graph","type_name":"G","description":"The graph with edge weights"},{"name":"edge_weights","type_name":"Vec<W>","description":"Edge weights w: E -> R"}]},{"name":"MaximalIS","category":"graph","description":"Find maximum weight maximal independent set","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"PaintShop","category":"specialized","description":"Minimize color changes in paint shop sequence","fields":[{"name":"sequence_indices","type_name":"Vec<usize>","description":"Car sequence as indices"},{"name":"car_labels","type_name":"Vec<String>","description":"Unique car labels"},{"name":"is_first","type_name":"Vec<bool>","description":"First occurrence flags"},{"name":"num_cars","type_name":"usize","description":"Number of unique cars"}]},{"name":"QUBO","category":"optimization","description":"Minimize quadratic unconstrained binary objective","fields":[{"name":"num_vars","type_name":"usize","description":"Number of binary variables"},{"name":"matrix","type_name":"Vec<Vec<W>>","description":"Upper-triangular Q matrix"}]},{"name":"Satisfiability","category":"satisfiability","description":"Find satisfying assignment for CNF formula","fields":[{"name":"num_vars","type_name":"usize","description":"Number of Boolean variables"},{"name":"clauses","type_name":"Vec<CNFClause>","description":"Clauses in conjunctive normal form"},{"name":"weights","type_name":"Vec<W>","description":"Clause weights for MAX-SAT"}]},{"name":"SetCovering","category":"set","description":"Find minimum weight collection covering the universe","fields":[{"name":"universe_size","type_name":"usize","description":"Size of the universe U"},{"name":"sets","type_name":"Vec<Vec<usize>>","description":"Collection of subsets of U"},{"name":"weights","type_name":"Vec<W>","description":"Weight for each set"}]},{"name":"SetPacking","category":"set","description":"Find maximum weight collection of disjoint sets","fields":[{"name":"sets","type_name":"Vec<Vec<usize>>","description":"Collection of sets over a universe"},{"name":"weights","type_name":"Vec<W>","description":"Weight for each set"}]},{"name":"SpinGlass","category":"optimization","description":"Minimize Ising Hamiltonian on a graph","fields":[{"name":"graph","type_name":"G","description":"The interaction graph"},{"name":"couplings","type_name":"Vec<W>","description":"Pairwise couplings J_ij"},{"name":"fields","type_name":"Vec<W>","description":"On-site fields h_i"}]},{"name":"VertexCovering","category":"graph","description":"Find minimum weight vertex cover in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]}] No newline at end of file | |||
There was a problem hiding this comment.
This committed JSON is a single very long minified line, which makes reviews and future diffs noisy. If this file is intended to live in the repo, please generate it in a pretty-printed, deterministic format (and with a trailing newline) to improve maintainability.
| [{"name":"BMF","category":"specialized","description":"Boolean matrix factorization","fields":[{"name":"matrix","type_name":"Vec<Vec<bool>>","description":"Target boolean matrix A"},{"name":"m","type_name":"usize","description":"Number of rows"},{"name":"n","type_name":"usize","description":"Number of columns"},{"name":"k","type_name":"usize","description":"Factorization rank"}]},{"name":"BicliqueCover","category":"specialized","description":"Cover bipartite edges with k bicliques","fields":[{"name":"left_size","type_name":"usize","description":"Vertices in left partition"},{"name":"right_size","type_name":"usize","description":"Vertices in right partition"},{"name":"edges","type_name":"Vec<(usize, usize)>","description":"Bipartite edges"},{"name":"k","type_name":"usize","description":"Number of bicliques"}]},{"name":"CircuitSAT","category":"satisfiability","description":"Find satisfying input to a boolean circuit","fields":[{"name":"circuit","type_name":"Circuit","description":"The boolean circuit"},{"name":"variables","type_name":"Vec<String>","description":"Circuit variable names"},{"name":"weights","type_name":"Vec<W>","description":"Assignment weights"}]},{"name":"Clique","category":"graph","description":"Find maximum weight clique in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"DominatingSet","category":"graph","description":"Find minimum weight dominating set in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"Factoring","category":"specialized","description":"Factor a composite integer into two factors","fields":[{"name":"m","type_name":"usize","description":"Bits for first factor"},{"name":"n","type_name":"usize","description":"Bits for second factor"},{"name":"target","type_name":"u64","description":"Number to factor"}]},{"name":"ILP","category":"optimization","description":"Optimize linear objective subject to linear constraints","fields":[{"name":"num_vars","type_name":"usize","description":"Number of integer variables"},{"name":"bounds","type_name":"Vec<VarBounds>","description":"Variable bounds"},{"name":"constraints","type_name":"Vec<LinearConstraint>","description":"Linear constraints"},{"name":"objective","type_name":"Vec<(usize, f64)>","description":"Sparse objective coefficients"},{"name":"sense","type_name":"ObjectiveSense","description":"Optimization direction"}]},{"name":"IndependentSet","category":"graph","description":"Find maximum weight independent set in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"KColoring","category":"graph","description":"Find valid k-coloring of a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"}]},{"name":"KSatisfiability","category":"satisfiability","description":"SAT with exactly k literals per clause","fields":[{"name":"num_vars","type_name":"usize","description":"Number of Boolean variables"},{"name":"clauses","type_name":"Vec<CNFClause>","description":"Clauses each with exactly K literals"},{"name":"weights","type_name":"Vec<W>","description":"Clause weights for MAX-K-SAT"}]},{"name":"Matching","category":"graph","description":"Find maximum weight matching in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"edge_weights","type_name":"Vec<W>","description":"Edge weights w: E -> R"}]},{"name":"MaxCut","category":"graph","description":"Find maximum weight cut in a graph","fields":[{"name":"graph","type_name":"G","description":"The graph with edge weights"},{"name":"edge_weights","type_name":"Vec<W>","description":"Edge weights w: E -> R"}]},{"name":"MaximalIS","category":"graph","description":"Find maximum weight maximal independent set","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]},{"name":"PaintShop","category":"specialized","description":"Minimize color changes in paint shop sequence","fields":[{"name":"sequence_indices","type_name":"Vec<usize>","description":"Car sequence as indices"},{"name":"car_labels","type_name":"Vec<String>","description":"Unique car labels"},{"name":"is_first","type_name":"Vec<bool>","description":"First occurrence flags"},{"name":"num_cars","type_name":"usize","description":"Number of unique cars"}]},{"name":"QUBO","category":"optimization","description":"Minimize quadratic unconstrained binary objective","fields":[{"name":"num_vars","type_name":"usize","description":"Number of binary variables"},{"name":"matrix","type_name":"Vec<Vec<W>>","description":"Upper-triangular Q matrix"}]},{"name":"Satisfiability","category":"satisfiability","description":"Find satisfying assignment for CNF formula","fields":[{"name":"num_vars","type_name":"usize","description":"Number of Boolean variables"},{"name":"clauses","type_name":"Vec<CNFClause>","description":"Clauses in conjunctive normal form"},{"name":"weights","type_name":"Vec<W>","description":"Clause weights for MAX-SAT"}]},{"name":"SetCovering","category":"set","description":"Find minimum weight collection covering the universe","fields":[{"name":"universe_size","type_name":"usize","description":"Size of the universe U"},{"name":"sets","type_name":"Vec<Vec<usize>>","description":"Collection of subsets of U"},{"name":"weights","type_name":"Vec<W>","description":"Weight for each set"}]},{"name":"SetPacking","category":"set","description":"Find maximum weight collection of disjoint sets","fields":[{"name":"sets","type_name":"Vec<Vec<usize>>","description":"Collection of sets over a universe"},{"name":"weights","type_name":"Vec<W>","description":"Weight for each set"}]},{"name":"SpinGlass","category":"optimization","description":"Minimize Ising Hamiltonian on a graph","fields":[{"name":"graph","type_name":"G","description":"The interaction graph"},{"name":"couplings","type_name":"Vec<W>","description":"Pairwise couplings J_ij"},{"name":"fields","type_name":"Vec<W>","description":"On-site fields h_i"}]},{"name":"VertexCovering","category":"graph","description":"Find minimum weight vertex cover in a graph","fields":[{"name":"graph","type_name":"G","description":"The underlying graph G=(V,E)"},{"name":"weights","type_name":"Vec<W>","description":"Vertex weights w: V -> R"}]}] | |
| [ | |
| { | |
| "name": "BMF", | |
| "category": "specialized", | |
| "description": "Boolean matrix factorization", | |
| "fields": [ | |
| { | |
| "name": "matrix", | |
| "type_name": "Vec<Vec<bool>>", | |
| "description": "Target boolean matrix A" | |
| }, | |
| { | |
| "name": "m", | |
| "type_name": "usize", | |
| "description": "Number of rows" | |
| }, | |
| { | |
| "name": "n", | |
| "type_name": "usize", | |
| "description": "Number of columns" | |
| }, | |
| { | |
| "name": "k", | |
| "type_name": "usize", | |
| "description": "Factorization rank" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "BicliqueCover", | |
| "category": "specialized", | |
| "description": "Cover bipartite edges with k bicliques", | |
| "fields": [ | |
| { | |
| "name": "left_size", | |
| "type_name": "usize", | |
| "description": "Vertices in left partition" | |
| }, | |
| { | |
| "name": "right_size", | |
| "type_name": "usize", | |
| "description": "Vertices in right partition" | |
| }, | |
| { | |
| "name": "edges", | |
| "type_name": "Vec<(usize, usize)>", | |
| "description": "Bipartite edges" | |
| }, | |
| { | |
| "name": "k", | |
| "type_name": "usize", | |
| "description": "Number of bicliques" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "CircuitSAT", | |
| "category": "satisfiability", | |
| "description": "Find satisfying input to a boolean circuit", | |
| "fields": [ | |
| { | |
| "name": "circuit", | |
| "type_name": "Circuit", | |
| "description": "The boolean circuit" | |
| }, | |
| { | |
| "name": "variables", | |
| "type_name": "Vec<String>", | |
| "description": "Circuit variable names" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Assignment weights" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Clique", | |
| "category": "graph", | |
| "description": "Find maximum weight clique in a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The underlying graph G=(V,E)" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Vertex weights w: V -> R" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "DominatingSet", | |
| "category": "graph", | |
| "description": "Find minimum weight dominating set in a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The underlying graph G=(V,E)" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Vertex weights w: V -> R" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Factoring", | |
| "category": "specialized", | |
| "description": "Factor a composite integer into two factors", | |
| "fields": [ | |
| { | |
| "name": "m", | |
| "type_name": "usize", | |
| "description": "Bits for first factor" | |
| }, | |
| { | |
| "name": "n", | |
| "type_name": "usize", | |
| "description": "Bits for second factor" | |
| }, | |
| { | |
| "name": "target", | |
| "type_name": "u64", | |
| "description": "Number to factor" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "ILP", | |
| "category": "optimization", | |
| "description": "Optimize linear objective subject to linear constraints", | |
| "fields": [ | |
| { | |
| "name": "num_vars", | |
| "type_name": "usize", | |
| "description": "Number of integer variables" | |
| }, | |
| { | |
| "name": "bounds", | |
| "type_name": "Vec<VarBounds>", | |
| "description": "Variable bounds" | |
| }, | |
| { | |
| "name": "constraints", | |
| "type_name": "Vec<LinearConstraint>", | |
| "description": "Linear constraints" | |
| }, | |
| { | |
| "name": "objective", | |
| "type_name": "Vec<(usize, f64)>", | |
| "description": "Sparse objective coefficients" | |
| }, | |
| { | |
| "name": "sense", | |
| "type_name": "ObjectiveSense", | |
| "description": "Optimization direction" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "IndependentSet", | |
| "category": "graph", | |
| "description": "Find maximum weight independent set in a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The underlying graph G=(V,E)" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Vertex weights w: V -> R" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "KColoring", | |
| "category": "graph", | |
| "description": "Find valid k-coloring of a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The underlying graph G=(V,E)" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "KSatisfiability", | |
| "category": "satisfiability", | |
| "description": "SAT with exactly k literals per clause", | |
| "fields": [ | |
| { | |
| "name": "num_vars", | |
| "type_name": "usize", | |
| "description": "Number of Boolean variables" | |
| }, | |
| { | |
| "name": "clauses", | |
| "type_name": "Vec<CNFClause>", | |
| "description": "Clauses each with exactly K literals" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Clause weights for MAX-K-SAT" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Matching", | |
| "category": "graph", | |
| "description": "Find maximum weight matching in a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The underlying graph G=(V,E)" | |
| }, | |
| { | |
| "name": "edge_weights", | |
| "type_name": "Vec<W>", | |
| "description": "Edge weights w: E -> R" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "MaxCut", | |
| "category": "graph", | |
| "description": "Find maximum weight cut in a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The graph with edge weights" | |
| }, | |
| { | |
| "name": "edge_weights", | |
| "type_name": "Vec<W>", | |
| "description": "Edge weights w: E -> R" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "MaximalIS", | |
| "category": "graph", | |
| "description": "Find maximum weight maximal independent set", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The underlying graph G=(V,E)" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Vertex weights w: V -> R" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "PaintShop", | |
| "category": "specialized", | |
| "description": "Minimize color changes in paint shop sequence", | |
| "fields": [ | |
| { | |
| "name": "sequence_indices", | |
| "type_name": "Vec<usize>", | |
| "description": "Car sequence as indices" | |
| }, | |
| { | |
| "name": "car_labels", | |
| "type_name": "Vec<String>", | |
| "description": "Unique car labels" | |
| }, | |
| { | |
| "name": "is_first", | |
| "type_name": "Vec<bool>", | |
| "description": "First occurrence flags" | |
| }, | |
| { | |
| "name": "num_cars", | |
| "type_name": "usize", | |
| "description": "Number of unique cars" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "QUBO", | |
| "category": "optimization", | |
| "description": "Minimize quadratic unconstrained binary objective", | |
| "fields": [ | |
| { | |
| "name": "num_vars", | |
| "type_name": "usize", | |
| "description": "Number of binary variables" | |
| }, | |
| { | |
| "name": "matrix", | |
| "type_name": "Vec<Vec<W>>", | |
| "description": "Upper-triangular Q matrix" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "Satisfiability", | |
| "category": "satisfiability", | |
| "description": "Find satisfying assignment for CNF formula", | |
| "fields": [ | |
| { | |
| "name": "num_vars", | |
| "type_name": "usize", | |
| "description": "Number of Boolean variables" | |
| }, | |
| { | |
| "name": "clauses", | |
| "type_name": "Vec<CNFClause>", | |
| "description": "Clauses in conjunctive normal form" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Clause weights for MAX-SAT" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "SetCovering", | |
| "category": "set", | |
| "description": "Find minimum weight collection covering the universe", | |
| "fields": [ | |
| { | |
| "name": "universe_size", | |
| "type_name": "usize", | |
| "description": "Size of the universe U" | |
| }, | |
| { | |
| "name": "sets", | |
| "type_name": "Vec<Vec<usize>>", | |
| "description": "Collection of subsets of U" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Weight for each set" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "SetPacking", | |
| "category": "set", | |
| "description": "Find maximum weight collection of disjoint sets", | |
| "fields": [ | |
| { | |
| "name": "sets", | |
| "type_name": "Vec<Vec<usize>>", | |
| "description": "Collection of sets over a universe" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Weight for each set" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "SpinGlass", | |
| "category": "optimization", | |
| "description": "Minimize Ising Hamiltonian on a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The interaction graph" | |
| }, | |
| { | |
| "name": "couplings", | |
| "type_name": "Vec<W>", | |
| "description": "Pairwise couplings J_ij" | |
| }, | |
| { | |
| "name": "fields", | |
| "type_name": "Vec<W>", | |
| "description": "On-site fields h_i" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "VertexCovering", | |
| "category": "graph", | |
| "description": "Find minimum weight vertex cover in a graph", | |
| "fields": [ | |
| { | |
| "name": "graph", | |
| "type_name": "G", | |
| "description": "The underlying graph G=(V,E)" | |
| }, | |
| { | |
| "name": "weights", | |
| "type_name": "Vec<W>", | |
| "description": "Vertex weights w: V -> R" | |
| } | |
| ] | |
| } | |
| ] |
Each node in the reduction graph JSON now includes a `doc_path` field pointing to the rustdoc struct page for that problem type. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Double-click a node to navigate to its rustdoc API page - Add paper download link - Add Problem Variants section with topology overview - Remove hardcoded Problem Categories table Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add chaining reductions and type safety sections from reductions/using.md. Update next steps links to point to interactive graph and API reference. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Makefile copies .claude/CLAUDE.md to docs/src/claude.md at build time - contributing.md links to CLAUDE.md for commands/architecture - Add docs/src/claude.md to .gitignore (auto-generated) Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Remove 11 hardcoded pages (problems/*, reductions/*, topology.md) - Update SUMMARY.md to 7-page structure - Add CLAUDE.md symlink for mdBook deployment - Fix API reference redirect URL - Remove copy command from Makefile (symlink replaces it) Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Add unit tests for registry/schema.rs (6 tests) and info.rs with_fields - Fix Typst prose for KColoring, MaxCut, Matching, SpinGlass to match actual struct fields from render-struct - Add fetch error handling in introduction.md interactive graph - Vendor cytoscape.min.js for offline docs (remove CDN dependency) - Pretty-print problem_schemas.json for readable diffs - Fix Makefile: add rm -rf before cp to prevent nesting, add rustdoc copy to mdbook target - Update docs.yml: add --all-features, generate graph/schemas/examples Co-Authored-By: Claude Opus 4.6 <[email protected]>
Summary
inventoryand exported toproblem_schemas.json. The typst document renders struct definitions from JSON via#render-struct().makecommands from README to.claude/CLAUDE.md.Test plan
make test— all 1528 tests passmake clippy— no warningsmake paper— PDF compiles with JSON-driven struct definitions, no diagrammake doc— mdBook builds with interactive Cytoscape.js diagrammdbook serve docs --open)Closes #33, closes #34
🤖 Generated with Claude Code