problemreductions/rules/
partition_subsetsum.rs1use crate::models::misc::{Partition, SubsetSum};
8use crate::reduction;
9use crate::rules::traits::{ReduceTo, ReductionResult};
10use num_bigint::BigUint;
11
12#[derive(Debug, Clone)]
14pub struct ReductionPartitionToSubsetSum {
15 target: SubsetSum,
16 source_n: usize,
19}
20
21impl ReductionResult for ReductionPartitionToSubsetSum {
22 type Source = Partition;
23 type Target = SubsetSum;
24
25 fn target_problem(&self) -> &Self::Target {
26 &self.target
27 }
28
29 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
30 if target_solution.len() == self.source_n {
31 target_solution.to_vec()
33 } else {
34 vec![0; self.source_n]
37 }
38 }
39}
40
41#[reduction(overhead = {
42 num_elements = "num_elements",
43})]
44impl ReduceTo<SubsetSum> for Partition {
45 type Result = ReductionPartitionToSubsetSum;
46
47 fn reduce_to(&self) -> Self::Result {
48 let total = self.total_sum();
49 let source_n = self.num_elements();
50
51 if !total.is_multiple_of(2) {
52 ReductionPartitionToSubsetSum {
55 target: SubsetSum::new_unchecked(vec![], BigUint::from(1u32)),
56 source_n,
57 }
58 } else {
59 let sizes: Vec<BigUint> = self.sizes().iter().map(|&s| BigUint::from(s)).collect();
60 let target_val = BigUint::from(total / 2);
61 ReductionPartitionToSubsetSum {
62 target: SubsetSum::new_unchecked(sizes, target_val),
63 source_n,
64 }
65 }
66 }
67}
68
69#[cfg(feature = "example-db")]
70pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
71 use crate::export::SolutionPair;
72
73 vec![crate::example_db::specs::RuleExampleSpec {
74 id: "partition_to_subsetsum",
75 build: || {
76 crate::example_db::specs::rule_example_with_witness::<_, SubsetSum>(
77 Partition::new(vec![3, 1, 1, 2, 2, 1]),
78 SolutionPair {
79 source_config: vec![1, 0, 0, 1, 0, 0],
80 target_config: vec![1, 0, 0, 1, 0, 0],
81 },
82 )
83 },
84 }]
85}
86
87#[cfg(test)]
88#[path = "../unit_tests/rules/partition_subsetsum.rs"]
89mod tests;