Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d468e49
Add CLI tool design document for `pred`
GiggleLiu Feb 17, 2026
1a6b364
Add CLI tool implementation plan for `pred`
GiggleLiu Feb 17, 2026
8e64b88
feat: scaffold problemreductions-cli crate with pred binary
GiggleLiu Feb 18, 2026
7ef0d74
feat(cli): add problem name resolver with aliases and variant parsing
GiggleLiu Feb 18, 2026
dcdf299
feat(cli): add output module for human/JSON output modes
GiggleLiu Feb 18, 2026
085fa90
feat(cli): add clap command hierarchy for all subcommands
GiggleLiu Feb 18, 2026
0d93358
feat(cli): implement 'pred graph list' command
GiggleLiu Feb 18, 2026
aa299c6
feat(cli): implement 'pred graph show' command
GiggleLiu Feb 18, 2026
4c1a461
feat(cli): implement 'pred graph path' command
GiggleLiu Feb 18, 2026
789e44d
feat(cli): implement 'pred schema' command
GiggleLiu Feb 18, 2026
da19c4b
build: add Makefile target for pred CLI tool
GiggleLiu Feb 18, 2026
74bdd1f
test(cli): add integration tests for graph and schema commands
GiggleLiu Feb 18, 2026
449dd0a
fix(cli): resolve clippy warnings in CLI crate
GiggleLiu Feb 18, 2026
dd15a75
new docs
GiggleLiu Feb 18, 2026
d4ca0d9
refactor(rules): replace ExecutablePath+ChainedReduction with Reducti…
GiggleLiu Feb 18, 2026
5614230
feat(cli): add DynProblem dispatch table for runtime problem loading
GiggleLiu Feb 18, 2026
693b859
feat(cli): implement 'pred evaluate' command
GiggleLiu Feb 18, 2026
ce56b70
feat(cli): implement 'pred reduce' command with full reduction bundle
GiggleLiu Feb 18, 2026
08f9d54
test(cli): add integration tests for evaluate and reduce commands
GiggleLiu Feb 18, 2026
c44b035
docs: document evaluate and reduce CLI commands
GiggleLiu Feb 18, 2026
823344d
update
GiggleLiu Feb 18, 2026
500dad4
update
GiggleLiu Feb 18, 2026
fd91f76
feat(cli): add solve command with ILP auto-reduction and configurable…
GiggleLiu Feb 18, 2026
784c0b5
polish CLI help messages and fix CI
GiggleLiu Feb 18, 2026
c949afd
feat(cli): implement --cost minimize:<field> and show size fields
GiggleLiu Feb 18, 2026
0ecc763
test(cli): add comprehensive tests for solve, create, and error cases
GiggleLiu Feb 18, 2026
b5997fa
chore: remove completed plan files
GiggleLiu Feb 18, 2026
618d1d0
docs: update CLI page to match actual command output
GiggleLiu Feb 18, 2026
458208a
ci: exclude CLI crate from codecov patch coverage
GiggleLiu Feb 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ See Key Patterns above for solver API signatures. Follow the reference files for

Unit tests in `src/unit_tests/` linked via `#[path]` (see Core Modules above). Integration tests in `tests/suites/`, consolidated through `tests/main.rs`. Example tests in `tests/suites/examples.rs` using `include!` for direct invocation.

## Documentation Locations
- `README.md` — Project overview and quickstart
- `.claude/` — Claude Code instructions and skills
- `docs/book/` — mdBook user documentation (built with `make doc`)
- `docs/paper/reductions.typ` — Typst paper with problem definitions and reduction theorems
- `examples/` — Reduction example code (also used in paper and tests)

## Documentation Requirements

**Reference:** search `docs/paper/reductions.typ` for `MinimumVertexCover` `MaximumIndependentSet` to see a complete problem-def + reduction-rule example.
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
components: clippy
- uses: Swatinem/rust-cache@v2
- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
run: cargo clippy --all-targets --features ilp-highs -- -D warnings

# Build and test
test:
Expand All @@ -34,13 +34,13 @@ jobs:
- uses: Swatinem/rust-cache@v2

