problemreductions/rules/
ksatisfiability_quadraticdiophantineequations.rs1use crate::models::algebraic::{QuadraticCongruences, QuadraticDiophantineEquations};
8use crate::models::formula::KSatisfiability;
9use crate::reduction;
10use crate::rules::ksatisfiability_quadraticcongruences::Reduction3SATToQuadraticCongruences;
11use crate::rules::traits::{ReduceTo, ReductionResult};
12use crate::variant::K3;
13use num_bigint::BigUint;
14use num_traits::One;
15
16#[derive(Debug, Clone)]
18pub struct Reduction3SATToQuadraticDiophantineEquations {
19 target: QuadraticDiophantineEquations,
20 congruence_reduction: Reduction3SATToQuadraticCongruences,
21}
22
23impl ReductionResult for Reduction3SATToQuadraticDiophantineEquations {
24 type Source = KSatisfiability<K3>;
25 type Target = QuadraticDiophantineEquations;
26
27 fn target_problem(&self) -> &Self::Target {
28 &self.target
29 }
30
31 fn extract_solution(
32 &self,
33 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
34 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
35 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
36
37 Ok({
38 self.congruence_reduction
39 .extract_solution(target_solution)?
40 })
41 }
42}
43
44fn no_instance() -> QuadraticDiophantineEquations {
45 QuadraticDiophantineEquations::new(1u32, 1u32, 1u32)
46}
47
48fn translate_congruence(source: &QuadraticCongruences) -> QuadraticDiophantineEquations {
49 if source.c() <= &BigUint::one() {
50 return no_instance();
51 }
52
53 let h = source.c().clone() - BigUint::one();
54 let h_squared = &h * &h;
55 if h_squared < *source.a() {
56 return no_instance();
57 }
58
59 let padding = ((&h_squared - source.a()) / source.b()) + BigUint::one();
60 let c = source.a() + (source.b() * &padding);
61
62 QuadraticDiophantineEquations::new(BigUint::one(), source.b().clone(), c)
63}
64
65#[reduction(
66 transform = upper_bound {
67 bit_length_a = "1",
68 bit_length_b = "64 * (2 * num_clauses + num_vars + 1)^2 + 3 * num_clauses + 4",
69 bit_length_c = "128 * (2 * num_clauses + num_vars + 1)^2 + 6 * num_clauses + 9",
70 }
71)]
72impl ReduceTo<QuadraticDiophantineEquations> for KSatisfiability<K3> {
73 type Result = Reduction3SATToQuadraticDiophantineEquations;
74
75 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
76 let congruence_reduction = ReduceTo::<QuadraticCongruences>::reduce_to(self)?;
77 let target = translate_congruence(congruence_reduction.target_problem());
78
79 Ok(Reduction3SATToQuadraticDiophantineEquations {
80 target,
81 congruence_reduction,
82 })
83 }
84}
85
86#[cfg(any(test, feature = "example-db"))]
87fn canonical_source() -> KSatisfiability<K3> {
88 use crate::models::formula::CNFClause;
89
90 KSatisfiability::<K3>::new(3, vec![CNFClause::new(vec![1, 2, 3])])
91}
92
93#[cfg(any(test, feature = "example-db"))]
94fn canonical_witness() -> BigUint {
95 BigUint::parse_bytes(b"3851422232510508672725868082377332726402809", 10)
96 .expect("canonical CRT witness must parse")
97}
98
99#[cfg(feature = "example-db")]
100pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
101 use crate::example_db::specs::assemble_rule_example;
102 use crate::export::SolutionPair;
103
104 vec![crate::example_db::specs::RuleExampleSpec {
105 id: "ksatisfiability_to_quadraticdiophantineequations",
106 build: || {
107 let source = canonical_source();
108 let reduction = ReduceTo::<QuadraticDiophantineEquations>::reduce_to(&source)
109 .expect("reduction should succeed");
110 let target_config = canonical_witness();
111
112 assemble_rule_example(
113 &source,
114 reduction.target_problem(),
115 vec![SolutionPair {
116 source_config: serde_json::json!(vec![true, false, false]),
117 target_config: serde_json::to_value(target_config)
118 .expect("solution serialization must succeed"),
119 }],
120 )
121 },
122 }]
123}
124
125#[cfg(test)]
126#[path = "../unit_tests/rules/ksatisfiability_quadraticdiophantineequations.rs"]
127mod tests;