problemreductions/rules/
partition_sequencingtominimizetardytaskweight.rs1use crate::models::misc::{Partition, SequencingToMinimizeTardyTaskWeight};
4use crate::reduction;
5use crate::rules::traits::{ReduceTo, ReductionResult};
6
7#[derive(Debug, Clone)]
9pub struct ReductionPartitionToSequencingToMinimizeTardyTaskWeight {
10 target: SequencingToMinimizeTardyTaskWeight,
11}
12
13impl ReductionResult for ReductionPartitionToSequencingToMinimizeTardyTaskWeight {
14 type Source = Partition;
15 type Target = SequencingToMinimizeTardyTaskWeight;
16
17 fn target_problem(&self) -> &Self::Target {
18 &self.target
19 }
20
21 fn extract_solution(
22 &self,
23 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
24 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
25 let value =
26 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
27 if !crate::rules::AggregateReductionResult::extract_value(self, value).0 {
28 return Err(crate::rules::ExtractionError::invalid(
29 "target schedule does not certify a balanced partition",
30 ));
31 }
32
33 Ok({
34 let mut source_config = vec![true; self.target.num_tasks()];
35 let mut completion_time = 0i64;
36
37 for &task in target_solution {
38 completion_time = completion_time
39 .checked_add(self.target.lengths()[task])
40 .ok_or_else(|| {
41 crate::rules::ExtractionError::invalid(
42 "target schedule completion time overflows i64",
43 )
44 })?;
45 if completion_time <= self.target.deadlines()[task] {
46 source_config[task] = false;
47 }
48 }
49
50 source_config
51 })
52 }
53}
54
55impl crate::rules::AggregateReductionResult
56 for ReductionPartitionToSequencingToMinimizeTardyTaskWeight
57{
58 type Source = Partition;
59 type Target = SequencingToMinimizeTardyTaskWeight;
60
61 fn target_problem(&self) -> &Self::Target {
62 &self.target
63 }
64
65 fn extract_value(&self, value: crate::types::Min<i64>) -> crate::types::Or {
66 crate::types::Or(value.0 == Some(self.target.deadlines()[0]))
68 }
69}
70
71#[reduction(
72 aggregate = custom,
73 transform = exact {
74 num_tasks = "num_elements",
75 })]
76impl ReduceTo<SequencingToMinimizeTardyTaskWeight> for Partition {
77 type Result = ReductionPartitionToSequencingToMinimizeTardyTaskWeight;
78
79 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
80 let common_deadline = self.total_sum() / 2;
81 let lengths = self.sizes().to_vec();
82 let weights = self.sizes().to_vec();
83 let deadlines = vec![common_deadline; self.num_elements()];
84
85 Ok(ReductionPartitionToSequencingToMinimizeTardyTaskWeight {
86 target: SequencingToMinimizeTardyTaskWeight::new(lengths, weights, deadlines),
87 })
88 }
89}
90
91#[cfg(feature = "example-db")]
92pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
93 use crate::export::SolutionPair;
94
95 vec![crate::example_db::specs::RuleExampleSpec {
96 id: "partition_to_sequencing_to_minimize_tardy_task_weight",
97 build: || {
98 crate::example_db::specs::rule_example_with_witness::<
99 _,
100 SequencingToMinimizeTardyTaskWeight,
101 >(
102 Partition::new(vec![3, 1, 1, 2, 2, 1]).unwrap(),
103 SolutionPair {
104 source_config: serde_json::json!(vec![true, false, false, true, false, false]),
105 target_config: serde_json::json!(vec![1, 2, 4, 5, 0, 3]),
106 },
107 )
108 },
109 }]
110}
111
112#[cfg(test)]
113#[path = "../unit_tests/rules/partition_sequencingtominimizetardytaskweight.rs"]
114mod tests;