- name: Build
run: cargo build --all-features --verbose
run: cargo build --features ilp-highs --verbose

- name: Run tests
run: cargo test --all-features --verbose
run: cargo test --features ilp-highs --verbose

- name: Run doc tests
run: cargo test --doc --all-features --verbose
run: cargo test --doc --features ilp-highs --verbose

# Code coverage
coverage:
Expand All @@ -55,7 +55,7 @@ jobs:
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate coverage
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
run: cargo llvm-cov --features ilp-highs --workspace --lcov --output-path lcov.info
- name: Upload to codecov.io
uses: codecov/codecov-action@v4
with:
Expand Down
15 changes: 11 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = [".", "problemreductions-macros"]
members = [".", "problemreductions-macros", "problemreductions-cli"]

[package]
name = "problemreductions"
Expand All @@ -12,8 +12,15 @@ keywords = ["np-hard", "optimization", "reduction", "sat", "graph"]
categories = ["algorithms", "science"]

[features]
default = ["ilp"]
ilp = ["good_lp"]
default = ["ilp-highs"]
ilp = ["ilp-highs"] # backward compat shorthand
ilp-solver = [] # marker: enables ILP solver code
ilp-highs = ["ilp-solver", "dep:good_lp", "good_lp/highs"]
ilp-coin-cbc = ["ilp-solver", "dep:good_lp", "good_lp/coin_cbc"]
ilp-clarabel = ["ilp-solver", "dep:good_lp", "good_lp/clarabel"]
ilp-scip = ["ilp-solver", "dep:good_lp", "good_lp/scip"]
ilp-lpsolve = ["ilp-solver", "dep:good_lp", "good_lp/lpsolve"]
ilp-microlp = ["ilp-solver", "dep:good_lp", "good_lp/microlp"]

[dependencies]
petgraph = { version = "0.8", features = ["serde-1"] }
Expand All @@ -22,7 +29,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "2.0"
num-traits = "0.2"
good_lp = { version = "1.8", default-features = false, features = ["highs"], optional = true }
good_lp = { version = "1.8", default-features = false, optional = true }
inventory = "0.3"
ordered-float = "5.0"
rand = "0.9"
Expand Down
23 changes: 14 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Makefile for problemreductions

.PHONY: help build test fmt clippy doc mdbook paper examples clean coverage rust-export compare qubo-testdata export-schemas release run-plan diagrams jl-testdata
.PHONY: help build test fmt clippy doc mdbook paper examples clean coverage rust-export compare qubo-testdata export-schemas release run-plan diagrams jl-testdata cli

# Default target
help:
Expand All @@ -24,15 +24,16 @@ help:
@echo " qubo-testdata - Regenerate QUBO test data (requires uv)"
@echo " jl-testdata - Regenerate Julia parity test data (requires julia)"
@echo " release V=x.y.z - Tag and push a new release (triggers CI publish)"
@echo " cli - Build the pred CLI tool"
@echo " run-plan - Execute a plan with Claude autorun (latest plan in docs/plans/)"

# Build the project
build:
cargo build --all-features
cargo build --features ilp-highs

# Run all tests (including ignored tests)
test:
cargo test --all-features -- --include-ignored
cargo test --features ilp-highs -- --include-ignored

# Format code
fmt:
Expand All @@ -44,14 +45,14 @@ fmt-check:

# Run clippy
clippy:
cargo clippy --all-targets --all-features -- -D warnings
cargo clippy --all-targets --features ilp-highs -- -D warnings

# Build mdBook documentation
doc:
cargo run --example export_graph
cargo run --example export_schemas
mdbook build docs
RUSTDOCFLAGS="--default-theme=dark" cargo doc --all-features --no-deps
RUSTDOCFLAGS="--default-theme=dark" cargo doc --features ilp-highs --no-deps
rm -rf docs/book/api
cp -r target/doc docs/book/api

