problemreductions/rules/
partition_productionplanning.rs1use 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(
21 &self,
22 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
23 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
24 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
25
26 Ok(target_solution[..self.target.num_periods() - 1]
27 .iter()
28 .map(|&production| production > 0)
29 .collect())
30 }
31}
32
33#[reduction(
34 transform = exact {
35 num_periods = "num_elements + 1",
36 },
37 unavailable = {
38 max_capacity = "the exact target parameter is not represented by this reduction's symbolic transform",
39 }
40)]
41impl ReduceTo<ProductionPlanning> for Partition {
42 type Result = ReductionPartitionToProductionPlanning;
43
44 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
45 let half_floor = self.total_sum() / 2;
46 let half_ceil = half_floor + (self.total_sum() % 2);
47 let mut demands = vec![0; self.num_elements()];
48 demands.push(half_ceil);
49
50 let mut capacities = self.sizes().to_vec();
51 capacities.push(0);
52
53 let mut setup_costs = self.sizes().to_vec();
54 setup_costs.push(0);
55
56 let production_costs = vec![0; self.num_elements() + 1];
57 let inventory_costs = vec![0; self.num_elements() + 1];
58
59 let num_periods = self.num_elements() + 1;
60 Ok(ReductionPartitionToProductionPlanning {
61 target: ProductionPlanning::new(
62 num_periods,
63 demands,
64 capacities,
65 setup_costs,
66 production_costs,
67 inventory_costs,
68 half_floor,
69 ),
70 })
71 }
72}
73
74#[cfg(feature = "example-db")]
75pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
76 use crate::export::SolutionPair;
77
78 vec![crate::example_db::specs::RuleExampleSpec {
79 id: "partition_to_production_planning",
80 build: || {
81 crate::example_db::specs::rule_example_with_witness::<_, ProductionPlanning>(
82 Partition::new(vec![3, 5, 2, 4, 6]).unwrap(),
83 SolutionPair {
84 source_config: serde_json::json!(vec![false, false, false, true, true]),
85 target_config: serde_json::json!(vec![0, 0, 0, 4, 6, 0]),
86 },
87 )
88 },
89 }]
90}
91
92#[cfg(test)]
93#[path = "../unit_tests/rules/partition_productionplanning.rs"]
94mod tests;