diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 182d874f..dbd7a3ae 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -49,7 +49,12 @@ make release V=x.y.z # Tag and push a new release (CI publishes to crates.io) ## Architecture ### Core Modules -- `src/models/` - Problem implementations (SAT, Graph, Set, Optimization) +- `src/models/` - Problem implementations organized by input structure: + - `graph/` - Problems on graphs (MIS, MaxClique, MaxCut, MinVC, MinDS, MaxMatching, MaximalIS, KColoring, TSP, SpinGlass, BicliqueCover) + - `formula/` - Logical formulas and circuits (SAT, k-SAT, CircuitSAT) + - `set/` - Set systems (MinSetCovering, MaxSetPacking) + - `algebraic/` - Matrices, linear systems, lattices (QUBO, ILP, CVP, BMF) + - `misc/` - Unique input structures (BinPacking, PaintShop, Factoring) - `src/rules/` - Reduction rules + inventory registration - `src/solvers/` - BruteForce solver, ILP solver (feature-gated) - `src/traits.rs` - `Problem`, `OptimizationProblem`, `SatisfactionProblem` traits @@ -140,7 +145,7 @@ Reduction graph nodes use variant key-value pairs from `Problem::variant()`: ### File Naming - Reduction files: `src/rules/_.rs` (e.g., `maximumindependentset_qubo.rs`) -- Model files: `src/models//.rs` (e.g., `maximum_independent_set.rs`) +- Model files: `src/models//.rs` — category is by input structure: `graph/` (graph input), `formula/` (boolean formula/circuit), `set/` (universe + subsets), `algebraic/` (matrix/linear system/lattice), `misc/` (other) - Example files: `examples/reduction__to_.rs` (must have `pub fn run()` + `fn main() { run() }`) - Test naming: `test__to__closed_loop` diff --git a/README.md b/README.md index 71ed753e..a72c953f 100644 --- a/README.md +++ b/README.md @@ -63,31 +63,20 @@ See the [MCP documentation](https://codingthrust.github.io/problem-reductions/mc ## Contributing -### Authorship Recognition +**No programming experience required.** You contribute domain knowledge; we handle the implementation. -**Contribute 10 non-trivial reduction rules and you will be automatically added to the author list of the paper.** AI tools handle the implementation — contributors focus on designing correct reductions and test cases. +1. **File an issue** — use the [Problem](https://github.com/CodingThrust/problem-reductions/issues/new?template=problem.md) or [Rule](https://github.com/CodingThrust/problem-reductions/issues/new?template=rule.md) template. Describe the problem or reduction you have in mind — the template guides you through the details. +2. **We implement it** — for reasonable requests, maintainers tag the issue `implement` and AI agents generate a tested implementation. +3. **We present it to you** — all issue contributors are invited to community calls (via [Zulip](https://problem-reductions.zulipchat.com/)), where maintainers walk through the implementation — documentation, CLI behavior, correctness — and you provide feedback. -### How to Contribute +**Authorship:** contribute 10 non-trivial reduction rules and you'll be added to the author list of the [paper](https://codingthrust.github.io/problem-reductions/reductions.pdf). -1. **Open an issue** using the [Problem](https://github.com/CodingThrust/problem-reductions/issues/new?template=problem.md) or [Rule](https://github.com/CodingThrust/problem-reductions/issues/new?template=rule.md) template. Fill in all sections — the templates guide you through the required information (definition, algorithm, size overhead, example instance, etc.). +> **Tip:** If you use Claude Code / OpenCode / Codex, you can file issues interactively: +> ``` +> File an issue on CodingThrust/problem-reductions, using the "Model" issue template, about the Closest Vector Problem. Brainstorm with me. +> ``` - **Hint:** If you use Claude Code / OpenCode / Codex (assume `gh` CLI tool and `superpowers` plugin are installed), you can just type: - ``` - File an issue on CodingThrust/problem-reductions, using the "Model" issue template, about the Closest Vector Problem. Brainstorm with me. - ``` - ``` - File an issue on CodingThrust/problem-reductions, using the "Rule" issue template, about reduction from Closest Vector Problem to QUBO. Brainstorm with me. - ``` - Then AI agents will guide you to fill in the issue template. - -2. Our AI agents will pick up the issue and generate a plan to implement the reduction rule. -3. You will be mentioned in the pull request, provide feedback to the AI agents. If you are satisfied with the plan, you can merge the PR. - -Optionally, if you prefer to **implement yourself**, I will recommend you to use the [superpowers:brainstorming](https://github.com/obra/superpowers) skill to help you write a detailed plan. Create a PR and let maintainers help review and merge the PR. - -### Developer Commands - -Run `make help` to see all available targets. See [CLAUDE.md](https://codingthrust.github.io/problem-reductions/claude.html) for the full command list and architecture details. +If you prefer to **implement yourself**, see the [Design](https://codingthrust.github.io/problem-reductions/design.html) guide. Run `make help` to see available developer commands. ## Acknowledgments diff --git a/benches/solver_benchmarks.rs b/benches/solver_benchmarks.rs index c77d7bbf..0ee082fc 100644 --- a/benches/solver_benchmarks.rs +++ b/benches/solver_benchmarks.rs @@ -1,11 +1,10 @@ //! Benchmarks for the BruteForce solver on various problem types. use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use problemreductions::models::formula::*; use problemreductions::models::graph::*; -use problemreductions::models::optimization::*; -use problemreductions::models::satisfiability::*; +use problemreductions::models::misc::*; use problemreductions::models::set::*; -use problemreductions::models::specialized::*; use problemreductions::prelude::*; use problemreductions::topology::SimpleGraph; use problemreductions::variant::K3; diff --git a/docs/plans/2026-03-01-problem-categorization-design.md b/docs/plans/2026-03-01-problem-categorization-design.md new file mode 100644 index 00000000..4db0704f --- /dev/null +++ b/docs/plans/2026-03-01-problem-categorization-design.md @@ -0,0 +1,84 @@ +# Problem Categorization Redesign + +## Problem + +The current categorization mixes two axes: +- **Input structure** (graph, set system, formula) +- **Problem type** (optimization vs satisfaction) + +This creates ambiguity: MIS is both a graph problem and an optimization problem. QUBO is on a matrix but lives in `optimization/`. CircuitSAT is a satisfiability problem but lives in `specialized/`. The `specialized/` folder is a catch-all with no unifying principle. + +## Design + +**Single axis: primary input structure** — "what data type does the problem operate on?" + +The optimization/satisfaction distinction is already captured by the trait hierarchy (`OptimizationProblem` vs `SatisfactionProblem`), so folders should not duplicate it. + +### New folder structure + +``` +src/models/ +├── graph/ # Input: a graph (optionally weighted) +│ ├── maximum_independent_set.rs +│ ├── maximum_clique.rs +│ ├── max_cut.rs +│ ├── maximum_matching.rs +│ ├── minimum_vertex_cover.rs +│ ├── minimum_dominating_set.rs +│ ├── maximal_is.rs +│ ├── kcoloring.rs +│ ├── traveling_salesman.rs +│ ├── spin_glass.rs ← from optimization/ +│ └── biclique_cover.rs ← from specialized/ +│ +├── formula/ # Input: a logical formula or circuit +│ ├── sat.rs +│ ├── ksat.rs +│ └── circuit.rs ← from specialized/ +│ +├── set/ # Input: universe + collection of subsets +│ ├── minimum_set_covering.rs +│ └── maximum_set_packing.rs +│ +├── algebraic/ # Input: matrix, linear system, or lattice +│ ├── qubo.rs ← from optimization/ +│ ├── ilp.rs ← from optimization/ +│ ├── closest_vector_problem.rs ← from optimization/ +│ └── bmf.rs ← from specialized/ +│ +└── misc/ # Problems with unique input structures + ├── bin_packing.rs ← from optimization/ + ├── paintshop.rs ← from specialized/ + └── factoring.rs ← from specialized/ +``` + +### Decision rule for new problems + +> "What is the primary data structure in the struct definition?" +> - Graph → `graph/` +> - Boolean formula or circuit → `formula/` +> - Universe + subsets → `set/` +> - Matrix, linear system, or lattice → `algebraic/` +> - None of the above → `misc/` + +### What moves + +| Problem | From | To | Reason | +|---|---|---|---| +| SpinGlass | optimization/ | graph/ | Parameterized by G, operates on graph edges | +| BicliqueCover | specialized/ | graph/ | Input is a BipartiteGraph | +| CircuitSAT | specialized/ | formula/ | Input is a boolean circuit | +| QUBO | optimization/ | algebraic/ | Input is a Q matrix (no graph param) | +| ILP | optimization/ | algebraic/ | Input is constraint matrix + objective | +| CVP | optimization/ | algebraic/ | Input is lattice basis matrix | +| BMF | specialized/ | algebraic/ | Input is a boolean matrix | +| BinPacking | optimization/ | misc/ | Input is items + capacity | +| PaintShop | specialized/ | misc/ | Input is a car sequence | +| Factoring | specialized/ | misc/ | Input is an integer | + +### What doesn't change + +- Trait hierarchy (`OptimizationProblem`, `SatisfactionProblem`) +- All public API, type names, re-exports +- Only `mod.rs` files, `use` paths, and `#[path]` test references change +- The `optimization/` and `specialized/` folders are eliminated diff --git a/docs/src/design.md b/docs/src/design.md index ef8ce6e8..dd2d7593 100644 --- a/docs/src/design.md +++ b/docs/src/design.md @@ -17,7 +17,7 @@ This guide covers the library internals for contributors. | Module | Purpose | |--------|---------| -| [`src/models/`](#problem-model) | Problem type implementations (SAT, Graph, Set, Optimization) | +| [`src/models/`](#problem-model) | Problem implementations by input structure: `graph/`, `formula/`, `set/`, `algebraic/`, `misc/` | | [`src/rules/`](#reduction-rules) | Reduction rules with `ReduceTo` implementations | | [`src/registry/`](#reduction-graph) | Reduction graph metadata (collected via `inventory`) | | [`src/solvers/`](#solvers) | BruteForce and ILP solvers | diff --git a/docs/src/getting-started.md b/docs/src/getting-started.md index 49e502b5..9ba6ef3a 100644 --- a/docs/src/getting-started.md +++ b/docs/src/getting-started.md @@ -39,7 +39,7 @@ A path graph `0–1–2–3` has 4 vertices and 3 edges. ```rust,ignore use problemreductions::prelude::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::solvers::ILPSolver; use problemreductions::topology::SimpleGraph; diff --git a/docs/src/introduction.md b/docs/src/introduction.md index 42b49d4e..753a3a8f 100644 --- a/docs/src/introduction.md +++ b/docs/src/introduction.md @@ -14,10 +14,10 @@
Graph + Formula Set - Optimization - Satisfiability - Specialized + Algebraic + Misc Variant Cast
@@ -62,14 +62,17 @@ This library is the foundation of that effort: an open-source, extensible reduct ## Call for Contributions -> **Everyone can contribute — no programming experience required.** If you know a computational problem or a reduction rule, just describe it in a GitHub issue. AI will generate a tested pull request for you to review. -> -> **Contribute 10 non-trivial reduction rules and you will be automatically added to the author list of the [paper](https://codingthrust.github.io/problem-reductions/reductions.pdf).** +> **No programming experience required.** You contribute domain knowledge — we handle the implementation. -1. **Open an issue** using the [Problem](https://github.com/CodingThrust/problem-reductions/issues/new?template=problem.md) or [Rule](https://github.com/CodingThrust/problem-reductions/issues/new?template=rule.md) template -2. **Fill in all sections** — definition, algorithm, size overhead, example instance -3. **Review AI-generated code** — AI generates code and you can comment on the pull request -4. **Merge** — ask maintainers' assistance to merge once you are satisfied +### How it works + +1. **File an issue** — use the [Problem](https://github.com/CodingThrust/problem-reductions/issues/new?template=problem.md) or [Rule](https://github.com/CodingThrust/problem-reductions/issues/new?template=rule.md) template. Describe the problem or reduction you have in mind; the template guides you through the details. +2. **We implement it** — for reasonable requests, maintainers tag the issue `implement` and AI agents generate a tested implementation. +3. **We present it to you** — all issue contributors are invited to community calls (via [Zulip](https://problem-reductions.zulipchat.com/)), where maintainers walk through the implementation — documentation, CLI behavior, correctness — and you provide feedback. + +### Authorship + +Contribute 10 non-trivial reduction rules and you'll be added to the author list of the [paper](https://codingthrust.github.io/problem-reductions/reductions.pdf). For manual implementation, see the [Design](./design.md#contributing) guide. diff --git a/docs/src/reductions/reduction_graph.json b/docs/src/reductions/reduction_graph.json index 9cf34c21..0b0c6850 100644 --- a/docs/src/reductions/reduction_graph.json +++ b/docs/src/reductions/reduction_graph.json @@ -3,15 +3,15 @@ { "name": "BMF", "variant": {}, - "category": "specialized", - "doc_path": "models/specialized/struct.BMF.html", + "category": "algebraic", + "doc_path": "models/algebraic/struct.BMF.html", "complexity": "2^(rows * rank + rank * cols)" }, { "name": "BicliqueCover", "variant": {}, - "category": "specialized", - "doc_path": "models/specialized/struct.BicliqueCover.html", + "category": "graph", + "doc_path": "models/graph/struct.BicliqueCover.html", "complexity": "2^num_vertices" }, { @@ -19,8 +19,8 @@ "variant": { "weight": "f64" }, - "category": "optimization", - "doc_path": "models/optimization/struct.BinPacking.html", + "category": "misc", + "doc_path": "models/misc/struct.BinPacking.html", "complexity": "2^num_items" }, { @@ -28,15 +28,15 @@ "variant": { "weight": "i32" }, - "category": "optimization", - "doc_path": "models/optimization/struct.BinPacking.html", + "category": "misc", + "doc_path": "models/misc/struct.BinPacking.html", "complexity": "2^num_items" }, { "name": "CircuitSAT", "variant": {}, - "category": "specialized", - "doc_path": "models/specialized/struct.CircuitSAT.html", + "category": "formula", + "doc_path": "models/formula/struct.CircuitSAT.html", "complexity": "2^num_variables" }, { @@ -44,8 +44,8 @@ "variant": { "weight": "f64" }, - "category": "optimization", - "doc_path": "models/optimization/struct.ClosestVectorProblem.html", + "category": "algebraic", + "doc_path": "models/algebraic/struct.ClosestVectorProblem.html", "complexity": "2^num_basis_vectors" }, { @@ -53,22 +53,22 @@ "variant": { "weight": "i32" }, - "category": "optimization", - "doc_path": "models/optimization/struct.ClosestVectorProblem.html", + "category": "algebraic", + "doc_path": "models/algebraic/struct.ClosestVectorProblem.html", "complexity": "2^num_basis_vectors" }, { "name": "Factoring", "variant": {}, - "category": "specialized", - "doc_path": "models/specialized/struct.Factoring.html", + "category": "misc", + "doc_path": "models/misc/struct.Factoring.html", "complexity": "exp((m + n)^(1/3) * log(m + n)^(2/3))" }, { "name": "ILP", "variant": {}, - "category": "optimization", - "doc_path": "models/optimization/struct.ILP.html", + "category": "algebraic", + "doc_path": "models/algebraic/struct.ILP.html", "complexity": "num_variables^num_variables" }, { @@ -126,8 +126,8 @@ "variant": { "k": "K2" }, - "category": "satisfiability", - "doc_path": "models/satisfiability/struct.KSatisfiability.html", + "category": "formula", + "doc_path": "models/formula/struct.KSatisfiability.html", "complexity": "num_variables + num_clauses" }, { @@ -135,8 +135,8 @@ "variant": { "k": "K3" }, - "category": "satisfiability", - "doc_path": "models/satisfiability/struct.KSatisfiability.html", + "category": "formula", + "doc_path": "models/formula/struct.KSatisfiability.html", "complexity": "1.307^num_variables" }, { @@ -144,8 +144,8 @@ "variant": { "k": "KN" }, - "category": "satisfiability", - "doc_path": "models/satisfiability/struct.KSatisfiability.html", + "category": "formula", + "doc_path": "models/formula/struct.KSatisfiability.html", "complexity": "2^num_variables" }, { @@ -317,8 +317,8 @@ { "name": "PaintShop", "variant": {}, - "category": "specialized", - "doc_path": "models/specialized/struct.PaintShop.html", + "category": "misc", + "doc_path": "models/misc/struct.PaintShop.html", "complexity": "2^num_cars" }, { @@ -326,15 +326,15 @@ "variant": { "weight": "f64" }, - "category": "optimization", - "doc_path": "models/optimization/struct.QUBO.html", + "category": "algebraic", + "doc_path": "models/algebraic/struct.QUBO.html", "complexity": "2^num_vars" }, { "name": "Satisfiability", "variant": {}, - "category": "satisfiability", - "doc_path": "models/satisfiability/struct.Satisfiability.html", + "category": "formula", + "doc_path": "models/formula/struct.Satisfiability.html", "complexity": "2^num_variables" }, { @@ -343,8 +343,8 @@ "graph": "SimpleGraph", "weight": "f64" }, - "category": "optimization", - "doc_path": "models/optimization/struct.SpinGlass.html", + "category": "graph", + "doc_path": "models/graph/struct.SpinGlass.html", "complexity": "2^num_spins" }, { @@ -353,8 +353,8 @@ "graph": "SimpleGraph", "weight": "i32" }, - "category": "optimization", - "doc_path": "models/optimization/struct.SpinGlass.html", + "category": "graph", + "doc_path": "models/graph/struct.SpinGlass.html", "complexity": "2^num_spins" }, { diff --git a/docs/src/static/reduction-graph.js b/docs/src/static/reduction-graph.js index 76c15a17..c497f681 100644 --- a/docs/src/static/reduction-graph.js +++ b/docs/src/static/reduction-graph.js @@ -14,12 +14,12 @@ document.addEventListener('DOMContentLoaded', function() { } var categoryColors = { - graph: '#c8f0c8', set: '#f0c8c8', optimization: '#f0f0a0', - satisfiability: '#c8c8f0', specialized: '#f0c8e0' + graph: '#c8f0c8', set: '#f0c8c8', algebraic: '#f0f0a0', + formula: '#c8c8f0', misc: '#f0c8e0' }; var categoryBorders = { - graph: '#4a8c4a', set: '#8c4a4a', optimization: '#8c8c4a', - satisfiability: '#4a4a8c', specialized: '#8c4a6a' + graph: '#4a8c4a', set: '#8c4a4a', algebraic: '#8c8c4a', + formula: '#4a4a8c', misc: '#8c4a6a' }; function variantId(name, variant) { diff --git a/examples/reduction_circuitsat_to_ilp.rs b/examples/reduction_circuitsat_to_ilp.rs index a5415087..4bbc42d4 100644 --- a/examples/reduction_circuitsat_to_ilp.rs +++ b/examples/reduction_circuitsat_to_ilp.rs @@ -23,8 +23,8 @@ // ``` use problemreductions::export::*; -use problemreductions::models::optimization::ILP; -use problemreductions::models::specialized::{Assignment, BooleanExpr, Circuit}; +use problemreductions::models::algebraic::ILP; +use problemreductions::models::formula::{Assignment, BooleanExpr, Circuit}; use problemreductions::prelude::*; pub fn run() { diff --git a/examples/reduction_circuitsat_to_spinglass.rs b/examples/reduction_circuitsat_to_spinglass.rs index 9e9675d4..7d986cd0 100644 --- a/examples/reduction_circuitsat_to_spinglass.rs +++ b/examples/reduction_circuitsat_to_spinglass.rs @@ -17,7 +17,7 @@ // Exports `docs/paper/examples/circuitsat_to_spinglass.json` and `circuitsat_to_spinglass.result.json`. use problemreductions::export::*; -use problemreductions::models::specialized::{Assignment, BooleanExpr, Circuit}; +use problemreductions::models::formula::{Assignment, BooleanExpr, Circuit}; use problemreductions::prelude::*; use problemreductions::topology::{Graph, SimpleGraph}; diff --git a/examples/reduction_factoring_to_circuitsat.rs b/examples/reduction_factoring_to_circuitsat.rs index 22a3651c..7083d46c 100644 --- a/examples/reduction_factoring_to_circuitsat.rs +++ b/examples/reduction_factoring_to_circuitsat.rs @@ -19,7 +19,7 @@ // Exports `docs/paper/examples/factoring_to_circuitsat.json` and `factoring_to_circuitsat.result.json`. use problemreductions::export::*; -use problemreductions::models::specialized::Circuit; +use problemreductions::models::formula::Circuit; use problemreductions::prelude::*; use std::collections::HashMap; diff --git a/examples/reduction_factoring_to_ilp.rs b/examples/reduction_factoring_to_ilp.rs index a9bf1fc0..1f0013ab 100644 --- a/examples/reduction_factoring_to_ilp.rs +++ b/examples/reduction_factoring_to_ilp.rs @@ -18,7 +18,7 @@ // Exports `docs/paper/examples/factoring_to_ilp.json` for use in paper code blocks. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::solvers::ILPSolver; diff --git a/examples/reduction_ilp_to_qubo.rs b/examples/reduction_ilp_to_qubo.rs index 2c2ff115..804cef94 100644 --- a/examples/reduction_ilp_to_qubo.rs +++ b/examples/reduction_ilp_to_qubo.rs @@ -36,7 +36,7 @@ // ``` use problemreductions::export::*; -use problemreductions::models::optimization::{LinearConstraint, ObjectiveSense, ILP}; +use problemreductions::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; use problemreductions::prelude::*; pub fn run() { diff --git a/examples/reduction_kcoloring_to_ilp.rs b/examples/reduction_kcoloring_to_ilp.rs index b52fac60..d287f0aa 100644 --- a/examples/reduction_kcoloring_to_ilp.rs +++ b/examples/reduction_kcoloring_to_ilp.rs @@ -16,7 +16,7 @@ // Exports `docs/paper/examples/kcoloring_to_ilp.json` and `kcoloring_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::solvers::ILPSolver; use problemreductions::topology::small_graphs::petersen; diff --git a/examples/reduction_maximumclique_to_ilp.rs b/examples/reduction_maximumclique_to_ilp.rs index 978eddc2..1785c242 100644 --- a/examples/reduction_maximumclique_to_ilp.rs +++ b/examples/reduction_maximumclique_to_ilp.rs @@ -15,7 +15,7 @@ // Exports `docs/paper/examples/maximumclique_to_ilp.json` and `maximumclique_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::topology::small_graphs::octahedral; use problemreductions::topology::{Graph, SimpleGraph}; diff --git a/examples/reduction_maximumindependentset_to_ilp.rs b/examples/reduction_maximumindependentset_to_ilp.rs index babac97a..cb66e151 100644 --- a/examples/reduction_maximumindependentset_to_ilp.rs +++ b/examples/reduction_maximumindependentset_to_ilp.rs @@ -14,7 +14,7 @@ // Exports `docs/paper/examples/maximumindependentset_to_ilp.json` and `maximumindependentset_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::topology::small_graphs::petersen; use problemreductions::topology::{Graph, SimpleGraph}; diff --git a/examples/reduction_maximummatching_to_ilp.rs b/examples/reduction_maximummatching_to_ilp.rs index 2c6ca348..ec482e64 100644 --- a/examples/reduction_maximummatching_to_ilp.rs +++ b/examples/reduction_maximummatching_to_ilp.rs @@ -14,7 +14,7 @@ // Exports `docs/paper/examples/maximummatching_to_ilp.json` and `maximummatching_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::topology::small_graphs::petersen; use problemreductions::topology::{Graph, SimpleGraph}; diff --git a/examples/reduction_maximumsetpacking_to_ilp.rs b/examples/reduction_maximumsetpacking_to_ilp.rs index 5e6ce4b7..86faf44e 100644 --- a/examples/reduction_maximumsetpacking_to_ilp.rs +++ b/examples/reduction_maximumsetpacking_to_ilp.rs @@ -15,7 +15,7 @@ // Exports `docs/paper/examples/maximumsetpacking_to_ilp.json` and `maximumsetpacking_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; pub fn run() { diff --git a/examples/reduction_minimumdominatingset_to_ilp.rs b/examples/reduction_minimumdominatingset_to_ilp.rs index 57aa18e6..959ec4e3 100644 --- a/examples/reduction_minimumdominatingset_to_ilp.rs +++ b/examples/reduction_minimumdominatingset_to_ilp.rs @@ -14,7 +14,7 @@ // Exports `docs/paper/examples/minimumdominatingset_to_ilp.json` and `minimumdominatingset_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::topology::small_graphs::petersen; use problemreductions::topology::{Graph, SimpleGraph}; diff --git a/examples/reduction_minimumsetcovering_to_ilp.rs b/examples/reduction_minimumsetcovering_to_ilp.rs index f7b28fa2..ba514c62 100644 --- a/examples/reduction_minimumsetcovering_to_ilp.rs +++ b/examples/reduction_minimumsetcovering_to_ilp.rs @@ -15,7 +15,7 @@ // Exports `docs/paper/examples/minimumsetcovering_to_ilp.json` and `minimumsetcovering_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; pub fn run() { diff --git a/examples/reduction_minimumvertexcover_to_ilp.rs b/examples/reduction_minimumvertexcover_to_ilp.rs index af6a212e..6e674008 100644 --- a/examples/reduction_minimumvertexcover_to_ilp.rs +++ b/examples/reduction_minimumvertexcover_to_ilp.rs @@ -14,7 +14,7 @@ // Exports `docs/paper/examples/minimumvertexcover_to_ilp.json` and `minimumvertexcover_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::topology::small_graphs::petersen; use problemreductions::topology::{Graph, SimpleGraph}; diff --git a/examples/reduction_qubo_to_ilp.rs b/examples/reduction_qubo_to_ilp.rs index 2dcaaa86..0ab13ced 100644 --- a/examples/reduction_qubo_to_ilp.rs +++ b/examples/reduction_qubo_to_ilp.rs @@ -26,7 +26,7 @@ // ``` use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; pub fn run() { diff --git a/examples/reduction_travelingsalesman_to_ilp.rs b/examples/reduction_travelingsalesman_to_ilp.rs index 28b629ba..b0ce59bf 100644 --- a/examples/reduction_travelingsalesman_to_ilp.rs +++ b/examples/reduction_travelingsalesman_to_ilp.rs @@ -15,7 +15,7 @@ // Exports `docs/paper/examples/travelingsalesman_to_ilp.json` and `travelingsalesman_to_ilp.result.json`. use problemreductions::export::*; -use problemreductions::models::optimization::ILP; +use problemreductions::models::algebraic::ILP; use problemreductions::prelude::*; use problemreductions::solvers::ILPSolver; use problemreductions::topology::{Graph, SimpleGraph}; diff --git a/problemreductions-cli/src/dispatch.rs b/problemreductions-cli/src/dispatch.rs index 877ffb2d..a6b0011f 100644 --- a/problemreductions-cli/src/dispatch.rs +++ b/problemreductions-cli/src/dispatch.rs @@ -1,5 +1,6 @@ use anyhow::{bail, Context, Result}; -use problemreductions::models::optimization::{BinPacking, ClosestVectorProblem, ILP}; +use problemreductions::models::algebraic::{ClosestVectorProblem, ILP}; +use problemreductions::models::misc::BinPacking; use problemreductions::prelude::*; use problemreductions::rules::{MinimizeSteps, ReductionGraph}; use problemreductions::solvers::{BruteForce, ILPSolver, Solver}; diff --git a/problemreductions-cli/src/mcp/tools.rs b/problemreductions-cli/src/mcp/tools.rs index 89d45627..f7a94026 100644 --- a/problemreductions-cli/src/mcp/tools.rs +++ b/problemreductions-cli/src/mcp/tools.rs @@ -1,11 +1,11 @@ use crate::util; +use problemreductions::models::algebraic::QUBO; +use problemreductions::models::formula::{CNFClause, Satisfiability}; use problemreductions::models::graph::{ MaxCut, MaximumClique, MaximumIndependentSet, MaximumMatching, MinimumDominatingSet, - MinimumVertexCover, TravelingSalesman, + MinimumVertexCover, SpinGlass, TravelingSalesman, }; -use problemreductions::models::optimization::{SpinGlass, QUBO}; -use problemreductions::models::satisfiability::{CNFClause, Satisfiability}; -use problemreductions::models::specialized::Factoring; +use problemreductions::models::misc::Factoring; use problemreductions::registry::collect_schemas; use problemreductions::rules::{ CustomCost, MinimizeSteps, ReductionGraph, ReductionPath, TraversalDirection, diff --git a/src/lib.rs b/src/lib.rs index 33ca9c45..ef67ab53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ //! //! | Module | Purpose | //! |--------|---------| -//! | [`models`] | Problem types — [`graph`](models::graph), [`satisfiability`](models::satisfiability), [`set`](models::set), [`optimization`](models::optimization), [`specialized`](models::specialized) | +//! | [`models`] | Problem types — [`graph`](models::graph), [`formula`](models::formula), [`set`](models::set), [`algebraic`](models::algebraic), [`misc`](models::misc) | //! | [`rules`] | Reduction rules, [`ReductionGraph`](rules::ReductionGraph) for path search | //! | [`solvers`] | [`BruteForce`] and [`ILPSolver`](solvers::ILPSolver) | //! | [`topology`] | Graph types — [`SimpleGraph`](topology::SimpleGraph), [`HyperGraph`](topology::HyperGraph), [`UnitDiskGraph`](topology::UnitDiskGraph), etc. | @@ -36,14 +36,15 @@ pub mod variant; /// Prelude module for convenient imports. pub mod prelude { // Problem types + pub use crate::models::algebraic::{BMF, QUBO}; + pub use crate::models::formula::{CNFClause, CircuitSAT, KSatisfiability, Satisfiability}; + pub use crate::models::graph::{BicliqueCover, SpinGlass}; pub use crate::models::graph::{ KColoring, MaxCut, MaximalIS, MaximumClique, MaximumIndependentSet, MaximumMatching, MinimumDominatingSet, MinimumVertexCover, TravelingSalesman, }; - pub use crate::models::optimization::{SpinGlass, QUBO}; - pub use crate::models::satisfiability::{CNFClause, KSatisfiability, Satisfiability}; + pub use crate::models::misc::{BinPacking, Factoring, PaintShop}; pub use crate::models::set::{MaximumSetPacking, MinimumSetCovering}; - pub use crate::models::specialized::{BicliqueCover, CircuitSAT, Factoring, PaintShop, BMF}; // Core traits pub use crate::rules::{ReduceTo, ReductionResult}; diff --git a/src/models/specialized/bmf.rs b/src/models/algebraic/bmf.rs similarity index 98% rename from src/models/specialized/bmf.rs rename to src/models/algebraic/bmf.rs index a7426044..552f82cc 100644 --- a/src/models/specialized/bmf.rs +++ b/src/models/algebraic/bmf.rs @@ -34,7 +34,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::specialized::BMF; +/// use problemreductions::models::algebraic::BMF; /// use problemreductions::{Problem, Solver, BruteForce}; /// /// // 2x2 identity matrix @@ -235,5 +235,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/specialized/bmf.rs"] +#[path = "../../unit_tests/models/algebraic/bmf.rs"] mod tests; diff --git a/src/models/optimization/closest_vector_problem.rs b/src/models/algebraic/closest_vector_problem.rs similarity index 97% rename from src/models/optimization/closest_vector_problem.rs rename to src/models/algebraic/closest_vector_problem.rs index e8883cd6..fe5d69c4 100644 --- a/src/models/optimization/closest_vector_problem.rs +++ b/src/models/algebraic/closest_vector_problem.rs @@ -3,7 +3,7 @@ //! Given a lattice basis B and target vector t, find integer coefficients x //! minimizing ‖Bx - t‖₂. -use crate::models::optimization::VarBounds; +use crate::models::algebraic::VarBounds; use crate::registry::{FieldInfo, ProblemSchemaEntry}; use crate::traits::{OptimizationProblem, Problem}; use crate::types::{Direction, SolutionSize}; @@ -178,5 +178,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/optimization/closest_vector_problem.rs"] +#[path = "../../unit_tests/models/algebraic/closest_vector_problem.rs"] mod tests; diff --git a/src/models/optimization/ilp.rs b/src/models/algebraic/ilp.rs similarity index 98% rename from src/models/optimization/ilp.rs rename to src/models/algebraic/ilp.rs index cd538789..fe2c31f6 100644 --- a/src/models/optimization/ilp.rs +++ b/src/models/algebraic/ilp.rs @@ -195,7 +195,7 @@ pub enum ObjectiveSense { /// # Example /// /// ``` -/// use problemreductions::models::optimization::{ILP, VarBounds, Comparison, LinearConstraint, ObjectiveSense}; +/// use problemreductions::models::algebraic::{ILP, VarBounds, Comparison, LinearConstraint, ObjectiveSense}; /// use problemreductions::Problem; /// /// // Create a simple ILP: maximize x0 + 2*x1 @@ -381,5 +381,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/optimization/ilp.rs"] +#[path = "../../unit_tests/models/algebraic/ilp.rs"] mod tests; diff --git a/src/models/optimization/mod.rs b/src/models/algebraic/mod.rs similarity index 59% rename from src/models/optimization/mod.rs rename to src/models/algebraic/mod.rs index b4feffe0..71964f28 100644 --- a/src/models/optimization/mod.rs +++ b/src/models/algebraic/mod.rs @@ -1,20 +1,17 @@ -//! Optimization problems. +//! Algebraic problems. //! -//! This module contains optimization problems: -//! - [`BinPacking`]: Bin Packing (minimize bins) -//! - [`ClosestVectorProblem`]: Closest Vector Problem (minimize lattice distance) -//! - [`SpinGlass`]: Ising model Hamiltonian +//! Problems whose input is a matrix, linear system, or lattice: //! - [`QUBO`]: Quadratic Unconstrained Binary Optimization //! - [`ILP`]: Integer Linear Programming +//! - [`ClosestVectorProblem`]: Closest Vector Problem (minimize lattice distance) +//! - [`BMF`]: Boolean Matrix Factorization -mod bin_packing; +pub(crate) mod bmf; mod closest_vector_problem; mod ilp; mod qubo; -mod spin_glass; -pub use bin_packing::BinPacking; +pub use bmf::BMF; pub use closest_vector_problem::ClosestVectorProblem; pub use ilp::{Comparison, LinearConstraint, ObjectiveSense, VarBounds, ILP}; pub use qubo::QUBO; -pub use spin_glass::SpinGlass; diff --git a/src/models/optimization/qubo.rs b/src/models/algebraic/qubo.rs similarity index 97% rename from src/models/optimization/qubo.rs rename to src/models/algebraic/qubo.rs index 21107188..1e30f35b 100644 --- a/src/models/optimization/qubo.rs +++ b/src/models/algebraic/qubo.rs @@ -33,7 +33,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::optimization::QUBO; +/// use problemreductions::models::algebraic::QUBO; /// use problemreductions::{Problem, Solver, BruteForce}; /// /// // Q matrix: minimize x0 - 2*x1 + x0*x1 @@ -193,5 +193,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/optimization/qubo.rs"] +#[path = "../../unit_tests/models/algebraic/qubo.rs"] mod tests; diff --git a/src/models/specialized/circuit.rs b/src/models/formula/circuit.rs similarity index 98% rename from src/models/specialized/circuit.rs rename to src/models/formula/circuit.rs index 024fd1b4..383f5a6b 100644 --- a/src/models/specialized/circuit.rs +++ b/src/models/formula/circuit.rs @@ -195,7 +195,7 @@ impl Circuit { /// # Example /// /// ``` -/// use problemreductions::models::specialized::{CircuitSAT, BooleanExpr, Assignment, Circuit}; +/// use problemreductions::models::formula::{CircuitSAT, BooleanExpr, Assignment, Circuit}; /// use problemreductions::{Problem, Solver, BruteForce}; /// /// // Create a simple circuit: c = x AND y @@ -309,5 +309,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/specialized/circuit.rs"] +#[path = "../../unit_tests/models/formula/circuit.rs"] mod tests; diff --git a/src/models/satisfiability/ksat.rs b/src/models/formula/ksat.rs similarity index 97% rename from src/models/satisfiability/ksat.rs rename to src/models/formula/ksat.rs index f2f0a1ac..4a542efb 100644 --- a/src/models/satisfiability/ksat.rs +++ b/src/models/formula/ksat.rs @@ -37,7 +37,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::satisfiability::{KSatisfiability, CNFClause}; +/// use problemreductions::models::formula::{KSatisfiability, CNFClause}; /// use problemreductions::variant::K3; /// use problemreductions::{Problem, Solver, BruteForce}; /// @@ -190,5 +190,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/satisfiability/ksat.rs"] +#[path = "../../unit_tests/models/formula/ksat.rs"] mod tests; diff --git a/src/models/satisfiability/mod.rs b/src/models/formula/mod.rs similarity index 50% rename from src/models/satisfiability/mod.rs rename to src/models/formula/mod.rs index 9766fd1c..f2a33cce 100644 --- a/src/models/satisfiability/mod.rs +++ b/src/models/formula/mod.rs @@ -1,11 +1,14 @@ -//! Satisfiability problems. +//! Logic and formula problems. //! -//! This module contains Boolean satisfiability problems: +//! Problems whose input is a boolean formula or circuit: //! - [`Satisfiability`]: Boolean satisfiability (SAT) with CNF clauses //! - [`KSatisfiability`]: K-SAT where each clause has exactly K literals +//! - [`CircuitSAT`]: Boolean circuit satisfiability +pub(crate) mod circuit; mod ksat; mod sat; +pub use circuit::{Assignment, BooleanExpr, BooleanOp, Circuit, CircuitSAT}; pub use ksat::KSatisfiability; pub use sat::{CNFClause, Satisfiability}; diff --git a/src/models/satisfiability/sat.rs b/src/models/formula/sat.rs similarity index 97% rename from src/models/satisfiability/sat.rs rename to src/models/formula/sat.rs index 4401008b..448f58fa 100644 --- a/src/models/satisfiability/sat.rs +++ b/src/models/formula/sat.rs @@ -89,7 +89,7 @@ impl CNFClause { /// # Example /// /// ``` -/// use problemreductions::models::satisfiability::{Satisfiability, CNFClause}; +/// use problemreductions::models::formula::{Satisfiability, CNFClause}; /// use problemreductions::{Problem, Solver, BruteForce}; /// /// // Formula: (x1 OR x2) AND (NOT x1 OR x3) AND (NOT x2 OR NOT x3) @@ -225,5 +225,5 @@ pub(crate) fn is_satisfying_assignment( } #[cfg(test)] -#[path = "../../unit_tests/models/satisfiability/sat.rs"] +#[path = "../../unit_tests/models/formula/sat.rs"] mod tests; diff --git a/src/models/specialized/biclique_cover.rs b/src/models/graph/biclique_cover.rs similarity index 98% rename from src/models/specialized/biclique_cover.rs rename to src/models/graph/biclique_cover.rs index 078c75b4..77bb9e5c 100644 --- a/src/models/specialized/biclique_cover.rs +++ b/src/models/graph/biclique_cover.rs @@ -32,7 +32,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::specialized::BicliqueCover; +/// use problemreductions::models::graph::BicliqueCover; /// use problemreductions::topology::BipartiteGraph; /// use problemreductions::{Problem, Solver, BruteForce}; /// @@ -248,5 +248,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/specialized/biclique_cover.rs"] +#[path = "../../unit_tests/models/graph/biclique_cover.rs"] mod tests; diff --git a/src/models/graph/mod.rs b/src/models/graph/mod.rs index a924af19..1198f7fb 100644 --- a/src/models/graph/mod.rs +++ b/src/models/graph/mod.rs @@ -1,6 +1,6 @@ -//! Graph-based optimization problems. +//! Graph problems. //! -//! This module contains NP-hard problems defined on graphs: +//! Problems whose input is a graph (optionally weighted): //! - [`MaximumIndependentSet`]: Maximum weight independent set //! - [`MaximalIS`]: Maximal independent set //! - [`MinimumVertexCover`]: Minimum weight vertex cover @@ -10,7 +10,10 @@ //! - [`KColoring`]: K-vertex coloring //! - [`MaximumMatching`]: Maximum weight matching //! - [`TravelingSalesman`]: Traveling Salesman (minimum weight Hamiltonian cycle) +//! - [`SpinGlass`]: Ising model Hamiltonian +//! - [`BicliqueCover`]: Biclique cover on bipartite graphs +pub(crate) mod biclique_cover; pub(crate) mod kcoloring; pub(crate) mod max_cut; pub(crate) mod maximal_is; @@ -19,8 +22,10 @@ pub(crate) mod maximum_independent_set; pub(crate) mod maximum_matching; pub(crate) mod minimum_dominating_set; pub(crate) mod minimum_vertex_cover; +pub(crate) mod spin_glass; pub(crate) mod traveling_salesman; +pub use biclique_cover::BicliqueCover; pub use kcoloring::KColoring; pub use max_cut::MaxCut; pub use maximal_is::MaximalIS; @@ -29,4 +34,5 @@ pub use maximum_independent_set::MaximumIndependentSet; pub use maximum_matching::MaximumMatching; pub use minimum_dominating_set::MinimumDominatingSet; pub use minimum_vertex_cover::MinimumVertexCover; +pub use spin_glass::SpinGlass; pub use traveling_salesman::TravelingSalesman; diff --git a/src/models/optimization/spin_glass.rs b/src/models/graph/spin_glass.rs similarity index 98% rename from src/models/optimization/spin_glass.rs rename to src/models/graph/spin_glass.rs index abeedb4c..30bf90ac 100644 --- a/src/models/optimization/spin_glass.rs +++ b/src/models/graph/spin_glass.rs @@ -42,7 +42,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::optimization::SpinGlass; +/// use problemreductions::models::graph::SpinGlass; /// use problemreductions::topology::SimpleGraph; /// use problemreductions::{Problem, Solver, BruteForce}; /// @@ -256,5 +256,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/optimization/spin_glass.rs"] +#[path = "../../unit_tests/models/graph/spin_glass.rs"] mod tests; diff --git a/src/models/optimization/bin_packing.rs b/src/models/misc/bin_packing.rs similarity index 97% rename from src/models/optimization/bin_packing.rs rename to src/models/misc/bin_packing.rs index 1641ee77..cfa1647c 100644 --- a/src/models/optimization/bin_packing.rs +++ b/src/models/misc/bin_packing.rs @@ -39,7 +39,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::optimization::BinPacking; +/// use problemreductions::models::misc::BinPacking; /// use problemreductions::{Problem, Solver, BruteForce}; /// /// // 4 items with sizes [3, 3, 2, 2], capacity 5 @@ -156,5 +156,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/optimization/bin_packing.rs"] +#[path = "../../unit_tests/models/misc/bin_packing.rs"] mod tests; diff --git a/src/models/specialized/factoring.rs b/src/models/misc/factoring.rs similarity index 97% rename from src/models/specialized/factoring.rs rename to src/models/misc/factoring.rs index 66de6907..f4408a72 100644 --- a/src/models/specialized/factoring.rs +++ b/src/models/misc/factoring.rs @@ -29,7 +29,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::specialized::Factoring; +/// use problemreductions::models::misc::Factoring; /// use problemreductions::{Problem, Solver, BruteForce}; /// /// // Factor 6 with 2-bit factors (allowing factors 0-3) @@ -167,5 +167,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/specialized/factoring.rs"] +#[path = "../../unit_tests/models/misc/factoring.rs"] mod tests; diff --git a/src/models/misc/mod.rs b/src/models/misc/mod.rs new file mode 100644 index 00000000..6e2fa084 --- /dev/null +++ b/src/models/misc/mod.rs @@ -0,0 +1,14 @@ +//! Miscellaneous problems. +//! +//! Problems with unique input structures that don't fit other categories: +//! - [`BinPacking`]: Bin Packing (minimize bins) +//! - [`Factoring`]: Integer factorization +//! - [`PaintShop`]: Minimize color switches in paint shop scheduling + +mod bin_packing; +pub(crate) mod factoring; +pub(crate) mod paintshop; + +pub use bin_packing::BinPacking; +pub use factoring::Factoring; +pub use paintshop::PaintShop; diff --git a/src/models/specialized/paintshop.rs b/src/models/misc/paintshop.rs similarity index 98% rename from src/models/specialized/paintshop.rs rename to src/models/misc/paintshop.rs index 2d21df3a..1fe68272 100644 --- a/src/models/specialized/paintshop.rs +++ b/src/models/misc/paintshop.rs @@ -33,7 +33,7 @@ inventory::submit! { /// # Example /// /// ``` -/// use problemreductions::models::specialized::PaintShop; +/// use problemreductions::models::misc::PaintShop; /// use problemreductions::{Problem, Solver, BruteForce}; /// /// // Sequence: a, b, a, c, c, b @@ -197,5 +197,5 @@ crate::declare_variants! { } #[cfg(test)] -#[path = "../../unit_tests/models/specialized/paintshop.rs"] +#[path = "../../unit_tests/models/misc/paintshop.rs"] mod tests; diff --git a/src/models/mod.rs b/src/models/mod.rs index e4671efc..15df5cfa 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,19 +1,19 @@ //! Problem model implementations. //! -//! Each sub-module groups related problem types. See individual modules for details. +//! Each sub-module groups related problem types by input structure. +pub mod algebraic; +pub mod formula; pub mod graph; -pub mod optimization; -pub mod satisfiability; +pub mod misc; pub mod set; -pub mod specialized; // Re-export commonly used types +pub use algebraic::{ClosestVectorProblem, BMF, ILP, QUBO}; +pub use formula::{CNFClause, CircuitSAT, KSatisfiability, Satisfiability}; pub use graph::{ - KColoring, MaxCut, MaximalIS, MaximumClique, MaximumIndependentSet, MaximumMatching, - MinimumDominatingSet, MinimumVertexCover, TravelingSalesman, + BicliqueCover, KColoring, MaxCut, MaximalIS, MaximumClique, MaximumIndependentSet, + MaximumMatching, MinimumDominatingSet, MinimumVertexCover, SpinGlass, TravelingSalesman, }; -pub use optimization::{BinPacking, ClosestVectorProblem, SpinGlass, ILP, QUBO}; -pub use satisfiability::{CNFClause, KSatisfiability, Satisfiability}; +pub use misc::{BinPacking, Factoring, PaintShop}; pub use set::{MaximumSetPacking, MinimumSetCovering}; -pub use specialized::{BicliqueCover, CircuitSAT, Factoring, PaintShop, BMF}; diff --git a/src/models/specialized/mod.rs b/src/models/specialized/mod.rs deleted file mode 100644 index 63b70c68..00000000 --- a/src/models/specialized/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Specialized NP-hard problems. -//! -//! This module contains problems that don't fit neatly into other categories: -//! - [`CircuitSAT`]: Boolean circuit satisfiability -//! - [`Factoring`]: Integer factorization -//! - [`PaintShop`]: Minimize color switches in paint shop scheduling -//! - [`BicliqueCover`]: Biclique cover on bipartite graphs -//! - [`BMF`]: Boolean matrix factorization - -pub(crate) mod biclique_cover; -pub(crate) mod bmf; -pub(crate) mod circuit; -pub(crate) mod factoring; -pub(crate) mod paintshop; - -pub use biclique_cover::BicliqueCover; -pub use bmf::BMF; -pub use circuit::{Assignment, BooleanExpr, BooleanOp, Circuit, CircuitSAT}; -pub use factoring::Factoring; -pub use paintshop::PaintShop; diff --git a/src/rules/circuit_ilp.rs b/src/rules/circuit_ilp.rs index 67e85ea4..6befb2bb 100644 --- a/src/rules/circuit_ilp.rs +++ b/src/rules/circuit_ilp.rs @@ -14,8 +14,8 @@ //! ## Objective //! Trivial (minimize 0): any feasible ILP solution is a satisfying assignment. -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; -use crate::models::specialized::{BooleanExpr, BooleanOp, CircuitSAT}; +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; +use crate::models::formula::{BooleanExpr, BooleanOp, CircuitSAT}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use std::collections::HashMap; diff --git a/src/rules/circuit_spinglass.rs b/src/rules/circuit_spinglass.rs index e002fd26..86473227 100644 --- a/src/rules/circuit_spinglass.rs +++ b/src/rules/circuit_spinglass.rs @@ -6,8 +6,8 @@ //! Each logic gate is encoded as a SpinGlass Hamiltonian where the ground //! states correspond to valid input/output combinations. -use crate::models::optimization::SpinGlass; -use crate::models::specialized::{Assignment, BooleanExpr, BooleanOp, CircuitSAT}; +use crate::models::formula::{Assignment, BooleanExpr, BooleanOp, CircuitSAT}; +use crate::models::graph::SpinGlass; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::SimpleGraph; diff --git a/src/rules/coloring_ilp.rs b/src/rules/coloring_ilp.rs index b80dad20..5bd45c26 100644 --- a/src/rules/coloring_ilp.rs +++ b/src/rules/coloring_ilp.rs @@ -7,8 +7,8 @@ //! 2. Adjacent vertices have different colors: x_{u,c} + x_{v,c} <= 1 for each edge (u,v) and color c //! - Objective: None (feasibility problem, minimize 0) +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::graph::KColoring; -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/coloring_qubo.rs b/src/rules/coloring_qubo.rs index 5f1573c6..e94975f0 100644 --- a/src/rules/coloring_qubo.rs +++ b/src/rules/coloring_qubo.rs @@ -8,8 +8,8 @@ //! //! QUBO has n*K variables. +use crate::models::algebraic::QUBO; use crate::models::graph::KColoring; -use crate::models::optimization::QUBO; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/factoring_circuit.rs b/src/rules/factoring_circuit.rs index 3160d7c3..1400a032 100644 --- a/src/rules/factoring_circuit.rs +++ b/src/rules/factoring_circuit.rs @@ -7,7 +7,8 @@ //! The multiplier circuit uses an array multiplier structure with //! carry propagation, building up partial products row by row. -use crate::models::specialized::{Assignment, BooleanExpr, Circuit, CircuitSAT, Factoring}; +use crate::models::formula::{Assignment, BooleanExpr, Circuit, CircuitSAT}; +use crate::models::misc::Factoring; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; /// Result of reducing Factoring to CircuitSAT. diff --git a/src/rules/factoring_ilp.rs b/src/rules/factoring_ilp.rs index 3cb0045d..e2724cc1 100644 --- a/src/rules/factoring_ilp.rs +++ b/src/rules/factoring_ilp.rs @@ -17,8 +17,8 @@ //! 2. Bit-position sums: Σ_{i+j=k} z_ij + c_{k-1} = N_k + 2·c_k //! 3. No overflow: c_{m+n-1} = 0 -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; -use crate::models::specialized::Factoring; +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; +use crate::models::misc::Factoring; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use std::cmp::min; diff --git a/src/rules/ilp_qubo.rs b/src/rules/ilp_qubo.rs index 6f2c7d6b..ab901a44 100644 --- a/src/rules/ilp_qubo.rs +++ b/src/rules/ilp_qubo.rs @@ -9,7 +9,7 @@ //! For Minimize sense, c is negated (convert to maximization). //! Slack variables: ceil(log2(slack_range)) bits per inequality constraint. -use crate::models::optimization::{Comparison, ObjectiveSense, ILP, QUBO}; +use crate::models::algebraic::{Comparison, ObjectiveSense, ILP, QUBO}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/ksatisfiability_casts.rs b/src/rules/ksatisfiability_casts.rs index 1f2857ff..e98a02a1 100644 --- a/src/rules/ksatisfiability_casts.rs +++ b/src/rules/ksatisfiability_casts.rs @@ -1,7 +1,7 @@ //! Variant cast reductions for KSatisfiability. use crate::impl_variant_reduction; -use crate::models::satisfiability::KSatisfiability; +use crate::models::formula::KSatisfiability; use crate::variant::{K2, K3, KN}; impl_variant_reduction!( diff --git a/src/rules/ksatisfiability_qubo.rs b/src/rules/ksatisfiability_qubo.rs index cbf60226..7bf640da 100644 --- a/src/rules/ksatisfiability_qubo.rs +++ b/src/rules/ksatisfiability_qubo.rs @@ -12,8 +12,8 @@ //! //! CNFClause uses 1-indexed signed integers: positive = variable, negative = negated. -use crate::models::optimization::QUBO; -use crate::models::satisfiability::KSatisfiability; +use crate::models::algebraic::QUBO; +use crate::models::formula::KSatisfiability; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::variant::{K2, K3}; @@ -265,7 +265,7 @@ fn add_3sat_clause_penalty(matrix: &mut [Vec], lits: &[i32], aux_var: usize /// Returns (matrix, num_source_vars) where matrix is (n + aux) x (n + aux). fn build_qubo_matrix( num_vars: usize, - clauses: &[crate::models::satisfiability::CNFClause], + clauses: &[crate::models::formula::CNFClause], k: usize, ) -> Vec> { match k { diff --git a/src/rules/maximumclique_ilp.rs b/src/rules/maximumclique_ilp.rs index 2bcd87d3..0b36bba2 100644 --- a/src/rules/maximumclique_ilp.rs +++ b/src/rules/maximumclique_ilp.rs @@ -6,8 +6,8 @@ //! at most one can be in the clique //! - Objective: Maximize the sum of weights of selected vertices +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::graph::MaximumClique; -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/maximumindependentset_ilp.rs b/src/rules/maximumindependentset_ilp.rs index 5396c396..10a02f2c 100644 --- a/src/rules/maximumindependentset_ilp.rs +++ b/src/rules/maximumindependentset_ilp.rs @@ -5,8 +5,8 @@ //! - Constraints: x_u + x_v <= 1 for each edge (u, v) - at most one endpoint can be selected //! - Objective: Maximize the sum of weights of selected vertices +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::graph::MaximumIndependentSet; -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/maximumindependentset_qubo.rs b/src/rules/maximumindependentset_qubo.rs index 9dd32a07..2d0b4dae 100644 --- a/src/rules/maximumindependentset_qubo.rs +++ b/src/rules/maximumindependentset_qubo.rs @@ -5,8 +5,8 @@ //! //! Q[i][i] = -w_i, Q[i][j] = P for edges. P = 1 + Σ w_i. +use crate::models::algebraic::QUBO; use crate::models::graph::MaximumIndependentSet; -use crate::models::optimization::QUBO; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/maximummatching_ilp.rs b/src/rules/maximummatching_ilp.rs index 681e0092..04c86793 100644 --- a/src/rules/maximummatching_ilp.rs +++ b/src/rules/maximummatching_ilp.rs @@ -6,8 +6,8 @@ //! (at most one incident edge can be selected) //! - Objective: Maximize the sum of weights of selected edges +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::graph::MaximumMatching; -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/maximumsetpacking_ilp.rs b/src/rules/maximumsetpacking_ilp.rs index 13f61071..cd2d7093 100644 --- a/src/rules/maximumsetpacking_ilp.rs +++ b/src/rules/maximumsetpacking_ilp.rs @@ -5,7 +5,7 @@ //! - Constraints: x_i + x_j <= 1 for each overlapping pair (i, j) //! - Objective: Maximize the sum of weights of selected sets -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::set::MaximumSetPacking; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximumsetpacking_qubo.rs b/src/rules/maximumsetpacking_qubo.rs index 9fdce7ee..7ccbf781 100644 --- a/src/rules/maximumsetpacking_qubo.rs +++ b/src/rules/maximumsetpacking_qubo.rs @@ -6,7 +6,7 @@ //! //! Q[i][i] = -w_i, Q[i][j] = P for overlapping pairs. P = 1 + Σ w_i. -use crate::models::optimization::QUBO; +use crate::models::algebraic::QUBO; use crate::models::set::MaximumSetPacking; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumdominatingset_ilp.rs b/src/rules/minimumdominatingset_ilp.rs index abce597b..e2981a81 100644 --- a/src/rules/minimumdominatingset_ilp.rs +++ b/src/rules/minimumdominatingset_ilp.rs @@ -6,8 +6,8 @@ //! (v or at least one of its neighbors must be selected) //! - Objective: Minimize the sum of weights of selected vertices +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::graph::MinimumDominatingSet; -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/minimumsetcovering_ilp.rs b/src/rules/minimumsetcovering_ilp.rs index 4f4bb6c5..ced7991d 100644 --- a/src/rules/minimumsetcovering_ilp.rs +++ b/src/rules/minimumsetcovering_ilp.rs @@ -5,7 +5,7 @@ //! - Constraints: For each element e: sum_{j: e in set_j} x_j >= 1 (element must be covered) //! - Objective: Minimize the sum of weights of selected sets -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::set::MinimumSetCovering; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumvertexcover_ilp.rs b/src/rules/minimumvertexcover_ilp.rs index 9f076bd8..d69c0232 100644 --- a/src/rules/minimumvertexcover_ilp.rs +++ b/src/rules/minimumvertexcover_ilp.rs @@ -5,8 +5,8 @@ //! - Constraints: x_u + x_v >= 1 for each edge (u, v) - at least one endpoint must be selected //! - Objective: Minimize the sum of weights of selected vertices +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::graph::MinimumVertexCover; -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/minimumvertexcover_qubo.rs b/src/rules/minimumvertexcover_qubo.rs index e484c724..a47e0cd5 100644 --- a/src/rules/minimumvertexcover_qubo.rs +++ b/src/rules/minimumvertexcover_qubo.rs @@ -6,8 +6,8 @@ //! Expanding: Q[i][i] = w_i - P·deg(i), Q[i][j] = P for edges. //! P = 1 + Σ w_i. +use crate::models::algebraic::QUBO; use crate::models::graph::MinimumVertexCover; -use crate::models::optimization::QUBO; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/qubo_ilp.rs b/src/rules/qubo_ilp.rs index 89d14f94..07a38226 100644 --- a/src/rules/qubo_ilp.rs +++ b/src/rules/qubo_ilp.rs @@ -14,7 +14,7 @@ //! ## Objective //! minimize Σ_i Q_ii · x_i + Σ_{i SAT: Trivial embedding (K-SAT is a special case of SAT) -use crate::models::satisfiability::{CNFClause, KSatisfiability, Satisfiability}; +use crate::models::formula::{CNFClause, KSatisfiability, Satisfiability}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::variant::{KValue, K2, K3, KN}; diff --git a/src/rules/sat_maximumindependentset.rs b/src/rules/sat_maximumindependentset.rs index f39afe72..de28824e 100644 --- a/src/rules/sat_maximumindependentset.rs +++ b/src/rules/sat_maximumindependentset.rs @@ -8,8 +8,8 @@ //! A satisfying assignment corresponds to an independent set of size = num_clauses, //! where we pick exactly one literal from each clause. +use crate::models::formula::Satisfiability; use crate::models::graph::MaximumIndependentSet; -use crate::models::satisfiability::Satisfiability; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::SimpleGraph; diff --git a/src/rules/sat_minimumdominatingset.rs b/src/rules/sat_minimumdominatingset.rs index 7dd1570f..ac0cf052 100644 --- a/src/rules/sat_minimumdominatingset.rs +++ b/src/rules/sat_minimumdominatingset.rs @@ -14,8 +14,8 @@ //! - Selecting the negative literal vertex means the variable is false //! - Selecting the dummy vertex means the variable can be either (unused in any clause) +use crate::models::formula::Satisfiability; use crate::models::graph::MinimumDominatingSet; -use crate::models::satisfiability::Satisfiability; use crate::reduction; use crate::rules::sat_maximumindependentset::BoolVar; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/spinglass_casts.rs b/src/rules/spinglass_casts.rs index 50868094..81693c23 100644 --- a/src/rules/spinglass_casts.rs +++ b/src/rules/spinglass_casts.rs @@ -1,7 +1,7 @@ //! Variant cast reductions for SpinGlass. use crate::impl_variant_reduction; -use crate::models::optimization::SpinGlass; +use crate::models::graph::SpinGlass; use crate::topology::SimpleGraph; use crate::variant::CastToParent; diff --git a/src/rules/spinglass_maxcut.rs b/src/rules/spinglass_maxcut.rs index 813480eb..75ca9df8 100644 --- a/src/rules/spinglass_maxcut.rs +++ b/src/rules/spinglass_maxcut.rs @@ -4,7 +4,7 @@ //! SpinGlass -> MaxCut: Requires ancilla vertex for onsite terms. use crate::models::graph::MaxCut; -use crate::models::optimization::SpinGlass; +use crate::models::graph::SpinGlass; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/spinglass_qubo.rs b/src/rules/spinglass_qubo.rs index 178c9481..d6b441b5 100644 --- a/src/rules/spinglass_qubo.rs +++ b/src/rules/spinglass_qubo.rs @@ -5,7 +5,8 @@ //! //! Transformation: s = 2x - 1 (so x=0 -> s=-1, x=1 -> s=+1) -use crate::models::optimization::{SpinGlass, QUBO}; +use crate::models::algebraic::QUBO; +use crate::models::graph::SpinGlass; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::SimpleGraph; diff --git a/src/rules/travelingsalesman_ilp.rs b/src/rules/travelingsalesman_ilp.rs index a5a331ca..5b5cc796 100644 --- a/src/rules/travelingsalesman_ilp.rs +++ b/src/rules/travelingsalesman_ilp.rs @@ -5,8 +5,8 @@ //! - Constraints: assignment, non-edge consecutive, McCormick //! - Objective: minimize total edge weight of the tour +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::models::graph::TravelingSalesman; -use crate::models::optimization::{LinearConstraint, ObjectiveSense, VarBounds, ILP}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/solvers/ilp/mod.rs b/src/solvers/ilp/mod.rs index d6169058..8244962c 100644 --- a/src/solvers/ilp/mod.rs +++ b/src/solvers/ilp/mod.rs @@ -6,7 +6,7 @@ //! # Example //! //! ```rust,ignore -//! use problemreductions::models::optimization::{ILP, VarBounds, LinearConstraint, ObjectiveSense}; +//! use problemreductions::models::algebraic::{ILP, VarBounds, LinearConstraint, ObjectiveSense}; //! use problemreductions::solvers::ILPSolver; //! //! // Create a simple ILP: maximize x0 + 2*x1 subject to x0 + x1 <= 1 diff --git a/src/solvers/ilp/solver.rs b/src/solvers/ilp/solver.rs index a6525bb9..23744dc5 100644 --- a/src/solvers/ilp/solver.rs +++ b/src/solvers/ilp/solver.rs @@ -1,6 +1,6 @@ //! ILP solver implementation using HiGHS. -use crate::models::optimization::{Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Comparison, ObjectiveSense, ILP}; use crate::rules::{ReduceTo, ReductionResult}; use good_lp::{default_solver, variable, ProblemVariables, Solution, SolverModel, Variable}; @@ -11,7 +11,7 @@ use good_lp::{default_solver, variable, ProblemVariables, Solution, SolverModel, /// # Example /// /// ```rust,ignore -/// use problemreductions::models::optimization::{ILP, VarBounds, LinearConstraint, ObjectiveSense}; +/// use problemreductions::models::algebraic::{ILP, VarBounds, LinearConstraint, ObjectiveSense}; /// use problemreductions::solvers::ILPSolver; /// /// // Create a simple ILP: maximize x0 + 2*x1 subject to x0 + x1 <= 1 diff --git a/src/unit_tests/jl_helpers.rs b/src/unit_tests/jl_helpers.rs index d45c68a8..cb51d27a 100644 --- a/src/unit_tests/jl_helpers.rs +++ b/src/unit_tests/jl_helpers.rs @@ -81,7 +81,7 @@ fn jl_parse_sets(val: &serde_json::Value) -> Vec> { #[allow(dead_code)] fn jl_parse_sat_clauses( instance: &serde_json::Value, -) -> (usize, Vec) { +) -> (usize, Vec) { let num_vars = instance["num_variables"] .as_u64() .expect("num_variables should be a u64") as usize; @@ -105,7 +105,7 @@ fn jl_parse_sat_clauses( if negated { -var } else { var } }) .collect(); - crate::models::satisfiability::CNFClause::new(literals) + crate::models::formula::CNFClause::new(literals) }) .collect(); (num_vars, clauses) diff --git a/src/unit_tests/models/specialized/bmf.rs b/src/unit_tests/models/algebraic/bmf.rs similarity index 100% rename from src/unit_tests/models/specialized/bmf.rs rename to src/unit_tests/models/algebraic/bmf.rs diff --git a/src/unit_tests/models/optimization/closest_vector_problem.rs b/src/unit_tests/models/algebraic/closest_vector_problem.rs similarity index 100% rename from src/unit_tests/models/optimization/closest_vector_problem.rs rename to src/unit_tests/models/algebraic/closest_vector_problem.rs diff --git a/src/unit_tests/models/optimization/ilp.rs b/src/unit_tests/models/algebraic/ilp.rs similarity index 100% rename from src/unit_tests/models/optimization/ilp.rs rename to src/unit_tests/models/algebraic/ilp.rs diff --git a/src/unit_tests/models/optimization/qubo.rs b/src/unit_tests/models/algebraic/qubo.rs similarity index 100% rename from src/unit_tests/models/optimization/qubo.rs rename to src/unit_tests/models/algebraic/qubo.rs diff --git a/src/unit_tests/models/specialized/circuit.rs b/src/unit_tests/models/formula/circuit.rs similarity index 100% rename from src/unit_tests/models/specialized/circuit.rs rename to src/unit_tests/models/formula/circuit.rs diff --git a/src/unit_tests/models/satisfiability/ksat.rs b/src/unit_tests/models/formula/ksat.rs similarity index 100% rename from src/unit_tests/models/satisfiability/ksat.rs rename to src/unit_tests/models/formula/ksat.rs diff --git a/src/unit_tests/models/satisfiability/sat.rs b/src/unit_tests/models/formula/sat.rs similarity index 100% rename from src/unit_tests/models/satisfiability/sat.rs rename to src/unit_tests/models/formula/sat.rs diff --git a/src/unit_tests/models/specialized/biclique_cover.rs b/src/unit_tests/models/graph/biclique_cover.rs similarity index 100% rename from src/unit_tests/models/specialized/biclique_cover.rs rename to src/unit_tests/models/graph/biclique_cover.rs diff --git a/src/unit_tests/models/optimization/spin_glass.rs b/src/unit_tests/models/graph/spin_glass.rs similarity index 100% rename from src/unit_tests/models/optimization/spin_glass.rs rename to src/unit_tests/models/graph/spin_glass.rs diff --git a/src/unit_tests/models/optimization/bin_packing.rs b/src/unit_tests/models/misc/bin_packing.rs similarity index 100% rename from src/unit_tests/models/optimization/bin_packing.rs rename to src/unit_tests/models/misc/bin_packing.rs diff --git a/src/unit_tests/models/specialized/factoring.rs b/src/unit_tests/models/misc/factoring.rs similarity index 100% rename from src/unit_tests/models/specialized/factoring.rs rename to src/unit_tests/models/misc/factoring.rs diff --git a/src/unit_tests/models/specialized/paintshop.rs b/src/unit_tests/models/misc/paintshop.rs similarity index 100% rename from src/unit_tests/models/specialized/paintshop.rs rename to src/unit_tests/models/misc/paintshop.rs diff --git a/src/unit_tests/problem_size.rs b/src/unit_tests/problem_size.rs index 7c7669b9..52116df9 100644 --- a/src/unit_tests/problem_size.rs +++ b/src/unit_tests/problem_size.rs @@ -1,10 +1,10 @@ //! Tests for problem_size() free function and Problem size implementations. +use crate::models::algebraic::*; +use crate::models::formula::*; use crate::models::graph::*; -use crate::models::optimization::*; -use crate::models::satisfiability::*; +use crate::models::misc::*; use crate::models::set::*; -use crate::models::specialized::*; use crate::topology::{BipartiteGraph, SimpleGraph}; use crate::traits::{problem_size, Problem}; @@ -94,7 +94,7 @@ fn test_problem_size_tsp() { #[test] fn test_problem_size_sat() { - use crate::models::satisfiability::CNFClause; + use crate::models::formula::CNFClause; let sat = Satisfiability::new( 3, vec![CNFClause::new(vec![1, -2]), CNFClause::new(vec![2, 3])], @@ -107,7 +107,7 @@ fn test_problem_size_sat() { #[test] fn test_problem_size_ksat() { - use crate::models::satisfiability::CNFClause; + use crate::models::formula::CNFClause; use crate::variant::K3; let ksat = KSatisfiability::::new( 3, @@ -143,7 +143,7 @@ fn test_problem_size_spinglass() { #[test] fn test_problem_size_ilp() { - use crate::models::optimization::{LinearConstraint, ObjectiveSense}; + use crate::models::algebraic::{LinearConstraint, ObjectiveSense}; let ilp = ILP::binary( 2, vec![LinearConstraint::le(vec![(0, 1.0), (1, 1.0)], 3.0)], @@ -165,7 +165,7 @@ fn test_problem_size_factoring() { #[test] fn test_problem_size_circuitsat() { - use crate::models::specialized::{Assignment, BooleanExpr, Circuit}; + use crate::models::formula::{Assignment, BooleanExpr, Circuit}; let circuit = Circuit::new(vec![Assignment::new( vec!["c".to_string()], BooleanExpr::and(vec![BooleanExpr::var("x"), BooleanExpr::var("y")]), diff --git a/src/unit_tests/reduction_graph.rs b/src/unit_tests/reduction_graph.rs index 6bb979ac..dd62524c 100644 --- a/src/unit_tests/reduction_graph.rs +++ b/src/unit_tests/reduction_graph.rs @@ -1,6 +1,6 @@ //! Tests for ReductionGraph: discovery, path finding, and typed API. -use crate::models::satisfiability::KSatisfiability; +use crate::models::formula::KSatisfiability; use crate::prelude::*; use crate::rules::{MinimizeSteps, ReductionGraph, TraversalDirection}; use crate::topology::{SimpleGraph, TriangularSubgraph}; @@ -74,7 +74,7 @@ fn test_multi_step_path() { let graph = ReductionGraph::new(); // Factoring -> CircuitSAT -> SpinGlass is a 2-step path - let src = ReductionGraph::variant_to_map(&crate::models::specialized::Factoring::variant()); + let src = ReductionGraph::variant_to_map(&crate::models::misc::Factoring::variant()); let dst = ReductionGraph::variant_to_map(&SpinGlass::::variant()); let path = graph.find_cheapest_path( "Factoring", @@ -279,7 +279,7 @@ fn test_reduction_path_display() { #[test] fn test_3sat_to_mis_triangular_overhead() { - use crate::models::satisfiability::CNFClause; + use crate::models::formula::CNFClause; let graph = ReductionGraph::new(); diff --git a/src/unit_tests/rules/circuit_ilp.rs b/src/unit_tests/rules/circuit_ilp.rs index 3b2b54a3..3e7bf257 100644 --- a/src/unit_tests/rules/circuit_ilp.rs +++ b/src/unit_tests/rules/circuit_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::specialized::{Assignment, BooleanExpr, Circuit, CircuitSAT}; +use crate::models::formula::{Assignment, BooleanExpr, Circuit, CircuitSAT}; use crate::solvers::BruteForce; use std::collections::HashSet; diff --git a/src/unit_tests/rules/circuit_spinglass.rs b/src/unit_tests/rules/circuit_spinglass.rs index 6342a128..e0331e02 100644 --- a/src/unit_tests/rules/circuit_spinglass.rs +++ b/src/unit_tests/rules/circuit_spinglass.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::specialized::Circuit; +use crate::models::formula::Circuit; use crate::solvers::BruteForce; use crate::types::{NumericSize, WeightElement}; use num_traits::Num; @@ -276,7 +276,7 @@ fn test_solution_extraction() { #[test] fn test_jl_parity_circuitsat_to_spinglass() { - use crate::models::specialized::{Assignment, BooleanExpr, Circuit}; + use crate::models::formula::{Assignment, BooleanExpr, Circuit}; let a = BooleanExpr::var("a"); let b = BooleanExpr::var("b"); let c = BooleanExpr::var("c"); diff --git a/src/unit_tests/rules/graph.rs b/src/unit_tests/rules/graph.rs index 357d64f6..b9d54db6 100644 --- a/src/unit_tests/rules/graph.rs +++ b/src/unit_tests/rules/graph.rs @@ -1,6 +1,6 @@ use super::*; +use crate::models::algebraic::QUBO; use crate::models::graph::{MaximumIndependentSet, MinimumVertexCover}; -use crate::models::optimization::QUBO; use crate::models::set::MaximumSetPacking; use crate::rules::cost::MinimizeSteps; use crate::rules::graph::{classify_problem_category, ReductionStep}; @@ -82,10 +82,9 @@ fn test_variant_level_paths() { let src = ReductionGraph::variant_to_map( &crate::models::graph::MaxCut::::variant(), ); - let dst = ReductionGraph::variant_to_map(&crate::models::optimization::SpinGlass::< - SimpleGraph, - i32, - >::variant()); + let dst = ReductionGraph::variant_to_map( + &crate::models::graph::SpinGlass::::variant(), + ); let paths = graph.find_all_paths("MaxCut", &src, "SpinGlass", &dst); assert!(!paths.is_empty()); assert_eq!(paths[0].type_names(), vec!["MaxCut", "SpinGlass"]); @@ -94,7 +93,7 @@ fn test_variant_level_paths() { let src_f64 = ReductionGraph::variant_to_map( &crate::models::graph::MaxCut::::variant(), ); - let dst_f64 = ReductionGraph::variant_to_map(&crate::models::optimization::SpinGlass::< + let dst_f64 = ReductionGraph::variant_to_map(&crate::models::graph::SpinGlass::< SimpleGraph, f64, >::variant()); @@ -110,10 +109,9 @@ fn test_find_shortest_path_variants() { let src = ReductionGraph::variant_to_map( &crate::models::graph::MaxCut::::variant(), ); - let dst = ReductionGraph::variant_to_map(&crate::models::optimization::SpinGlass::< - SimpleGraph, - i32, - >::variant()); + let dst = ReductionGraph::variant_to_map( + &crate::models::graph::SpinGlass::::variant(), + ); let shortest = graph.find_cheapest_path( "MaxCut", &src, @@ -125,11 +123,10 @@ fn test_find_shortest_path_variants() { assert!(shortest.is_some()); assert_eq!(shortest.unwrap().len(), 1); // Direct path - let src = ReductionGraph::variant_to_map(&crate::models::specialized::Factoring::variant()); - let dst = ReductionGraph::variant_to_map(&crate::models::optimization::SpinGlass::< - SimpleGraph, - i32, - >::variant()); + let src = ReductionGraph::variant_to_map(&crate::models::misc::Factoring::variant()); + let dst = ReductionGraph::variant_to_map( + &crate::models::graph::SpinGlass::::variant(), + ); let shortest = graph.find_cheapest_path( "Factoring", &src, @@ -216,7 +213,7 @@ fn test_to_json() { assert!(json.nodes.len() >= 10); assert!(json.nodes.iter().any(|n| n.name == "MaximumIndependentSet")); assert!(json.nodes.iter().any(|n| n.category == "graph")); - assert!(json.nodes.iter().any(|n| n.category == "optimization")); + assert!(json.nodes.iter().any(|n| n.category == "algebraic")); // Check edges assert!(json.edges.len() >= 10); @@ -268,18 +265,16 @@ fn test_category_from_module_path() { "set" ); assert_eq!( - ReductionGraph::category_from_module_path("problemreductions::models::optimization::qubo"), - "optimization" + ReductionGraph::category_from_module_path("problemreductions::models::algebraic::qubo"), + "algebraic" ); assert_eq!( - ReductionGraph::category_from_module_path("problemreductions::models::satisfiability::sat"), - "satisfiability" + ReductionGraph::category_from_module_path("problemreductions::models::formula::sat"), + "formula" ); assert_eq!( - ReductionGraph::category_from_module_path( - "problemreductions::models::specialized::factoring" - ), - "specialized" + ReductionGraph::category_from_module_path("problemreductions::models::misc::factoring"), + "misc" ); // Fallback for unexpected format assert_eq!( @@ -299,18 +294,18 @@ fn test_doc_path_from_module_path() { ); assert_eq!( ReductionGraph::doc_path_from_module_path( - "problemreductions::models::optimization::qubo", + "problemreductions::models::algebraic::qubo", "QUBO" ), - "models/optimization/struct.QUBO.html" + "models/algebraic/struct.QUBO.html" ); } #[test] fn test_sat_based_reductions() { + use crate::models::formula::Satisfiability; use crate::models::graph::KColoring; use crate::models::graph::MinimumDominatingSet; - use crate::models::satisfiability::Satisfiability; use crate::variant::K3; let graph = ReductionGraph::new(); @@ -327,8 +322,9 @@ fn test_sat_based_reductions() { #[test] fn test_circuit_reductions() { - use crate::models::optimization::SpinGlass; - use crate::models::specialized::{CircuitSAT, Factoring}; + use crate::models::formula::CircuitSAT; + use crate::models::graph::SpinGlass; + use crate::models::misc::Factoring; let graph = ReductionGraph::new(); @@ -358,8 +354,9 @@ fn test_circuit_reductions() { #[test] fn test_optimization_reductions() { + use crate::models::algebraic::QUBO; use crate::models::graph::MaxCut; - use crate::models::optimization::{SpinGlass, QUBO}; + use crate::models::graph::SpinGlass; let graph = ReductionGraph::new(); @@ -374,7 +371,7 @@ fn test_optimization_reductions() { #[test] fn test_ksat_reductions() { - use crate::models::satisfiability::{KSatisfiability, Satisfiability}; + use crate::models::formula::{KSatisfiability, Satisfiability}; use crate::variant::K3; let graph = ReductionGraph::new(); @@ -394,9 +391,9 @@ fn test_all_categories_present() { assert!(categories.contains("graph")); assert!(categories.contains("set")); - assert!(categories.contains("optimization")); - assert!(categories.contains("satisfiability")); - assert!(categories.contains("specialized")); + assert!(categories.contains("algebraic")); + assert!(categories.contains("formula")); + assert!(categories.contains("misc")); } #[test] @@ -499,7 +496,7 @@ fn test_category_derived_from_schema() { let graph = ReductionGraph::new(); let json = graph.to_json(); let circuit = json.nodes.iter().find(|n| n.name == "CircuitSAT").unwrap(); - assert_eq!(circuit.category, "specialized"); + assert_eq!(circuit.category, "formula"); } #[test] @@ -779,16 +776,16 @@ fn test_classify_problem_category() { "graph" ); assert_eq!( - classify_problem_category("problemreductions::models::satisfiability::satisfiability"), - "satisfiability" + classify_problem_category("problemreductions::models::formula::satisfiability"), + "formula" ); assert_eq!( classify_problem_category("problemreductions::models::set::maximum_set_packing"), "set" ); assert_eq!( - classify_problem_category("problemreductions::models::optimization::qubo"), - "optimization" + classify_problem_category("problemreductions::models::algebraic::qubo"), + "algebraic" ); assert_eq!(classify_problem_category("unknown::path"), "other"); } @@ -889,7 +886,7 @@ fn test_reduction_chain_multi_step() { #[test] fn test_reduction_chain_with_variant_casts() { - use crate::models::satisfiability::{CNFClause, KSatisfiability}; + use crate::models::formula::{CNFClause, KSatisfiability}; use crate::rules::MinimizeSteps; use crate::solvers::{BruteForce, Solver}; use crate::topology::UnitDiskGraph; diff --git a/src/unit_tests/rules/ilp_qubo.rs b/src/unit_tests/rules/ilp_qubo.rs index c3568f01..df21dc98 100644 --- a/src/unit_tests/rules/ilp_qubo.rs +++ b/src/unit_tests/rules/ilp_qubo.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::optimization::{LinearConstraint, ObjectiveSense}; +use crate::models::algebraic::{LinearConstraint, ObjectiveSense}; use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/rules/ksatisfiability_qubo.rs b/src/unit_tests/rules/ksatisfiability_qubo.rs index a3ec43e6..ac7fe8d6 100644 --- a/src/unit_tests/rules/ksatisfiability_qubo.rs +++ b/src/unit_tests/rules/ksatisfiability_qubo.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::satisfiability::CNFClause; +use crate::models::formula::CNFClause; use crate::solvers::BruteForce; use crate::traits::Problem; use crate::variant::{K2, K3}; diff --git a/src/unit_tests/rules/reduction_path_parity.rs b/src/unit_tests/rules/reduction_path_parity.rs index a655b418..f84244a1 100644 --- a/src/unit_tests/rules/reduction_path_parity.rs +++ b/src/unit_tests/rules/reduction_path_parity.rs @@ -2,9 +2,9 @@ //! Verifies that chained reductions via `find_cheapest_path` + `reduce_along_path` //! produce correct solutions matching direct source solves. -use crate::models::graph::MaxCut; -use crate::models::optimization::{SpinGlass, QUBO}; -use crate::models::specialized::Factoring; +use crate::models::algebraic::QUBO; +use crate::models::graph::{MaxCut, SpinGlass}; +use crate::models::misc::Factoring; use crate::rules::{MinimizeSteps, ReductionGraph}; use crate::solvers::{BruteForce, Solver}; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/rules/registry.rs b/src/unit_tests/rules/registry.rs index 4fc5f5cc..fb9c3b09 100644 --- a/src/unit_tests/rules/registry.rs +++ b/src/unit_tests/rules/registry.rs @@ -231,7 +231,7 @@ fn test_overhead_eval_fn_cross_check_mis_to_mvc() { #[test] fn test_overhead_eval_fn_cross_check_factoring_to_ilp() { - use crate::models::specialized::Factoring; + use crate::models::misc::Factoring; let problem = Factoring::new(3, 4, 42); @@ -273,7 +273,7 @@ fn test_complexity_eval_fn_cross_check_mis() { #[test] fn test_complexity_eval_fn_cross_check_factoring() { - use crate::models::specialized::Factoring; + use crate::models::misc::Factoring; use crate::registry::VariantEntry; let problem = Factoring::new(8, 8, 100); diff --git a/src/unit_tests/rules/sat_circuitsat.rs b/src/unit_tests/rules/sat_circuitsat.rs index 019c6e81..dd028a7c 100644 --- a/src/unit_tests/rules/sat_circuitsat.rs +++ b/src/unit_tests/rules/sat_circuitsat.rs @@ -1,6 +1,5 @@ use super::*; -use crate::models::satisfiability::{CNFClause, Satisfiability}; -use crate::models::specialized::CircuitSAT; +use crate::models::formula::{CNFClause, CircuitSAT, Satisfiability}; use crate::rules::ReduceTo; use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/rules/sat_coloring.rs b/src/unit_tests/rules/sat_coloring.rs index 456b3c8f..7d7847b9 100644 --- a/src/unit_tests/rules/sat_coloring.rs +++ b/src/unit_tests/rules/sat_coloring.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::satisfiability::CNFClause; +use crate::models::formula::CNFClause; use crate::solvers::BruteForce; use crate::topology::Graph; use crate::variant::K3; diff --git a/src/unit_tests/rules/sat_maximumindependentset.rs b/src/unit_tests/rules/sat_maximumindependentset.rs index b60f40a5..ce85a7eb 100644 --- a/src/unit_tests/rules/sat_maximumindependentset.rs +++ b/src/unit_tests/rules/sat_maximumindependentset.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::satisfiability::CNFClause; +use crate::models::formula::CNFClause; use crate::solvers::BruteForce; use crate::topology::Graph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/sat_minimumdominatingset.rs b/src/unit_tests/rules/sat_minimumdominatingset.rs index e6ae2405..8627613b 100644 --- a/src/unit_tests/rules/sat_minimumdominatingset.rs +++ b/src/unit_tests/rules/sat_minimumdominatingset.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::satisfiability::CNFClause; +use crate::models::formula::CNFClause; use crate::solvers::BruteForce; use crate::topology::Graph; use crate::traits::Problem; diff --git a/src/unit_tests/solvers/brute_force.rs b/src/unit_tests/solvers/brute_force.rs index 19561c01..2e80628e 100644 --- a/src/unit_tests/solvers/brute_force.rs +++ b/src/unit_tests/solvers/brute_force.rs @@ -262,7 +262,7 @@ fn test_solver_with_real_mis() { #[test] fn test_solver_with_real_sat() { - use crate::models::satisfiability::{CNFClause, Satisfiability}; + use crate::models::formula::{CNFClause, Satisfiability}; use crate::traits::Problem; // (x1 OR x2) AND (NOT x1 OR NOT x2) diff --git a/src/unit_tests/solvers/ilp/solver.rs b/src/unit_tests/solvers/ilp/solver.rs index abf5f831..20ff5ec2 100644 --- a/src/unit_tests/solvers/ilp/solver.rs +++ b/src/unit_tests/solvers/ilp/solver.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::optimization::{LinearConstraint, VarBounds}; +use crate::models::algebraic::{LinearConstraint, VarBounds}; use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/trait_consistency.rs b/src/unit_tests/trait_consistency.rs index 7c3fa2e2..7eef0660 100644 --- a/src/unit_tests/trait_consistency.rs +++ b/src/unit_tests/trait_consistency.rs @@ -1,8 +1,8 @@ +use crate::models::algebraic::*; +use crate::models::formula::*; use crate::models::graph::*; -use crate::models::optimization::*; -use crate::models::satisfiability::*; +use crate::models::misc::*; use crate::models::set::*; -use crate::models::specialized::*; use crate::topology::{BipartiteGraph, SimpleGraph}; use crate::traits::Problem; use crate::variant::K3; diff --git a/src/unit_tests/unitdiskmapping_algorithms/common.rs b/src/unit_tests/unitdiskmapping_algorithms/common.rs index 03d12de4..53e99169 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/common.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/common.rs @@ -1,6 +1,6 @@ //! Common test utilities for mapping tests. -use crate::models::optimization::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; use crate::models::MaximumIndependentSet; use crate::rules::unitdiskmapping::MappingResult; use crate::rules::{ReduceTo, ReductionResult}; diff --git a/src/unit_tests/unitdiskmapping_algorithms/weighted.rs b/src/unit_tests/unitdiskmapping_algorithms/weighted.rs index 17189cc6..917a7977 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/weighted.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/weighted.rs @@ -657,7 +657,7 @@ fn test_square_danglinleg_weights() { #[test] fn test_weighted_map_config_back_standard_graphs() { use super::common::{is_independent_set, solve_mis}; - use crate::models::optimization::{LinearConstraint, ObjectiveSense, ILP}; + use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; use crate::solvers::ILPSolver; use crate::topology::smallgraph; diff --git a/src/unit_tests/variant.rs b/src/unit_tests/variant.rs index 90b582e2..13753324 100644 --- a/src/unit_tests/variant.rs +++ b/src/unit_tests/variant.rs @@ -79,14 +79,15 @@ fn test_variant_params_macro_multiple() { #[test] fn test_variant_for_problems() { + use crate::models::algebraic::{BMF, QUBO}; + use crate::models::formula::{CircuitSAT, KSatisfiability, Satisfiability}; + use crate::models::graph::{BicliqueCover, SpinGlass}; use crate::models::graph::{ KColoring, MaxCut, MaximalIS, MaximumClique, MaximumIndependentSet, MaximumMatching, MinimumDominatingSet, MinimumVertexCover, }; - use crate::models::optimization::{SpinGlass, QUBO}; - use crate::models::satisfiability::{KSatisfiability, Satisfiability}; + use crate::models::misc::{Factoring, PaintShop}; use crate::models::set::{MaximumSetPacking, MinimumSetCovering}; - use crate::models::specialized::{BicliqueCover, CircuitSAT, Factoring, PaintShop, BMF}; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/tests/suites/integration.rs b/tests/suites/integration.rs index 94ebd5be..49e43f6f 100644 --- a/tests/suites/integration.rs +++ b/tests/suites/integration.rs @@ -3,11 +3,11 @@ //! These tests verify that all problem types work correctly with the //! BruteForce solver and that related problems have consistent solutions. +use problemreductions::models::algebraic::*; +use problemreductions::models::formula::*; use problemreductions::models::graph::*; -use problemreductions::models::optimization::*; -use problemreductions::models::satisfiability::*; +use problemreductions::models::misc::*; use problemreductions::models::set::*; -use problemreductions::models::specialized::*; use problemreductions::prelude::*; use problemreductions::topology::{BipartiteGraph, SimpleGraph}; use problemreductions::variant::K3; diff --git a/tests/suites/reductions.rs b/tests/suites/reductions.rs index d757f2a1..daad3adc 100644 --- a/tests/suites/reductions.rs +++ b/tests/suites/reductions.rs @@ -3,7 +3,7 @@ //! These tests verify that reduction chains work correctly and //! solutions can be properly extracted through the reduction pipeline. -use problemreductions::models::optimization::{LinearConstraint, ObjectiveSense, ILP}; +use problemreductions::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; use problemreductions::prelude::*; use problemreductions::topology::{Graph, SimpleGraph}; use problemreductions::variant::{K2, K3};