snark_tool/service/colour/recursive/
bfs_basic.rs

1use crate::graph::edge::Edge;
2use crate::graph::graph::Graph;
3use crate::graph::vertex::Vertex;
4use crate::service::colour::colouriser::Colouriser;
5use crate::service::graph_traversal::bfs::BfsOfGraph;
6
7///
8/// Works only for cubic graphs
9///
10#[derive(Debug, Clone)]
11pub struct BFSColouriserBasic {}
12
13struct BFSColouriserGraph<'a, G: Graph> {
14    vertices: Vec<[(usize, usize); 3]>,
15    bfs: BfsOfGraph<'a, G>,
16}
17
18impl Colouriser for BFSColouriserBasic {
19    fn is_colorable<G: Graph>(graph: &G) -> bool {
20        let mut color_graph = BFSColouriserGraph::new(graph);
21        color_graph.color()
22    }
23
24    fn new() -> Self {
25        BFSColouriserBasic {}
26    }
27}
28
29impl<'a, G: Graph> BFSColouriserGraph<'a, G> {
30    pub fn new(graph: &'a G) -> Self {
31        let mut vertices = Vec::with_capacity(graph.size());
32        // create local graph
33        for vertex in graph.vertices() {
34            let mut neighbors = [(0, 0); 3];
35            let mut i = 0;
36            for edge in graph.edges_of_vertex(vertex.index()) {
37                // important for subcubic graphs?
38                // neighbors[i].1 = 1;
39                neighbors[i].1 = 0;
40                if edge.from() == vertex.index() {
41                    neighbors[i].0 = edge.to();
42                } else {
43                    neighbors[i].0 = edge.from();
44                }
45                i += 1;
46            }
47            vertices.push(neighbors);
48        }
49        let first_vertex = 0;
50        let colors = vec![3, 4, 5];
51        let bfs = BfsOfGraph::new(graph, first_vertex);
52
53        let mut color_graph = BFSColouriserGraph { vertices, bfs };
54
55        // pre color edges of first vertex
56        color_graph.bfs.next();
57        color_graph.set_edge_color(
58            first_vertex,
59            color_graph.vertices[first_vertex][0].0,
60            colors[0],
61        );
62        color_graph.set_edge_color(
63            first_vertex,
64            color_graph.vertices[first_vertex][1].0,
65            colors[1],
66        );
67        color_graph.set_edge_color(
68            first_vertex,
69            color_graph.vertices[first_vertex][2].0,
70            colors[2],
71        );
72
73        color_graph
74    }
75
76    fn color(&mut self) -> bool {
77        if let Some(next) = self.bfs.next() {
78            let actual = next.index();
79
80            // compute actual sum of colors of edges of next
81            let mut color_sum = 0;
82            let mut first_neighbor = 0;
83            let mut second_neighbor = 0;
84            for neighbor in self.vertices[next.index()].iter() {
85                color_sum += neighbor.1;
86
87                if neighbor.1 == 0 {
88                    second_neighbor = first_neighbor;
89                    first_neighbor = neighbor.0;
90                }
91            }
92
93            match color_sum {
94                // one already colored edge
95                3 => {
96                    self.set_edge_color(actual, first_neighbor, 4);
97                    self.set_edge_color(actual, second_neighbor, 5);
98                    if self.are_vertices_without_conflict(first_neighbor, second_neighbor) {
99                        if self.color() {
100                            return true;
101                        }
102                    }
103                    self.set_edge_color(actual, first_neighbor, 5);
104                    self.set_edge_color(actual, second_neighbor, 4);
105                    if self.are_vertices_without_conflict(first_neighbor, second_neighbor) {
106                        if self.color() {
107                            return true;
108                        }
109                    }
110                    self.set_edge_color(actual, first_neighbor, 0);
111                    self.set_edge_color(actual, second_neighbor, 0);
112                }
113                4 => {
114                    self.set_edge_color(actual, first_neighbor, 3);
115                    self.set_edge_color(actual, second_neighbor, 5);
116                    if self.are_vertices_without_conflict(first_neighbor, second_neighbor) {
117                        if self.color() {
118                            return true;
119                        }
120                    }
121                    self.set_edge_color(actual, first_neighbor, 5);
122                    self.set_edge_color(actual, second_neighbor, 3);
123                    if self.are_vertices_without_conflict(first_neighbor, second_neighbor) {
124                        if self.color() {
125                            return true;
126                        }
127                    }
128                    self.set_edge_color(actual, first_neighbor, 0);
129                    self.set_edge_color(actual, second_neighbor, 0);
130                }
131                5 => {
132                    self.set_edge_color(actual, first_neighbor, 3);
133                    self.set_edge_color(actual, second_neighbor, 4);
134                    if self.are_vertices_without_conflict(first_neighbor, second_neighbor) {
135                        if self.color() {
136                            return true;
137                        }
138                    }
139                    self.set_edge_color(actual, first_neighbor, 4);
140                    self.set_edge_color(actual, second_neighbor, 3);
141                    if self.are_vertices_without_conflict(first_neighbor, second_neighbor) {
142                        if self.color() {
143                            return true;
144                        }
145                    }
146                    self.set_edge_color(actual, first_neighbor, 0);
147                    self.set_edge_color(actual, second_neighbor, 0);
148                }
149                // two already colored edges
150                7 => {
151                    self.set_edge_color(actual, first_neighbor, 5);
152                    if self.is_vertex_without_conflict(&self.vertices[first_neighbor]) {
153                        if self.color() {
154                            return true;
155                        }
156                    }
157                    self.set_edge_color(actual, first_neighbor, 0);
158                }
159                8 => {
160                    self.set_edge_color(actual, first_neighbor, 4);
161                    if self.is_vertex_without_conflict(&self.vertices[first_neighbor]) {
162                        if self.color() {
163                            return true;
164                        }
165                    }
166                    self.set_edge_color(actual, first_neighbor, 0);
167                }
168                9 => {
169                    self.set_edge_color(actual, first_neighbor, 3);
170                    if self.is_vertex_without_conflict(&self.vertices[first_neighbor]) {
171                        if self.color() {
172                            return true;
173                        }
174                    }
175                    self.set_edge_color(actual, first_neighbor, 0);
176                }
177
178                12 => {
179                    if self.color() {
180                        return true;
181                    }
182                }
183                _ => panic!("unknown color sum: {}", color_sum),
184            }
185
186            self.bfs.back();
187            return false;
188        }
189        true
190    }
191
192    fn set_edge_color(&mut self, from: usize, to: usize, color: usize) {
193        for neighbor in self.vertices[from].iter_mut() {
194            if neighbor.0 == to {
195                neighbor.1 = color;
196                break;
197            }
198        }
199        for neighbor in self.vertices[to].iter_mut() {
200            if neighbor.0 == from {
201                neighbor.1 = color;
202                break;
203            }
204        }
205    }
206
207    fn is_vertex_without_conflict(&self, neighbors: &[(usize, usize); 3]) -> bool {
208        is_without_conflict(neighbors[0].1, neighbors[1].1, neighbors[2].1)
209    }
210
211    fn are_vertices_without_conflict(&self, first: usize, second: usize) -> bool {
212        self.is_vertex_without_conflict(&self.vertices[first])
213            && self.is_vertex_without_conflict(&self.vertices[second])
214    }
215}
216
217fn is_without_conflict(color1: usize, color2: usize, color3: usize) -> bool {
218    if (color1 == color2) && (color1 > 1) {
219        return false;
220    }
221    if (color1 == color3) && (color1 > 1) {
222        return false;
223    }
224    if (color3 == color2) && (color3 > 1) {
225        return false;
226    }
227    return true;
228}