problemreductions/rules/
schedulingwithindividualdeadlines_ilp.rs1use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP};
15use crate::models::misc::SchedulingWithIndividualDeadlines;
16use crate::reduction;
17use crate::rules::traits::{ReduceTo, ReductionResult};
18
19#[derive(Debug, Clone)]
24pub struct ReductionSWIDToILP {
25 target: ILP<bool>,
26 num_tasks: usize,
27 max_deadline: usize,
28}
29
30impl ReductionResult for ReductionSWIDToILP {
31 type Source = SchedulingWithIndividualDeadlines;
32 type Target = ILP<bool>;
33
34 fn target_problem(&self) -> &ILP<bool> {
35 &self.target
36 }
37
38 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
42 let d = self.max_deadline;
43 (0..self.num_tasks)
44 .map(|j| {
45 (0..d)
46 .find(|&t| target_solution.get(j * d + t).copied().unwrap_or(0) == 1)
47 .unwrap_or(0)
48 })
49 .collect()
50 }
51}
52
53#[reduction(
54 overhead = {
55 num_vars = "num_tasks * max_deadline",
56 num_constraints = "num_tasks + max_deadline + num_precedences",
57 }
58)]
59impl ReduceTo<ILP<bool>> for SchedulingWithIndividualDeadlines {
60 type Result = ReductionSWIDToILP;
61
62 fn reduce_to(&self) -> Self::Result {
63 let n = self.num_tasks();
64 let m = self.num_processors();
65 let max_d = self.max_deadline();
66 let num_vars = n * max_d;
67
68 let var = |j: usize, t: usize| j * max_d + t;
69
70 let mut constraints = Vec::new();
71
72 for j in 0..n {
74 let dj = self.deadlines()[j];
75 let terms: Vec<(usize, f64)> = (0..dj).map(|t| (var(j, t), 1.0)).collect();
76 constraints.push(LinearConstraint::eq(terms, 1.0));
77 }
78
79 for t in 0..max_d {
81 let terms: Vec<(usize, f64)> = (0..n).map(|j| (var(j, t), 1.0)).collect();
82 constraints.push(LinearConstraint::le(terms, m as f64));
83 }
84
85 for &(i, j) in self.precedences() {
87 let di = self.deadlines()[i];
88 let dj = self.deadlines()[j];
89 let mut terms: Vec<(usize, f64)> = Vec::new();
90 for t in 0..dj {
91 terms.push((var(j, t), t as f64));
92 }
93 for t in 0..di {
94 terms.push((var(i, t), -(t as f64)));
95 }
96 constraints.push(LinearConstraint::ge(terms, 1.0));
97 }
98
99 ReductionSWIDToILP {
100 target: ILP::new(num_vars, constraints, vec![], ObjectiveSense::Minimize),
101 num_tasks: n,
102 max_deadline: max_d,
103 }
104 }
105}
106
107#[cfg(feature = "example-db")]
108pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
109 vec![crate::example_db::specs::RuleExampleSpec {
110 id: "schedulingwithindividualdeadlines_to_ilp",
111 build: || {
112 let source = SchedulingWithIndividualDeadlines::new(3, 2, vec![2, 2, 3], vec![(0, 2)]);
114 crate::example_db::specs::rule_example_via_ilp::<_, bool>(source)
115 },
116 }]
117}
118
119#[cfg(test)]
120#[path = "../unit_tests/rules/schedulingwithindividualdeadlines_ilp.rs"]
121mod tests;