problemreductions/rules/
minimummaximalmatching_ilp.rs1use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP};
11use crate::models::graph::MinimumMaximalMatching;
12use crate::reduction;
13use crate::rules::traits::{ReduceTo, ReductionResult};
14use crate::topology::{Graph, SimpleGraph};
15
16#[derive(Debug, Clone)]
25pub struct ReductionMMMToILP {
26 target: ILP<bool>,
27}
28
29impl ReductionResult for ReductionMMMToILP {
30 type Source = MinimumMaximalMatching<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_edges",
49 num_constraints = "num_vertices + num_edges",
50 }
51)]
52impl ReduceTo<ILP<bool>> for MinimumMaximalMatching<SimpleGraph> {
53 type Result = ReductionMMMToILP;
54
55 fn reduce_to(&self) -> Self::Result {
56 let edges = self.graph().edges();
57 let num_vars = edges.len();
58 let mut constraints = Vec::new();
59
60 let n = self.graph().num_vertices();
63 let mut v2e: Vec<Vec<usize>> = vec![Vec::new(); n];
64 for (idx, &(u, v)) in edges.iter().enumerate() {
65 v2e[u].push(idx);
66 v2e[v].push(idx);
67 }
68 for incident in &v2e {
69 if !incident.is_empty() {
70 let terms: Vec<(usize, f64)> = incident.iter().map(|&e| (e, 1.0)).collect();
71 constraints.push(LinearConstraint::le(terms, 1.0));
72 }
73 }
74
75 for (j, &(uj, vj)) in edges.iter().enumerate() {
79 let mut neighbors: Vec<usize> = vec![j];
81 for &i in v2e[uj].iter().chain(v2e[vj].iter()) {
82 if i != j && !neighbors.contains(&i) {
83 neighbors.push(i);
84 }
85 }
86 let terms: Vec<(usize, f64)> = neighbors.iter().map(|&i| (i, 1.0)).collect();
87 constraints.push(LinearConstraint::ge(terms, 1.0));
88 }
89
90 let objective: Vec<(usize, f64)> = (0..num_vars).map(|i| (i, 1.0)).collect();
92
93 let target = ILP::new(num_vars, constraints, objective, ObjectiveSense::Minimize);
94 ReductionMMMToILP { target }
95 }
96}
97
98#[cfg(feature = "example-db")]
99pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
100 vec![crate::example_db::specs::RuleExampleSpec {
101 id: "minimummaximalmatching_to_ilp",
102 build: || {
103 let source = MinimumMaximalMatching::new(SimpleGraph::new(
105 6,
106 vec![(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)],
107 ));
108 crate::example_db::specs::rule_example_via_ilp::<_, bool>(source)
109 },
110 }]
111}
112
113#[cfg(test)]
114#[path = "../unit_tests/rules/minimummaximalmatching_ilp.rs"]
115mod tests;