mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
AdjacencyMatrix.cpp
Go to the documentation of this file.
2
3#include <queue>
4
5
6using namespace m;
7
8
9/*======================================================================================================================
10 * AdjacencyMatrix
11 *====================================================================================================================*/
12
14{
15 AdjacencyMatrix closure(*this); // copy
16
17 bool changed;
18 do {
19 changed = false;
20 for (std::size_t i = 0; i != num_vertices_; ++i) {
21 for (std::size_t j = 0; j != num_vertices_; ++j) {
22 if (not closure(i, j)) {
23 const SmallBitset row = closure.m_[i];
24 const SmallBitset col_mask = SmallBitset::Singleton(j);
25 for (std::size_t k : row) {
26 M_insist(row[k]);
27 if (closure.m_[k] & col_mask) {
28 closure(i, j) = true;
29 changed = true;
30 break;
31 }
32 }
33 }
34 }
35 }
36 } while (changed);
37
38 return closure;
39}
40
42{
43 AdjacencyMatrix closure(*this); // copy
44
45 bool changed;
46 do {
47 changed = false;
48 for (std::size_t i = 0; i != num_vertices_; ++i) {
49 for (std::size_t j = i; j != num_vertices_; ++j) { // exploit symmetry
50 M_insist(closure(i, j) == closure(j, i), "not symmetric");
51 const bool before = closure(i, j);
52 const SmallBitset row = closure.m_[i];
53 const SmallBitset col = closure.m_[j]; // exploit symmetry
54 const bool dot = not (row & col).empty(); // compute connected-ness as "dot product"
55 closure(i, j) = closure(j, i) = dot;
56 changed = changed or before != dot;
57 }
58 }
59 } while (changed);
60
61 return closure;
62}
63
64AdjacencyMatrix AdjacencyMatrix::minimum_spanning_forest(std::function<double(std::size_t, std::size_t)> weight) const
65{
67
68 if (num_vertices_ == 0)
69 return MSF;
70
71 struct weighted_edge
72 {
73 std::size_t source, sink;
74 double weight;
75
76 weighted_edge() = default;
77 weighted_edge(std::size_t source, std::size_t sink, double weight)
78 : source(source), sink(sink), weight(weight)
79 { }
80
81 bool operator<(const weighted_edge &other) const { return this->weight < other.weight; }
82 bool operator>(const weighted_edge &other) const { return this->weight > other.weight; }
83 };
84 std::priority_queue<weighted_edge, std::vector<weighted_edge>, std::greater<weighted_edge>> Q;
85
86 /* Run Prim's algorithm for each remaining vertex to compute a MSF. */
87 SmallBitset vertices_remaining = SmallBitset::All(num_vertices_);
88
89 while (vertices_remaining) {
90 SmallBitset next_vertex = vertices_remaining.begin().as_set();
91 vertices_remaining = vertices_remaining - next_vertex;
92
93 /* Prim's algorithm for finding a MST. */
94 while (next_vertex) {
95 /* Explore edges of `next_vertex`. */
96 M_insist(next_vertex.is_singleton());
97 const SmallBitset N = neighbors(next_vertex) & vertices_remaining;
98 const std::size_t u = *next_vertex.begin();
99 for (std::size_t v : N)
100 Q.emplace(u, v, weight(u, v));
101
102 /* Search for the cheapest edge not within the MSF. */
103 weighted_edge E;
104 do {
105 if (Q.empty())
106 goto MST_done;
107 E = Q.top();
108 Q.pop();
109 } while (not vertices_remaining[E.sink]);
110
111 /* Add edge to MSF. */
112 M_insist(vertices_remaining[E.sink], "sink must not yet be in the MSF");
113 vertices_remaining[E.sink] = false;
114 MSF(E.source, E.sink) = MSF(E.sink, E.source) = true; // add undirected edge to MSF
115 next_vertex = SmallBitset::Singleton(E.sink);
116 }
117MST_done: /* MST is complete */;
118 }
119 return MSF;
120}
121
123{
124 M_insist(root.is_singleton());
125 AdjacencyMatrix directed_tree(num_vertices_);
126 SmallBitset V = root;
128 while (not V.empty()) {
129 X |= V;
130 for (auto v : V)
131 directed_tree.m_[v] = this->m_[v] - X;
132 V = directed_tree.neighbors(V);
133 }
134
135 return directed_tree;
136}
137
139void AdjacencyMatrix::dump(std::ostream &out) const { out << *this << std::endl; }
140void AdjacencyMatrix::dump() const { dump(std::cerr); }
#define M_insist(...)
Definition: macro.hpp:129
‍mutable namespace
Definition: Backend.hpp:10
An adjacency matrix for a given query graph.
AdjacencyMatrix transitive_closure_directed() const
Computes the transitive closure of this adjacency matrix.
std::array< SmallBitset, SmallBitset::CAPACITY > m_
matrix entries
AdjacencyMatrix transitive_closure_undirected() const
Computes the transitive closure of this adjacency matrix.
std::size_t num_vertices_
number of sources of the QueryGraph represented by this matrix
AdjacencyMatrix minimum_spanning_forest(std::function< double(std::size_t, std::size_t)> weight) const
Computes the minimum spanning forest for this graph.
AdjacencyMatrix tree_directed_away_from(SmallBitset root)
Computes an AdjacencyMatrix with all edges directed away from root.
SmallBitset neighbors(SmallBitset S) const
Computes the neighbors of S.
Implements a small and efficient set over integers in the range of 0 to 63 (including).
Definition: ADT.hpp:26
bool is_singleton() const
Definition: ADT.hpp:165
static SmallBitset All(std::size_t n)
Factory method for creating a SmallBitset with first n bits set.
Definition: ADT.hpp:117
bool empty() const
Returns true if there are no elements in this SmallBitset.
Definition: ADT.hpp:163
static SmallBitset Singleton(std::size_t n)
Factory method for creating a Singleton Smallbitset with n -th bit set.
Definition: ADT.hpp:125
auto begin() const
Definition: ADT.hpp:173