This repository has been archived by the owner on Aug 5, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lex_p.h
149 lines (121 loc) · 3.73 KB
/
lex_p.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* Implementation of the LEX P algorithm described by Rose & Tarjan in
* "Algorithmic aspects of vertex elimination on graphs".
*
* See: https://doi.org/10.1137/0205021
*/
#ifndef ALGO_LEXP_H
#define ALGO_LEXP_H
#include <limits>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <boost/graph/graph_concepts.hpp>
#include "utils.h"
/**
* Compute a perfect elimination order for the given perfect elimination graph.
*
* @param g graph to compute the order for
* @return a perfect elimination order for the graph as an ordered sequence of
* all its vertices
*
* @pre `g` is a simple, connected, undirected, perfect elimination graph
*/
template <class Graph>
VertexOrder<Graph> lex_p(const Graph &g) {
struct Label;
struct LabeledVertex;
typedef VertexDesc<Graph> Vertex;
typedef VertexSizeT<Graph> VertexSz;
typedef std::unordered_map<Vertex, LabeledVertex *> LabeledVertexMap;
struct Label {
LabeledVertexMap vertex_map;
Label *prev;
Label *next;
Label() = delete;
Label(VertexSz n): vertex_map(n), prev(nullptr), next(nullptr) {}
};
struct LabeledVertex {
Vertex id;
Label *label;
LabeledVertex() = delete;
LabeledVertex(Vertex id, Label *l) : id(id), label(l) {}
};
static_assert(!std::numeric_limits<VertexSz>::is_signed);
BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept<Graph>));
BOOST_CONCEPT_ASSERT((boost::AdjacencyGraphConcept<Graph>));
const auto n_vertices = boost::num_vertices(g);
Label *head = new Label(n_vertices);
LabeledVertexMap unnumbered(n_vertices);
VertexOrder<Graph> order(n_vertices);
std::unordered_map<Label *, Label *> fix;
LabeledVertex *cur_vertex;
// Assign the empty label to all the vertices of the graph
for (const auto id : iter_vertices(g)) {
LabeledVertex *v = new LabeledVertex(id, head);
head->vertex_map[id] = v;
unnumbered[id] = v;
}
// Number each vertex of the graph in reverse order
for (auto index = n_vertices - 1; index < n_vertices; index--) {
cur_vertex = nullptr;
// Find cur_vertex as the highest-labeled unnumbered vertex scanning the
// linked list of labels
for (auto label = head; !cur_vertex && label; label = label->next) {
for (const auto [id, v] : label->vertex_map) {
auto it = unnumbered.find(id);
if (it != unnumbered.end()) {
cur_vertex = v;
unnumbered.erase(it);
break;
}
}
}
// Assign index to cur_vertex
assert(cur_vertex);
order[index] = cur_vertex->id;
// For each unnumbered neighbor of the current vertex
for (const auto neighbor_id : iter_neighbors(g, cur_vertex->id)) {
auto it = unnumbered.find(neighbor_id);
if (it != unnumbered.end()) {
// Create a new label (if not already created) which preceeds
// the current neighbor's label of exactly one position in the
// list of labels
auto neighbor = (*it).second;
auto prev_it = fix.find(neighbor->label);
Label *new_label;
if (prev_it != fix.end()) {
new_label = (*prev_it).second;
} else {
new_label = new Label(1);
fix[neighbor->label] = new_label;
}
// Remove this neighbor from its current label and assign it to
// the newly created label
neighbor->label->vertex_map.erase(neighbor_id);
neighbor->label = new_label;
neighbor->label->vertex_map[neighbor_id] = neighbor;
}
}
// Add newly created labels to the list
for (const auto [label, new_label] : fix) {
if (label->prev)
label->prev->next = new_label;
else
head = new_label;
new_label->next = label;
new_label->prev = label->prev;
label->prev = new_label;
}
fix.clear();
}
while (head) {
auto nxt = head->next;
for (auto v : head->vertex_map)
delete v.second;
delete head;
head = nxt;
}
return order;
}
#endif // ALGO_LEXP_H