Skip to main content

problemreductions/rules/
hamiltonianpath_isomorphicspanningtree.rs

1//! Reduction from HamiltonianPath to IsomorphicSpanningTree<SimpleGraph>.
2//!
3//! A Hamiltonian path in G exists iff G has a spanning tree isomorphic to the
4//! path graph P_n. The reduction keeps G unchanged as the host graph and
5//! constructs T = P_n (the path on n vertices: edges {0,1},{1,2},...,{n-2,n-1}).
6
7use crate::models::graph::{HamiltonianPath, IsomorphicSpanningTree};
8use crate::reduction;
9use crate::rules::traits::{ReduceTo, ReductionResult};
10use crate::topology::SimpleGraph;
11
12/// Result of reducing HamiltonianPath to IsomorphicSpanningTree<SimpleGraph>.
13#[derive(Debug, Clone)]
14pub struct ReductionHPToIST {
15    target: IsomorphicSpanningTree<SimpleGraph>,
16}
17
18impl ReductionResult for ReductionHPToIST {
19    type Source = HamiltonianPath<SimpleGraph>;
20    type Target = IsomorphicSpanningTree<SimpleGraph>;
21
22    fn target_problem(&self) -> &Self::Target {
23        &self.target
24    }
25
26    /// Solution extraction: identity mapping.
27    ///
28    /// The IST config maps tree vertex i to graph vertex config[i]. Since the
29    /// tree is P_n (path 0-1-2-...-n-1), this mapping directly gives the
30    /// vertex ordering of the Hamiltonian path.
31    fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
32        target_solution.to_vec()
33    }
34}
35
36#[reduction(
37    overhead = {
38        num_vertices = "num_vertices",
39        num_graph_edges = "num_edges",
40        num_tree_edges = "num_vertices - 1",
41    }
42)]
43impl ReduceTo<IsomorphicSpanningTree<SimpleGraph>> for HamiltonianPath<SimpleGraph> {
44    type Result = ReductionHPToIST;
45
46    fn reduce_to(&self) -> Self::Result {
47        let n = self.num_vertices();
48
49        // Host graph: keep G unchanged
50        let graph = self.graph().clone();
51
52        let tree = SimpleGraph::path(n);
53
54        ReductionHPToIST {
55            target: IsomorphicSpanningTree::new(graph, tree),
56        }
57    }
58}
59
60#[cfg(feature = "example-db")]
61pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
62    use crate::export::SolutionPair;
63
64    vec![crate::example_db::specs::RuleExampleSpec {
65        id: "hamiltonianpath_to_isomorphicspanningtree",
66        build: || {
67            // Path graph 0-1-2-3-4 has a trivial Hamiltonian path
68            let source = HamiltonianPath::new(SimpleGraph::path(5));
69            crate::example_db::specs::rule_example_with_witness::<
70                _,
71                IsomorphicSpanningTree<SimpleGraph>,
72            >(
73                source,
74                SolutionPair {
75                    source_config: vec![0, 1, 2, 3, 4],
76                    target_config: vec![0, 1, 2, 3, 4],
77                },
78            )
79        },
80    }]
81}
82
83#[cfg(test)]
84#[path = "../unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs"]
85mod tests;