problemreductions/models/graph/
kcoloring.rs1use crate::registry::{FieldInfo, ProblemSchemaEntry, VariantDimension};
7use crate::topology::{Graph, SimpleGraph};
8use crate::traits::Problem;
9use crate::variant::{KValue, VariantParam, K2, K3, K4, K5, KN};
10use serde::{Deserialize, Serialize};
11
12inventory::submit! {
13 ProblemSchemaEntry {
14 name: "KColoring",
15 display_name: "K-Coloring",
16 aliases: &[],
17 dimensions: &[
18 VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]),
19 VariantDimension::new("k", "KN", &["KN", "K2", "K3", "K4", "K5"]),
20 ],
21 module_path: module_path!(),
22 description: "Find valid k-coloring of a graph",
23 fields: &[
24 FieldInfo { name: "graph", type_name: "G", description: "The underlying graph G=(V,E)" },
25 ],
26 }
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
60#[serde(bound(deserialize = "G: serde::Deserialize<'de>"))]
61pub struct KColoring<K: KValue, G> {
62 graph: G,
64 #[serde(default = "default_num_colors::<K>")]
66 num_colors: usize,
67 #[serde(skip)]
68 _phantom: std::marker::PhantomData<K>,
69}
70
71fn default_num_colors<K: KValue>() -> usize {
72 K::K.unwrap_or(0)
73}
74
75impl<K: KValue, G: Graph> KColoring<K, G> {
76 pub fn new(graph: G) -> Self {
81 Self {
82 graph,
83 num_colors: K::K.expect("KN requires with_k"),
84 _phantom: std::marker::PhantomData,
85 }
86 }
87
88 pub fn graph(&self) -> &G {
90 &self.graph
91 }
92
93 pub fn num_colors(&self) -> usize {
95 self.num_colors
96 }
97
98 pub fn is_valid_solution(&self, config: &[usize]) -> bool {
100 is_valid_coloring(&self.graph, config, self.num_colors)
101 }
102
103 fn is_valid_coloring(&self, config: &[usize]) -> bool {
105 for (u, v) in self.graph.edges() {
106 let color_u = config.get(u).copied().unwrap_or(0);
107 let color_v = config.get(v).copied().unwrap_or(0);
108 if color_u == color_v {
109 return false;
110 }
111 }
112 true
113 }
114}
115
116impl<G: Graph> KColoring<KN, G> {
117 pub fn with_k(graph: G, num_colors: usize) -> Self {
123 Self {
124 graph,
125 num_colors,
126 _phantom: std::marker::PhantomData,
127 }
128 }
129}
130
131impl<K: KValue, G: Graph> KColoring<K, G> {
132 pub fn num_vertices(&self) -> usize {
134 self.graph().num_vertices()
135 }
136
137 pub fn num_edges(&self) -> usize {
139 self.graph().num_edges()
140 }
141}
142
143impl<K: KValue, G> Problem for KColoring<K, G>
144where
145 G: Graph + VariantParam,
146{
147 const NAME: &'static str = "KColoring";
148 type Value = crate::types::Or;
149
150 fn variant() -> Vec<(&'static str, &'static str)> {
151 crate::variant_params![K, G]
152 }
153
154 fn dims(&self) -> Vec<usize> {
155 vec![self.num_colors; self.graph.num_vertices()]
156 }
157
158 fn evaluate(&self, config: &[usize]) -> crate::types::Or {
159 crate::types::Or(self.is_valid_coloring(config))
160 }
161}
162
163pub(crate) fn is_valid_coloring<G: Graph>(
168 graph: &G,
169 coloring: &[usize],
170 num_colors: usize,
171) -> bool {
172 assert_eq!(
173 coloring.len(),
174 graph.num_vertices(),
175 "coloring length must match num_vertices"
176 );
177 if coloring.iter().any(|&c| c >= num_colors) {
179 return false;
180 }
181 for (u, v) in graph.edges() {
183 if coloring[u] == coloring[v] {
184 return false;
185 }
186 }
187 true
188}
189
190#[cfg(feature = "example-db")]
191pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::ModelExampleSpec> {
192 vec![crate::example_db::specs::ModelExampleSpec {
193 id: "kcoloring_k3_simplegraph",
194 instance: Box::new(KColoring::<K3, _>::new(SimpleGraph::new(
195 5,
196 vec![(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)],
197 ))),
198 optimal_config: vec![0, 1, 1, 0, 2],
199 optimal_value: serde_json::json!(true),
200 }]
201}
202
203crate::declare_variants! {
204 default KColoring<KN, SimpleGraph> => "2^num_vertices",
205 KColoring<K2, SimpleGraph> => "num_vertices + num_edges",
206 KColoring<K3, SimpleGraph> => "1.3289^num_vertices",
207 KColoring<K4, SimpleGraph> => "1.7159^num_vertices",
208 KColoring<K5, SimpleGraph> => "2^num_vertices",
210}
211
212#[cfg(test)]
213#[path = "../../unit_tests/models/graph/kcoloring.rs"]
214mod tests;