graph_algo_ptas/algorithm/
tree_decomposition.rs1use arboretum_td::tree_decomposition::TreeDecomposition;
3use fxhash::FxHashSet;
4
5use std::collections::{HashMap, HashSet};
6
7use crate::algorithm::spantree::Span;
8use crate::data_structure::{
9 graph_dcel::GraphDCEL,
10 link_graph::{LinkDart, LinkFace, LinkGraphIter, LinkVertex},
11};
12
13fn tree_decomposition(
14 graph: &impl GraphDCEL<
15 LinkVertex,
16 LinkDart,
17 LinkFace,
18 LinkGraphIter<LinkVertex>,
19 LinkGraphIter<LinkDart>,
20 LinkGraphIter<LinkFace>,
21 >,
22 dual_graph: HashMap<LinkFace, HashSet<LinkFace>>,
23 spantree: &Span<LinkVertex>,
24 root_vertex: LinkFace,
25) -> TreeDecomposition {
26 let mut tree: TreeDecomposition = Default::default();
27
28 add_bags(root_vertex, 0, &mut tree, spantree, &dual_graph, graph);
29
30 tree
31}
32
33fn add_bags(
34 vertex: LinkFace,
35 parent: usize,
36 tree: &mut TreeDecomposition,
37 spantree: &Span<LinkVertex>,
38 dual_graph: &HashMap<LinkFace, HashSet<LinkFace>>,
39 graph: &impl GraphDCEL<
40 LinkVertex,
41 LinkDart,
42 LinkFace,
43 LinkGraphIter<LinkVertex>,
44 LinkGraphIter<LinkDart>,
45 LinkGraphIter<LinkFace>,
46 >,
47) {
48 let face_dart = graph.dart_face(&vertex);
49
50 let face_vertices = get_face_vertices(graph, face_dart);
51
52 let bag = create_bag(face_vertices, &spantree);
53
54 if parent == 0 {
55 tree.add_bag(bag);
56 } else {
57 tree.add_child_bags(parent, vec![bag]);
58 }
59
60 for c in dual_graph.get(&vertex).unwrap_or(&HashSet::new()) {
61 add_bags(
62 c.clone(),
63 vertex.get_id(),
64 tree,
65 spantree,
66 dual_graph,
67 graph,
68 );
69 }
70}
71
72fn create_bag(
73 face_vertices: HashSet<LinkVertex>,
74 spantree: &&Span<LinkVertex>,
75) -> FxHashSet<usize> {
76 let mut vertices: FxHashSet<usize> = FxHashSet::default();
77
78 for v in face_vertices {
79 let mut node = v;
80
81 vertices.insert(node.get_id());
82
83 while spantree.upwards.get(&node).is_some() {
84 node = spantree.upwards.get(&node).unwrap().clone();
85 vertices.insert(node.get_id());
86 }
87 }
88 vertices
89}
90
91fn get_face_vertices(
92 graph: &impl GraphDCEL<
93 LinkVertex,
94 LinkDart,
95 LinkFace,
96 LinkGraphIter<LinkVertex>,
97 LinkGraphIter<LinkDart>,
98 LinkGraphIter<LinkFace>,
99 >,
100 mut dart: LinkDart,
101) -> HashSet<LinkVertex> {
102 let mut result: HashSet<LinkVertex> = HashSet::new();
103
104 while result.insert(graph.dart_target(&dart)) {
105 dart = graph.next(&dart);
106 }
107 result
108}
109
110#[cfg(test)]
111mod tests {
112 use crate::algorithm::dualgraph::dual_graph;
113 use crate::algorithm::spantree::Span;
114 use crate::algorithm::tree_decomposition::tree_decomposition;
115 use crate::data_structure::graph_dcel::GraphDCEL;
116 use crate::data_structure::link_graph::LinkGraph;
117 use crate::embedding::{index::Embedding, maximal_planar::index::MaximalPlanar};
118 use crate::utils::convert::UndirectedGraph;
119 use fxhash::FxHashSet;
120 use petgraph::stable_graph::StableGraph;
121
122 #[test]
123 fn single_edge() {
124 let mut lg = LinkGraph::new();
125 let lv1 = lg.new_vertex();
126 let lv2 = lg.new_vertex();
127
128 let ld1 = lg.new_dart(lv1.clone(), lv2.clone(), None, None, None, None);
129 let lf = lg.new_face(ld1.clone());
130 lg.new_dart(
131 lv2.clone(),
132 lv1.clone(),
133 Some(ld1.clone()),
134 Some(ld1.clone()),
135 Some(ld1),
136 Some(lf.clone()),
137 );
138 let span = Span::compute(&lg, lv1.clone());
139 let td = tree_decomposition(&lg, dual_graph(&lg, &span), &span, lf);
140
141 println!("[RESULT]: {:?}", td);
142
143 assert_eq!(td.bags.len(), 1);
144 assert_eq!(td.max_bag_size, 2);
145 assert_eq!(td.bags[0].vertex_set.len(), 2);
146 let mut cb = FxHashSet::default();
147 cb.insert(lv1.get_id());
148 cb.insert(lv2.get_id());
149 assert_eq!(td.bags[0].vertex_set, cb)
150 }
151
152 #[test]
153 fn triangle() {
154 let sg: UndirectedGraph = StableGraph::from_edges(&[(0, 1), (1, 2), (2, 0)]);
155
156 let lg = MaximalPlanar::embed(sg);
157 assert_eq!(lg.vertex_count(), 3);
158 let lv0 = lg.vertex_by_id(0).unwrap();
159 let lv1 = lg.vertex_by_id(1).unwrap();
160 let lv2 = lg.vertex_by_id(2).unwrap();
161 let lof = lg.face(&lg.get_dart(&lv1, &lv0).unwrap());
162
163 let span = Span::compute(&lg, lv1.clone());
164 let td = tree_decomposition(&lg, dual_graph(&lg, &span), &span, lof);
165
166 println!("[RESULT]: {:?}", td);
167
168 assert_eq!(td.bags.len(), 1);
169 assert_eq!(td.max_bag_size, 3);
170 assert_eq!(td.bags[0].vertex_set.len(), 3);
171 let mut cb = FxHashSet::default();
172 cb.insert(lv1.get_id());
173 cb.insert(lv0.get_id());
174 cb.insert(lv2.get_id());
175 assert_eq!(td.bags[0].vertex_set, cb)
176 }
177}