Expand All @@ -70,7 +71,7 @@ diagrams:
mdbook:
cargo run --example export_graph
cargo run --example export_schemas
RUSTDOCFLAGS="--default-theme=dark" cargo doc --all-features --no-deps
RUSTDOCFLAGS="--default-theme=dark" cargo doc --features ilp-highs --no-deps
mdbook build
rm -rf book/api
cp -r target/doc book/api
Expand All @@ -85,9 +86,9 @@ examples:
@mkdir -p docs/paper/examples
@for example in $(REDUCTION_EXAMPLES); do \
echo "Running $$example..."; \
cargo run --all-features --example $$example || exit 1; \
cargo run --features ilp-highs --example $$example || exit 1; \
done
cargo run --all-features --example export_petersen_mapping
cargo run --features ilp-highs --example export_petersen_mapping

# Export problem schemas to JSON
export-schemas:
Expand All @@ -102,7 +103,7 @@ paper: examples
# Generate coverage report (requires: cargo install cargo-llvm-cov)
coverage:
@command -v cargo-llvm-cov >/dev/null 2>&1 || { echo "Installing cargo-llvm-cov..."; cargo install cargo-llvm-cov; }
cargo llvm-cov --all-features --workspace --html --open
cargo llvm-cov --features ilp-highs --workspace --html --open

# Clean build artifacts
clean:
Expand Down Expand Up @@ -135,6 +136,10 @@ endif
git push origin main --tags
@echo "v$(V) pushed — CI will publish to crates.io"

# Build the pred CLI tool
cli:
cargo build -p problemreductions-cli --release

