Skip to main content

problemreductions/registry/
problem_type.rs

1//! Problem type catalog: runtime lookup by name, alias, and variant validation.
2
3use super::schema::{ProblemSchemaEntry, VariantDimension};
4use super::FieldInfo;
5use std::collections::BTreeMap;
6
7/// A runtime view of a registered problem type from the catalog.
8#[derive(Debug, Clone)]
9pub struct ProblemType {
10    /// Canonical problem name (e.g., `"MaximumIndependentSet"`).
11    pub canonical_name: &'static str,
12    /// Human-readable display name (e.g., `"Maximum Independent Set"`).
13    pub display_name: &'static str,
14    /// Short aliases (e.g., `["MIS"]`).
15    pub aliases: &'static [&'static str],
16    /// Declared variant dimensions with defaults and allowed values.
17    pub dimensions: &'static [VariantDimension],
18    /// Human-readable description.
19    pub description: &'static str,
20    /// Struct fields.
21    pub fields: &'static [FieldInfo],
22}
23
24impl ProblemType {
25    /// Build a `ProblemType` view from a schema entry.
26    fn from_entry(entry: &'static ProblemSchemaEntry) -> Self {
27        Self {
28            canonical_name: entry.name,
29            display_name: entry.display_name,
30            aliases: entry.aliases,
31            dimensions: entry.dimensions,
32            description: entry.description,
33            fields: entry.fields,
34        }
35    }
36
37    /// Get the default variant map (each dimension set to its default value).
38    pub fn default_variant(&self) -> BTreeMap<String, String> {
39        self.dimensions
40            .iter()
41            .map(|d| (d.key.to_string(), d.default_value.to_string()))
42            .collect()
43    }
44}
45
46/// Find a problem type by exact canonical name.
47pub fn find_problem_type(name: &str) -> Option<ProblemType> {
48    inventory::iter::<ProblemSchemaEntry>
49        .into_iter()
50        .find(|entry| entry.name == name)
51        .map(ProblemType::from_entry)
52}
53
54/// Find a problem type by alias (case-insensitive).
55///
56/// Searches both canonical names and declared aliases.
57pub fn find_problem_type_by_alias(input: &str) -> Option<ProblemType> {
58    let lower = input.to_lowercase();
59    inventory::iter::<ProblemSchemaEntry>
60        .into_iter()
61        .find(|entry| {
62            entry.name.to_lowercase() == lower
63                || entry.aliases.iter().any(|a| a.to_lowercase() == lower)
64        })
65        .map(ProblemType::from_entry)
66}
67
68/// Return all registered problem types.
69pub fn problem_types() -> Vec<ProblemType> {
70    let mut types: Vec<ProblemType> = inventory::iter::<ProblemSchemaEntry>
71        .into_iter()
72        .map(ProblemType::from_entry)
73        .collect();
74    types.sort_by_key(|t| t.canonical_name);
75    types
76}
77
78#[cfg(test)]
79#[path = "../unit_tests/registry/problem_type.rs"]
80mod tests;