problemreductions/rules/
minimummetricdimension_ilp.rs1use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP};
11use crate::models::graph::minimum_metric_dimension::bfs_distances;
12use crate::models::graph::MinimumMetricDimension;
13use crate::reduction;
14use crate::rules::traits::{ReduceTo, ReductionResult};
15use crate::topology::{Graph, SimpleGraph};
16
17#[derive(Debug, Clone)]
25pub struct ReductionMDToILP {
26 target: ILP<bool>,
27}
28
29impl ReductionResult for ReductionMDToILP {
30 type Source = MinimumMetricDimension<SimpleGraph>;
31 type Target = ILP<bool>;
32
33 fn target_problem(&self) -> &ILP<bool> {
34 &self.target
35 }
36
37 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
42 target_solution.to_vec()
43 }
44}
45
46#[reduction(
47 overhead = {
48 num_vars = "num_vertices",
49 num_constraints = "num_vertices * (num_vertices - 1) / 2",
50 }
51)]
52impl ReduceTo<ILP<bool>> for MinimumMetricDimension<SimpleGraph> {
53 type Result = ReductionMDToILP;
54
55 fn reduce_to(&self) -> Self::Result {
56 let n = self.graph().num_vertices();
57
58 let all_dists: Vec<Vec<usize>> = (0..n).map(|v| bfs_distances(self.graph(), v)).collect();
60
61 let mut constraints = Vec::new();
64 for u in 0..n {
65 for v in (u + 1)..n {
66 let terms: Vec<(usize, f64)> = (0..n)
67 .filter(|&w| all_dists[w][u] != all_dists[w][v])
68 .map(|w| (w, 1.0))
69 .collect();
70 constraints.push(LinearConstraint::ge(terms, 1.0));
71 }
72 }
73
74 let objective: Vec<(usize, f64)> = (0..n).map(|v| (v, 1.0)).collect();
76
77 let target = ILP::new(n, constraints, objective, ObjectiveSense::Minimize);
78
79 ReductionMDToILP { target }
80 }
81}
82
83#[cfg(feature = "example-db")]
84pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
85 vec![crate::example_db::specs::RuleExampleSpec {
86 id: "minimummetricdimension_to_ilp",
87 build: || {
88 let source = MinimumMetricDimension::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]));
90 crate::example_db::specs::rule_example_via_ilp::<_, bool>(source)
91 },
92 }]
93}
94
95#[cfg(test)]
96#[path = "../unit_tests/rules/minimummetricdimension_ilp.rs"]
97mod tests;