diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 9ac350bc..97890640 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -153,7 +153,7 @@ Max, Min, Sum, Or, And, Extremum, ExtremumSense - `variant_params!` macro implements `Problem::variant()` — e.g., `crate::variant_params![G, W]` for two type params, `crate::variant_params![]` for none (see `src/variant.rs`) - `declare_variants!` proc macro registers concrete type instantiations with best-known complexity and registry-backed load/serialize/value-solve/witness-solve metadata. One entry per problem may be marked `default`, and variable names in complexity strings are validated at compile time against actual getter methods. Ordinary models are constructed directly from their construction schema. When user-facing construction differs from persisted JSON, define a model-local `#[derive(CreateSpec)]` DTO plus `TryFrom`, use its generated `FIELDS` in `ProblemSchemaEntry`, and register it with `create LocalSpec`; never add model-name branches in CLI or MCP code. - `decision_problem_meta!` macro registers `DecisionProblemMeta` for a concrete inner type, providing the `DECISION_NAME` constant. -- `register_decision_variant!` macro generates `declare_variants!`, `ProblemSchemaEntry`, and both `ReductionEntry` submissions (aggregate Decision→Opt + Turing Opt→Decision) for a `Decision

` variant. Callers must define inherent getters (`num_vertices()`, `num_edges()`, `k()`) on `Decision

` before invoking. Accepts `dims`, `fields`, and `size_getters` parameters for problem-specific size fields. +- `register_decision_variant!` macro generates `declare_variants!`, `ProblemSchemaEntry`, and both `ReductionEntry` submissions (aggregate Decision→Opt + Turing Opt→Decision) for a `Decision

` variant. Callers must define inherent getters (`num_vertices()`, `num_edges()`, `k()`) on `Decision

` before invoking. Accepts an explicit structural `category` plus `dims`, `fields`, and `size_getters` parameters for problem-specific size fields. - Problems parameterized by graph type `G` and optionally weight type `W` (problem-dependent) - `Solver::solve()` computes the aggregate value for any `Problem` whose `Value` implements `Aggregate` - `BruteForce::find_witness()` / `find_all_witnesses()` recover witnesses only when `P::Value::supports_witnesses()` @@ -204,6 +204,7 @@ Reduction graph nodes use variant key-value pairs from `Problem::variant()`: ### Extension Points - New models register dynamic load/serialize/brute-force dispatch through `declare_variants!` in the model file, not by adding manual match arms in the CLI +- **Model category is explicit registry metadata.** Every `ProblemSchemaEntry` declares exactly one of `Algebraic`, `Formula`, `Graph`, `Misc`, or `Set`; catalog behavior never derives it from `module_path!()` or source location. - **CLI creation is registry-driven and deferred:** `pred create` expands flags only for the selected concrete variant. Ordinary models use `ProblemSchemaEntry.fields` directly. Models whose construction differs from persisted JSON own a typed `CreateSpec` and fallible conversion beside the model; CLI and MCP only normalize transport values and invoke the registered constructor. - **Each construction input has one name and one concrete type per variant.** Do not add compatibility aliases or infer types from flag names. `CreateSpec` field names render as `snake_case → kebab-case` in CLI and remain `snake_case` in MCP. Add a reusable codec only for a genuinely new transport representation, never a model-name parser branch. - **Random generation is optional and variant-owned.** Not every model has a useful, well-defined random-instance distribution. Add `RandomGenerate` only when the generator has clear semantics and a concrete use (for example, testing or examples); never invent arbitrary bounds or distributions merely to make every model support `--random`. Implement it beside the model (normally through `impl_random_generate!` and a typed `CreateSpec` input DTO), then add `random` only to the applicable `declare_variants!` entries. CLI and MCP discover the exact variant's inputs and callback; never add a model-name random dispatch or advertise random generation on an unsupported variant. diff --git a/.claude/skills/add-model/SKILL.md b/.claude/skills/add-model/SKILL.md index 9fb5b505..87e47256 100644 --- a/.claude/skills/add-model/SKILL.md +++ b/.claude/skills/add-model/SKILL.md @@ -75,7 +75,7 @@ Read these first to understand the patterns: Before implementing, make sure the plan explicitly covers these items that structural review checks later: - Derive numeric implementation types from the mathematical domains in the issue and follow `docs/src/design.md#numeric-types-and-arithmetic`; serde/CLI construction uses the same validation as `new`/`try_new`, and boundary tests cover the supported maximum without requiring impractical allocation -- `ProblemSchemaEntry` metadata is complete for the construction interface (`display_name`, `aliases`, `dimensions`, and `fields`) +- `ProblemSchemaEntry` metadata is complete (`display_name`, `aliases`, `dimensions`, explicit `category`, and construction `fields`) - `Problem::Value` uses the correct aggregate wrapper and witness support is intentional - `declare_variants!` is present with exactly one `default` variant when multiple concrete variants exist - CLI discovery and `pred create ` support are included where applicable @@ -92,6 +92,8 @@ Choose the appropriate sub-module under `src/models/`: - `algebraic/` -- matrices, linear systems, lattices (QUBO, ILP, CVP, BMF) - `misc/` -- unique input structures that don't fit other categories (BinPacking, PaintShop, Factoring) +Declare the same structural choice explicitly in `ProblemSchemaEntry.category`. This is required metadata and is never inferred from `module_path!()` or the file location. + ## Step 1.5: Infer problem size getters From the **best known exact algorithm** complexity (item 9), infer what problem size getter methods the struct should expose. The variables used in the complexity expression define the natural size metrics. @@ -122,7 +124,7 @@ Create `src/models//.rs`: ``` Key decisions: -- **Schema metadata:** `ProblemSchemaEntry` must reflect the construction interface, including `display_name`, `aliases`, `dimensions`, and `fields` +- **Schema metadata:** `ProblemSchemaEntry` must include the explicit structural `category` and reflect the construction interface through `display_name`, `aliases`, `dimensions`, and `fields` - **Objective problems:** use `type Value = Max<_>`, `Min<_>`, or `Extremum<_>` when the model should expose optimization-style witness helpers - **Witness problems:** use `type Value = Or` for existential feasibility problems - **Aggregate-only problems:** use a value-only aggregate such as `Sum<_>`, `And`, or a custom `Aggregate` when witnesses are not meaningful @@ -313,6 +315,7 @@ Structural and quality review is handled by the `review-pipeline` stage, not her |---------|-----| | Implementing weight management as a trait | Use inherent methods: `weights()`, `set_weights()`, `is_weighted()` | | Forgetting `inventory::submit!` | Every problem needs a `ProblemSchemaEntry` registration | +| Omitting or inferring the model category | Set the required `ProblemSchemaEntry.category` explicitly to one of `Algebraic`, `Formula`, `Graph`, `Misc`, or `Set`; never parse `module_path!()`. | | Missing `#[path]` test link | Add `#[cfg(test)] #[path = "..."] mod tests;` at file bottom | | Wrong `dims()` | Must match the actual configuration space (e.g., `vec![2; n]` for binary) | | Using the wrong aggregate wrapper | Objective models use `Max` / `Min` / `Extremum`, witness models use `bool`, aggregate-only models use a fold value like `Sum` / `And` | diff --git a/problemreductions-cli/src/cli.rs b/problemreductions-cli/src/cli.rs index 23b39cfa..4a8138af 100644 --- a/problemreductions-cli/src/cli.rs +++ b/problemreductions-cli/src/cli.rs @@ -1,4 +1,5 @@ use clap::{CommandFactory, Parser, Subcommand, ValueEnum}; +use problemreductions::registry::ProblemCategory; use std::path::PathBuf; pub use crate::create_args::CreateArgs; @@ -68,7 +69,7 @@ Examples: /// Restrict problems to a model category such as graph, set, or misc #[arg(long, conflicts_with = "rules")] - category: Option, + category: Option, /// List the complete catalog instead of the summary #[arg(long)] diff --git a/problemreductions-cli/src/commands/graph.rs b/problemreductions-cli/src/commands/graph.rs index e2c74732..5cd72f3a 100644 --- a/problemreductions-cli/src/commands/graph.rs +++ b/problemreductions-cli/src/commands/graph.rs @@ -3,6 +3,7 @@ use crate::output::OutputConfig; use crate::problem_name::{aliases_for, parse_problem_spec, resolve_problem_ref}; use anyhow::Result; use problemreductions::registry::collect_schemas; +use problemreductions::registry::ProblemCategory; use problemreductions::rules::{MeasuredPath, ReductionGraph, ReductionPath, TraversalFlow}; use problemreductions::{Expr, Growth}; use std::any::Any; @@ -11,7 +12,7 @@ use std::path::Path; pub fn list( query: Option<&str>, - category: Option<&str>, + category: Option, all: bool, verbose: bool, out: &OutputConfig, @@ -38,30 +39,25 @@ pub fn list( } } let query = query.map(str::to_lowercase); - let category = category.map(str::to_lowercase); let selected = catalog .iter() .filter(|problem| { - category.as_ref().is_none_or(|wanted| { - problem - .category - .unwrap_or("uncategorized") - .eq_ignore_ascii_case(wanted) - }) && query.as_ref().is_none_or(|needle| { - problem.canonical_name.to_lowercase().contains(needle) - || problem.display_name.to_lowercase().contains(needle) - || problem - .aliases - .iter() - .any(|alias| alias.to_lowercase().contains(needle)) - || variant_aliases - .get(problem.canonical_name) - .is_some_and(|aliases| { - aliases - .iter() - .any(|alias| alias.to_lowercase().contains(needle)) - }) - }) + category.is_none_or(|wanted| problem.category == wanted) + && query.as_ref().is_none_or(|needle| { + problem.canonical_name.to_lowercase().contains(needle) + || problem.display_name.to_lowercase().contains(needle) + || problem + .aliases + .iter() + .any(|alias| alias.to_lowercase().contains(needle)) + || variant_aliases + .get(problem.canonical_name) + .is_some_and(|aliases| { + aliases + .iter() + .any(|alias| alias.to_lowercase().contains(needle)) + }) + }) }) .collect::>(); let graph = needs_variant_rows.then(ReductionGraph::new); @@ -79,6 +75,7 @@ pub fn list( rules: usize, /// Best-known complexity complexity: String, + category: ProblemCategory, } let mut rows_data: Vec = Vec::new(); @@ -124,6 +121,7 @@ pub fn list( is_default, rules: if i == 0 { rules } else { 0 }, complexity, + category: problem.category, }); } } @@ -131,9 +129,7 @@ pub fn list( let mut category_counts = BTreeMap::new(); for problem in &catalog { - *category_counts - .entry(problem.category.unwrap_or("uncategorized")) - .or_insert(0usize) += 1; + *category_counts.entry(problem.category).or_insert(0usize) += 1; } let columns: Vec<(&str, Align, usize)> = vec![ @@ -201,7 +197,7 @@ pub fn list( vec![ problem.canonical_name.to_string(), aliases.join(", "), - problem.category.unwrap_or("uncategorized").to_string(), + problem.category.to_string(), variant_counts .get(problem.canonical_name) .copied() @@ -248,6 +244,7 @@ pub fn list( "default": r.is_default, "rules": r.rules, "complexity": r.complexity, + "category": r.category, }) }).collect::>(), }); diff --git a/problemreductions-cli/src/main.rs b/problemreductions-cli/src/main.rs index 6cb313b2..aa4361ae 100644 --- a/problemreductions-cli/src/main.rs +++ b/problemreductions-cli/src/main.rs @@ -60,7 +60,7 @@ fn main() -> anyhow::Result<()> { if rules { commands::graph::list_rules(query.as_deref(), all, verbose, &out) } else { - commands::graph::list(query.as_deref(), category.as_deref(), all, verbose, &out) + commands::graph::list(query.as_deref(), category, all, verbose, &out) } } Commands::Show { problem } => commands::graph::show(&problem, &out), diff --git a/problemreductions-cli/src/test_support.rs b/problemreductions-cli/src/test_support.rs index 3ef84f17..539e03a7 100644 --- a/problemreductions-cli/src/test_support.rs +++ b/problemreductions-cli/src/test_support.rs @@ -135,6 +135,7 @@ problemreductions::inventory::submit! { display_name: "CLI test aggregate value source", aliases: &[], dimensions: &[], + category: problemreductions::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Test-only dynamically discovered construction model", fields: &[FieldInfo { @@ -145,6 +146,23 @@ problemreductions::inventory::submit! { } } +problemreductions::inventory::submit! { + ProblemSchemaEntry { + name: AggregateValueTarget::NAME, + display_name: "CLI test aggregate value target", + aliases: &[], + dimensions: &[], + category: problemreductions::registry::ProblemCategory::Misc, + module_path: module_path!(), + description: "Test-only aggregate reduction target", + fields: &[FieldInfo { + name: "base", + type_name: "u64", + description: "Base aggregate value", + }], + } +} + problemreductions::inventory::submit! { VariantEntry { name: AggregateValueSource::NAME, diff --git a/problemreductions-cli/tests/cli_tests.rs b/problemreductions-cli/tests/cli_tests.rs index adcea193..44f8a31d 100644 --- a/problemreductions-cli/tests/cli_tests.rs +++ b/problemreductions-cli/tests/cli_tests.rs @@ -88,6 +88,9 @@ fn test_list() { let stdout = String::from_utf8(output.stdout).unwrap(); assert!(stdout.contains("Registered catalog")); assert!(stdout.contains("graph")); + for category in ["algebraic", "formula", "graph", "misc", "set"] { + assert!(stdout.contains(category)); + } assert!(!stdout.contains("MaximumIndependentSet")); assert!(stdout.lines().count() < 30, "default list is too verbose"); } @@ -117,11 +120,26 @@ fn test_list_json_respects_category_filter() { assert!(variants .iter() .all(|variant| variant["name"] != "MaximumIndependentSet")); + assert!(variants + .iter() + .all(|variant| variant["category"] == "formula")); assert!(variants .iter() .any(|variant| variant["name"] == "KSatisfiability/K3")); } +#[test] +fn test_list_category_rejects_unknown_value() { + let output = pred() + .args(["list", "--category", "unknown"]) + .output() + .unwrap(); + assert!(!output.status.success()); + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(stderr.contains("unknown problem category `unknown`")); + assert!(stderr.contains("algebraic, formula, graph, misc, set")); +} + #[test] fn test_list_searches_variant_aliases() { let output = pred().args(["list", "3SAT"]).output().unwrap(); diff --git a/src/models/algebraic/algebraic_equations_over_gf2.rs b/src/models/algebraic/algebraic_equations_over_gf2.rs index be8d8c33..2f937258 100644 --- a/src/models/algebraic/algebraic_equations_over_gf2.rs +++ b/src/models/algebraic/algebraic_equations_over_gf2.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Algebraic Equations over GF(2)", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Find assignment satisfying multilinear polynomial equations over GF(2)", fields: &[ diff --git a/src/models/algebraic/bmf.rs b/src/models/algebraic/bmf.rs index 455514fe..5ac8f429 100644 --- a/src/models/algebraic/bmf.rs +++ b/src/models/algebraic/bmf.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "BMF", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Boolean matrix factorization", fields: &[ diff --git a/src/models/algebraic/closest_vector_problem.rs b/src/models/algebraic/closest_vector_problem.rs index 2070593a..a6d004a2 100644 --- a/src/models/algebraic/closest_vector_problem.rs +++ b/src/models/algebraic/closest_vector_problem.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Closest Vector Problem", aliases: &["CVP"], dimensions: &[VariantDimension::new("weight", "i32", &["i32", "f64"])], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Find the closest lattice point to a target vector", fields: ClosestVectorProblemI32CreateSpec::FIELDS, diff --git a/src/models/algebraic/consecutive_block_minimization.rs b/src/models/algebraic/consecutive_block_minimization.rs index d816abed..5b5efc62 100644 --- a/src/models/algebraic/consecutive_block_minimization.rs +++ b/src/models/algebraic/consecutive_block_minimization.rs @@ -18,6 +18,7 @@ inventory::submit! { display_name: "Consecutive Block Minimization", aliases: &["CBM"], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Permute columns of a binary matrix to have at most K consecutive blocks of 1s", fields: ConsecutiveBlockMinimizationCreateSpec::FIELDS, diff --git a/src/models/algebraic/consecutive_ones_matrix_augmentation.rs b/src/models/algebraic/consecutive_ones_matrix_augmentation.rs index 10daa96c..8337ffe9 100644 --- a/src/models/algebraic/consecutive_ones_matrix_augmentation.rs +++ b/src/models/algebraic/consecutive_ones_matrix_augmentation.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Consecutive Ones Matrix Augmentation", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Augment a binary matrix with at most K zero-to-one flips so some column permutation has the consecutive ones property", fields: ConsecutiveOnesMatrixAugmentationCreateSpec::FIELDS, diff --git a/src/models/algebraic/consecutive_ones_submatrix.rs b/src/models/algebraic/consecutive_ones_submatrix.rs index 3b7308dd..85e8834a 100644 --- a/src/models/algebraic/consecutive_ones_submatrix.rs +++ b/src/models/algebraic/consecutive_ones_submatrix.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Consecutive Ones Submatrix", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Find K columns of a binary matrix that can be permuted to have the consecutive ones property", fields: &[ diff --git a/src/models/algebraic/equilibrium_point.rs b/src/models/algebraic/equilibrium_point.rs index d87f37c3..c987b8f1 100644 --- a/src/models/algebraic/equilibrium_point.rs +++ b/src/models/algebraic/equilibrium_point.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Equilibrium Point", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Decide whether a pure-strategy Nash equilibrium exists for a multi-player game with polynomial payoff functions", fields: &[ diff --git a/src/models/algebraic/feasible_basis_extension.rs b/src/models/algebraic/feasible_basis_extension.rs index bcdfbf81..4866ed45 100644 --- a/src/models/algebraic/feasible_basis_extension.rs +++ b/src/models/algebraic/feasible_basis_extension.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Feasible Basis Extension", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Given matrix A, vector a_bar, and required columns S, find a feasible basis extending S", fields: FeasibleBasisExtensionCreateSpec::FIELDS, diff --git a/src/models/algebraic/ilp.rs b/src/models/algebraic/ilp.rs index 2a890aa4..c58ff7e2 100644 --- a/src/models/algebraic/ilp.rs +++ b/src/models/algebraic/ilp.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "ILP", aliases: &[], dimensions: &[VariantDimension::new("variable", "bool", &["bool", "i32"])], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Optimize linear objective subject to linear constraints", fields: &[ diff --git a/src/models/algebraic/minimum_matrix_cover.rs b/src/models/algebraic/minimum_matrix_cover.rs index 7aada4ce..1474c10e 100644 --- a/src/models/algebraic/minimum_matrix_cover.rs +++ b/src/models/algebraic/minimum_matrix_cover.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Minimum Matrix Cover", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Find sign assignment minimizing quadratic form over nonnegative integer matrix", fields: &[ diff --git a/src/models/algebraic/minimum_matrix_domination.rs b/src/models/algebraic/minimum_matrix_domination.rs index 49fc9a2e..b633984c 100644 --- a/src/models/algebraic/minimum_matrix_domination.rs +++ b/src/models/algebraic/minimum_matrix_domination.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Minimum Matrix Domination", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Find minimum subset of 1-entries in a binary matrix that dominates all other 1-entries by shared row or column", fields: &[ diff --git a/src/models/algebraic/minimum_weight_decoding.rs b/src/models/algebraic/minimum_weight_decoding.rs index 9cc5dab8..18d42a76 100644 --- a/src/models/algebraic/minimum_weight_decoding.rs +++ b/src/models/algebraic/minimum_weight_decoding.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Minimum Weight Decoding", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Find minimum Hamming weight binary vector x such that Hx ≡ s (mod 2)", fields: MinimumWeightDecodingCreateSpec::FIELDS, diff --git a/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs b/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs index 7c33f0eb..ff04f504 100644 --- a/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs +++ b/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Minimum Weight Solution to Linear Equations", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Find a rational solution to Ay=b minimizing the number of non-zero entries", fields: MinimumWeightSolutionCreateSpec::FIELDS, diff --git a/src/models/algebraic/quadratic_assignment.rs b/src/models/algebraic/quadratic_assignment.rs index 2582d310..741ef103 100644 --- a/src/models/algebraic/quadratic_assignment.rs +++ b/src/models/algebraic/quadratic_assignment.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Quadratic Assignment", aliases: &["QAP"], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Minimize total cost of assigning facilities to locations", fields: &[ diff --git a/src/models/algebraic/quadratic_congruences.rs b/src/models/algebraic/quadratic_congruences.rs index 12ba2fc3..a09cca56 100644 --- a/src/models/algebraic/quadratic_congruences.rs +++ b/src/models/algebraic/quadratic_congruences.rs @@ -22,6 +22,7 @@ inventory::submit! { display_name: "Quadratic Congruences", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Decide whether x² ≡ a (mod b) has a solution for x in {1, ..., c-1}", fields: &[ diff --git a/src/models/algebraic/quadratic_diophantine_equations.rs b/src/models/algebraic/quadratic_diophantine_equations.rs index 7fdc2984..087b780e 100644 --- a/src/models/algebraic/quadratic_diophantine_equations.rs +++ b/src/models/algebraic/quadratic_diophantine_equations.rs @@ -20,6 +20,7 @@ inventory::submit! { display_name: "Quadratic Diophantine Equations", aliases: &["QDE"], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Decide whether ax^2 + by = c has a solution in positive integers x, y", fields: &[ diff --git a/src/models/algebraic/qubo.rs b/src/models/algebraic/qubo.rs index 73bb5e6f..e15eba61 100644 --- a/src/models/algebraic/qubo.rs +++ b/src/models/algebraic/qubo.rs @@ -13,6 +13,7 @@ inventory::submit! { display_name: "QUBO", aliases: &[], dimensions: &[VariantDimension::new("weight", "f64", &["f64"])], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Minimize quadratic unconstrained binary objective", fields: QuboCreateSpec::FIELDS, diff --git a/src/models/algebraic/simultaneous_incongruences.rs b/src/models/algebraic/simultaneous_incongruences.rs index 5dc6263d..bf590a7d 100644 --- a/src/models/algebraic/simultaneous_incongruences.rs +++ b/src/models/algebraic/simultaneous_incongruences.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Simultaneous Incongruences", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Decide whether there exists x with x ≢ aᵢ (mod bᵢ) for all i", fields: &[ diff --git a/src/models/algebraic/sparse_matrix_compression.rs b/src/models/algebraic/sparse_matrix_compression.rs index 186b8a1a..a92d8fc0 100644 --- a/src/models/algebraic/sparse_matrix_compression.rs +++ b/src/models/algebraic/sparse_matrix_compression.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Sparse Matrix Compression", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Algebraic, module_path: module_path!(), description: "Overlay binary-matrix rows into a short storage vector by shifting each row without collisions", fields: SparseMatrixCompressionCreateSpec::FIELDS, diff --git a/src/models/decision.rs b/src/models/decision.rs index 6874d1f9..e9414ff0 100644 --- a/src/models/decision.rs +++ b/src/models/decision.rs @@ -42,6 +42,7 @@ macro_rules! register_decision_variant { $complexity:literal, $aliases:expr, $description:literal, + category: $category:expr, dims: [$($dim:expr),* $(,)?], fields: [$($field:expr),* $(,)?], size_getters: [$(($sg_name:literal, $sg_method:ident)),* $(,)?] @@ -64,6 +65,7 @@ macro_rules! register_decision_variant { display_name: $crate::register_decision_variant!(@display_name $name), aliases: $aliases, dimensions: &[$($dim),*], + category: $category, module_path: module_path!(), description: $description, fields: &[$($field),*], diff --git a/src/models/formula/circuit.rs b/src/models/formula/circuit.rs index 1a951265..65905e22 100644 --- a/src/models/formula/circuit.rs +++ b/src/models/formula/circuit.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Circuit SAT", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "Find satisfying input to a boolean circuit", fields: &[ diff --git a/src/models/formula/ksat.rs b/src/models/formula/ksat.rs index e53d094d..23e185bd 100644 --- a/src/models/formula/ksat.rs +++ b/src/models/formula/ksat.rs @@ -54,6 +54,7 @@ inventory::submit! { display_name: "K-Satisfiability", aliases: &["KSAT"], dimensions: &[VariantDimension::new("k", "KN", &["KN", "K2", "K3"])], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "SAT with exactly k literals per clause", fields: &[ diff --git a/src/models/formula/maximum_2_satisfiability.rs b/src/models/formula/maximum_2_satisfiability.rs index ee6f83fd..ca415b87 100644 --- a/src/models/formula/maximum_2_satisfiability.rs +++ b/src/models/formula/maximum_2_satisfiability.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Maximum 2-Satisfiability", aliases: &["MAX2SAT"], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "Maximize the number of satisfied 2-literal clauses", fields: &[ diff --git a/src/models/formula/nae_satisfiability.rs b/src/models/formula/nae_satisfiability.rs index 834b9a4e..6874d5c9 100644 --- a/src/models/formula/nae_satisfiability.rs +++ b/src/models/formula/nae_satisfiability.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Not-All-Equal Satisfiability", aliases: &["NAESAT"], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "Find an assignment where every CNF clause has both a true and a false literal", fields: &[ diff --git a/src/models/formula/non_tautology.rs b/src/models/formula/non_tautology.rs index 7e983cfb..941149d1 100644 --- a/src/models/formula/non_tautology.rs +++ b/src/models/formula/non_tautology.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Non-Tautology", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "Find a falsifying assignment for a DNF formula (proving it is not a tautology)", fields: &[ diff --git a/src/models/formula/one_in_three_satisfiability.rs b/src/models/formula/one_in_three_satisfiability.rs index 6a6c8759..2d320ba8 100644 --- a/src/models/formula/one_in_three_satisfiability.rs +++ b/src/models/formula/one_in_three_satisfiability.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "One-in-Three Satisfiability", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "3-SAT variant where each clause has exactly one true literal", fields: &[ diff --git a/src/models/formula/planar_3_satisfiability.rs b/src/models/formula/planar_3_satisfiability.rs index 6162c19b..0f5e51c5 100644 --- a/src/models/formula/planar_3_satisfiability.rs +++ b/src/models/formula/planar_3_satisfiability.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Planar 3-Satisfiability", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "3-SAT with planar variable-clause incidence graph", fields: &[ diff --git a/src/models/formula/qbf.rs b/src/models/formula/qbf.rs index c47b88bc..99a8e76f 100644 --- a/src/models/formula/qbf.rs +++ b/src/models/formula/qbf.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Quantified Boolean Formulas", aliases: &["QBF"], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "Determine if a quantified Boolean formula is true", fields: &[ diff --git a/src/models/formula/sat.rs b/src/models/formula/sat.rs index 0557598a..920660ad 100644 --- a/src/models/formula/sat.rs +++ b/src/models/formula/sat.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Satisfiability", aliases: &["SAT"], dimensions: &[], + category: crate::registry::ProblemCategory::Formula, module_path: module_path!(), description: "Find satisfying assignment for CNF formula", fields: &[ diff --git a/src/models/graph/acyclic_partition.rs b/src/models/graph/acyclic_partition.rs index acec604d..1510dedf 100644 --- a/src/models/graph/acyclic_partition.rs +++ b/src/models/graph/acyclic_partition.rs @@ -21,6 +21,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Partition a directed graph into bounded-weight groups with an acyclic quotient graph and bounded inter-partition cost", fields: AcyclicPartitionCreateSpec::FIELDS, diff --git a/src/models/graph/balanced_complete_bipartite_subgraph.rs b/src/models/graph/balanced_complete_bipartite_subgraph.rs index 9f7bd812..6609764f 100644 --- a/src/models/graph/balanced_complete_bipartite_subgraph.rs +++ b/src/models/graph/balanced_complete_bipartite_subgraph.rs @@ -10,6 +10,7 @@ inventory::submit! { display_name: "Balanced Complete Bipartite Subgraph", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Decide whether a bipartite graph contains a K_{k,k} subgraph", fields: BalancedCompleteBipartiteSubgraphCreateSpec::FIELDS, diff --git a/src/models/graph/biclique_cover.rs b/src/models/graph/biclique_cover.rs index 63c36f75..69b5b6a9 100644 --- a/src/models/graph/biclique_cover.rs +++ b/src/models/graph/biclique_cover.rs @@ -26,6 +26,7 @@ inventory::submit! { display_name: "Biclique Cover", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Cover bipartite edges with k bicliques", fields: BicliqueCoverCreateSpec::FIELDS, diff --git a/src/models/graph/biconnectivity_augmentation.rs b/src/models/graph/biconnectivity_augmentation.rs index 2b4d5949..70e084a2 100644 --- a/src/models/graph/biconnectivity_augmentation.rs +++ b/src/models/graph/biconnectivity_augmentation.rs @@ -21,6 +21,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Add weighted potential edges to make a graph biconnected within budget", fields: BiconnectivityAugmentationCreateSpec::FIELDS, diff --git a/src/models/graph/bottleneck_traveling_salesman.rs b/src/models/graph/bottleneck_traveling_salesman.rs index 030f55f3..ea0b841b 100644 --- a/src/models/graph/bottleneck_traveling_salesman.rs +++ b/src/models/graph/bottleneck_traveling_salesman.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Bottleneck Traveling Salesman", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a Hamiltonian cycle minimizing the maximum selected edge weight", fields: BottleneckTravelingSalesmanCreateSpec::FIELDS, diff --git a/src/models/graph/bounded_component_spanning_forest.rs b/src/models/graph/bounded_component_spanning_forest.rs index c9d0c09d..68dc4e49 100644 --- a/src/models/graph/bounded_component_spanning_forest.rs +++ b/src/models/graph/bounded_component_spanning_forest.rs @@ -21,6 +21,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Partition vertices into at most K connected components, each of total weight at most B", fields: BoundedComponentSpanningForestCreateSpec::FIELDS, diff --git a/src/models/graph/bounded_diameter_spanning_tree.rs b/src/models/graph/bounded_diameter_spanning_tree.rs index 42b5561a..16b580dc 100644 --- a/src/models/graph/bounded_diameter_spanning_tree.rs +++ b/src/models/graph/bounded_diameter_spanning_tree.rs @@ -22,6 +22,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Does G have a spanning tree with total weight <= B and diameter <= D?", fields: BoundedDiameterSpanningTreeCreateSpec::FIELDS, diff --git a/src/models/graph/degree_constrained_spanning_tree.rs b/src/models/graph/degree_constrained_spanning_tree.rs index 47338a8f..e17ac695 100644 --- a/src/models/graph/degree_constrained_spanning_tree.rs +++ b/src/models/graph/degree_constrained_spanning_tree.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Does G have a spanning tree with maximum vertex degree at most K?", fields: &[ diff --git a/src/models/graph/directed_hamiltonian_path.rs b/src/models/graph/directed_hamiltonian_path.rs index b395853c..6dd2d612 100644 --- a/src/models/graph/directed_hamiltonian_path.rs +++ b/src/models/graph/directed_hamiltonian_path.rs @@ -16,6 +16,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "DirectedGraph", &["DirectedGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Does the directed graph contain a Hamiltonian path?", fields: &[ diff --git a/src/models/graph/directed_two_commodity_integral_flow.rs b/src/models/graph/directed_two_commodity_integral_flow.rs index f67445df..9a1d18b9 100644 --- a/src/models/graph/directed_two_commodity_integral_flow.rs +++ b/src/models/graph/directed_two_commodity_integral_flow.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Directed Two-Commodity Integral Flow", aliases: &["D2CIF"], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Two-commodity integral flow feasibility on a directed graph", fields: &[ diff --git a/src/models/graph/disjoint_connecting_paths.rs b/src/models/graph/disjoint_connecting_paths.rs index b48a1f1a..92599eb1 100644 --- a/src/models/graph/disjoint_connecting_paths.rs +++ b/src/models/graph/disjoint_connecting_paths.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find pairwise vertex-disjoint paths connecting given terminal pairs", fields: DisjointConnectingPathsCreateSpec::FIELDS, diff --git a/src/models/graph/eulerian_path.rs b/src/models/graph/eulerian_path.rs index b45f43db..8f29e426 100644 --- a/src/models/graph/eulerian_path.rs +++ b/src/models/graph/eulerian_path.rs @@ -28,6 +28,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "DirectedGraph", &["DirectedGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Does the directed multigraph admit a directed trail using every arc exactly once?", fields: &[ diff --git a/src/models/graph/generalized_hex.rs b/src/models/graph/generalized_hex.rs index 06f9d791..0e44aef5 100644 --- a/src/models/graph/generalized_hex.rs +++ b/src/models/graph/generalized_hex.rs @@ -20,6 +20,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Determine whether Player 1 has a forced blue path between two terminals", fields: GeneralizedHexCreateSpec::FIELDS, diff --git a/src/models/graph/graph_partitioning.rs b/src/models/graph/graph_partitioning.rs index f69aadd2..8901f07d 100644 --- a/src/models/graph/graph_partitioning.rs +++ b/src/models/graph/graph_partitioning.rs @@ -17,6 +17,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum cut balanced bisection of a graph", fields: &[ diff --git a/src/models/graph/hamiltonian_circuit.rs b/src/models/graph/hamiltonian_circuit.rs index a66d8568..7617b761 100644 --- a/src/models/graph/hamiltonian_circuit.rs +++ b/src/models/graph/hamiltonian_circuit.rs @@ -17,6 +17,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Does the graph contain a Hamiltonian circuit?", fields: &[ diff --git a/src/models/graph/hamiltonian_path.rs b/src/models/graph/hamiltonian_path.rs index a50787e0..fc324b7d 100644 --- a/src/models/graph/hamiltonian_path.rs +++ b/src/models/graph/hamiltonian_path.rs @@ -17,6 +17,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a Hamiltonian path in a graph", fields: &[ diff --git a/src/models/graph/hamiltonian_path_between_two_vertices.rs b/src/models/graph/hamiltonian_path_between_two_vertices.rs index a11c6fdb..42b1ba45 100644 --- a/src/models/graph/hamiltonian_path_between_two_vertices.rs +++ b/src/models/graph/hamiltonian_path_between_two_vertices.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a Hamiltonian path between two specified vertices in a graph", fields: &[ diff --git a/src/models/graph/highly_connected_deletion.rs b/src/models/graph/highly_connected_deletion.rs index a932f3c8..53c4d92a 100644 --- a/src/models/graph/highly_connected_deletion.rs +++ b/src/models/graph/highly_connected_deletion.rs @@ -32,6 +32,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Minimum number of edge deletions so every component is an isolated vertex or a highly connected graph on >=3 vertices", fields: &[ diff --git a/src/models/graph/integral_flow_bundles.rs b/src/models/graph/integral_flow_bundles.rs index 70e9f5eb..935c2076 100644 --- a/src/models/graph/integral_flow_bundles.rs +++ b/src/models/graph/integral_flow_bundles.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Integral Flow with Bundles", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Integral flow feasibility on a directed graph with overlapping bundle capacities", fields: IntegralFlowBundlesCreateSpec::FIELDS, diff --git a/src/models/graph/integral_flow_homologous_arcs.rs b/src/models/graph/integral_flow_homologous_arcs.rs index 29a0c500..c54f7ea7 100644 --- a/src/models/graph/integral_flow_homologous_arcs.rs +++ b/src/models/graph/integral_flow_homologous_arcs.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Integral Flow with Homologous Arcs", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Integral flow feasibility with arc-pair equality constraints", fields: IntegralFlowHomologousArcsCreateSpec::FIELDS, diff --git a/src/models/graph/integral_flow_with_multipliers.rs b/src/models/graph/integral_flow_with_multipliers.rs index f8ed7210..7fda1c4a 100644 --- a/src/models/graph/integral_flow_with_multipliers.rs +++ b/src/models/graph/integral_flow_with_multipliers.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Integral Flow With Multipliers", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Integral flow feasibility on a directed graph with multiplier-scaled conservation at non-terminal vertices", fields: IntegralFlowWithMultipliersCreateSpec::FIELDS, diff --git a/src/models/graph/isomorphic_spanning_tree.rs b/src/models/graph/isomorphic_spanning_tree.rs index b624280e..3bb981c6 100644 --- a/src/models/graph/isomorphic_spanning_tree.rs +++ b/src/models/graph/isomorphic_spanning_tree.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Does graph G contain a spanning tree isomorphic to tree T?", fields: &[ diff --git a/src/models/graph/kclique.rs b/src/models/graph/kclique.rs index 5f3618a7..24d99b66 100644 --- a/src/models/graph/kclique.rs +++ b/src/models/graph/kclique.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "k-Clique", aliases: &["Clique"], dimensions: &[VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"])], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Determine whether a graph contains a clique of size at least k", fields: KCliqueCreateSpec::FIELDS, diff --git a/src/models/graph/kcoloring.rs b/src/models/graph/kcoloring.rs index 9dfa3629..d1fa16fd 100644 --- a/src/models/graph/kcoloring.rs +++ b/src/models/graph/kcoloring.rs @@ -18,6 +18,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("k", "KN", &["KN", "K2", "K3", "K4", "K5"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find valid k-coloring of a graph", fields: RuntimeKColoringCreateSpec::FIELDS, diff --git a/src/models/graph/kernel.rs b/src/models/graph/kernel.rs index 72b3e1b5..d9dc901a 100644 --- a/src/models/graph/kernel.rs +++ b/src/models/graph/kernel.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "DirectedGraph", &["DirectedGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Does the directed graph contain a kernel (independent and absorbing vertex subset)?", fields: &[ diff --git a/src/models/graph/kth_best_spanning_tree.rs b/src/models/graph/kth_best_spanning_tree.rs index d008f6b6..51f6204b 100644 --- a/src/models/graph/kth_best_spanning_tree.rs +++ b/src/models/graph/kth_best_spanning_tree.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Kth Best Spanning Tree", aliases: &[], dimensions: &[VariantDimension::new("weight", "i32", &["i32"])], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Do there exist k distinct spanning trees with total weight at most B?", fields: KthBestSpanningTreeCreateSpec::FIELDS, diff --git a/src/models/graph/length_bounded_disjoint_paths.rs b/src/models/graph/length_bounded_disjoint_paths.rs index 4cde1aa9..7d4e7a36 100644 --- a/src/models/graph/length_bounded_disjoint_paths.rs +++ b/src/models/graph/length_bounded_disjoint_paths.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Maximize the number of internally vertex-disjoint s-t paths of length at most K", fields: LengthBoundedDisjointPathsCreateSpec::FIELDS, diff --git a/src/models/graph/longest_circuit.rs b/src/models/graph/longest_circuit.rs index 08807033..16d330f7 100644 --- a/src/models/graph/longest_circuit.rs +++ b/src/models/graph/longest_circuit.rs @@ -20,6 +20,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a simple circuit in a graph that maximizes total edge length", fields: LongestCircuitCreateSpec::FIELDS, diff --git a/src/models/graph/longest_path.rs b/src/models/graph/longest_path.rs index 74fd5f9a..86e2292a 100644 --- a/src/models/graph/longest_path.rs +++ b/src/models/graph/longest_path.rs @@ -20,6 +20,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "One"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a simple s-t path of maximum total edge length", fields: LongestPathI32CreateSpec::FIELDS, diff --git a/src/models/graph/max_cut.rs b/src/models/graph/max_cut.rs index cdba9c76..9ff562fc 100644 --- a/src/models/graph/max_cut.rs +++ b/src/models/graph/max_cut.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "One"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find maximum weight cut in a graph", fields: MaxCutI32CreateSpec::FIELDS, diff --git a/src/models/graph/maximal_is.rs b/src/models/graph/maximal_is.rs index 9caaa80c..1c750f1f 100644 --- a/src/models/graph/maximal_is.rs +++ b/src/models/graph/maximal_is.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find maximum weight maximal independent set", fields: MaximalISCreateSpec::FIELDS, diff --git a/src/models/graph/maximum_achromatic_number.rs b/src/models/graph/maximum_achromatic_number.rs index 57d08f85..de91a7b5 100644 --- a/src/models/graph/maximum_achromatic_number.rs +++ b/src/models/graph/maximum_achromatic_number.rs @@ -20,6 +20,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a complete proper coloring maximizing the number of colors", fields: &[ diff --git a/src/models/graph/maximum_clique.rs b/src/models/graph/maximum_clique.rs index 00eba9ba..b7dd79e9 100644 --- a/src/models/graph/maximum_clique.rs +++ b/src/models/graph/maximum_clique.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "One", &["One", "i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find maximum weight clique in a graph", fields: MaximumCliqueCreateSpec::::FIELDS, diff --git a/src/models/graph/maximum_co_k_plex.rs b/src/models/graph/maximum_co_k_plex.rs index a22e22a8..969934cd 100644 --- a/src/models/graph/maximum_co_k_plex.rs +++ b/src/models/graph/maximum_co_k_plex.rs @@ -26,6 +26,7 @@ inventory::submit! { VariantDimension::new("weight", "One", &["One", "i32"]), VariantDimension::new("k", "KN", &["KN"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find maximum-weight vertex subset whose induced subgraph has maximum degree at most k-1", fields: MaximumCoKPlexCreateSpec::::FIELDS, diff --git a/src/models/graph/maximum_common_edge_subgraph.rs b/src/models/graph/maximum_common_edge_subgraph.rs index d35668c6..8a6577b9 100644 --- a/src/models/graph/maximum_common_edge_subgraph.rs +++ b/src/models/graph/maximum_common_edge_subgraph.rs @@ -23,6 +23,7 @@ inventory::submit! { display_name: "Maximum Common Edge Subgraph", aliases: &["MCES"], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Maximize the number of preserved labelled directed arcs under a partial injective vertex map from G1 into G2", fields: &[ diff --git a/src/models/graph/maximum_contact_map_overlap.rs b/src/models/graph/maximum_contact_map_overlap.rs index a325a83b..d331c474 100644 --- a/src/models/graph/maximum_contact_map_overlap.rs +++ b/src/models/graph/maximum_contact_map_overlap.rs @@ -26,6 +26,7 @@ inventory::submit! { display_name: "Maximum Contact Map Overlap", aliases: &["CMO", "MaxCMO"], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Maximize the number of preserved contacts under an order-preserving partial injective alignment from G_1 into G_2", fields: &[ diff --git a/src/models/graph/maximum_domatic_number.rs b/src/models/graph/maximum_domatic_number.rs index 518ebaff..185b16b4 100644 --- a/src/models/graph/maximum_domatic_number.rs +++ b/src/models/graph/maximum_domatic_number.rs @@ -17,6 +17,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find maximum number of disjoint dominating sets partitioning V", fields: &[ diff --git a/src/models/graph/maximum_edge_weighted_k_clique.rs b/src/models/graph/maximum_edge_weighted_k_clique.rs index e4d814e4..74ab09b6 100644 --- a/src/models/graph/maximum_edge_weighted_k_clique.rs +++ b/src/models/graph/maximum_edge_weighted_k_clique.rs @@ -24,6 +24,7 @@ inventory::submit! { display_name: "Maximum Edge-Weighted k-Clique", aliases: &[], dimensions: &[VariantDimension::new("weight", "i32", &["i32", "f64"])], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Select exactly k pairwise-adjacent vertices maximizing the total weight of induced clique edges", fields: MaximumEdgeWeightedKCliqueCreateSpec::::FIELDS, diff --git a/src/models/graph/maximum_independent_set.rs b/src/models/graph/maximum_independent_set.rs index 1d3eb588..f3e6d047 100644 --- a/src/models/graph/maximum_independent_set.rs +++ b/src/models/graph/maximum_independent_set.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph", "KingsSubgraph", "TriangularSubgraph", "UnitDiskGraph"]), VariantDimension::new("weight", "One", &["One", "i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find maximum weight independent set in a graph", fields: MaximumIndependentSetSimpleOneCreateSpec::FIELDS, diff --git a/src/models/graph/maximum_leaf_spanning_tree.rs b/src/models/graph/maximum_leaf_spanning_tree.rs index 3feb0c48..475808b0 100644 --- a/src/models/graph/maximum_leaf_spanning_tree.rs +++ b/src/models/graph/maximum_leaf_spanning_tree.rs @@ -17,6 +17,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find spanning tree maximizing the number of leaves", fields: &[ diff --git a/src/models/graph/maximum_matching.rs b/src/models/graph/maximum_matching.rs index 73bb8652..f6137ca5 100644 --- a/src/models/graph/maximum_matching.rs +++ b/src/models/graph/maximum_matching.rs @@ -20,6 +20,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find maximum weight matching in a graph", fields: MaximumMatchingCreateSpec::FIELDS, diff --git a/src/models/graph/min_max_multicenter.rs b/src/models/graph/min_max_multicenter.rs index a270a6cb..52f002e2 100644 --- a/src/models/graph/min_max_multicenter.rs +++ b/src/models/graph/min_max_multicenter.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "One"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find K centers minimizing the maximum weighted distance from any vertex to its nearest center (vertex p-center)", fields: MinMaxMulticenterI32CreateSpec::FIELDS, diff --git a/src/models/graph/minimum_capacitated_spanning_tree.rs b/src/models/graph/minimum_capacitated_spanning_tree.rs index 3de793ec..2b008f23 100644 --- a/src/models/graph/minimum_capacitated_spanning_tree.rs +++ b/src/models/graph/minimum_capacitated_spanning_tree.rs @@ -22,6 +22,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight spanning tree with subtree capacity constraints", fields: MinimumCapacitatedSpanningTreeCreateSpec::FIELDS, diff --git a/src/models/graph/minimum_cost_circulation.rs b/src/models/graph/minimum_cost_circulation.rs index 9a405aab..f9471cb3 100644 --- a/src/models/graph/minimum_cost_circulation.rs +++ b/src/models/graph/minimum_cost_circulation.rs @@ -43,6 +43,7 @@ inventory::submit! { display_name: "Minimum-Cost Circulation", aliases: &["MCC"], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Integral circulation on a directed multigraph minimizing total signed arc cost", fields: &[ diff --git a/src/models/graph/minimum_cost_maximum_flow.rs b/src/models/graph/minimum_cost_maximum_flow.rs index 8065983f..852a310e 100644 --- a/src/models/graph/minimum_cost_maximum_flow.rs +++ b/src/models/graph/minimum_cost_maximum_flow.rs @@ -51,6 +51,7 @@ inventory::submit! { display_name: "Minimum-Cost Maximum-Flow", aliases: &["MCMF"], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Integral flow that lexicographically maximizes value then minimizes total arc cost", fields: &[ diff --git a/src/models/graph/minimum_covering_by_cliques.rs b/src/models/graph/minimum_covering_by_cliques.rs index 05be374b..db4e9dab 100644 --- a/src/models/graph/minimum_covering_by_cliques.rs +++ b/src/models/graph/minimum_covering_by_cliques.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum number of cliques covering all edges", fields: &[ diff --git a/src/models/graph/minimum_cut_into_bounded_sets.rs b/src/models/graph/minimum_cut_into_bounded_sets.rs index 855302fa..f13bf699 100644 --- a/src/models/graph/minimum_cut_into_bounded_sets.rs +++ b/src/models/graph/minimum_cut_into_bounded_sets.rs @@ -20,6 +20,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a minimum-weight cut partitioning vertices into two bounded-size sets", fields: MinimumCutIntoBoundedSetsCreateSpec::FIELDS, diff --git a/src/models/graph/minimum_dominating_set.rs b/src/models/graph/minimum_dominating_set.rs index f3c5cad3..932cefcb 100644 --- a/src/models/graph/minimum_dominating_set.rs +++ b/src/models/graph/minimum_dominating_set.rs @@ -21,6 +21,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "One"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight dominating set in a graph", fields: MinimumDominatingSetCreateSpec::::FIELDS, @@ -246,6 +247,7 @@ crate::register_decision_variant!( "1.4969^num_vertices", &[], "Decision version: does a dominating set of cost <= bound exist?", + category: crate::registry::ProblemCategory::Graph, dims: [ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "One"]), diff --git a/src/models/graph/minimum_dummy_activities_pert.rs b/src/models/graph/minimum_dummy_activities_pert.rs index 2c3b6225..10dc3a5e 100644 --- a/src/models/graph/minimum_dummy_activities_pert.rs +++ b/src/models/graph/minimum_dummy_activities_pert.rs @@ -20,6 +20,7 @@ inventory::submit! { display_name: "Minimum Dummy Activities in PERT Networks", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a PERT event network for a precedence DAG minimizing dummy activities", fields: MinimumDummyActivitiesPertCreateSpec::FIELDS, diff --git a/src/models/graph/minimum_edge_cost_flow.rs b/src/models/graph/minimum_edge_cost_flow.rs index 86edf998..fd0edc75 100644 --- a/src/models/graph/minimum_edge_cost_flow.rs +++ b/src/models/graph/minimum_edge_cost_flow.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Minimum Edge-Cost Flow", aliases: &["MECF"], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Integral flow minimizing the number of arcs with nonzero flow (weighted by price)", fields: &[ diff --git a/src/models/graph/minimum_feedback_arc_set.rs b/src/models/graph/minimum_feedback_arc_set.rs index 14049d9e..cefc8dcf 100644 --- a/src/models/graph/minimum_feedback_arc_set.rs +++ b/src/models/graph/minimum_feedback_arc_set.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight feedback arc set in a directed graph", fields: MinimumFeedbackArcSetCreateSpec::FIELDS, diff --git a/src/models/graph/minimum_feedback_vertex_set.rs b/src/models/graph/minimum_feedback_vertex_set.rs index cb1130bf..3b03e69c 100644 --- a/src/models/graph/minimum_feedback_vertex_set.rs +++ b/src/models/graph/minimum_feedback_vertex_set.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight feedback vertex set in a directed graph", fields: MinimumFeedbackVertexSetCreateSpec::FIELDS, diff --git a/src/models/graph/minimum_geometric_connected_dominating_set.rs b/src/models/graph/minimum_geometric_connected_dominating_set.rs index b295af09..3d79d415 100644 --- a/src/models/graph/minimum_geometric_connected_dominating_set.rs +++ b/src/models/graph/minimum_geometric_connected_dominating_set.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Minimum Geometric Connected Dominating Set", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum connected dominating set in a geometric point set", fields: &[ diff --git a/src/models/graph/minimum_graph_bandwidth.rs b/src/models/graph/minimum_graph_bandwidth.rs index aac0cbce..22768224 100644 --- a/src/models/graph/minimum_graph_bandwidth.rs +++ b/src/models/graph/minimum_graph_bandwidth.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a vertex ordering minimizing the maximum edge stretch", fields: &[ diff --git a/src/models/graph/minimum_intersection_graph_basis.rs b/src/models/graph/minimum_intersection_graph_basis.rs index 19a89400..f4485d4a 100644 --- a/src/models/graph/minimum_intersection_graph_basis.rs +++ b/src/models/graph/minimum_intersection_graph_basis.rs @@ -19,6 +19,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum universe size for intersection graph representation", fields: &[ diff --git a/src/models/graph/minimum_maximal_matching.rs b/src/models/graph/minimum_maximal_matching.rs index 3b4c53d5..6e195a38 100644 --- a/src/models/graph/minimum_maximal_matching.rs +++ b/src/models/graph/minimum_maximal_matching.rs @@ -17,6 +17,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph", "BipartiteGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a minimum-size matching that cannot be extended", fields: &[ diff --git a/src/models/graph/minimum_metric_dimension.rs b/src/models/graph/minimum_metric_dimension.rs index 21299860..3414349b 100644 --- a/src/models/graph/minimum_metric_dimension.rs +++ b/src/models/graph/minimum_metric_dimension.rs @@ -19,6 +19,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum resolving set of a graph", fields: &[ diff --git a/src/models/graph/minimum_multiway_cut.rs b/src/models/graph/minimum_multiway_cut.rs index 2a5009b4..8143937b 100644 --- a/src/models/graph/minimum_multiway_cut.rs +++ b/src/models/graph/minimum_multiway_cut.rs @@ -20,6 +20,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight set of edges whose removal disconnects all terminal pairs", fields: MinimumMultiwayCutCreateSpec::FIELDS, diff --git a/src/models/graph/minimum_sum_multicenter.rs b/src/models/graph/minimum_sum_multicenter.rs index c2f9bba6..fb98566b 100644 --- a/src/models/graph/minimum_sum_multicenter.rs +++ b/src/models/graph/minimum_sum_multicenter.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find K centers minimizing total weighted distance (p-median problem)", fields: MinimumSumMulticenterCreateSpec::FIELDS, diff --git a/src/models/graph/minimum_vertex_cover.rs b/src/models/graph/minimum_vertex_cover.rs index 95ef994c..82c5b2aa 100644 --- a/src/models/graph/minimum_vertex_cover.rs +++ b/src/models/graph/minimum_vertex_cover.rs @@ -20,6 +20,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "One"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight vertex cover in a graph", fields: MinimumVertexCoverCreateSpec::::FIELDS, @@ -251,6 +252,7 @@ crate::register_decision_variant!( "1.1996^num_vertices", &["DMVC", "VC", "VertexCover"], "Decision version: does a vertex cover of cost <= bound exist?", + category: crate::registry::ProblemCategory::Graph, dims: [ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), diff --git a/src/models/graph/mixed_chinese_postman.rs b/src/models/graph/mixed_chinese_postman.rs index 85237232..a0d067bf 100644 --- a/src/models/graph/mixed_chinese_postman.rs +++ b/src/models/graph/mixed_chinese_postman.rs @@ -22,6 +22,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("weight", "i32", &["i32", "One"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a minimum-cost closed walk covering all arcs and edges in a mixed graph", fields: MixedChinesePostmanI32CreateSpec::FIELDS, diff --git a/src/models/graph/monochromatic_triangle.rs b/src/models/graph/monochromatic_triangle.rs index 17366640..ae7746a5 100644 --- a/src/models/graph/monochromatic_triangle.rs +++ b/src/models/graph/monochromatic_triangle.rs @@ -20,6 +20,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "2-color edges so that no triangle is monochromatic", fields: &[ diff --git a/src/models/graph/multiple_choice_branching.rs b/src/models/graph/multiple_choice_branching.rs index f3279669..e334347c 100644 --- a/src/models/graph/multiple_choice_branching.rs +++ b/src/models/graph/multiple_choice_branching.rs @@ -20,6 +20,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a branching with partition constraints and weight at least K", fields: MultipleChoiceBranchingCreateSpec::FIELDS, diff --git a/src/models/graph/multiple_copy_file_allocation.rs b/src/models/graph/multiple_copy_file_allocation.rs index a3b6d00d..433f7d14 100644 --- a/src/models/graph/multiple_copy_file_allocation.rs +++ b/src/models/graph/multiple_copy_file_allocation.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Multiple Copy File Allocation", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Place file copies on graph vertices to minimize total storage plus access cost", fields: MultipleCopyFileAllocationCreateSpec::FIELDS, diff --git a/src/models/graph/optimal_linear_arrangement.rs b/src/models/graph/optimal_linear_arrangement.rs index 829fb046..ac89218c 100644 --- a/src/models/graph/optimal_linear_arrangement.rs +++ b/src/models/graph/optimal_linear_arrangement.rs @@ -19,6 +19,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a vertex ordering on a line minimizing total edge length", fields: &[ @@ -193,6 +194,7 @@ crate::register_decision_variant!( "2^num_vertices", &["DOLA"], "Decision version: does a linear arrangement of total edge length <= bound exist?", + category: crate::registry::ProblemCategory::Graph, dims: [ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], diff --git a/src/models/graph/partial_feedback_edge_set.rs b/src/models/graph/partial_feedback_edge_set.rs index ef988d00..f8403580 100644 --- a/src/models/graph/partial_feedback_edge_set.rs +++ b/src/models/graph/partial_feedback_edge_set.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Remove at most K edges so that every cycle of length at most L is hit", fields: PartialFeedbackEdgeSetCreateSpec::FIELDS, diff --git a/src/models/graph/partition_into_cliques.rs b/src/models/graph/partition_into_cliques.rs index 4189399b..869872aa 100644 --- a/src/models/graph/partition_into_cliques.rs +++ b/src/models/graph/partition_into_cliques.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Partition vertices into K groups each inducing a clique", fields: &[ diff --git a/src/models/graph/partition_into_forests.rs b/src/models/graph/partition_into_forests.rs index 4c82a565..98f78335 100644 --- a/src/models/graph/partition_into_forests.rs +++ b/src/models/graph/partition_into_forests.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Partition vertices into K classes each inducing an acyclic subgraph", fields: &[ diff --git a/src/models/graph/partition_into_paths_of_length_2.rs b/src/models/graph/partition_into_paths_of_length_2.rs index 717bcab9..e97d4304 100644 --- a/src/models/graph/partition_into_paths_of_length_2.rs +++ b/src/models/graph/partition_into_paths_of_length_2.rs @@ -20,6 +20,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Partition vertices into triples each inducing at least two edges (P3 or triangle)", fields: &[ diff --git a/src/models/graph/partition_into_perfect_matchings.rs b/src/models/graph/partition_into_perfect_matchings.rs index 89fcef0b..c6944c48 100644 --- a/src/models/graph/partition_into_perfect_matchings.rs +++ b/src/models/graph/partition_into_perfect_matchings.rs @@ -19,6 +19,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Partition vertices into K groups each inducing a perfect matching", fields: &[ diff --git a/src/models/graph/partition_into_triangles.rs b/src/models/graph/partition_into_triangles.rs index b14d5efe..02148b0c 100644 --- a/src/models/graph/partition_into_triangles.rs +++ b/src/models/graph/partition_into_triangles.rs @@ -17,6 +17,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Partition vertices into triangles (K3 subgraphs)", fields: &[ diff --git a/src/models/graph/path_constrained_network_flow.rs b/src/models/graph/path_constrained_network_flow.rs index 8ad111ff..8bc785b1 100644 --- a/src/models/graph/path_constrained_network_flow.rs +++ b/src/models/graph/path_constrained_network_flow.rs @@ -18,6 +18,7 @@ inventory::submit! { display_name: "Path-Constrained Network Flow", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Integral flow feasibility on a prescribed collection of directed s-t paths", fields: PathConstrainedNetworkFlowCreateSpec::FIELDS, diff --git a/src/models/graph/prize_collecting_steiner_forest.rs b/src/models/graph/prize_collecting_steiner_forest.rs index e970a4aa..412b1f05 100644 --- a/src/models/graph/prize_collecting_steiner_forest.rs +++ b/src/models/graph/prize_collecting_steiner_forest.rs @@ -42,6 +42,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "f64"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a forest minimizing omitted-prize plus edge-cost plus omega times the number of tree components", fields: PrizeCollectingSteinerForestI32CreateSpec::FIELDS, diff --git a/src/models/graph/rooted_tree_arrangement.rs b/src/models/graph/rooted_tree_arrangement.rs index d5ac3e9f..59be6969 100644 --- a/src/models/graph/rooted_tree_arrangement.rs +++ b/src/models/graph/rooted_tree_arrangement.rs @@ -18,6 +18,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a rooted-tree embedding of a graph with bounded total edge stretch", fields: &[ diff --git a/src/models/graph/rural_postman.rs b/src/models/graph/rural_postman.rs index bb2f5c5b..8743ffe0 100644 --- a/src/models/graph/rural_postman.rs +++ b/src/models/graph/rural_postman.rs @@ -20,6 +20,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a minimum-cost circuit covering all required edges (Rural Postman Problem)", fields: RuralPostmanCreateSpec::FIELDS, diff --git a/src/models/graph/shortest_weight_constrained_path.rs b/src/models/graph/shortest_weight_constrained_path.rs index 4494edf6..9518f1e2 100644 --- a/src/models/graph/shortest_weight_constrained_path.rs +++ b/src/models/graph/shortest_weight_constrained_path.rs @@ -21,6 +21,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find a simple s-t path minimizing total length subject to a weight budget", fields: ShortestWeightConstrainedPathCreateSpec::FIELDS, diff --git a/src/models/graph/spin_glass.rs b/src/models/graph/spin_glass.rs index bdc8e4a6..9349e830 100644 --- a/src/models/graph/spin_glass.rs +++ b/src/models/graph/spin_glass.rs @@ -17,6 +17,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32", "f64"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Minimize Ising Hamiltonian on a graph", fields: SpinGlassI32CreateSpec::FIELDS, diff --git a/src/models/graph/steiner_tree.rs b/src/models/graph/steiner_tree.rs index 3b2a49bf..5a805e04 100644 --- a/src/models/graph/steiner_tree.rs +++ b/src/models/graph/steiner_tree.rs @@ -24,6 +24,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["One", "i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight tree connecting terminal vertices", fields: SteinerTreeCreateSpec::::FIELDS, diff --git a/src/models/graph/steiner_tree_in_graphs.rs b/src/models/graph/steiner_tree_in_graphs.rs index e176e1d1..236ede26 100644 --- a/src/models/graph/steiner_tree_in_graphs.rs +++ b/src/models/graph/steiner_tree_in_graphs.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["One", "i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight subtree connecting all terminal vertices", fields: SteinerTreeInGraphsCreateSpec::::FIELDS, diff --git a/src/models/graph/strong_connectivity_augmentation.rs b/src/models/graph/strong_connectivity_augmentation.rs index d2290640..4b67424d 100644 --- a/src/models/graph/strong_connectivity_augmentation.rs +++ b/src/models/graph/strong_connectivity_augmentation.rs @@ -20,6 +20,7 @@ inventory::submit! { dimensions: &[ VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Add a bounded set of weighted candidate arcs to make a digraph strongly connected", fields: &[ diff --git a/src/models/graph/subgraph_isomorphism.rs b/src/models/graph/subgraph_isomorphism.rs index ca7f7506..ecbba124 100644 --- a/src/models/graph/subgraph_isomorphism.rs +++ b/src/models/graph/subgraph_isomorphism.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Subgraph Isomorphism", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Determine if host graph G contains a subgraph isomorphic to pattern graph H", fields: &[ diff --git a/src/models/graph/traveling_salesman.rs b/src/models/graph/traveling_salesman.rs index efbc9880..15a13700 100644 --- a/src/models/graph/traveling_salesman.rs +++ b/src/models/graph/traveling_salesman.rs @@ -19,6 +19,7 @@ inventory::submit! { VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]), VariantDimension::new("weight", "i32", &["i32"]), ], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Find minimum weight Hamiltonian cycle in a graph (Traveling Salesman Problem)", fields: TravelingSalesmanCreateSpec::FIELDS, diff --git a/src/models/graph/undirected_flow_lower_bounds.rs b/src/models/graph/undirected_flow_lower_bounds.rs index 38822478..7d78832b 100644 --- a/src/models/graph/undirected_flow_lower_bounds.rs +++ b/src/models/graph/undirected_flow_lower_bounds.rs @@ -25,6 +25,7 @@ inventory::submit! { display_name: "Undirected Flow with Lower Bounds", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Determine whether an undirected lower-bounded flow of value at least R exists", fields: UndirectedFlowLowerBoundsCreateSpec::FIELDS, diff --git a/src/models/graph/undirected_two_commodity_integral_flow.rs b/src/models/graph/undirected_two_commodity_integral_flow.rs index 9d866682..d293f564 100644 --- a/src/models/graph/undirected_two_commodity_integral_flow.rs +++ b/src/models/graph/undirected_two_commodity_integral_flow.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Undirected Two-Commodity Integral Flow", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Graph, module_path: module_path!(), description: "Determine whether two integral commodities can satisfy sink demands in an undirected capacitated graph", fields: UndirectedTwoCommodityIntegralFlowCreateSpec::FIELDS, diff --git a/src/models/misc/additional_key.rs b/src/models/misc/additional_key.rs index 6073fc46..e1827a9c 100644 --- a/src/models/misc/additional_key.rs +++ b/src/models/misc/additional_key.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Additional Key", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether a relational schema has a candidate key not in a given set", fields: &[ diff --git a/src/models/misc/betweenness.rs b/src/models/misc/betweenness.rs index 2062f6af..4d63462e 100644 --- a/src/models/misc/betweenness.rs +++ b/src/models/misc/betweenness.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Betweenness", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a linear ordering where specified elements are between others", fields: &[ diff --git a/src/models/misc/bin_packing.rs b/src/models/misc/bin_packing.rs index a778c239..25dc9d39 100644 --- a/src/models/misc/bin_packing.rs +++ b/src/models/misc/bin_packing.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Bin Packing", aliases: &[], dimensions: &[VariantDimension::new("weight", "i32", &["i32", "f64"])], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign items to bins minimizing number of bins used, subject to capacity", fields: &[ diff --git a/src/models/misc/boyce_codd_normal_form_violation.rs b/src/models/misc/boyce_codd_normal_form_violation.rs index 7d6cc133..1d34f66a 100644 --- a/src/models/misc/boyce_codd_normal_form_violation.rs +++ b/src/models/misc/boyce_codd_normal_form_violation.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Boyce-Codd Normal Form Violation", aliases: &["BCNFViolation", "BCNF"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Test whether a subset of attributes violates Boyce-Codd normal form", fields: BoyceCoddNormalFormViolationCreateSpec::FIELDS, diff --git a/src/models/misc/capacity_assignment.rs b/src/models/misc/capacity_assignment.rs index ecb7e27e..4008bbe4 100644 --- a/src/models/misc/capacity_assignment.rs +++ b/src/models/misc/capacity_assignment.rs @@ -13,6 +13,7 @@ inventory::submit! { display_name: "Capacity Assignment", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Minimize total cost of capacity assignment subject to a delay budget", fields: CapacityAssignmentCreateSpec::FIELDS, diff --git a/src/models/misc/closest_string.rs b/src/models/misc/closest_string.rs index 05c64689..6cfc7865 100644 --- a/src/models/misc/closest_string.rs +++ b/src/models/misc/closest_string.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Closest String", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a center string of fixed length that minimizes the maximum Hamming distance to a list of equal-length input strings", fields: &[ diff --git a/src/models/misc/closest_substring.rs b/src/models/misc/closest_substring.rs index 7e33a1b5..67e825dc 100644 --- a/src/models/misc/closest_substring.rs +++ b/src/models/misc/closest_substring.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Closest Substring", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a center string of fixed length and one length-ell window per input string that minimize the maximum Hamming distance between the center and any selected window", fields: &[ diff --git a/src/models/misc/clustering.rs b/src/models/misc/clustering.rs index 3bb34008..469cbf9d 100644 --- a/src/models/misc/clustering.rs +++ b/src/models/misc/clustering.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Clustering", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Partition elements into at most K clusters where all intra-cluster distances are at most B", fields: &[ diff --git a/src/models/misc/conjunctive_boolean_query.rs b/src/models/misc/conjunctive_boolean_query.rs index fad6fdd9..9179d118 100644 --- a/src/models/misc/conjunctive_boolean_query.rs +++ b/src/models/misc/conjunctive_boolean_query.rs @@ -20,6 +20,7 @@ inventory::submit! { display_name: "Conjunctive Boolean Query", aliases: &["CBQ"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Evaluate a conjunctive Boolean query over a relational database", fields: ConjunctiveBooleanQueryCreateSpec::FIELDS, diff --git a/src/models/misc/conjunctive_query_foldability.rs b/src/models/misc/conjunctive_query_foldability.rs index cd3963c5..7e1014ed 100644 --- a/src/models/misc/conjunctive_query_foldability.rs +++ b/src/models/misc/conjunctive_query_foldability.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Conjunctive Query Foldability", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine if one conjunctive query can be folded into another by substituting undistinguished variables", fields: &[ diff --git a/src/models/misc/consistency_of_database_frequency_tables.rs b/src/models/misc/consistency_of_database_frequency_tables.rs index 250751da..4f8dab42 100644 --- a/src/models/misc/consistency_of_database_frequency_tables.rs +++ b/src/models/misc/consistency_of_database_frequency_tables.rs @@ -88,6 +88,7 @@ inventory::submit! { display_name: "Consistency of Database Frequency Tables", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether pairwise frequency tables and known values admit a consistent complete database assignment", fields: ConsistencyOfDatabaseFrequencyTablesCreateSpec::FIELDS, diff --git a/src/models/misc/cosine_product_integration.rs b/src/models/misc/cosine_product_integration.rs index 1716cc77..595a23b6 100644 --- a/src/models/misc/cosine_product_integration.rs +++ b/src/models/misc/cosine_product_integration.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Cosine Product Integration", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Decide whether a balanced sign assignment exists for a sequence of integer frequencies", fields: &[ diff --git a/src/models/misc/cyclic_ordering.rs b/src/models/misc/cyclic_ordering.rs index 9087fe49..ba884db6 100644 --- a/src/models/misc/cyclic_ordering.rs +++ b/src/models/misc/cyclic_ordering.rs @@ -18,6 +18,7 @@ inventory::submit! { display_name: "Cyclic Ordering", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a permutation satisfying cyclic ordering constraints on triples", fields: &[ diff --git a/src/models/misc/dynamic_storage_allocation.rs b/src/models/misc/dynamic_storage_allocation.rs index adcba4d9..8a9c3f6a 100644 --- a/src/models/misc/dynamic_storage_allocation.rs +++ b/src/models/misc/dynamic_storage_allocation.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Dynamic Storage Allocation", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign starting addresses for items with time intervals and sizes within bounded memory", fields: &[ diff --git a/src/models/misc/ensemble_computation.rs b/src/models/misc/ensemble_computation.rs index 479e7eb4..5fcd2476 100644 --- a/src/models/misc/ensemble_computation.rs +++ b/src/models/misc/ensemble_computation.rs @@ -11,6 +11,7 @@ inventory::submit! { display_name: "Ensemble Computation", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find the minimum-length sequence of disjoint unions that builds all required subsets", fields: &[ diff --git a/src/models/misc/expected_retrieval_cost.rs b/src/models/misc/expected_retrieval_cost.rs index 573e6f49..f6df30c4 100644 --- a/src/models/misc/expected_retrieval_cost.rs +++ b/src/models/misc/expected_retrieval_cost.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Expected Retrieval Cost", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign records to circular storage sectors to minimize expected retrieval latency", fields: &[ diff --git a/src/models/misc/factoring.rs b/src/models/misc/factoring.rs index 9b72b275..bf71653b 100644 --- a/src/models/misc/factoring.rs +++ b/src/models/misc/factoring.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Factoring", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Factor a composite integer into two factors", fields: &[ diff --git a/src/models/misc/feasible_register_assignment.rs b/src/models/misc/feasible_register_assignment.rs index 64c0e340..9f68aafa 100644 --- a/src/models/misc/feasible_register_assignment.rs +++ b/src/models/misc/feasible_register_assignment.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Feasible Register Assignment", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether a DAG computation can be scheduled without register conflicts under a fixed assignment", fields: &[ diff --git a/src/models/misc/flow_shop_scheduling.rs b/src/models/misc/flow_shop_scheduling.rs index d29937b8..a86d6e3c 100644 --- a/src/models/misc/flow_shop_scheduling.rs +++ b/src/models/misc/flow_shop_scheduling.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Flow Shop Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine if a flow-shop schedule for jobs on m processors meets a deadline", fields: &[ diff --git a/src/models/misc/grouping_by_swapping.rs b/src/models/misc/grouping_by_swapping.rs index e9f99cb5..eb2185ed 100644 --- a/src/models/misc/grouping_by_swapping.rs +++ b/src/models/misc/grouping_by_swapping.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Grouping by Swapping", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Group equal symbols into contiguous blocks using at most K adjacent swaps", fields: GroupingBySwappingCreateSpec::FIELDS, diff --git a/src/models/misc/integer_expression_membership.rs b/src/models/misc/integer_expression_membership.rs index 0e47f300..d7ff2f32 100644 --- a/src/models/misc/integer_expression_membership.rs +++ b/src/models/misc/integer_expression_membership.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Integer Expression Membership", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Decide whether a target integer belongs to the set represented by an expression tree over union and Minkowski sum", fields: &[ diff --git a/src/models/misc/job_shop_scheduling.rs b/src/models/misc/job_shop_scheduling.rs index bdec8b68..26733f47 100644 --- a/src/models/misc/job_shop_scheduling.rs +++ b/src/models/misc/job_shop_scheduling.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Job-Shop Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Minimize the makespan of a job-shop schedule", fields: JobShopSchedulingCreateSpec::FIELDS, diff --git a/src/models/misc/knapsack.rs b/src/models/misc/knapsack.rs index 1b268c48..d7c9e04e 100644 --- a/src/models/misc/knapsack.rs +++ b/src/models/misc/knapsack.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Knapsack", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Select items to maximize total value subject to weight capacity constraint", fields: KnapsackCreateSpec::FIELDS, diff --git a/src/models/misc/kth_largest_m_tuple.rs b/src/models/misc/kth_largest_m_tuple.rs index 49489f93..ef5d378c 100644 --- a/src/models/misc/kth_largest_m_tuple.rs +++ b/src/models/misc/kth_largest_m_tuple.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Kth Largest m-Tuple", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Count m-tuples whose total size meets a bound and compare against a threshold K", fields: KthLargestMTupleCreateSpec::FIELDS, diff --git a/src/models/misc/longest_common_subsequence.rs b/src/models/misc/longest_common_subsequence.rs index 20b05e6a..35120209 100644 --- a/src/models/misc/longest_common_subsequence.rs +++ b/src/models/misc/longest_common_subsequence.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Longest Common Subsequence", aliases: &["LCS"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a longest common subsequence for a set of strings", fields: LongestCommonSubsequenceCreateSpec::FIELDS, diff --git a/src/models/misc/maximum_likelihood_ranking.rs b/src/models/misc/maximum_likelihood_ranking.rs index 89d178d4..d4c6361e 100644 --- a/src/models/misc/maximum_likelihood_ranking.rs +++ b/src/models/misc/maximum_likelihood_ranking.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Maximum Likelihood Ranking", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a ranking minimizing total pairwise disagreement cost", fields: &[ diff --git a/src/models/misc/minimum_axiom_set.rs b/src/models/misc/minimum_axiom_set.rs index 705e155c..d6cde9bd 100644 --- a/src/models/misc/minimum_axiom_set.rs +++ b/src/models/misc/minimum_axiom_set.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Minimum Axiom Set", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find smallest axiom subset whose deductive closure equals the true sentences", fields: &[ diff --git a/src/models/misc/minimum_code_generation_one_register.rs b/src/models/misc/minimum_code_generation_one_register.rs index 58fe83a2..b7dde257 100644 --- a/src/models/misc/minimum_code_generation_one_register.rs +++ b/src/models/misc/minimum_code_generation_one_register.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Minimum Code Generation (One Register)", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find minimum-length instruction sequence for a one-register machine to evaluate an expression DAG", fields: &[ diff --git a/src/models/misc/minimum_code_generation_parallel_assignments.rs b/src/models/misc/minimum_code_generation_parallel_assignments.rs index 09f4595f..7617ee15 100644 --- a/src/models/misc/minimum_code_generation_parallel_assignments.rs +++ b/src/models/misc/minimum_code_generation_parallel_assignments.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Minimum Code Generation (Parallel Assignments)", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find an ordering of parallel assignments minimizing backward dependencies", fields: &[ diff --git a/src/models/misc/minimum_code_generation_unlimited_registers.rs b/src/models/misc/minimum_code_generation_unlimited_registers.rs index e4144d60..4233734e 100644 --- a/src/models/misc/minimum_code_generation_unlimited_registers.rs +++ b/src/models/misc/minimum_code_generation_unlimited_registers.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Minimum Code Generation (Unlimited Registers)", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find minimum-length instruction sequence for an unlimited-register machine with 2-address instructions to evaluate an expression DAG", fields: &[ diff --git a/src/models/misc/minimum_decision_tree.rs b/src/models/misc/minimum_decision_tree.rs index 8fdbe13d..c3948e94 100644 --- a/src/models/misc/minimum_decision_tree.rs +++ b/src/models/misc/minimum_decision_tree.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Minimum Decision Tree", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find decision tree identifying objects with minimum total path length", fields: MinimumDecisionTreeCreateSpec::FIELDS, diff --git a/src/models/misc/minimum_discrete_planar_inverse_kinematics.rs b/src/models/misc/minimum_discrete_planar_inverse_kinematics.rs index deff9704..351b58f7 100644 --- a/src/models/misc/minimum_discrete_planar_inverse_kinematics.rs +++ b/src/models/misc/minimum_discrete_planar_inverse_kinematics.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Minimum Discrete Planar Inverse Kinematics", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Pick one sampled absolute orientation per link, subject to consecutive-pair feasibility constraints, to minimize the squared distance from the end-effector to a target point", fields: &[ diff --git a/src/models/misc/minimum_disjunctive_normal_form.rs b/src/models/misc/minimum_disjunctive_normal_form.rs index a705a34e..b4e3211a 100644 --- a/src/models/misc/minimum_disjunctive_normal_form.rs +++ b/src/models/misc/minimum_disjunctive_normal_form.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Minimum Disjunctive Normal Form", aliases: &["MinDNF"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find minimum-term DNF formula equivalent to a Boolean function", fields: &[ diff --git a/src/models/misc/minimum_external_macro_data_compression.rs b/src/models/misc/minimum_external_macro_data_compression.rs index dd6fbbd0..32d99b11 100644 --- a/src/models/misc/minimum_external_macro_data_compression.rs +++ b/src/models/misc/minimum_external_macro_data_compression.rs @@ -25,6 +25,7 @@ inventory::submit! { display_name: "Minimum External Macro Data Compression", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find minimum-cost compression using an external dictionary and compressed string with pointers", fields: &[ diff --git a/src/models/misc/minimum_fault_detection_test_set.rs b/src/models/misc/minimum_fault_detection_test_set.rs index 43efeae6..9ae36bb7 100644 --- a/src/models/misc/minimum_fault_detection_test_set.rs +++ b/src/models/misc/minimum_fault_detection_test_set.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Minimum Fault Detection Test Set", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find minimum set of input-output paths covering all internal DAG vertices", fields: &[ diff --git a/src/models/misc/minimum_internal_macro_data_compression.rs b/src/models/misc/minimum_internal_macro_data_compression.rs index 15f76309..34d902f3 100644 --- a/src/models/misc/minimum_internal_macro_data_compression.rs +++ b/src/models/misc/minimum_internal_macro_data_compression.rs @@ -23,6 +23,7 @@ inventory::submit! { display_name: "Minimum Internal Macro Data Compression", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find minimum-cost self-referencing compression of a string with embedded pointers", fields: &[ diff --git a/src/models/misc/minimum_register_sufficiency_for_loops.rs b/src/models/misc/minimum_register_sufficiency_for_loops.rs index fc6d1902..747ee6a2 100644 --- a/src/models/misc/minimum_register_sufficiency_for_loops.rs +++ b/src/models/misc/minimum_register_sufficiency_for_loops.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Minimum Register Sufficiency for Loops", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign registers to loop variables minimizing register count, no two conflicting variables share a register", fields: &[ diff --git a/src/models/misc/minimum_tardiness_sequencing.rs b/src/models/misc/minimum_tardiness_sequencing.rs index a743fcc4..94c7f7c1 100644 --- a/src/models/misc/minimum_tardiness_sequencing.rs +++ b/src/models/misc/minimum_tardiness_sequencing.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Minimum Tardiness Sequencing", aliases: &[], dimensions: &[VariantDimension::new("weight", "One", &["One", "i32"])], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule tasks with precedence constraints and deadlines to minimize the number of tardy tasks", fields: MinimumTardinessSequencingOneCreateSpec::FIELDS, diff --git a/src/models/misc/minimum_weight_and_or_graph.rs b/src/models/misc/minimum_weight_and_or_graph.rs index 662fc359..d1a2d2f7 100644 --- a/src/models/misc/minimum_weight_and_or_graph.rs +++ b/src/models/misc/minimum_weight_and_or_graph.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Minimum Weight AND/OR Graph", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find the minimum-weight solution subgraph from a source in a DAG with AND/OR gates", fields: MinimumWeightAndOrGraphCreateSpec::FIELDS, diff --git a/src/models/misc/multiprocessor_scheduling.rs b/src/models/misc/multiprocessor_scheduling.rs index 65d9ff2c..7617024e 100644 --- a/src/models/misc/multiprocessor_scheduling.rs +++ b/src/models/misc/multiprocessor_scheduling.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Multiprocessor Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign tasks to processors so that no processor's load exceeds a deadline", fields: MultiprocessorSchedulingCreateSpec::FIELDS, diff --git a/src/models/misc/non_liveness_free_petri_net.rs b/src/models/misc/non_liveness_free_petri_net.rs index 322a2e72..cd3584ec 100644 --- a/src/models/misc/non_liveness_free_petri_net.rs +++ b/src/models/misc/non_liveness_free_petri_net.rs @@ -23,6 +23,7 @@ inventory::submit! { display_name: "Non-Liveness Free Petri Net", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether a free-choice Petri net is not live (some transition can become permanently dead)", fields: &[ diff --git a/src/models/misc/numerical_3_dimensional_matching.rs b/src/models/misc/numerical_3_dimensional_matching.rs index cb436364..db763f51 100644 --- a/src/models/misc/numerical_3_dimensional_matching.rs +++ b/src/models/misc/numerical_3_dimensional_matching.rs @@ -18,6 +18,7 @@ inventory::submit! { display_name: "Numerical 3-Dimensional Matching", aliases: &["N3DM"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Partition W∪X∪Y into m triples (one from each set) each summing to B", fields: &[ diff --git a/src/models/misc/numerical_matching_with_target_sums.rs b/src/models/misc/numerical_matching_with_target_sums.rs index 377c4438..fd985739 100644 --- a/src/models/misc/numerical_matching_with_target_sums.rs +++ b/src/models/misc/numerical_matching_with_target_sums.rs @@ -18,6 +18,7 @@ inventory::submit! { display_name: "Numerical Matching with Target Sums", aliases: &["NMTS"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Partition X∪Y into m pairs (one from X, one from Y) with pair sums matching targets", fields: &[ diff --git a/src/models/misc/open_shop_scheduling.rs b/src/models/misc/open_shop_scheduling.rs index 9cbb33bc..f5ff161e 100644 --- a/src/models/misc/open_shop_scheduling.rs +++ b/src/models/misc/open_shop_scheduling.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Open Shop Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Minimize the makespan of an open-shop schedule", fields: OpenShopSchedulingCreateSpec::FIELDS, diff --git a/src/models/misc/optimum_communication_spanning_tree.rs b/src/models/misc/optimum_communication_spanning_tree.rs index 41c0f763..c354d8ac 100644 --- a/src/models/misc/optimum_communication_spanning_tree.rs +++ b/src/models/misc/optimum_communication_spanning_tree.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Optimum Communication Spanning Tree", aliases: &["OCST"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find spanning tree minimizing total weighted communication cost", fields: OptimumCommunicationSpanningTreeCreateSpec::FIELDS, diff --git a/src/models/misc/paintshop.rs b/src/models/misc/paintshop.rs index b144ced5..bcf21dc9 100644 --- a/src/models/misc/paintshop.rs +++ b/src/models/misc/paintshop.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Paint Shop", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Minimize color changes in paint shop sequence", fields: &[ diff --git a/src/models/misc/partially_ordered_knapsack.rs b/src/models/misc/partially_ordered_knapsack.rs index e70e3be4..57e9b8fc 100644 --- a/src/models/misc/partially_ordered_knapsack.rs +++ b/src/models/misc/partially_ordered_knapsack.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Partially Ordered Knapsack", aliases: &["POK"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Select items to maximize total value subject to precedence constraints and weight capacity", fields: PartiallyOrderedKnapsackCreateSpec::FIELDS, diff --git a/src/models/misc/partition.rs b/src/models/misc/partition.rs index 1f42dddb..bf9ebd1d 100644 --- a/src/models/misc/partition.rs +++ b/src/models/misc/partition.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Partition", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether a multiset of positive integers can be partitioned into two subsets of equal sum", fields: &[ diff --git a/src/models/misc/precedence_constrained_scheduling.rs b/src/models/misc/precedence_constrained_scheduling.rs index b46dcc5f..15f726e6 100644 --- a/src/models/misc/precedence_constrained_scheduling.rs +++ b/src/models/misc/precedence_constrained_scheduling.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Precedence Constrained Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule unit-length tasks on m processors by deadline D respecting precedence constraints", fields: PrecedenceConstrainedSchedulingCreateSpec::FIELDS, diff --git a/src/models/misc/preemptive_scheduling.rs b/src/models/misc/preemptive_scheduling.rs index fbe1d98e..2533ef86 100644 --- a/src/models/misc/preemptive_scheduling.rs +++ b/src/models/misc/preemptive_scheduling.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Preemptive Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Minimize makespan for preemptive parallel-processor scheduling with precedence constraints", fields: PreemptiveSchedulingCreateSpec::FIELDS, diff --git a/src/models/misc/production_planning.rs b/src/models/misc/production_planning.rs index e670d35e..375a3592 100644 --- a/src/models/misc/production_planning.rs +++ b/src/models/misc/production_planning.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Production Planning", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether a multi-period production plan can satisfy all demand within a cost bound", fields: ProductionPlanningCreateSpec::FIELDS, diff --git a/src/models/misc/rectilinear_picture_compression.rs b/src/models/misc/rectilinear_picture_compression.rs index 13243e40..50f66275 100644 --- a/src/models/misc/rectilinear_picture_compression.rs +++ b/src/models/misc/rectilinear_picture_compression.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Rectilinear Picture Compression", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Cover all 1-entries of a binary matrix with at most K axis-aligned all-1 rectangles", fields: &[ diff --git a/src/models/misc/register_sufficiency.rs b/src/models/misc/register_sufficiency.rs index 3530cdde..e843fedc 100644 --- a/src/models/misc/register_sufficiency.rs +++ b/src/models/misc/register_sufficiency.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Register Sufficiency", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether a DAG computation can be performed using K or fewer registers", fields: &[ diff --git a/src/models/misc/resource_constrained_scheduling.rs b/src/models/misc/resource_constrained_scheduling.rs index 4a714371..c12a38e1 100644 --- a/src/models/misc/resource_constrained_scheduling.rs +++ b/src/models/misc/resource_constrained_scheduling.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Resource Constrained Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule unit-length tasks on m processors with resource constraints and a deadline", fields: &[ diff --git a/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs b/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs index 24ac4fcb..46fbb2bf 100644 --- a/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs +++ b/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Scheduling to Minimize Weighted Completion Time", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign tasks to processors to minimize total weighted completion time (Smith's rule ordering)", fields: SchedulingToMinimizeWeightedCompletionTimeCreateSpec::FIELDS, diff --git a/src/models/misc/scheduling_with_individual_deadlines.rs b/src/models/misc/scheduling_with_individual_deadlines.rs index f48c82a0..e98cb534 100644 --- a/src/models/misc/scheduling_with_individual_deadlines.rs +++ b/src/models/misc/scheduling_with_individual_deadlines.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Scheduling With Individual Deadlines", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether unit-length tasks can be scheduled on m processors while meeting individual deadlines", fields: SchedulingWithIndividualDeadlinesCreateSpec::FIELDS, diff --git a/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs b/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs index b34045d6..ada08db4 100644 --- a/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs +++ b/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Sequencing to Minimize Maximum Cumulative Cost", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule tasks with precedence constraints to minimize the maximum cumulative cost prefix", fields: SequencingCumulativeCostCreateSpec::FIELDS, diff --git a/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs b/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs index 3bd89bba..2b16cf9d 100644 --- a/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs +++ b/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Sequencing to Minimize Tardy Task Weight", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule tasks with lengths, weights, and deadlines to minimize total weight of tardy tasks", fields: SequencingToMinimizeTardyTaskWeightCreateSpec::FIELDS, diff --git a/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs b/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs index 4390ecbe..d02e32dd 100644 --- a/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs +++ b/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs @@ -21,6 +21,7 @@ inventory::submit! { display_name: "Sequencing to Minimize Weighted Completion Time", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule tasks with lengths, weights, and precedence constraints to minimize total weighted completion time", fields: SequencingToMinimizeWeightedCompletionTimeCreateSpec::FIELDS, diff --git a/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs b/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs index 46d2c0aa..c3c5edc3 100644 --- a/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs +++ b/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Sequencing to Minimize Weighted Tardiness", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule jobs on one machine so total weighted tardiness is at most K", fields: SequencingToMinimizeWeightedTardinessCreateSpec::FIELDS, diff --git a/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs b/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs index 3b14e6bc..98f67f2e 100644 --- a/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs +++ b/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Sequencing with Deadlines and Set-Up Times", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Determine whether all tasks can be scheduled on a single machine by their deadlines given compiler-switch setup penalties", fields: &[ diff --git a/src/models/misc/sequencing_with_release_times_and_deadlines.rs b/src/models/misc/sequencing_with_release_times_and_deadlines.rs index 35c7c960..b418549e 100644 --- a/src/models/misc/sequencing_with_release_times_and_deadlines.rs +++ b/src/models/misc/sequencing_with_release_times_and_deadlines.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Sequencing with Release Times and Deadlines", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Single-machine scheduling feasibility: can all tasks be scheduled within their release-deadline windows without overlap?", fields: &[ diff --git a/src/models/misc/sequencing_within_intervals.rs b/src/models/misc/sequencing_within_intervals.rs index 8534f501..53d4d446 100644 --- a/src/models/misc/sequencing_within_intervals.rs +++ b/src/models/misc/sequencing_within_intervals.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Sequencing Within Intervals", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Schedule tasks non-overlappingly within their time windows", fields: SequencingWithinIntervalsCreateSpec::FIELDS, diff --git a/src/models/misc/shortest_common_supersequence.rs b/src/models/misc/shortest_common_supersequence.rs index 03204134..cc878de3 100644 --- a/src/models/misc/shortest_common_supersequence.rs +++ b/src/models/misc/shortest_common_supersequence.rs @@ -23,6 +23,7 @@ inventory::submit! { display_name: "Shortest Common Supersequence", aliases: &["SCS"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a shortest common supersequence for a set of strings", fields: ShortestCommonSupersequenceCreateSpec::FIELDS, diff --git a/src/models/misc/shortest_common_superstring.rs b/src/models/misc/shortest_common_superstring.rs index 9aabc97d..82c8ec80 100644 --- a/src/models/misc/shortest_common_superstring.rs +++ b/src/models/misc/shortest_common_superstring.rs @@ -27,6 +27,7 @@ inventory::submit! { display_name: "Shortest Common Superstring", aliases: &["SCSS"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a shortest string that contains every input string as a contiguous substring", fields: &[ diff --git a/src/models/misc/square_tiling.rs b/src/models/misc/square_tiling.rs index fe27d4a3..e6131387 100644 --- a/src/models/misc/square_tiling.rs +++ b/src/models/misc/square_tiling.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Square Tiling", aliases: &["WangTiling"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Place colored square tiles on an N x N grid with matching edge colors", fields: &[ diff --git a/src/models/misc/stacker_crane.rs b/src/models/misc/stacker_crane.rs index 45326675..bcc136ad 100644 --- a/src/models/misc/stacker_crane.rs +++ b/src/models/misc/stacker_crane.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "Stacker Crane", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a closed walk that traverses each required directed arc and minimizes total length", fields: StackerCraneCreateSpec::FIELDS, diff --git a/src/models/misc/staff_scheduling.rs b/src/models/misc/staff_scheduling.rs index 990063e7..eae9d161 100644 --- a/src/models/misc/staff_scheduling.rs +++ b/src/models/misc/staff_scheduling.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Staff Scheduling", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign workers to schedule patterns to satisfy per-period staffing requirements within a worker budget", fields: StaffSchedulingCreateSpec::FIELDS, diff --git a/src/models/misc/string_to_string_correction.rs b/src/models/misc/string_to_string_correction.rs index f884cc52..0e9df252 100644 --- a/src/models/misc/string_to_string_correction.rs +++ b/src/models/misc/string_to_string_correction.rs @@ -24,6 +24,7 @@ inventory::submit! { display_name: "String-to-String Correction", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Derive target string from source using at most K deletions and adjacent swaps", fields: StringToStringCorrectionCreateSpec::FIELDS, diff --git a/src/models/misc/subset_product.rs b/src/models/misc/subset_product.rs index b82136ed..478cfc20 100644 --- a/src/models/misc/subset_product.rs +++ b/src/models/misc/subset_product.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Subset Product", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a subset of positive integers whose product equals exactly a target value", fields: &[ diff --git a/src/models/misc/subset_sum.rs b/src/models/misc/subset_sum.rs index d0346613..a151d418 100644 --- a/src/models/misc/subset_sum.rs +++ b/src/models/misc/subset_sum.rs @@ -19,6 +19,7 @@ inventory::submit! { display_name: "Subset Sum", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Find a subset of positive integers that sums to exactly a target value", fields: &[ diff --git a/src/models/misc/sum_of_squares_partition.rs b/src/models/misc/sum_of_squares_partition.rs index 050042bd..e93e7553 100644 --- a/src/models/misc/sum_of_squares_partition.rs +++ b/src/models/misc/sum_of_squares_partition.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Sum of Squares Partition", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Partition positive integers into K groups minimizing the sum of squared group sums", fields: &[ diff --git a/src/models/misc/three_partition.rs b/src/models/misc/three_partition.rs index 47c3f26e..9f903de0 100644 --- a/src/models/misc/three_partition.rs +++ b/src/models/misc/three_partition.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "3-Partition", aliases: &["3Partition", "3-Partition"], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Partition 3m bounded positive integers into m triples whose sums all equal B", fields: ThreePartitionCreateSpec::FIELDS, diff --git a/src/models/misc/timetable_design.rs b/src/models/misc/timetable_design.rs index 94f687ac..627dc1db 100644 --- a/src/models/misc/timetable_design.rs +++ b/src/models/misc/timetable_design.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Timetable Design", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Misc, module_path: module_path!(), description: "Assign craftsmen to tasks over work periods subject to availability and exact pairwise requirements", fields: TimetableDesignCreateSpec::FIELDS, diff --git a/src/models/set/comparative_containment.rs b/src/models/set/comparative_containment.rs index 94d510c9..07e06af2 100644 --- a/src/models/set/comparative_containment.rs +++ b/src/models/set/comparative_containment.rs @@ -23,6 +23,7 @@ inventory::submit! { display_name: "Comparative Containment", aliases: &[], dimensions: &[VariantDimension::new("weight", "i32", &["One", "i32", "f64"])], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Compare containment-weight sums for two set families over a shared universe", fields: ComparativeContainmentI32CreateSpec::FIELDS, diff --git a/src/models/set/consecutive_sets.rs b/src/models/set/consecutive_sets.rs index 1e50f29d..6d354b3b 100644 --- a/src/models/set/consecutive_sets.rs +++ b/src/models/set/consecutive_sets.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Consecutive Sets", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Determine if a string exists where each subset's elements appear consecutively", fields: &[ diff --git a/src/models/set/exact_cover_by_3_sets.rs b/src/models/set/exact_cover_by_3_sets.rs index a4aab228..9cc04def 100644 --- a/src/models/set/exact_cover_by_3_sets.rs +++ b/src/models/set/exact_cover_by_3_sets.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Exact Cover by 3-Sets", aliases: &["X3C"], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Determine if a collection of 3-element subsets contains an exact cover", fields: ExactCoverBy3SetsCreateSpec::FIELDS, diff --git a/src/models/set/integer_knapsack.rs b/src/models/set/integer_knapsack.rs index aba6cb1f..f522ac07 100644 --- a/src/models/set/integer_knapsack.rs +++ b/src/models/set/integer_knapsack.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Integer Knapsack", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Select items with integer multiplicities to maximize total value subject to capacity constraint", fields: &[ diff --git a/src/models/set/maximum_set_packing.rs b/src/models/set/maximum_set_packing.rs index 6dede9a3..2b5eb139 100644 --- a/src/models/set/maximum_set_packing.rs +++ b/src/models/set/maximum_set_packing.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Maximum Set Packing", aliases: &[], dimensions: &[VariantDimension::new("weight", "One", &["One", "i32", "f64"])], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Find maximum weight collection of disjoint sets", fields: MaximumSetPackingCreateSpec::::FIELDS, diff --git a/src/models/set/minimum_cardinality_key.rs b/src/models/set/minimum_cardinality_key.rs index 7aa90dda..01cafece 100644 --- a/src/models/set/minimum_cardinality_key.rs +++ b/src/models/set/minimum_cardinality_key.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Minimum Cardinality Key", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Find a candidate key of minimum cardinality in a relational system", fields: &[ diff --git a/src/models/set/minimum_hitting_set.rs b/src/models/set/minimum_hitting_set.rs index 17fdb7b9..04fef79f 100644 --- a/src/models/set/minimum_hitting_set.rs +++ b/src/models/set/minimum_hitting_set.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Minimum Hitting Set", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Find a minimum-size subset of universe elements that hits every set", fields: MinimumHittingSetCreateSpec::FIELDS, diff --git a/src/models/set/minimum_set_covering.rs b/src/models/set/minimum_set_covering.rs index fb28fd1a..fb0aea94 100644 --- a/src/models/set/minimum_set_covering.rs +++ b/src/models/set/minimum_set_covering.rs @@ -16,6 +16,7 @@ inventory::submit! { display_name: "Minimum Set Covering", aliases: &[], dimensions: &[VariantDimension::new("weight", "i32", &["i32"])], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Find minimum weight collection covering the universe", fields: MinimumSetCoveringCreateSpec::FIELDS, diff --git a/src/models/set/prime_attribute_name.rs b/src/models/set/prime_attribute_name.rs index d956424d..ccd9c9ed 100644 --- a/src/models/set/prime_attribute_name.rs +++ b/src/models/set/prime_attribute_name.rs @@ -13,6 +13,7 @@ inventory::submit! { display_name: "Prime Attribute Name", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Determine if an attribute belongs to any candidate key under functional dependencies", fields: PrimeAttributeNameCreateSpec::FIELDS, diff --git a/src/models/set/rooted_tree_storage_assignment.rs b/src/models/set/rooted_tree_storage_assignment.rs index b4138f5a..287e3ecf 100644 --- a/src/models/set/rooted_tree_storage_assignment.rs +++ b/src/models/set/rooted_tree_storage_assignment.rs @@ -11,6 +11,7 @@ inventory::submit! { display_name: "Rooted Tree Storage Assignment", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Does there exist a rooted tree whose subset path extensions cost at most K?", fields: &[ diff --git a/src/models/set/set_basis.rs b/src/models/set/set_basis.rs index b8fc22da..8620e296 100644 --- a/src/models/set/set_basis.rs +++ b/src/models/set/set_basis.rs @@ -14,6 +14,7 @@ inventory::submit! { display_name: "Set Basis", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Determine whether a collection of sets admits a basis of size k under union", fields: SetBasisCreateSpec::FIELDS, diff --git a/src/models/set/set_splitting.rs b/src/models/set/set_splitting.rs index e63053aa..72bebeed 100644 --- a/src/models/set/set_splitting.rs +++ b/src/models/set/set_splitting.rs @@ -13,6 +13,7 @@ inventory::submit! { display_name: "Set Splitting", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Partition a universe into two parts so that every subset is non-monochromatic", fields: &[ diff --git a/src/models/set/three_dimensional_matching.rs b/src/models/set/three_dimensional_matching.rs index fcad3854..ab0d9a85 100644 --- a/src/models/set/three_dimensional_matching.rs +++ b/src/models/set/three_dimensional_matching.rs @@ -15,6 +15,7 @@ inventory::submit! { display_name: "Three-Dimensional Matching", aliases: &["3DM"], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Find a perfect matching in a tripartite hypergraph", fields: &[ diff --git a/src/models/set/three_matroid_intersection.rs b/src/models/set/three_matroid_intersection.rs index 75959467..0b7cb93e 100644 --- a/src/models/set/three_matroid_intersection.rs +++ b/src/models/set/three_matroid_intersection.rs @@ -13,6 +13,7 @@ inventory::submit! { display_name: "Three-Matroid Intersection", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Find a common independent set of size K in three partition matroids", fields: &[ diff --git a/src/models/set/two_dimensional_consecutive_sets.rs b/src/models/set/two_dimensional_consecutive_sets.rs index de247c11..a34a2b1a 100644 --- a/src/models/set/two_dimensional_consecutive_sets.rs +++ b/src/models/set/two_dimensional_consecutive_sets.rs @@ -17,6 +17,7 @@ inventory::submit! { display_name: "2-Dimensional Consecutive Sets", aliases: &[], dimensions: &[], + category: crate::registry::ProblemCategory::Set, module_path: module_path!(), description: "Determine if alphabet can be partitioned into ordered groups with intersection and consecutiveness constraints", fields: &[ diff --git a/src/registry/mod.rs b/src/registry/mod.rs index d1536462..c5a220a2 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -56,8 +56,9 @@ pub use info::{ComplexityClass, FieldInfo, ProblemInfo, ProblemMetadata}; pub use problem_ref::{parse_catalog_problem_ref, require_graph_variant, ProblemRef}; pub use problem_type::{find_problem_type, find_problem_type_by_alias, problem_types, ProblemType}; pub use schema::{ - collect_schemas, declared_size_fields, FieldInfoJson, ProblemSchemaEntry, ProblemSchemaJson, - ProblemSizeFieldEntry, VariantDimension, + collect_schemas, declared_size_fields, FieldInfoJson, ParseProblemCategoryError, + ProblemCategory, ProblemSchemaEntry, ProblemSchemaJson, ProblemSizeFieldEntry, + VariantDimension, }; pub use variant::{ find_variant_by_alias, find_variant_entry, validate_create_inputs, diff --git a/src/registry/problem_type.rs b/src/registry/problem_type.rs index 85ada4ac..509ecff4 100644 --- a/src/registry/problem_type.rs +++ b/src/registry/problem_type.rs @@ -1,6 +1,6 @@ //! Problem type catalog: runtime lookup by name, alias, and variant validation. -use super::schema::{ProblemSchemaEntry, VariantDimension}; +use super::schema::{ProblemCategory, ProblemSchemaEntry, VariantDimension}; use super::FieldInfo; use std::collections::BTreeMap; @@ -19,8 +19,8 @@ pub struct ProblemType { pub description: &'static str, /// Inputs accepted when constructing this problem. pub fields: &'static [FieldInfo], - /// Top-level model category derived from the declaring module path. - pub category: Option<&'static str>, + /// Explicit structural model category. + pub category: ProblemCategory, } impl ProblemType { @@ -33,7 +33,7 @@ impl ProblemType { dimensions: entry.dimensions, description: entry.description, fields: entry.fields, - category: problem_category_from_module_path(entry.module_path), + category: entry.category, } } @@ -46,12 +46,6 @@ impl ProblemType { } } -/// Extract a model category from `...::models::::...`. -pub(crate) fn problem_category_from_module_path(module_path: &str) -> Option<&str> { - let (_, model_path) = module_path.split_once("::models::")?; - model_path.split("::").next() -} - /// Find a problem type by exact canonical name. pub fn find_problem_type(name: &str) -> Option { inventory::iter:: diff --git a/src/registry/schema.rs b/src/registry/schema.rs index 0cf5ce15..fa2fcbd4 100644 --- a/src/registry/schema.rs +++ b/src/registry/schema.rs @@ -2,6 +2,73 @@ use super::FieldInfo; use serde::Serialize; +use std::fmt; +use std::str::FromStr; + +/// Structural category used to organize problem implementations and catalog output. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum ProblemCategory { + Algebraic, + Formula, + Graph, + Misc, + Set, +} + +impl ProblemCategory { + pub const ALL: [Self; 5] = [ + Self::Algebraic, + Self::Formula, + Self::Graph, + Self::Misc, + Self::Set, + ]; + + pub const fn as_str(self) -> &'static str { + match self { + Self::Algebraic => "algebraic", + Self::Formula => "formula", + Self::Graph => "graph", + Self::Misc => "misc", + Self::Set => "set", + } + } +} + +impl fmt::Display for ProblemCategory { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str(self.as_str()) + } +} + +/// Error returned when a catalog category is not one of the five supported values. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseProblemCategoryError(String); + +impl fmt::Display for ParseProblemCategoryError { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + let expected = ProblemCategory::ALL.map(ProblemCategory::as_str).join(", "); + write!( + formatter, + "unknown problem category `{}`; expected one of: {expected}", + self.0, + ) + } +} + +impl std::error::Error for ParseProblemCategoryError {} + +impl FromStr for ProblemCategory { + type Err = ParseProblemCategoryError; + + fn from_str(value: &str) -> Result { + Self::ALL + .into_iter() + .find(|category| category.as_str() == value) + .ok_or_else(|| ParseProblemCategoryError(value.to_string())) + } +} /// A declared variant dimension for a problem type. /// @@ -33,6 +100,22 @@ impl VariantDimension { } /// A registered problem schema entry for static inventory registration. +/// +/// Category is required rather than inferred from source location: +/// +/// ```compile_fail +/// use problemreductions::registry::ProblemSchemaEntry; +/// +/// let _schema = ProblemSchemaEntry { +/// name: "Example", +/// display_name: "Example", +/// aliases: &[], +/// dimensions: &[], +/// module_path: module_path!(), +/// description: "Example schema", +/// fields: &[], +/// }; +/// ``` pub struct ProblemSchemaEntry { /// Problem name (e.g., "MaximumIndependentSet"). pub name: &'static str, @@ -42,6 +125,8 @@ pub struct ProblemSchemaEntry { pub aliases: &'static [&'static str], /// Declared variant dimensions with defaults and allowed values. pub dimensions: &'static [VariantDimension], + /// Explicit structural category shown in catalog output. + pub category: ProblemCategory, /// Module path from `module_path!()` (e.g., "problemreductions::models::graph::maximum_independent_set"). pub module_path: &'static str, /// Human-readable description. @@ -72,6 +157,8 @@ pub struct ProblemSchemaJson { pub name: String, /// Problem description. pub description: String, + /// Structural catalog category. + pub category: ProblemCategory, /// Inputs accepted when constructing this problem. pub fields: Vec, } @@ -94,6 +181,7 @@ pub fn collect_schemas() -> Vec { .map(|entry| ProblemSchemaJson { name: entry.name.to_string(), description: entry.description.to_string(), + category: entry.category, fields: entry .fields .iter() diff --git a/src/rules/graph.rs b/src/rules/graph.rs index 697a72c8..abf1ed10 100644 --- a/src/rules/graph.rs +++ b/src/rules/graph.rs @@ -84,8 +84,8 @@ pub(crate) struct NodeJson { pub(crate) name: String, /// Variant attributes as key-value pairs. pub(crate) variant: BTreeMap, - /// Category of the problem (e.g., "graph", "set", "optimization", "satisfiability", "specialized"). - pub(crate) category: String, + /// Structural category declared by the problem schema. + pub(crate) category: crate::registry::ProblemCategory, /// Relative rustdoc path (e.g., "models/graph/maximum_independent_set"). pub(crate) doc_path: String, /// Worst-case time complexity expression (empty if not declared). @@ -1672,11 +1672,12 @@ impl ReductionGraph { pub(crate) fn to_json(&self) -> ReductionGraphJson { use crate::registry::ProblemSchemaEntry; - // Build name -> module_path lookup from ProblemSchemaEntry inventory - let schema_modules: HashMap<&str, &str> = inventory::iter:: - .into_iter() - .map(|entry| (entry.name, entry.module_path)) - .collect(); + // Build the model-owned metadata lookup from ProblemSchemaEntry inventory. + let schema_metadata: HashMap<&str, (&str, crate::registry::ProblemCategory)> = + inventory::iter:: + .into_iter() + .map(|entry| (entry.name, (entry.module_path, entry.category))) + .collect(); // Build sorted node list from the internal nodes let mut json_nodes: Vec<(usize, NodeJson)> = self @@ -1684,21 +1685,20 @@ impl ReductionGraph { .iter() .enumerate() .map(|(i, node)| { - let (category, doc_path) = if let Some(&mod_path) = schema_modules.get(node.name) { - ( - Self::category_from_module_path(mod_path), - Self::doc_path_from_module_path(mod_path, node.name), - ) - } else { - ("other".to_string(), String::new()) - }; + let &(module_path, category) = + schema_metadata.get(node.name).unwrap_or_else(|| { + panic!( + "missing problem schema for registered variant `{}`", + node.name + ) + }); ( i, NodeJson { name: node.name.to_string(), variant: node.variant.clone(), category, - doc_path, + doc_path: Self::doc_path_from_module_path(module_path, node.name), complexity: node.complexity.to_string(), }, ) @@ -1845,15 +1845,6 @@ impl ReductionGraph { format!("{}/index.html", stripped.replace("::", "/")) } - /// Extract the category from a module path. - /// - /// E.g., `"problemreductions::models::graph::maximum_independent_set"` -> `"graph"`. - fn category_from_module_path(module_path: &str) -> String { - crate::registry::problem_type::problem_category_from_module_path(module_path) - .unwrap_or("other") - .to_string() - } - /// Build the rustdoc path from a module path and problem name. /// /// E.g., `"problemreductions::models::graph::maximum_independent_set"`, `"MaximumIndependentSet"` diff --git a/src/unit_tests/registry/problem_type.rs b/src/unit_tests/registry/problem_type.rs index 6ca8cfdb..02f87ce6 100644 --- a/src/unit_tests/registry/problem_type.rs +++ b/src/unit_tests/registry/problem_type.rs @@ -1,6 +1,6 @@ use crate::registry::{ find_problem_type, find_problem_type_by_alias, parse_catalog_problem_ref, problem_types, - ProblemRef, ProblemSchemaEntry, + ProblemCategory, ProblemRef, ProblemSchemaEntry, }; use std::collections::HashMap; @@ -66,6 +66,43 @@ fn problem_types_returns_all_registered() { .any(|t| t.canonical_name == "MaximumIndependentSet")); } +#[test] +fn problem_category_comes_from_explicit_schema_metadata() { + assert_eq!( + find_problem_type("QUBO").unwrap().category, + ProblemCategory::Algebraic + ); + assert_eq!( + find_problem_type("KSatisfiability").unwrap().category, + ProblemCategory::Formula + ); + assert_eq!( + find_problem_type("MaximumClique").unwrap().category, + ProblemCategory::Graph + ); + assert_eq!( + find_problem_type("JobShopScheduling").unwrap().category, + ProblemCategory::Misc + ); + assert_eq!( + find_problem_type("MinimumSetCovering").unwrap().category, + ProblemCategory::Set + ); + + static MISMATCHED_PATH_SCHEMA: ProblemSchemaEntry = ProblemSchemaEntry { + name: "ExplicitCategoryTest", + display_name: "Explicit category test", + aliases: &[], + dimensions: &[], + category: ProblemCategory::Set, + module_path: "problemreductions::models::graph::explicit_category_test", + description: "Test fixture", + fields: &[], + }; + let problem = super::ProblemType::from_entry(&MISMATCHED_PATH_SCHEMA); + assert_eq!(problem.category, ProblemCategory::Set); +} + #[test] fn problem_ref_from_values_no_values_uses_all_defaults() { let problem = find_problem_type("MaximumIndependentSet").unwrap(); diff --git a/src/unit_tests/registry/schema.rs b/src/unit_tests/registry/schema.rs index 8950d933..473759c7 100644 --- a/src/unit_tests/registry/schema.rs +++ b/src/unit_tests/registry/schema.rs @@ -1,6 +1,20 @@ use super::*; use crate::registry::find_variant_entry; use std::collections::BTreeMap; +use std::str::FromStr; + +#[test] +fn problem_category_parses_only_declared_values() { + for category in ProblemCategory::ALL { + assert_eq!(ProblemCategory::from_str(category.as_str()), Ok(category)); + } + assert_eq!( + ProblemCategory::from_str("unknown") + .unwrap_err() + .to_string(), + "unknown problem category `unknown`; expected one of: algebraic, formula, graph, misc, set" + ); +} #[test] fn test_collect_schemas_returns_all_problems() { @@ -70,6 +84,7 @@ fn test_schema_json_serialization() { let json = serde_json::to_string(&schemas).expect("Schemas should serialize to JSON"); assert!(json.contains("MaximumIndependentSet")); assert!(json.contains("graph")); + assert!(json.contains("\"category\":\"graph\"")); } #[test] diff --git a/src/unit_tests/rules/graph.rs b/src/unit_tests/rules/graph.rs index e1d2ed2b..36461361 100644 --- a/src/unit_tests/rules/graph.rs +++ b/src/unit_tests/rules/graph.rs @@ -8,7 +8,7 @@ use crate::models::graph::MaxCut; use crate::models::graph::{MaximumIndependentSet, MinimumVertexCover}; use crate::models::misc::Knapsack; use crate::models::set::MaximumSetPacking; -use crate::registry::problem_type::problem_category_from_module_path; +use crate::registry::ProblemCategory; use crate::rules::graph::{ReductionMode, ReductionStep}; use crate::rules::registry::{ReductionEntry, ReductionSizeDeclarations}; use crate::rules::traits::{AggregateReductionResult, ReductionResult}; @@ -1037,8 +1037,14 @@ fn test_to_json() { // Check nodes 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 == "algebraic")); + assert!(json + .nodes + .iter() + .any(|n| n.category == ProblemCategory::Graph)); + assert!(json + .nodes + .iter() + .any(|n| n.category == ProblemCategory::Algebraic)); // Check edges assert!(json.edges.len() >= 10); @@ -1076,39 +1082,6 @@ fn test_to_json_string() { ); } -#[test] -fn test_category_from_module_path() { - assert_eq!( - ReductionGraph::category_from_module_path( - "problemreductions::models::graph::maximum_independent_set" - ), - "graph" - ); - assert_eq!( - ReductionGraph::category_from_module_path( - "problemreductions::models::set::minimum_set_covering" - ), - "set" - ); - assert_eq!( - ReductionGraph::category_from_module_path("problemreductions::models::algebraic::qubo"), - "algebraic" - ); - assert_eq!( - ReductionGraph::category_from_module_path("problemreductions::models::formula::sat"), - "formula" - ); - assert_eq!( - ReductionGraph::category_from_module_path("problemreductions::models::misc::factoring"), - "misc" - ); - // Fallback for unexpected format - assert_eq!( - ReductionGraph::category_from_module_path("foo::bar"), - "other" - ); -} - #[test] fn test_doc_path_from_module_path() { assert_eq!( @@ -1321,12 +1294,11 @@ fn test_unknown_name_returns_empty() { } #[test] -fn test_category_derived_from_schema() { - // CircuitSAT's category is derived from its ProblemSchemaEntry module_path +fn test_category_comes_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, "formula"); + assert_eq!(circuit.category, ProblemCategory::Formula); } #[test] @@ -1399,8 +1371,6 @@ fn test_to_json_nodes_have_variants() { for node in &json.nodes { // Verify node has a name assert!(!node.name.is_empty()); - // Verify node has a category - assert!(!node.category.is_empty()); } } @@ -1508,29 +1478,6 @@ fn test_edges_have_doc_paths() { } } -#[test] -fn test_problem_category_from_module_path() { - assert_eq!( - problem_category_from_module_path( - "problemreductions::models::graph::maximum_independent_set" - ), - Some("graph") - ); - assert_eq!( - problem_category_from_module_path("problemreductions::models::formula::satisfiability"), - Some("formula") - ); - assert_eq!( - problem_category_from_module_path("problemreductions::models::set::maximum_set_packing"), - Some("set") - ); - assert_eq!( - problem_category_from_module_path("problemreductions::models::algebraic::qubo"), - Some("algebraic") - ); - assert_eq!(problem_category_from_module_path("unknown::path"), None); -} - #[test] fn test_reduce_along_path_direct() { let graph = ReductionGraph::new();