P4C
The P4 Compiler
Loading...
Searching...
No Matches
boost_graph.h
1
20
21#ifndef BF_P4C_LIB_BOOST_GRAPH_H_
22#define BF_P4C_LIB_BOOST_GRAPH_H_
23
24#include <map>
25#include <optional>
26
27#include <boost/graph/adjacency_list.hpp>
28#include <boost/tuple/tuple.hpp>
29
30#include "lib/bitvec.h"
31#include "lib/cstring.h"
32#include "lib/exceptions.h"
33
34using namespace P4;
35
38template <class Graph>
40 public:
41 using Vertex = typename Graph::vertex_descriptor;
42
43 using EdgeSet =
44 typename boost::container_gen<typename Graph::vertex_list_selector, bitvec>::type;
45
47 bool canReach(Vertex v1, Vertex v2) {
48 if (forwardsReachableVertices.empty()) recompute();
49 return forwardsReachableVertices.at(v1).getbit(v2);
50 }
51
54 bitvec reachableBetween(Vertex v1, Vertex v2) {
55 if (forwardsReachableVertices.empty() || backwardsReachableVertices.empty()) recompute();
56 return forwardsReachableVertices.at(v1) & backwardsReachableVertices.at(v2);
57 }
58
62 void clear() {
63 forwardsReachableVertices.clear();
64 backwardsReachableVertices.clear();
65 }
66
68 void setSink(std::optional<Vertex> sink) {
69 this->sink = sink;
70 clear();
71 }
72
73 explicit Reachability(const Graph &g) : g(g) {}
74
75 private:
77 void recompute() {
78 forwardsReachableVertices.clear();
79 backwardsReachableVertices.clear();
80
81 forwardsReachableVertices.resize(boost::num_vertices(g), bitvec());
82 backwardsReachableVertices.resize(boost::num_vertices(g), bitvec());
83
84 // Ensure the reachability matrices have an entry for each vertex.
85 typename Graph::vertex_iterator v, v_end;
86 for (boost::tie(v, v_end) = boost::vertices(g); v != v_end; ++v) {
87 forwardsReachableVertices[*v].clear();
88 backwardsReachableVertices[*v].clear();
89 }
90
91 // Initialize with edges.
92 typename Graph::edge_iterator edges, edges_end;
93 for (boost::tie(edges, edges_end) = boost::edges(g); edges != edges_end; ++edges) {
94 auto src = boost::source(*edges, g);
95 auto dst = boost::target(*edges, g);
96 forwardsReachableVertices[src].setbit(dst);
97 backwardsReachableVertices[dst].setbit(src);
98 }
99
100 // Propagate reachability information via Floyd-Warshall.
101 typename Graph::vertex_iterator mid, mid_end;
102 for (boost::tie(mid, mid_end) = boost::vertices(g); mid != mid_end; ++mid) {
103 // Ignore the sink node.
104 if (sink && *mid == *sink) continue;
105
106 typename Graph::vertex_iterator src, src_end;
107 for (boost::tie(src, src_end) = boost::vertices(g); src != src_end; ++src) {
108 recompute(backwardsReachableVertices, *src, *mid);
109
110 // Ignore the sink node for forwards reachability.
111 if (sink && *src == *sink) continue;
112 recompute(forwardsReachableVertices, *src, *mid);
113 }
114 }
115 }
116
119 void recompute(EdgeSet &reachMatrix, Vertex src, Vertex mid) {
120 // If we can't reach mid from src, don't bother going through dsts.
121 if (!reachMatrix[src].getbit(mid)) return;
122
123 // This is a vectorized form of a loop that goes through all dsts and sets
124 //
125 // reachMatrix[src][dst] |= reachMatrix[src][mid] & reachMatrix[mid][dst]
126 //
127 // while taking advantage of the fact that we know that
128 //
129 // reachMatrix[src][mid] = 1
130 reachMatrix[src] |= reachMatrix[mid];
131 }
132
134 const Graph &g;
135
137 std::optional<Vertex> sink = std::nullopt;
138
141 EdgeSet forwardsReachableVertices;
142
145 EdgeSet backwardsReachableVertices;
146};
147
148#endif /* BF_P4C_LIB_BOOST_GRAPH_H_ */
Definition bitvec.h:120
Definition boost_graph.h:39
void setSink(std::optional< Vertex > sink)
Sets the sink node; no nodes will be considered reachable from this node.
Definition boost_graph.h:68
void clear()
Definition boost_graph.h:62
bool canReach(Vertex v1, Vertex v2)
Determines whether vertex v2 is reachable from the vertex v1.
Definition boost_graph.h:47
bitvec reachableBetween(Vertex v1, Vertex v2)
Definition boost_graph.h:54
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24