graph_algo_ptas/embedding/maximal_planar/
phase1.rs1use super::stack_item::StackItem;
6use crate::utils::convert::UndirectedGraph;
7use petgraph::graph::NodeIndex;
8use petgraph::visit::EdgeRef;
9use std::collections::BTreeSet;
10
11pub struct Phase1<'a> {
12 graph: &'a mut UndirectedGraph,
13 stack: &'a mut Vec<StackItem>,
14 reducible: BTreeSet<NodeIndex>,
15}
16
17impl Phase1<'_> {
18 pub fn new<'a>(graph: &'a mut UndirectedGraph, stack: &'a mut Vec<StackItem>) -> Phase1<'a> {
19 let mut phase1 = Phase1 {
20 graph,
21 stack,
22 reducible: Default::default(),
23 };
24
25 phase1.reducible = phase1
26 .graph
27 .clone()
29 .node_indices()
30 .filter(|n| phase1.is_reducible(*n))
31 .collect::<BTreeSet<_>>();
32
33 phase1
34 }
35
36 pub fn execute(&mut self) {
37 while self.graph.node_count() > 4 {
38 let v = match self.reducible.iter().next() {
39 Some(v) => *v,
40 None => panic!(), };
42 self.reducible.remove(&v);
43 let degree = self.graph.edges(v).count();
44 let h = self.graph.neighbors(v).collect::<BTreeSet<_>>();
45
46 self.graph.clone().edges(v).for_each(|e| {
47 self.stack
48 .push(StackItem::Edge(self.graph.edge_endpoints(e.id()).unwrap()));
49 self.graph.remove_edge(e.id());
50 });
51
52 self.graph.remove_node(v);
53 self.stack.push(StackItem::Node(v));
54
55 let new_h = h.clone();
56 let w = if degree >= 4 {
57 new_h.iter().find(|n| self.find_neighbors(&h, **n))
58 } else {
59 None
60 };
61
62 if degree >= 4 {
63 let mut x = h.clone();
64 self.graph.neighbors(*w.unwrap()).for_each(|n| {
65 x.remove(&n);
66 });
67 x.remove(w.unwrap());
68
69 let mut xi = x.iter();
70
71 self.add_edge(*w.unwrap(), *xi.next().unwrap());
72
73 if degree == 5 {
74 self.add_edge(*w.unwrap(), *xi.next().unwrap());
75 }
76 }
77
78 self.update_local(&h);
79 self.stack.push(StackItem::Degree(degree))
80 }
81 }
82
83 fn is_reducible(&mut self, node_idx: NodeIndex) -> bool {
84 let count = self.graph.edges(node_idx).count();
85 let small_neighbor_count = self.get_small_neighbor_count(node_idx);
86
87 count <= 3
88 || count == 4 && small_neighbor_count >= 2
89 || count == 5 && small_neighbor_count >= 4
90 }
91
92 fn get_small_neighbor_count(&mut self, node_idx: NodeIndex) -> usize {
93 self.graph
94 .neighbors(node_idx)
95 .into_iter()
96 .filter(|n| self.graph.edges(*n).count() < 18)
97 .count()
98 }
99
100 fn find_neighbors(&mut self, h: &BTreeSet<NodeIndex>, node_idx: NodeIndex) -> bool {
101 let neighbors = self.graph.neighbors(node_idx);
102 let mut count = 0;
103
104 neighbors.for_each(|n| {
105 if h.contains(&n) {
106 count += 1;
107 }
108 });
109
110 count == 2
111 }
112
113 fn update_local(&mut self, h: &BTreeSet<NodeIndex>) {
114 h.iter().for_each(|x| {
115 if self.graph.edges(*x).count() < 18
116 {
118 self.update_reducible(*x);
119 }
120
121 self.graph.clone().neighbors(*x).for_each(|n| {
123 if self.graph.edges(n).into_iter().count() <= 5 {
124 self.update_reducible(n);
125 }
126 })
127 })
128 }
129
130 fn update_reducible(&mut self, node_idx: NodeIndex) {
131 let is_reducible = self.is_reducible(node_idx);
132
133 if is_reducible {
134 self.reducible.insert(node_idx);
135 } else {
136 self.reducible.remove(&node_idx);
137 }
138 }
139
140 fn add_edge(&mut self, a: NodeIndex, b: NodeIndex) {
141 self.graph.add_edge(a, b, ());
142 self.stack.push(StackItem::Edge((a, b)));
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use petgraph::stable_graph::StableGraph;
149
150 use crate::{embedding::maximal_planar::phase1::Phase1, utils::convert::UndirectedGraph};
151
152 fn other_graph() -> UndirectedGraph {
153 StableGraph::from_edges([
154 (0, 1),
155 (1, 2),
156 (2, 0),
157 (1, 3),
158 (2, 3),
159 (0, 4),
160 (1, 4),
161 (2, 4),
162 (3, 4),
163 ])
164 }
165
166 #[test]
167 fn phase_1() {
168 let mut graph = other_graph();
169 let mut stack = Vec::new();
170
171 Phase1::new(&mut graph, &mut stack).execute();
172
173 }
175}