Skip to main content

problemreductions/rules/
partition_productionplanning.rs

1//! Reduction from Partition to Production Planning.
2
3use crate::models::misc::{Partition, ProductionPlanning};
4use crate::reduction;
5use crate::rules::traits::{ReduceTo, ReductionResult};
6
7#[derive(Debug, Clone)]
8pub struct ReductionPartitionToProductionPlanning {
9    target: ProductionPlanning,
10}
11
12impl ReductionResult for ReductionPartitionToProductionPlanning {
13    type Source = Partition;
14    type Target = ProductionPlanning;
15
16    fn target_problem(&self) -> &Self::Target {
17        &self.target
18    }
19
20    fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
21        target_solution
22            .iter()
23            .take(self.target.num_periods().saturating_sub(1))
24            .map(|&production| usize::from(production > 0))
25            .collect()
26    }
27}
28
29#[reduction(overhead = {
30    num_periods = "num_elements + 1",
31})]
32impl ReduceTo<ProductionPlanning> for Partition {
33    type Result = ReductionPartitionToProductionPlanning;
34
35    fn reduce_to(&self) -> Self::Result {
36        let half_floor = self.total_sum() / 2;
37        let half_ceil = half_floor + (self.total_sum() % 2);
38        let mut demands = vec![0; self.num_elements()];
39        demands.push(half_ceil);
40
41        let mut capacities = self.sizes().to_vec();
42        capacities.push(0);
43
44        let mut setup_costs = self.sizes().to_vec();
45        setup_costs.push(0);
46
47        let production_costs = vec![0; self.num_elements() + 1];
48        let inventory_costs = vec![0; self.num_elements() + 1];
49
50        let num_periods = self.num_elements() + 1;
51        ReductionPartitionToProductionPlanning {
52            target: ProductionPlanning::new(
53                num_periods,
54                demands,
55                capacities,
56                setup_costs,
57                production_costs,
58                inventory_costs,
59                half_floor,
60            ),
61        }
62    }
63}
64
65#[cfg(feature = "example-db")]
66pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
67    use crate::export::SolutionPair;
68
69    vec![crate::example_db::specs::RuleExampleSpec {
70        id: "partition_to_production_planning",
71        build: || {
72            crate::example_db::specs::rule_example_with_witness::<_, ProductionPlanning>(
73                Partition::new(vec![3, 5, 2, 4, 6]),
74                SolutionPair {
75                    source_config: vec![0, 0, 0, 1, 1],
76                    target_config: vec![0, 0, 0, 4, 6, 0],
77                },
78            )
79        },
80    }]
81}
82
83#[cfg(test)]
84#[path = "../unit_tests/rules/partition_productionplanning.rs"]
85mod tests;