problemreductions/rules/
maximumindependentset_integralflowbundles.rs1use crate::models::graph::{IntegralFlowBundles, MaximumIndependentSet};
21use crate::reduction;
22use crate::rules::traits::{ReduceTo, ReductionResult};
23use crate::topology::{Graph, SimpleGraph};
24
25#[cfg(feature = "example-db")]
26use crate::solvers::BruteForce;
27
28#[derive(Debug, Clone)]
30pub struct ReductionMISToIFB {
31 target: IntegralFlowBundles,
32 num_source_vertices: usize,
34}
35
36impl ReductionResult for ReductionMISToIFB {
37 type Source = MaximumIndependentSet<SimpleGraph, i32>;
38 type Target = IntegralFlowBundles;
39
40 fn target_problem(&self) -> &Self::Target {
41 &self.target
42 }
43
44 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
47 (0..self.num_source_vertices)
48 .map(|i| {
49 if target_solution.get(2 * i + 1).copied().unwrap_or(0) > 0 {
50 1
51 } else {
52 0
53 }
54 })
55 .collect()
56 }
57}
58
59#[reduction(
60 overhead = {
61 num_vertices = "num_vertices + 2",
62 num_arcs = "2 * num_vertices",
63 num_bundles = "num_edges + num_vertices",
64 }
65)]
66impl ReduceTo<IntegralFlowBundles> for MaximumIndependentSet<SimpleGraph, i32> {
67 type Result = ReductionMISToIFB;
68
69 fn reduce_to(&self) -> Self::Result {
70 let n = self.graph().num_vertices();
71 let edges = self.graph().edges();
72
73 let requirement = 1u64;
76
77 let source_vertex = 0;
79 let sink_vertex = n + 1;
80
81 let mut arcs = Vec::with_capacity(2 * n);
83 for i in 0..n {
84 arcs.push((source_vertex, i + 1)); arcs.push((i + 1, sink_vertex)); }
87
88 let directed_graph = crate::topology::DirectedGraph::new(n + 2, arcs);
89
90 let mut bundles = Vec::with_capacity(edges.len() + n);
92 let mut bundle_capacities = Vec::with_capacity(edges.len() + n);
93
94 for &(u, v) in &edges {
96 bundles.push(vec![2 * u + 1, 2 * v + 1]);
97 bundle_capacities.push(1);
98 }
99
100 for i in 0..n {
105 bundles.push(vec![2 * i, 2 * i + 1]);
106 bundle_capacities.push(2);
107 }
108
109 let target = IntegralFlowBundles::new(
110 directed_graph,
111 source_vertex,
112 sink_vertex,
113 bundles,
114 bundle_capacities,
115 requirement,
116 );
117
118 ReductionMISToIFB {
119 target,
120 num_source_vertices: n,
121 }
122 }
123}
124
125#[cfg(feature = "example-db")]
126pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
127 use crate::export::SolutionPair;
128
129 vec![crate::example_db::specs::RuleExampleSpec {
130 id: "maximumindependentset_to_integralflowbundles",
131 build: || {
132 let source = MaximumIndependentSet::new(
135 SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)]),
136 vec![1i32; 4],
137 );
138 let reduction = ReduceTo::<IntegralFlowBundles>::reduce_to(&source);
139 let target = reduction.target_problem();
140
141 let target_witness = BruteForce::new()
142 .find_witness(target)
143 .expect("target should have a feasible solution");
144 let source_witness = reduction.extract_solution(&target_witness);
145
146 crate::example_db::specs::rule_example_with_witness::<_, IntegralFlowBundles>(
147 source,
148 SolutionPair {
149 source_config: source_witness,
150 target_config: target_witness,
151 },
152 )
153 },
154 }]
155}
156
157#[cfg(test)]
158#[path = "../unit_tests/rules/maximumindependentset_integralflowbundles.rs"]
159mod tests;