problemreductions/rules/
hamiltoniancircuit_quadraticassignment.rs1use crate::models::algebraic::QuadraticAssignment;
9use crate::models::decision::Decision;
10use crate::models::graph::HamiltonianCircuit;
11use crate::reduction;
12use crate::rules::traits::{ReduceTo, ReductionResult};
13use crate::topology::{Graph, SimpleGraph};
14
15#[derive(Debug, Clone)]
17pub struct ReductionHamiltonianCircuitToQuadraticAssignment {
18 target: Decision<QuadraticAssignment>,
19}
20
21impl ReductionResult for ReductionHamiltonianCircuitToQuadraticAssignment {
22 type Source = HamiltonianCircuit<SimpleGraph>;
23 type Target = Decision<QuadraticAssignment>;
24
25 fn target_problem(&self) -> &Self::Target {
26 &self.target
27 }
28
29 fn extract_solution(
30 &self,
31 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
32 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
33 crate::rules::traits::validate_target_witness(
34 self.target_problem(),
35 target_solution,
36 |value| value.0,
37 "target assignment does not certify a Hamiltonian circuit",
38 )?;
39
40 Ok(target_solution.to_vec())
42 }
43}
44
45#[crate::aggregate_reduction(identity)]
46impl crate::rules::AggregateReductionResult for ReductionHamiltonianCircuitToQuadraticAssignment {}
47
48#[reduction(
49 transform = upper_bound {
50 num_facilities = "num_vertices + 3",
51 num_locations = "num_vertices + 3",
52 }
53)]
54impl ReduceTo<Decision<QuadraticAssignment>> for HamiltonianCircuit<SimpleGraph> {
55 type Result = ReductionHamiltonianCircuitToQuadraticAssignment;
56
57 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
58 let source_n = self.num_vertices();
59 let n = source_n.max(3);
62 let cost_matrix: Vec<Vec<i64>> = (0..n)
63 .map(|i| (0..n).map(|j| i64::from(j == (i + 1) % n)).collect())
64 .collect();
65 let distance_matrix: Vec<Vec<i64>> = (0..n)
66 .map(|k| {
67 (0..n)
68 .map(|l| i64::from(k != l && (source_n < 3 || !self.graph().has_edge(k, l))))
69 .collect()
70 })
71 .collect();
72
73 let target = QuadraticAssignment::new(cost_matrix, distance_matrix);
74 Ok(ReductionHamiltonianCircuitToQuadraticAssignment {
75 target: Decision::new(target, 0),
76 })
77 }
78}
79
80#[cfg(feature = "example-db")]
81pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
82 use crate::export::SolutionPair;
83
84 vec![crate::example_db::specs::RuleExampleSpec {
85 id: "hamiltoniancircuit_to_quadraticassignment",
86 build: || {
87 let source = HamiltonianCircuit::new(SimpleGraph::cycle(4));
88 crate::example_db::specs::rule_example_with_witness::<_, Decision<QuadraticAssignment>>(
89 source,
90 SolutionPair {
91 source_config: serde_json::json!(vec![0, 1, 2, 3]),
92 target_config: serde_json::json!(vec![0, 1, 2, 3]),
93 },
94 )
95 },
96 }]
97}
98
99#[cfg(test)]
100#[path = "../unit_tests/rules/hamiltoniancircuit_quadraticassignment.rs"]
101mod tests;