problemreductions/rules/
pathconstrainednetworkflow_ilp.rs1use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP};
7use crate::models::graph::PathConstrainedNetworkFlow;
8use crate::reduction;
9use crate::rules::traits::{ReduceTo, ReductionResult};
10
11#[derive(Debug, Clone)]
13pub struct ReductionPCNFToILP {
14 target: ILP<i32>,
15}
16
17impl ReductionResult for ReductionPCNFToILP {
18 type Source = PathConstrainedNetworkFlow;
19 type Target = ILP<i32>;
20
21 fn target_problem(&self) -> &ILP<i32> {
22 &self.target
23 }
24
25 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
26 target_solution.to_vec()
27 }
28}
29
30#[reduction(
31 overhead = {
32 num_vars = "num_paths",
33 num_constraints = "num_arcs + 1",
34 }
35)]
36impl ReduceTo<ILP<i32>> for PathConstrainedNetworkFlow {
37 type Result = ReductionPCNFToILP;
38
39 fn reduce_to(&self) -> Self::Result {
40 let num_paths = self.num_paths();
41 let num_arcs = self.num_arcs();
42 let mut constraints = Vec::new();
43
44 for arc_idx in 0..num_arcs {
46 let terms: Vec<(usize, f64)> = self
47 .paths()
48 .iter()
49 .enumerate()
50 .filter(|(_, path)| path.contains(&arc_idx))
51 .map(|(path_idx, _)| (path_idx, 1.0))
52 .collect();
53 if !terms.is_empty() {
54 constraints.push(LinearConstraint::le(
55 terms,
56 self.capacities()[arc_idx] as f64,
57 ));
58 }
59 }
60
61 let total_terms: Vec<(usize, f64)> = (0..num_paths).map(|i| (i, 1.0)).collect();
63 constraints.push(LinearConstraint::ge(total_terms, self.requirement() as f64));
64
65 ReductionPCNFToILP {
66 target: ILP::new(num_paths, constraints, vec![], ObjectiveSense::Minimize),
67 }
68 }
69}
70
71#[cfg(feature = "example-db")]
72pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
73 use crate::topology::DirectedGraph;
74
75 vec![crate::example_db::specs::RuleExampleSpec {
76 id: "pathconstrainednetworkflow_to_ilp",
77 build: || {
78 let source = PathConstrainedNetworkFlow::new(
81 DirectedGraph::new(3, vec![(0, 1), (1, 2), (0, 2)]),
82 vec![1, 1, 1],
83 0,
84 2,
85 vec![vec![0, 1], vec![2]],
86 2,
87 );
88 crate::example_db::specs::rule_example_via_ilp::<_, i32>(source)
89 },
90 }]
91}
92
93#[cfg(test)]
94#[path = "../unit_tests/rules/pathconstrainednetworkflow_ilp.rs"]
95mod tests;