problemreductions/rules/
kclique_balancedcompletebipartitesubgraph.rs1use crate::models::graph::{BalancedCompleteBipartiteSubgraph, KClique};
9use crate::reduction;
10use crate::rules::traits::{ReduceTo, ReductionResult};
11use crate::topology::{BipartiteGraph, Graph, SimpleGraph};
12
13#[derive(Debug, Clone)]
18pub struct ReductionKCliqueToBCBS {
19 target: BalancedCompleteBipartiteSubgraph,
20 num_original_vertices: usize,
22}
23
24impl ReductionResult for ReductionKCliqueToBCBS {
25 type Source = KClique<SimpleGraph>;
26 type Target = BalancedCompleteBipartiteSubgraph;
27
28 fn target_problem(&self) -> &BalancedCompleteBipartiteSubgraph {
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_solution(self.target_problem(), target_solution)?;
42
43 Ok({
44 (0..self.num_original_vertices)
45 .map(|v| !target_solution[v])
46 .collect()
47 })
48 }
49}
50
51#[reduction(
52 transform = exact {
53 left_size = "num_vertices + k * (k - 1) / 2",
54 right_size = "num_edges + num_vertices - k",
55 k = "num_vertices + k * (k - 1) / 2 - k",
56 },
57 unavailable = {
58 num_vertices = "the exact target parameter is not represented by this reduction's symbolic transform",
59 }
60)]
61impl ReduceTo<BalancedCompleteBipartiteSubgraph> for KClique<SimpleGraph> {
62 type Result = ReductionKCliqueToBCBS;
63
64 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
65 let n = self.num_vertices();
66 let k = self.k();
67 let edges: Vec<(usize, usize)> = self.graph().edges();
68 let m = edges.len();
69
70 let ck2 = k * (k - 1) / 2;
72
73 let left_size = n + ck2;
75
76 let num_padding = n - k;
78 let right_size = m + num_padding;
79
80 let target_k = left_size - k;
82
83 let mut bip_edges = Vec::new();
85
86 for v in 0..left_size {
87 for (j, &(u, w)) in edges.iter().enumerate() {
89 if v != u && v != w {
90 bip_edges.push((v, j));
93 }
94 }
95
96 for p in 0..num_padding {
98 bip_edges.push((v, m + p));
99 }
100 }
101
102 let graph = BipartiteGraph::new(left_size, right_size, bip_edges);
103 let target = BalancedCompleteBipartiteSubgraph::new(graph, target_k);
104
105 Ok(ReductionKCliqueToBCBS {
106 target,
107 num_original_vertices: n,
108 })
109 }
110}
111
112#[cfg(feature = "example-db")]
113pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
114 use crate::export::SolutionPair;
115
116 vec![crate::example_db::specs::RuleExampleSpec {
117 id: "kclique_to_balancedcompletebipartitesubgraph",
118 build: || {
119 let source = KClique::new(SimpleGraph::new(4, vec![(0, 1), (0, 2), (1, 2), (2, 3)]), 3);
122 crate::example_db::specs::rule_example_with_witness::<
133 _,
134 BalancedCompleteBipartiteSubgraph,
135 >(
136 source,
137 SolutionPair {
138 source_config: serde_json::json!(vec![true, true, true, false]),
139 target_config: serde_json::json!(vec![
140 false, false, false, true, true, true, true, true, true, true, false, true
141 ]),
142 },
143 )
144 },
145 }]
146}
147
148#[cfg(test)]
149#[path = "../unit_tests/rules/kclique_balancedcompletebipartitesubgraph.rs"]
150mod tests;