Skip to content

JSON schema export & interactive reduction diagram (#33, #34)#36

Merged
GiggleLiu merged 18 commits intomainfrom
feat/json-schema-interactive-viz
Feb 10, 2026
Merged

JSON schema export & interactive reduction diagram (#33, #34)#36
GiggleLiu merged 18 commits intomainfrom
feat/json-schema-interactive-viz

Conversation

@GiggleLiu
Copy link
Copy Markdown
Contributor

Summary

  • Issue Introduce JSON schema rather than the type definition in the typst document #33: Replace manually-maintained Rust struct code blocks in the typst paper with auto-generated JSON. Problem schemas are registered via inventory and exported to problem_schemas.json. The typst document renders struct definitions from JSON via #render-struct().
  • Issue Interactive visualization of the reduction diagram #34: Move the reduction diagram from the typst paper to an interactive Cytoscape.js visualization in mdBook. Supports pan/zoom, category-colored nodes, hover tooltips, and two-click shortest-path highlighting.
  • Move developer make commands from README to .claude/CLAUDE.md.

Test plan

  • make test — all 1528 tests pass
  • make clippy — no warnings
  • make paper — PDF compiles with JSON-driven struct definitions, no diagram
  • make doc — mdBook builds with interactive Cytoscape.js diagram
  • Verify interactive diagram in browser (mdbook serve docs --open)

Closes #33, closes #34

🤖 Generated with Claude Code

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.30%. Comparing base (dc2ccf1) to head (926b72d).
⚠️ Report is 1 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

GiggleLiu and others added 3 commits February 10, 2026 13:43
- 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]>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 to docs/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
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
cargo doc --all-features --no-deps
cargo doc --all-features --no-deps
cp -r target/doc docs/book/api

Copilot uses AI. Check for mistakes.
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">
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
<meta http-equiv="refresh" content="0; url=../api/problemreductions/index.html">
<script>
window.location.replace("../api/problemreductions/index.html");
</script>

Copilot uses AI. Check for mistakes.
```
#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.
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
Comment on lines +129 to 131
/// Struct field descriptions for schema export.
pub fields: &'static [FieldInfo],
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +18
let json = serde_json::to_string(&schemas).expect("Failed to serialize");
std::fs::write(output_path, &json).expect("Failed to write file");
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +52
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;
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
```
#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.
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
```
#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$.
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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$.

Copilot uses AI. Check for mistakes.
```
#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.
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
@@ -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
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
[{"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"
}
]
}
]

Copilot uses AI. Check for mistakes.
GiggleLiu and others added 8 commits February 10, 2026 14:37
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]>
- 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]>
@GiggleLiu GiggleLiu merged commit d6e82e3 into main Feb 10, 2026
5 checks passed
@GiggleLiu GiggleLiu deleted the feat/json-schema-interactive-viz branch April 12, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Interactive visualization of the reduction diagram Introduce JSON schema rather than the type definition in the typst document

2 participants