You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Rust library for NP-hard problem definitions and reductions. We aim to implement >100 NP-hard problems and reductions rule between them, under the assistance of AI.
8
+
A Rust library for NP-hard problem definitions and reductions. We aim to implement [100+ problems and reduction rules](https://codingthrust.github.io/problem-reductions/)between them, with automatic reduction path search. Built with AI assistance.
9
9
10
10
This infrastructure aims to solve two problems:
11
-
- Given a hard problem $A$, reduce it to the most vaible problem $B$, to be solved efficiently with an external solver.
12
-
- Given a solver $S$ for problem $B$, explore how efficient it can be used for solving other problems.
11
+
- Given a hard problem $A$, reduce it to the most viable problem $B$, to be solved efficiently with an external solver.
12
+
- Given a solver $S$ for problem $B$, explore how efficiently it can be used for solving other problems.
13
13
14
14
Download [PDF manual](https://codingthrust.github.io/problem-reductions/reductions.pdf) for humans.
15
15
@@ -19,30 +19,10 @@ Add to your `Cargo.toml`:
19
19
20
20
```toml
21
21
[dependencies]
22
-
problemreductions = "0.1"
22
+
problemreductions = "0.2"
23
23
```
24
24
25
-
## Quick Start
26
-
27
-
```rust
28
-
useproblemreductions::prelude::*;
29
-
useproblemreductions::models::optimization::ILP;
30
-
31
-
// Create an Independent Set problem on a path graph
|[`src/registry/`](#reduction-graph)|Reduction graph metadata (collected via `inventory`)|
23
23
|[`src/solvers/`](#solvers)| BruteForce and ILP solvers |
24
-
|`src/traits.rs`| Core `Problem` and `OptimizationProblem` traits (see [Problem Model](#problem-model)) |
24
+
|`src/traits.rs`| Core `Problem`, `OptimizationProblem`, `SatisfactionProblem` traits (see [Problem Model](#problem-model)) |
25
25
|`src/types.rs`| Shared types: `SolutionSize`, `Direction`, `ProblemSize` (see [Problem Model](#problem-model)) |
26
26
|`src/variant.rs`| Variant parameter system (see [Variant System](#variant-system)) |
27
27
28
28
## Problem Model
29
29
30
30
Every problem implements `Problem`. Optimization problems additionally implement `OptimizationProblem`; satisfaction problems implement `SatisfactionProblem`.
31
31
32
-
-**`Problem`** — the base trait. Every problem declares a `NAME` (e.g., `"MaximumIndependentSet"`). The solver explores the configuration space defined by `dims()` and scores each configuration with `evaluate()`. For example, a 4-vertex MIS has `dims() = [2, 2, 2, 2]` (each vertex is selected or not); `evaluate(&[1, 0, 1, 0])` returns `Valid(2)` if vertices 0 and 2 form an independent set, or `Invalid` if they share an edge.
33
-
-**`OptimizationProblem`** — extends `Problem` with a comparable `Value` type and a `direction()` (`Maximize` or `Minimize`).
34
-
-**`SatisfactionProblem`** — constrains `Metric = bool`: `true` if all constraints are satisfied, `false` otherwise.
-**`Problem`** — the base trait. Every problem declares a `NAME` (e.g., `"MaximumIndependentSet"`). The solver explores the configuration space defined by `dims()` and scores each configuration with `evaluate()`. For example, a 4-vertex MIS has `dims() = [2, 2, 2, 2]` (each vertex is selected or not); `evaluate(&[1, 0, 1, 0])` returns `Valid(2)` if vertices 0 and 2 form an independent set, or `Invalid` if they share an edge. `problem_size_names()` and `problem_size_values()` expose the instance's structural dimensions (e.g., `num_vertices`, `num_edges`) as a `ProblemSize` — used by the reduction graph to evaluate overhead polynomials along a path.
53
+
-**`OptimizationProblem`** — extends `Problem` with a comparable `Value` type and a `direction()` (`Maximize` or `Minimize`).
54
+
-**`SatisfactionProblem`** — constrains `Metric = bool`: `true` if all constraints are satisfied, `false` otherwise.
46
55
47
56
## Variant System
48
57
@@ -83,7 +92,7 @@ Variant types fall into three categories:
83
92
84
93
Each variant parameter type implements `VariantParam`, which declares its category, value, and optional parent:
The `#[reduction]` attribute expands to the original `impl` block plus an `inventory::submit!` call:
200
209
201
-
```rust
210
+
```rust,ignore
202
211
inventory::submit! {
203
212
ReductionEntry {
204
213
source_name: "MaximumIndependentSet",
@@ -218,17 +227,24 @@ inventory::submit! {
218
227
}
219
228
```
220
229
221
-
This`ReductionEntry` is collected at compile time by `inventory`, making the reduction discoverable by the `ReductionGraph` without any manual registration. The `reduce_fn` field provides a type-erased executor that enables runtime-discovered paths to chain reductions automatically.
230
+
Each`ReductionEntry` is collected by `inventory`at link time and iterated at runtime, making every reduction discoverable by `ReductionGraph` without manual registration. The `reduce_fn` field provides a type-erased executor that enables dynamically discovered paths to chain reductions automatically.
222
231
223
232
</details>
224
233
225
234
## Reduction Graph
226
235
227
-
`ReductionGraph::new()`scans `inventory::iter::<ReductionEntry>` and builds a variant-level directed graph:
236
+
`ReductionGraph::new()`iterates all registered `ReductionEntry` items (via `inventory`) and builds a variant-level directed graph:
-**Edges** come exclusively from `#[reduction]` registrations — both cross-problem reductions and variant casts. There are no auto-generated edges.
231
240
241
+
Exported files:
242
+
243
+
-[reduction_graph.json](reductions/reduction_graph.json) — all problem variants and reduction edges
244
+
-[problem_schemas.json](reductions/problem_schemas.json) — field definitions for each problem type
245
+
246
+
Regenerate with `cargo run --example export_graph` and `cargo run --example export_schemas`.
247
+
232
248
### Path finding
233
249
234
250
All path-finding operates on **exact variant nodes**. Use `ReductionGraph::variant_to_map(&T::variant())` to convert a `Problem::variant()` into the required `BTreeMap<String, String>`.
@@ -245,8 +261,10 @@ The `PathCostFn` trait (used by `find_cheapest_path`) computes edge cost from ov
245
261
| Cost function | Strategy |
246
262
|--------------|----------|
247
263
|`MinimizeSteps`| Minimize number of hops (unit edge cost) |
248
-
|`Minimize("field")`| Minimize a single output field |
249
-
|`CustomCost(closure)`| User-defined cost function |
264
+
|`Minimize("field")`| Minimize a single output field (e.g., `Minimize("num_variables")`) |
`CustomCost` wraps a closure that receives the edge's `ReductionOverhead` (polynomial mapping from input to output size fields) and the current `ProblemSize` (accumulated field values at that point in the path), and returns an `f64` edge cost. Dijkstra minimizes the total cost along the path.
250
268
251
269
**Example:** Finding a path from `MIS{KingsSubgraph, i32}` to `VC{SimpleGraph, i32}`:
let target: &SpinGlass<SimpleGraph, f64> = reduction.target_problem();
291
+
let solution: Vec<usize> = reduction.extract_solution(&target_solution);
270
292
```
271
293
272
-
Internally, `ExecutablePath` holds a type-erased executor per edge. `ChainedReduction` stores intermediate results and extracts solutions back through the chain in reverse.
294
+
`ExecutablePath` holds a type-erased `ReduceFn` per edge. `reduce()` applies them sequentially, producing a `ChainedReduction`that stores each intermediate result. `extract_solution` maps the final solution back through the chain in reverse order.
273
295
274
296
For full type control, you can also chain `ReduceTo::reduce_to()` calls manually at each step.
275
297
@@ -278,7 +300,7 @@ For full type control, you can also chain `ReduceTo::reduce_to()` calls manually
278
300
279
301
Each reduction declares how the output problem size relates to the input, expressed as polynomials. The `poly!` macro provides concise syntax:
|**BruteForce**| Enumerates all configurations. Also provides `find_all_best()` and `find_all_satisfying()`. Used for testing and verification. |
322
-
|**ILPSolver**|Feature-gated (`ilp`). Uses HiGHS via `good_lp`. Also provides `solve_reduced()` for problems that implement `ReduceTo<ILP>`. |
344
+
|**ILPSolver**|Enabled by default (`ilp` feature). Uses HiGHS via `good_lp`. Also provides `solve_reduced()` for problems that implement `ReduceTo<ILP>`. |
323
345
324
346
## JSON Serialization
325
347
326
348
All problem types support JSON serialization via serde:
327
349
328
-
```rust
350
+
```rust,ignore
329
351
use problemreductions::io::{to_json, from_json};
330
352
331
-
letjson=to_json(&problem)?;
353
+
let json: String = to_json(&problem)?;
332
354
let restored: MaximumIndependentSet<SimpleGraph, i32> = from_json(&json)?;
333
355
```
334
356
335
-
Exported files:
336
-
337
-
-[reduction_graph.json](reductions/reduction_graph.json) — all problem variants and reduction edges
338
-
-[problem_schemas.json](reductions/problem_schemas.json) — field definitions for each problem type
339
-
340
-
Regenerate with `cargo run --example export_graph` and `cargo run --example export_schemas`.
341
-
342
357
## Contributing
343
358
344
359
See [Call for Contributions](./introduction.md#call-for-contributions) for the recommended issue-based workflow (no coding required).
0 commit comments