# Generate Rust mapping JSON exports for all graphs and modes
GRAPHS := diamond bull house petersen
MODES := unweighted weighted triangular
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,32 @@ Download [PDF manual](https://codingthrust.github.io/problem-reductions/reductio

## Installation

### As a library

Add to your `Cargo.toml`:

```toml
[dependencies]
problemreductions = "0.2"
```

See the [Getting Started](https://codingthrust.github.io/problem-reductions/getting-started.html) guide for usage examples and the reduction workflow.
### CLI tool

Install the `pred` command-line tool for exploring the reduction graph from your terminal:

```bash
cargo install --git https://github.com/CodingThrust/problem-reductions problemreductions-cli
```

Or build from source:

```bash
git clone https://github.com/CodingThrust/problem-reductions
cd problem-reductions
make cli # builds target/release/pred
```

See the [Getting Started](https://codingthrust.github.io/problem-reductions/getting-started.html) guide for usage examples, the reduction workflow, and [CLI usage](https://codingthrust.github.io/problem-reductions/cli.html).

## Contributing

Expand Down
6 changes: 5 additions & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ coverage:
threshold: 2%

# Exclude proc-macro crate from coverage since it runs at compile time
# and traditional runtime coverage tools cannot measure it
# and traditional runtime coverage tools cannot measure it.
# Exclude CLI crate from patch coverage: it is a thin dispatch layer
# with many boilerplate type-dispatch match arms that are tested
# end-to-end via integration tests, not amenable to 95% line coverage.
ignore:
- "problemreductions-macros/**/*"
- "problemreductions-cli/**/*"
152 changes: 152 additions & 0 deletions docs/plans/2026-02-18-cli-tool-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# CLI Tool Design: `pred`

## Overview

A command-line tool for researchers and students to explore NP-hard problem reductions and solve problem instances without writing Rust code. Implemented as a separate workspace crate (`problemreductions-cli`), binary name `pred`.

## Audience

Researchers and students studying NP-hard reductions who want to explore and visualize without writing any Rust code.

## Command Structure

Subcommand-based CLI with two top-level groups: `graph` (exploration) and solve/reduce/evaluate (computation).

### Graph Exploration

```
pred graph list # List all registered problems
pred graph show <Problem> # Show problem details, variants, reductions
pred graph show MIS --variants # List all variants
pred graph path <Source> <Target> # Find cheapest reduction path
pred graph path MIS QUBO --cost minimize:num_vars # Custom cost function
pred graph export [--output path] # Export reduction_graph.json
```

### Computation

```
pred solve <input.json> --via <Target> # Reduce + solve + map solution back
pred solve --problem MIS --edges 0-1,1-2 --via QUBO # Inline input
pred reduce <input.json> --to <Target> # Reduce only, output target as JSON
pred evaluate <input.json> --config 1,0,1 # Evaluate a configuration
pred schema <Problem> # Show JSON schema for a problem type
```

### Global Flags

- `--json` — structured JSON output, saved to file (default filename derived from command)
- `--output <path>` — custom output file path (used with `--json`)
- `--help` / `-h` — per-command help

## Problem Name Resolution

Case-insensitive matching with common aliases:

| Input | Resolves to |
|-------|-------------|
| `MIS`, `mis` | `MaximumIndependentSet` |
| `MVC` | `MinimumVertexCover` |
| `SAT` | `Satisfiability` |
| `3SAT` | `KSatisfiability` (K=3) |
| `QUBO` | `QUBO` |
| `MaxCut` | `MaxCut` |

Unambiguous prefix matching: `MaximumI` → `MaximumIndependentSet`, but `Maximum` is rejected (ambiguous).

## Variant Syntax

Slash-based positional notation after the problem name. Order follows `Problem::variant()` key order. Partial specification fills from the left; no skipping.

```
MIS → defaults (SimpleGraph, One)
MIS/UnitDiskGraph → UnitDiskGraph, default weight
MIS/SimpleGraph/f64 → must spell out graph to set weight
KColoring/K3 → SimpleGraph, K=3
3SAT → alias for KSatisfiability/K3
QUBO → no variants
```

## Input Formats

### JSON Files

Reuses the library's existing serde serialization:

```json
{
"problem": "MaximumIndependentSet",
"graph": {"edges": [[0,1], [1,2], [2,0]], "num_vertices": 3},
"weights": [1, 1, 1]
}
```

### Inline Arguments

For simple cases without a JSON file:

```
pred solve --problem MIS --edges 0-1,1-2,2-0 --weights 1,1,1 --via QUBO
```

## Output

- **Human-readable (default):** plain text to stdout
- **`--json`:** structured JSON saved to file (default name derived from command, e.g., `pred_path_MIS_QUBO.json`)
- **`--json --output custom.json`:** custom output path
- **Errors:** always to stderr
- **Exit codes:** non-zero on any error

## Architecture

### Crate Layout

Separate workspace crate: `problemreductions-cli/`

```
src/
main.rs # Cli::parse(), dispatch to commands
cli.rs # Clap derive structs (Cli, Commands, GraphCommands)
commands/
graph.rs # list, show, path, export
solve.rs # reduce + solve + extract solution
reduce.rs # reduce only, output target problem
evaluate.rs # evaluate a config
schema.rs # show JSON schema for a problem type
output.rs # OutputMode enum, write_json_file(), print_human()
problem_name.rs # Alias resolution + variant parsing (slash notation)
```

### Dependencies

- `clap` (derive) — argument parsing
- `anyhow` — error handling
- `serde_json` — JSON I/O
- `problemreductions` — the library (all features)

### Dynamic Dispatch

- **Graph commands:** use `ReductionGraph` directly — already works with string names
- **Solve/reduce/evaluate:** dispatch table — a `match` over known problem names that constructs concrete types from JSON. ~20 match arms, one per problem type.

### Error Handling

`anyhow::Result` throughout, with `.context()` for actionable error messages. Non-zero exit code on any error.

## V1 Scope

### In scope

- `pred graph list`
- `pred graph show <Problem>` (with `--variants`)
- `pred graph path <Source> <Target>` (with `--cost`)
- `pred graph export`
- `pred solve` (JSON file and inline input, brute-force solver)
- `pred reduce` (reduce only)
- `pred evaluate`
- `pred schema`
- `--json` output to file

### Out of scope (v2+)

See GitHub issue for future plans.
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# User Guide

- [Getting Started](./getting-started.md)
- [CLI Tool](./cli.md)
- [Design](./design.md)

# Developer Guide
Expand Down
Loading