1use crate::base::{EdgeWeight, Graph, Node};
6use std::collections::{HashMap, HashSet};
7
8#[derive(Debug, Clone)]
10pub struct GraphColoring<N: Node> {
11 pub coloring: HashMap<N, usize>,
13 pub num_colors: usize,
15}
16
17#[allow(dead_code)]
28pub fn greedy_coloring<N, E, Ix>(graph: &Graph<N, E, Ix>) -> GraphColoring<N>
29where
30 N: Node + std::fmt::Debug,
31 E: EdgeWeight,
32 Ix: petgraph::graph::IndexType,
33{
34 let mut coloring: HashMap<N, usize> = HashMap::new();
35 let mut max_color = 0;
36
37 for node_idx in graph.inner().node_indices() {
39 let mut used_colors = HashSet::new();
41 for neighbor_idx in graph.inner().neighbors(node_idx) {
42 if let Some(neighbor_node) = graph.inner().node_weight(neighbor_idx) {
43 if let Some(&color) = coloring.get(neighbor_node) {
44 used_colors.insert(color);
45 }
46 }
47 }
48
49 let mut color = 0;
51 while used_colors.contains(&color) {
52 color += 1;
53 }
54
55 let node = graph.inner()[node_idx].clone();
56 coloring.insert(node, color);
57 max_color = max_color.max(color);
58 }
59
60 GraphColoring {
61 coloring,
62 num_colors: max_color + 1,
63 }
64}
65
66#[allow(dead_code)]
78pub fn chromatic_number<N, E, Ix>(graph: &Graph<N, E, Ix>, max_colors: usize) -> Option<usize>
79where
80 N: Node + std::fmt::Debug,
81 E: EdgeWeight,
82 Ix: petgraph::graph::IndexType,
83{
84 if graph.inner().node_count() == 0 {
85 return Some(0);
86 }
87
88 (1..=max_colors).find(|&num_colors| can_color_with_k_colors(graph, num_colors))
90}
91
92#[allow(dead_code)]
94fn can_color_with_k_colors<N, E, Ix>(graph: &Graph<N, E, Ix>, k: usize) -> bool
95where
96 N: Node + std::fmt::Debug,
97 E: EdgeWeight,
98 Ix: petgraph::graph::IndexType,
99{
100 let nodes: Vec<_> = graph.inner().node_indices().collect();
101 let mut coloring = vec![0; nodes.len()];
102
103 fn backtrack<N, E, Ix>(
104 _graph: &Graph<N, E, Ix>,
105 nodes: &[petgraph::graph::NodeIndex<Ix>],
106 coloring: &mut [usize],
107 node_idx: usize,
108 k: usize,
109 ) -> bool
110 where
111 N: Node + std::fmt::Debug,
112 E: EdgeWeight,
113 Ix: petgraph::graph::IndexType,
114 {
115 if node_idx == nodes.len() {
116 return true;
117 }
118
119 let node = nodes[node_idx];
120
121 for color in 0..k {
122 let mut valid = true;
124 for (i, &other_node) in nodes.iter().enumerate().take(node_idx) {
125 if (_graph.inner().contains_edge(node, other_node)
126 || _graph.inner().contains_edge(other_node, node))
127 && coloring[i] == color
128 {
129 valid = false;
130 break;
131 }
132 }
133
134 if valid {
135 coloring[node_idx] = color;
136 if backtrack(_graph, nodes, coloring, node_idx + 1, k) {
137 return true;
138 }
139 }
140 }
141
142 false
143 }
144
145 backtrack(graph, &nodes, &mut coloring, 0, k)
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151 use crate::generators::create_graph;
152
153 #[test]
154 fn test_greedy_coloring() {
155 let mut graph = create_graph::<char, ()>();
157 graph.add_edge('A', 'B', ()).unwrap();
158 graph.add_edge('B', 'C', ()).unwrap();
159 graph.add_edge('C', 'A', ()).unwrap();
160
161 let coloring = greedy_coloring(&graph);
162 assert_eq!(coloring.num_colors, 3);
163
164 assert_ne!(coloring.coloring[&'A'], coloring.coloring[&'B']);
166 assert_ne!(coloring.coloring[&'B'], coloring.coloring[&'C']);
167 assert_ne!(coloring.coloring[&'C'], coloring.coloring[&'A']);
168 }
169
170 #[test]
171 fn test_bipartite_graph_coloring() {
172 let mut graph = create_graph::<i32, ()>();
174
175 graph.add_edge(0, 1, ()).unwrap();
177 graph.add_edge(0, 3, ()).unwrap();
178 graph.add_edge(2, 1, ()).unwrap();
179 graph.add_edge(2, 3, ()).unwrap();
180
181 let coloring = greedy_coloring(&graph);
182 assert!(coloring.num_colors <= 2);
183 }
184
185 #[test]
186 fn test_chromatic_number() {
187 let mut triangle = create_graph::<i32, ()>();
189
190 triangle.add_edge(0, 1, ()).unwrap();
191 triangle.add_edge(1, 2, ()).unwrap();
192 triangle.add_edge(2, 0, ()).unwrap();
193
194 assert_eq!(chromatic_number(&triangle, 5), Some(3));
195
196 let mut bipartite = create_graph::<i32, ()>();
198
199 bipartite.add_edge(0, 1, ()).unwrap();
200 bipartite.add_edge(1, 2, ()).unwrap();
201 bipartite.add_edge(2, 3, ()).unwrap();
202 bipartite.add_edge(3, 0, ()).unwrap();
203
204 assert_eq!(chromatic_number(&bipartite, 5), Some(2));
205
206 let empty = create_graph::<i32, ()>();
208 assert_eq!(chromatic_number(&empty, 5), Some(0));
209 }
210}