problemreductions/rules/
hamiltoniancircuit_bottlenecktravelingsalesman.rs1use crate::models::graph::{BottleneckTravelingSalesman, HamiltonianCircuit};
8use crate::reduction;
9use crate::rules::traits::{ReduceTo, ReductionResult};
10use crate::topology::{Graph, SimpleGraph};
11
12#[derive(Debug, Clone)]
14pub struct ReductionHamiltonianCircuitToBottleneckTravelingSalesman {
15 target: BottleneckTravelingSalesman,
16}
17
18impl ReductionResult for ReductionHamiltonianCircuitToBottleneckTravelingSalesman {
19 type Source = HamiltonianCircuit<SimpleGraph>;
20 type Target = BottleneckTravelingSalesman;
21
22 fn target_problem(&self) -> &Self::Target {
23 &self.target
24 }
25
26 fn extract_solution(
27 &self,
28 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
29 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
30 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
31
32 crate::rules::graph_helpers::edges_to_cycle_order(self.target.graph(), target_solution)
33 }
34}
35
36#[reduction(
37 transform = exact {
38 num_vertices = "num_vertices",
39 num_edges = "num_vertices * (num_vertices - 1) / 2",
40 }
41)]
42impl ReduceTo<BottleneckTravelingSalesman> for HamiltonianCircuit<SimpleGraph> {
43 type Result = ReductionHamiltonianCircuitToBottleneckTravelingSalesman;
44
45 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
46 let num_vertices = self.num_vertices();
47 let target_graph = SimpleGraph::complete(num_vertices);
48 let weights = target_graph
49 .edges()
50 .into_iter()
51 .map(|(u, v)| if self.graph().has_edge(u, v) { 1 } else { 2 })
52 .collect();
53 let target = BottleneckTravelingSalesman::new(target_graph, weights);
54
55 Ok(ReductionHamiltonianCircuitToBottleneckTravelingSalesman { target })
56 }
57}
58
59#[cfg(feature = "example-db")]
60pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
61 use crate::export::SolutionPair;
62
63 vec![crate::example_db::specs::RuleExampleSpec {
64 id: "hamiltoniancircuit_to_bottlenecktravelingsalesman",
65 build: || {
66 let source = HamiltonianCircuit::new(SimpleGraph::cycle(4));
67 crate::example_db::specs::rule_example_with_witness::<_, BottleneckTravelingSalesman>(
68 source,
69 SolutionPair {
70 source_config: serde_json::json!(vec![0, 1, 2, 3]),
71 target_config: serde_json::json!(vec![true, false, true, true, false, true]),
72 },
73 )
74 },
75 }]
76}
77
78#[cfg(test)]
79#[path = "../unit_tests/rules/hamiltoniancircuit_bottlenecktravelingsalesman.rs"]
80mod tests;