problemreductions/rules/
kclique_conjunctivebooleanquery.rs1use crate::models::graph::KClique;
12use crate::models::misc::{CbqRelation, ConjunctiveBooleanQuery, QueryArg};
13use crate::reduction;
14use crate::rules::traits::{ReduceTo, ReductionResult};
15use crate::topology::{Graph, SimpleGraph};
16
17#[derive(Debug, Clone)]
19pub struct ReductionKCliqueToCBQ {
20 target: ConjunctiveBooleanQuery,
21 num_vertices: usize,
22}
23
24impl ReductionResult for ReductionKCliqueToCBQ {
25 type Source = KClique<SimpleGraph>;
26 type Target = ConjunctiveBooleanQuery;
27
28 fn target_problem(&self) -> &ConjunctiveBooleanQuery {
29 &self.target
30 }
31
32 fn extract_solution(
38 &self,
39 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
40 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
41 crate::rules::traits::validate_target_witness(
42 self.target_problem(),
43 target_solution,
44 |value| value.0,
45 "target witness is not satisfying",
46 )?;
47
48 Ok(KClique::<SimpleGraph>::config_from_vertices(
49 self.num_vertices,
50 target_solution,
51 ))
52 }
53}
54
55#[crate::aggregate_reduction(identity)]
56impl crate::rules::AggregateReductionResult for ReductionKCliqueToCBQ {}
57
58#[reduction(
59 transform = exact {
60 domain_size = "num_vertices",
61 num_relations = "1",
62 num_variables = "k",
63 num_conjuncts = "k * (k - 1) / 2",
64 }
65)]
66impl ReduceTo<ConjunctiveBooleanQuery> for KClique<SimpleGraph> {
67 type Result = ReductionKCliqueToCBQ;
68
69 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
70 let n = self.num_vertices();
71 let k = self.k();
72
73 let mut tuples = Vec::with_capacity(self.num_edges() * 2);
75 for (u, v) in self.graph().edges() {
76 if u == v {
78 continue;
79 }
80 tuples.push(vec![u, v]);
81 tuples.push(vec![v, u]);
82 }
83 let relation = CbqRelation { arity: 2, tuples };
84
85 let mut conjuncts = Vec::with_capacity(k * k.saturating_sub(1) / 2);
87 for i in 0..k {
88 for j in (i + 1)..k {
89 conjuncts.push((0, vec![QueryArg::Variable(i), QueryArg::Variable(j)]));
90 }
91 }
92
93 let target = ConjunctiveBooleanQuery::new(n, vec![relation], k, conjuncts);
94
95 Ok(ReductionKCliqueToCBQ {
96 target,
97 num_vertices: n,
98 })
99 }
100}
101
102#[cfg(feature = "example-db")]
103pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
104 use crate::export::SolutionPair;
105
106 vec![crate::example_db::specs::RuleExampleSpec {
107 id: "kclique_to_conjunctivebooleanquery",
108 build: || {
109 let source = KClique::new(
111 SimpleGraph::new(5, vec![(0, 1), (0, 2), (1, 2), (2, 3), (3, 4)]),
112 3,
113 );
114 crate::example_db::specs::rule_example_with_witness::<_, ConjunctiveBooleanQuery>(
115 source,
116 SolutionPair {
117 source_config: serde_json::json!(vec![true, true, true, false, false]),
118 target_config: serde_json::json!(vec![0, 1, 2]),
119 },
120 )
121 },
122 }]
123}
124
125#[cfg(test)]
126#[path = "../unit_tests/rules/kclique_conjunctivebooleanquery.rs"]
127mod tests;