problemreductions/models/graph/
kclique.rs1use crate::registry::{FieldInfo, ProblemSchemaEntry, VariantDimension};
7use crate::topology::{Graph, SimpleGraph};
8use crate::traits::Problem;
9use serde::{Deserialize, Serialize};
10
11inventory::submit! {
12 ProblemSchemaEntry {
13 name: "KClique",
14 display_name: "k-Clique",
15 aliases: &["Clique"],
16 dimensions: &[VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"])],
17 module_path: module_path!(),
18 description: "Determine whether a graph contains a clique of size at least k",
19 fields: &[
20 FieldInfo { name: "graph", type_name: "G", description: "The underlying graph G=(V,E)" },
21 FieldInfo { name: "k", type_name: "usize", description: "Minimum clique size threshold" },
22 ],
23 }
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct KClique<G> {
33 graph: G,
34 k: usize,
35}
36
37impl<G: Graph> KClique<G> {
38 pub fn new(graph: G, k: usize) -> Self {
40 assert!(k > 0, "k must be positive");
41 assert!(k <= graph.num_vertices(), "k must be <= graph num_vertices");
42 Self { graph, k }
43 }
44
45 pub fn graph(&self) -> &G {
47 &self.graph
48 }
49
50 pub fn k(&self) -> usize {
52 self.k
53 }
54
55 pub fn num_vertices(&self) -> usize {
57 self.graph.num_vertices()
58 }
59
60 pub fn num_edges(&self) -> usize {
62 self.graph.num_edges()
63 }
64
65 pub fn is_valid_solution(&self, config: &[usize]) -> bool {
67 is_kclique_config(&self.graph, config, self.k)
68 }
69
70 pub fn config_from_vertices(num_vertices: usize, selected_vertices: &[usize]) -> Vec<usize> {
72 let mut config = vec![0; num_vertices];
73 for &vertex in selected_vertices {
74 config[vertex] = 1;
75 }
76 config
77 }
78
79 pub fn config_from_selected_vertices(&self, selected_vertices: &[usize]) -> Vec<usize> {
81 Self::config_from_vertices(self.num_vertices(), selected_vertices)
82 }
83}
84
85impl<G> Problem for KClique<G>
86where
87 G: Graph + crate::variant::VariantParam,
88{
89 const NAME: &'static str = "KClique";
90 type Value = crate::types::Or;
91
92 fn variant() -> Vec<(&'static str, &'static str)> {
93 crate::variant_params![G]
94 }
95
96 fn dims(&self) -> Vec<usize> {
97 vec![2; self.graph.num_vertices()]
98 }
99
100 fn evaluate(&self, config: &[usize]) -> crate::types::Or {
101 crate::types::Or(is_kclique_config(&self.graph, config, self.k))
102 }
103}
104
105fn is_kclique_config<G: Graph>(graph: &G, config: &[usize], k: usize) -> bool {
106 if config.len() != graph.num_vertices() {
107 return false;
108 }
109
110 let selected: Vec<usize> = match config
111 .iter()
112 .enumerate()
113 .map(|(index, &value)| match value {
114 0 => Ok(None),
115 1 => Ok(Some(index)),
116 _ => Err(()),
117 })
118 .collect::<Result<Vec<_>, _>>()
119 {
120 Ok(values) => values.into_iter().flatten().collect(),
121 Err(()) => return false,
122 };
123
124 if selected.len() < k {
125 return false;
126 }
127
128 for i in 0..selected.len() {
129 for j in (i + 1)..selected.len() {
130 if !graph.has_edge(selected[i], selected[j]) {
131 return false;
132 }
133 }
134 }
135 true
136}
137
138crate::declare_variants! {
139 default KClique<SimpleGraph> => "1.1996^num_vertices",
140}
141
142#[cfg(feature = "example-db")]
143pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::ModelExampleSpec> {
144 vec![crate::example_db::specs::ModelExampleSpec {
145 id: "kclique_simplegraph",
146 instance: Box::new(KClique::new(
147 SimpleGraph::new(5, vec![(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)]),
148 3,
149 )),
150 optimal_config: vec![0, 0, 1, 1, 1],
151 optimal_value: serde_json::json!(true),
152 }]
153}
154
155#[cfg(test)]
156#[path = "../../unit_tests/models/graph/kclique.rs"]
157mod tests;