problemreductions/rules/
subsetsum_closestvectorproblem.rs1use crate::models::algebraic::{ClosestVectorProblem, VarBounds};
4use crate::models::misc::SubsetSum;
5use crate::reduction;
6use crate::rules::traits::{ReduceTo, ReductionResult};
7use num_bigint::BigUint;
8use num_traits::ToPrimitive;
9
10#[derive(Debug, Clone)]
12pub struct ReductionSubsetSumToClosestVectorProblem {
13 target: ClosestVectorProblem<i32>,
14}
15
16impl ReductionResult for ReductionSubsetSumToClosestVectorProblem {
17 type Source = SubsetSum;
18 type Target = ClosestVectorProblem<i32>;
19
20 fn target_problem(&self) -> &Self::Target {
21 &self.target
22 }
23
24 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
25 target_solution.to_vec()
26 }
27}
28
29fn biguint_to_i32(value: &BigUint) -> i32 {
30 value
31 .to_i32()
32 .expect("SubsetSum -> ClosestVectorProblem requires all sizes and target to fit in i32")
33}
34
35#[reduction(
36 overhead = {
37 ambient_dimension = "num_elements + 1",
38 num_basis_vectors = "num_elements",
39 }
40)]
41impl ReduceTo<ClosestVectorProblem<i32>> for SubsetSum {
42 type Result = ReductionSubsetSumToClosestVectorProblem;
43
44 fn reduce_to(&self) -> Self::Result {
45 let n = self.num_elements();
46 let mut basis = Vec::with_capacity(n);
47 for (i, size) in self.sizes().iter().enumerate() {
48 let mut column = vec![0i32; n + 1];
49 column[i] = 1;
50 column[n] = biguint_to_i32(size);
51 basis.push(column);
52 }
53
54 let mut target = vec![0.5; n];
55 target.push(biguint_to_i32(self.target()) as f64);
56
57 ReductionSubsetSumToClosestVectorProblem {
58 target: ClosestVectorProblem::new(basis, target, vec![VarBounds::binary(); n]),
59 }
60 }
61}
62
63#[cfg(feature = "example-db")]
64pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
65 use crate::export::SolutionPair;
66
67 vec![crate::example_db::specs::RuleExampleSpec {
68 id: "subsetsum_to_closestvectorproblem",
69 build: || {
70 crate::example_db::specs::rule_example_with_witness::<_, ClosestVectorProblem<i32>>(
71 SubsetSum::new(vec![3u32, 7, 1, 8], 11u32),
72 SolutionPair {
73 source_config: vec![1, 0, 0, 1],
74 target_config: vec![1, 0, 0, 1],
75 },
76 )
77 },
78 }]
79}
80
81#[cfg(test)]
82#[path = "../unit_tests/rules/subsetsum_closestvectorproblem.rs"]
83mod tests;