ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
Graph.h
Go to the documentation of this file.
1/**
2 * @file Graph.h
3 * @brief Undirected graph used in tree-decomposition computations.
4 *
5 * Originally taken and adapted from https://github.com/smaniu/treewidth
6 *
7 * @c Graph is a mutable, adjacency-list-based undirected (or directed)
8 * graph over @c unsigned @c long node IDs. It is used during the
9 * tree-decomposition algorithm to represent the "primal graph" of a
10 * @c BooleanCircuit: nodes correspond to gates and edges connect gates
11 * that are connected by a wire.
12 *
13 * The mutating operations (@c remove_node, @c fill, @c contract_edge)
14 * are used by the elimination-ordering heuristic implemented in
15 * @c PermutationStrategy and @c TreeDecomposition.
16 */
17#ifndef Graph_h
18#define Graph_h
19#include <cstdlib>
20#include <unordered_map>
21#include <unordered_set>
22#include <cassert>
23
24#include "BooleanCircuit.h"
25
26/**
27 * @brief Mutable adjacency-list graph over unsigned-long node IDs.
28 *
29 * Supports both directed and undirected edges, node/edge removal,
30 * clique-fill operations, and edge contraction, as needed by the
31 * min-fill tree-decomposition algorithm.
32 */
33class Graph {
34private:
35std::unordered_map<unsigned long, std::unordered_set<unsigned long> > adj_list; ///< Adjacency lists
36std::unordered_set<unsigned long> node_set; ///< Set of all node IDs
37unsigned long num_edges = 0; ///< Current edge count
38
39public:
40/** @brief Construct an empty graph, to be populated with @c add_node() / @c add_edge(). */
41Graph() = default;
42
43/**
44 * @brief Construct the primal graph of a @c BooleanCircuit.
45 *
46 * Each gate (except @c UNDETERMINED and @c MULVAR) becomes a node.
47 * Each wire between two gates becomes an undirected edge.
48 *
49 * @param bc The Boolean circuit whose structure defines the graph.
50 */
52{
53 for(gate_t g1{0}; g1<bc.getNbGates(); ++g1) {
54 // We do not take into account these gates, which have no purpose
55 // in the circuit
57 continue;
58
59 add_node(static_cast<unsigned long>(g1));
60 for(auto g2: bc.getWires(g1))
61 add_edge(static_cast<unsigned long>(g1), static_cast<unsigned long>(g2), true);
62 }
63}
64
65/**
66 * @brief Add an edge between @p src and @p tgt.
67 *
68 * If the edge already exists the call is a no-op. Both endpoint nodes
69 * are added to @c node_set if not already present.
70 *
71 * @param src Source node.
72 * @param tgt Target node.
73 * @param undirected If @c true, also add the reverse edge.
74 */
75void add_edge(unsigned long src, unsigned long tgt, bool undirected=true){
76 if(!has_edge(src, tgt)) {
77 node_set.insert(src);
78 node_set.insert(tgt);
79 adj_list[src].insert(tgt);
80 if(undirected) adj_list[tgt].insert(src);
81 num_edges++;
82 }
83};
84
85/**
86 * @brief Add @p node to the graph (no edges).
87 * @param node Node ID to insert.
88 */
89void add_node(unsigned long node){
90 node_set.insert(node);
91}
92
93/**
94 * @brief Remove @p node and all its incident edges.
95 *
96 * @param node Node ID to remove.
97 * @return The adjacency set of @p node before removal.
98 */
99std::unordered_set<unsigned long> remove_node(unsigned long node){
100 node_set.erase(node);
101 for(auto neighbour:adj_list[node]) {
102 adj_list[neighbour].erase(node);
103 num_edges--;
104 }
105 auto it = adj_list.find(node);
106 auto adjacency_list = std::move(it->second);
107 adj_list.erase(it);
108 return adjacency_list;
109}
110
111/**
112 * @brief Test whether two nodes share more than @p k-1 common neighbours.
113 *
114 * Used by the min-fill heuristic to decide whether eliminating a node
115 * improves the treewidth bound.
116 *
117 * @param k Treewidth bound being tested.
118 * @param n1 First node.
119 * @param n2 Second node.
120 * @return @c true if the common-neighbour count exceeds @p k-1.
121 */
122bool neighbour_improved(unsigned k,unsigned long n1, unsigned long n2){
123 bool retval = false;
124 auto &neigh1 = get_neighbours(n1);
125 auto &neigh2 = get_neighbours(n2);
126
127 unsigned long count = 0;
128 if (neigh1.size()>k-1 && neigh2.size()>k-1) {
129 for (auto nn1:neigh1) {
130 for (auto nn2:neigh2) {
131 if (nn1==nn2) {
132 count = count+1;
133 break;
134 }
135
136 }
137 }
138 }
139 if (count > k-1) {
140 retval = true;
141 }
142
143 return retval;
144}
145
146/**
147 * @brief Add all missing edges within @p nodes (clique fill).
148 *
149 * Connects every pair of nodes in @p nodes that is not already connected,
150 * making the subgraph induced by @p nodes into a clique.
151 *
152 * @param nodes Set of node IDs to fill.
153 * @param undirected If @c true, add edges in both directions.
154 */
155void fill(const std::unordered_set<unsigned long>& nodes, \
156 bool undirected=true){
157 for(auto src: nodes)
158 for(auto tgt: nodes)
159 if(undirected) {
160 if(src<tgt)
161 add_edge(src, tgt, undirected);
162 }
163 else{
164 if(src!=tgt)
165 add_edge(src, tgt, undirected);
166 }
167
168}
169
170/**
171 * @brief Contract the edge (src, tgt) by merging @p tgt into @p src.
172 *
173 * All edges from @p tgt are redirected to @p src, then @p tgt is removed.
174 *
175 * @param src The node that survives the contraction.
176 * @param tgt The node to be merged into @p src.
177 */
178void contract_edge(unsigned long src, unsigned long tgt){
179 for(auto v:get_neighbours(tgt))
180 if((v!=src)&&!has_edge(src,v)) add_edge(src,v);
181 remove_node(tgt);
182}
183
184/**
185 * @brief Return @c true if @p node has any adjacent edges.
186 * @param node Node to query.
187 * @return @c true if the adjacency list contains an entry for @p node.
188 */
189bool has_neighbours(unsigned long node) const {
190 return adj_list.find(node)!=adj_list.end();
191}
192
193/**
194 * @brief Return @c true if @p node is present in the graph.
195 * @param node Node to query.
196 * @return @c true if @p node exists in the node set.
197 */
198bool has_node(unsigned long node) const {
199 return node_set.find(node)!=node_set.end();
200}
201
202/**
203 * @brief Return @c true if a directed edge from @p src to @p tgt exists.
204 * @param src Source node.
205 * @param tgt Target node.
206 * @return @c true if the edge @p src → @p tgt is present.
207 */
208bool has_edge(unsigned long src, unsigned long tgt) {
209 bool retval = false;
210 if(has_neighbours(src)) {
211 auto &neigh = get_neighbours(src);
212 retval = neigh.find(tgt)!=neigh.end();
213 }
214 return retval;
215}
216
217/**
218 * @brief Return the neighbour set of @p node.
219 *
220 * @p node must be present in the graph (asserted in debug builds).
221 *
222 * @param node Node to query.
223 * @return Const reference to the adjacency set.
224 */
225const std::unordered_set<unsigned long> &get_neighbours(unsigned long node) const {
226 assert(has_node(node));
227
228 return (adj_list.find(node))->second;
229}
230
231/**
232 * @brief Return the set of all node IDs in the graph.
233 * @return Const reference to the node set.
234 */
235const std::unordered_set<unsigned long> &get_nodes() const {
236 return node_set;
237}
238
239/**
240 * @brief Return the number of nodes in the graph.
241 * @return Total node count.
242 */
243unsigned long number_nodes() const {
244 return node_set.size();
245}
246
247/**
248 * @brief Return the number of edges in the graph.
249 * @return Total edge count.
250 */
251unsigned long number_edges() const {
252 return num_edges;
253}
254};
255
256
257#endif /* Graph_h */
Boolean provenance circuit with support for knowledge compilation.
@ MULVAR
Auxiliary gate grouping all MULIN siblings.
@ UNDETERMINED
Placeholder gate whose type has not been set yet.
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:49
Boolean circuit for provenance formula evaluation.
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
Definition Circuit.h:140
gateType getGateType(gate_t g) const
Return the type of gate g.
Definition Circuit.h:130
std::vector< gate_t >::size_type getNbGates() const
Return the total number of gates in the circuit.
Definition Circuit.h:103
void add_edge(unsigned long src, unsigned long tgt, bool undirected=true)
Add an edge between src and tgt.
Definition Graph.h:75
void fill(const std::unordered_set< unsigned long > &nodes, bool undirected=true)
Add all missing edges within nodes (clique fill).
Definition Graph.h:155
bool has_node(unsigned long node) const
Return true if node is present in the graph.
Definition Graph.h:198
std::unordered_set< unsigned long > node_set
Set of all node IDs.
Definition Graph.h:36
void add_node(unsigned long node)
Add node to the graph (no edges).
Definition Graph.h:89
unsigned long number_edges() const
Return the number of edges in the graph.
Definition Graph.h:251
const std::unordered_set< unsigned long > & get_nodes() const
Return the set of all node IDs in the graph.
Definition Graph.h:235
void contract_edge(unsigned long src, unsigned long tgt)
Contract the edge (src, tgt) by merging tgt into src.
Definition Graph.h:178
bool has_edge(unsigned long src, unsigned long tgt)
Return true if a directed edge from src to tgt exists.
Definition Graph.h:208
Graph()=default
Construct an empty graph, to be populated with add_node() / add_edge().
bool has_neighbours(unsigned long node) const
Return true if node has any adjacent edges.
Definition Graph.h:189
std::unordered_set< unsigned long > remove_node(unsigned long node)
Remove node and all its incident edges.
Definition Graph.h:99
unsigned long num_edges
Current edge count.
Definition Graph.h:37
const std::unordered_set< unsigned long > & get_neighbours(unsigned long node) const
Return the neighbour set of node.
Definition Graph.h:225
bool neighbour_improved(unsigned k, unsigned long n1, unsigned long n2)
Test whether two nodes share more than k-1 common neighbours.
Definition Graph.h:122
std::unordered_map< unsigned long, std::unordered_set< unsigned long > > adj_list
Adjacency lists.
Definition Graph.h:35
Graph(const BooleanCircuit &bc)
Construct the primal graph of a BooleanCircuit.
Definition Graph.h:51
unsigned long number_nodes() const
Return the number of nodes in the graph.
Definition Graph.h:243