snark_tool/service/matching/
perfect_matchings.rs

1use crate::graph::edge::{Edge, EdgeConstructor};
2use crate::graph::graph::Graph;
3use crate::graph::undirected::edge::UndirectedEdge;
4use std::collections::VecDeque;
5use std::slice;
6
7// TODO - refactor, rename MatchingGraph, impl Graph for MatchingGraph
8
9#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
10pub struct Matching {
11    pub edges: Vec<UndirectedEdge>,
12}
13
14impl Matching {
15    pub fn new() -> Self {
16        Matching { edges: vec![] }
17    }
18}
19
20#[derive(Debug, Clone)]
21pub struct MatchingGraph {
22    vertices: Vec<MatchingVertex>,
23    size: usize,
24}
25
26#[derive(Debug, Clone)]
27pub struct MatchingVertex {
28    index: usize,
29    active: bool,
30    neighbors: Vec<usize>,
31}
32
33impl MatchingVertex {
34    pub fn new(index: usize) -> Self {
35        MatchingVertex {
36            index,
37            active: true,
38            neighbors: vec![],
39        }
40    }
41
42    pub fn new_non_active(index: usize) -> Self {
43        MatchingVertex {
44            index,
45            active: false,
46            neighbors: vec![],
47        }
48    }
49
50    pub fn index(&self) -> &usize {
51        &self.index
52    }
53
54    #[allow(dead_code)]
55    pub fn neighbors(&self) -> &Vec<usize> {
56        &self.neighbors
57    }
58}
59
60#[allow(dead_code)]
61impl MatchingGraph {
62    pub fn new() -> Self {
63        Self::with_capacity(0)
64    }
65
66    pub fn with_capacity(capacity: usize) -> Self {
67        MatchingGraph {
68            vertices: Vec::with_capacity(capacity),
69            size: 0,
70        }
71    }
72
73    pub fn from_graph<G: Graph>(graph: &G) -> Self {
74        let mut match_graph = MatchingGraph::with_capacity(graph.size());
75        for edge in graph.edges() {
76            match_graph.add_edge(edge.from(), edge.to());
77        }
78        match_graph
79    }
80
81    pub fn has_edge(&self, from: usize, to: usize) -> bool {
82        if !self.vertices[from].active || !self.vertices[to].active {
83            return false;
84        }
85        let mut first = false;
86        for neighbor in self.neighbors(from) {
87            if neighbor == &to {
88                first = true;
89                break;
90            }
91        }
92        if !first {
93            return false;
94        }
95        let mut second = false;
96        for neighbor in self.neighbors(to) {
97            if neighbor == &from {
98                second = true;
99            }
100        }
101        if !second {
102            return false;
103        }
104        true
105    }
106
107    pub fn add_edge(&mut self, from: usize, to: usize) {
108        self.create_vertex_if_not_exists(from);
109        self.create_vertex_if_not_exists(to);
110        self.vertices[from]
111            .neighbors
112            .retain(|neighbor| neighbor != &to);
113        self.vertices[from].neighbors.push(to);
114        self.vertices[to]
115            .neighbors
116            .retain(|neighbor| neighbor != &from);
117        self.vertices[to].neighbors.push(from);
118    }
119
120    pub fn remove_edge(&mut self, from: usize, to: usize) {
121        self.vertices[from]
122            .neighbors
123            .retain(|neighbor| neighbor != &to);
124        self.vertices[to]
125            .neighbors
126            .retain(|neighbor| neighbor != &from);
127    }
128
129    ///
130    /// if given vertex is removed but has neighbors - will be recovered as is
131    ///
132    pub fn create_vertex_if_not_exists(&mut self, vertex: usize) {
133        if self.vertices.len() > vertex {
134            if !self.vertices[vertex].active {
135                self.size += 1;
136                self.vertices[vertex].active = true;
137                self.vertices[vertex].neighbors = vec![];
138            }
139            return;
140        }
141        while self.vertices.len() <= vertex {
142            if self.vertices.len() == vertex {
143                self.vertices.push(MatchingVertex::new(self.vertices.len()));
144                self.size += 1;
145            } else {
146                self.vertices
147                    .push(MatchingVertex::new_non_active(self.vertices.len()));
148            }
149        }
150    }
151
152    pub fn add_vertex(&mut self, vertex: MatchingVertex) {
153        self.create_vertex_if_not_exists(vertex.index);
154        for neighbor in vertex.neighbors.iter() {
155            self.create_vertex_if_not_exists(*neighbor);
156            let mut already_has = false;
157            for neighbor in self.vertices[*neighbor].neighbors.iter() {
158                if neighbor == &vertex.index {
159                    already_has = true;
160                    break;
161                }
162            }
163            if !already_has {
164                self.vertices[*neighbor].neighbors.push(vertex.index);
165            }
166        }
167        self.vertices[vertex.index].neighbors = vertex.neighbors;
168    }
169
170    pub fn size(&self) -> usize {
171        self.size
172    }
173
174    pub fn max_vertex_index(&self) -> usize {
175        self.vertices.len()
176    }
177
178    pub fn vertices(&self) -> MatchingGraphVerticesIter {
179        MatchingGraphVerticesIter {
180            vertices: self.vertices.iter(),
181        }
182    }
183
184    ///
185    /// can crash if vertex >= self.vertices.len()
186    ///
187    pub fn neighbors(&self, vertex: usize) -> &Vec<usize> {
188        &self.vertices[vertex].neighbors
189    }
190
191    fn first_vertex(&self) -> Option<&MatchingVertex> {
192        for vertex in self.vertices.iter() {
193            if vertex.active {
194                return Some(vertex);
195            }
196        }
197        None
198    }
199
200    pub fn remove_vertex(&mut self, vertex: usize) {
201        let neighbors = self.vertices[vertex].neighbors.clone();
202        for neighbor in neighbors {
203            self.vertices[neighbor]
204                .neighbors
205                .retain(|neighb| neighb != &vertex);
206        }
207        self.vertices[vertex].active = false;
208        self.size -= 1;
209    }
210
211    pub fn has_odd_size_component(&mut self) -> bool {
212        let mut removed_vertices = vec![];
213        while let Some(start) = self.first_vertex() {
214            let mut bfs_graph = BfsGraph::new(self, start.index);
215            let mut visited_vertices = vec![];
216            while let Some(vertex) = bfs_graph.bfs_next() {
217                visited_vertices.push(vertex);
218            }
219            if visited_vertices.len() % 2 == 1 {
220                self.activate_vertices(removed_vertices);
221                return true;
222            }
223
224            // shortcut
225            if visited_vertices.len() == self.size() {
226                return false;
227            }
228            // remove visited vertices
229            for visited_vertex in visited_vertices {
230                removed_vertices.push(visited_vertex);
231                self.vertices[visited_vertex].active = false;
232            }
233        }
234        self.activate_vertices(removed_vertices);
235        false
236    }
237
238    fn activate_vertices(&mut self, vertices_to_activate: Vec<usize>) {
239        for vertex_to_activate in vertices_to_activate {
240            self.vertices[vertex_to_activate].active = true;
241        }
242    }
243
244    pub fn perfect_matchings(&mut self) -> Vec<Matching> {
245        let mut matchings = vec![];
246        if self.size == 0 {
247            matchings.push(Matching::new());
248            return matchings;
249        }
250        if !self.has_odd_size_component() {
251            if let Some(vertex) = self.first_vertex() {
252                let vertex = vertex.clone();
253                for neighbor in vertex.neighbors.iter() {
254                    // remove vertices
255                    let mut removed_vertices = vec![];
256                    removed_vertices.push(self.vertices[vertex.index].clone());
257                    removed_vertices.push(self.vertices[*neighbor].clone());
258
259                    self.remove_vertex(vertex.index);
260                    self.remove_vertex(*neighbor);
261                    let mut matchings_local = self.perfect_matchings();
262                    for matching in matchings_local.iter_mut() {
263                        matching
264                            .edges
265                            .push(UndirectedEdge::new(vertex.index, *neighbor));
266                    }
267                    matchings.append(&mut matchings_local);
268                    // recover removed vertices
269                    for removed_vertex in removed_vertices {
270                        self.add_vertex(removed_vertex);
271                    }
272                }
273            }
274        }
275        matchings
276    }
277}
278
279pub struct MatchingGraphVerticesIter<'a> {
280    vertices: slice::Iter<'a, MatchingVertex>,
281}
282
283impl<'a> Iterator for MatchingGraphVerticesIter<'a> {
284    type Item = &'a MatchingVertex;
285
286    fn next(&mut self) -> Option<Self::Item> {
287        while let Some(vertex) = self.vertices.next() {
288            if vertex.active {
289                return Some(vertex);
290            }
291        }
292        None
293    }
294}
295
296pub struct BfsGraph<'a> {
297    graph: &'a MatchingGraph,
298    visited: Vec<bool>,
299    to_visit: VecDeque<usize>,
300}
301
302impl<'a> BfsGraph<'a> {
303    pub fn new(graph: &'a MatchingGraph, start: usize) -> Self {
304        let visited = vec![false; graph.vertices.len()];
305        let mut to_visit = VecDeque::new();
306        to_visit.push_back(start);
307
308        let mut bfs = Self {
309            graph,
310            visited,
311            to_visit,
312        };
313        bfs.visit(start);
314        bfs
315    }
316
317    ///
318    /// if true, visited for the first time
319    ///
320    fn visit(&mut self, vertex: usize) -> bool {
321        let old_val = self.visited[vertex];
322        self.visited[vertex] = true;
323        !old_val
324    }
325
326    pub fn bfs_next(&mut self) -> Option<usize> {
327        if let Some(vertex) = self.to_visit.pop_front() {
328            for neighbor in self.graph.neighbors(vertex) {
329                if self.visit(*neighbor) {
330                    self.to_visit.push_back(*neighbor);
331                }
332            }
333            return Some(vertex);
334        }
335        None
336    }
337}