10#include "slang/util/FlatMap.h"
26 friend auto operator==(
const EdgeType &A,
const EdgeType &B)
noexcept
28 return A.getDerived().isEqualTo(B);
42 auto isEqualTo(
const EdgeType &edge)
const ->
bool {
return this == &edge; }
45 auto getDerived() -> EdgeType & {
return *
static_cast<EdgeType *
>(
this); }
47 return *
static_cast<const EdgeType *
>(
this);
59template <
class NodeType,
class EdgeType>
class Node {
64 using iterator =
typename OutEdgeListType::iterator;
94 friend auto operator==(NodeType
const &A, NodeType
const &B)
noexcept
96 return A.getDerived().isEqualTo(B);
105 return std::ranges::find_if(
inEdges, [&](EdgeType *e) {
106 return &e->getSourceNode() == &sourceNode;
112 return std::ranges::find_if(
inEdges, [&](EdgeType
const *e) {
113 return &e->getSourceNode() == &sourceNode;
120 return &e->getTargetNode() == &targetNode;
127 return &e->getTargetNode() == &targetNode;
144 auto addEdge(NodeType &targetNode) -> EdgeType & {
145 bool isSelfEdge = (&
getDerived() == &targetNode);
146 std::lock_guard<std::mutex> lock(
edgeMutex);
147 if (
auto *existing = lookupOutEdge(targetNode); existing !=
nullptr) {
150 auto edge = std::make_unique<EdgeType>(
getDerived(), targetNode);
151 auto *edgePtr = edge.get();
152 outEdges.emplace_back(std::move(edge));
153 insertOutEdgeIndex(&targetNode, edgePtr);
157 std::lock_guard<std::mutex> lock2(targetNode.edgeMutex);
158 targetNode.inEdges.push_back(edgePtr);
171 bool isSelfEdge = (&
getDerived() == &targetNode);
172 auto edge = std::make_unique<EdgeType>(
getDerived(), targetNode);
173 auto *edgePtr = edge.get();
175 std::lock_guard<std::mutex> lock(
edgeMutex);
176 outEdges.emplace_back(std::move(edge));
180 tryInsertOutEdgeIndex(&targetNode, edgePtr);
184 std::lock_guard<std::mutex> lock(
edgeMutex);
185 outEdges.emplace_back(std::move(edge));
186 tryInsertOutEdgeIndex(&targetNode, edgePtr);
189 std::lock_guard<std::mutex> lock(targetNode.edgeMutex);
190 targetNode.inEdges.push_back(edgePtr);
201 auto success = targetNode.removeInEdge(
getDerived());
202 assert(success &&
"No corresponding in edge reference");
207 auto survivor = std::ranges::find_if(
outEdges, [&](
auto &e) {
208 return &e->getTargetNode() == &targetNode;
213 (*outEdgeIndex)[&targetNode] = survivor->get();
225 edge->getTargetNode().removeInEdge(
getDerived());
231 std::vector<NodeType *> sourceNodes;
233 sourceNodes.push_back(&edge->getSourceNode());
235 for (
auto *sourceNode : sourceNodes) {
243 auto getEdgesTo(
const NodeType &targetNode, std::vector<EdgeType *> &result)
245 assert(result.empty() &&
"Expected the results parameter to be empty");
247 if (edge->getTargetNode() == targetNode) {
248 result.push_back(edge.get());
251 return !result.empty();
286 auto isEqualTo(
const NodeType &node)
const ->
bool {
return this == &node; }
289 auto getDerived() -> NodeType & {
return *
static_cast<NodeType *
>(
this); }
291 return *
static_cast<const NodeType *
>(
this);
299 auto removeInEdge(NodeType &sourceNode) ->
bool {
311 auto lookupOutEdge(NodeType
const &targetNode) -> EdgeType * {
314 return it !=
outEdgeIndex->end() ? it->second :
nullptr;
317 return &e->getTargetNode() == &targetNode;
319 return it !=
outEdges.end() ? it->get() :
nullptr;
324 void buildOutEdgeIndex() {
328 outEdgeIndex->try_emplace(&e->getTargetNode(), e.get());
335 void insertOutEdgeIndex(NodeType
const *targetNode, EdgeType *edgePtr) {
345 void tryInsertOutEdgeIndex(NodeType
const *targetNode, EdgeType *edgePtr) {
368 static const size_t null_node = std::numeric_limits<size_t>::max();
380 return const_cast<const NodeType &
>(*node) == nodeToFind;
382 if (it !=
nodes.end()) {
383 return it -
nodes.begin();
390 assert(node <
nodes.size() &&
"Node does not exist");
399 nodes.push_back(std::make_unique<NodeType>());
400 return *(
nodes.back().get());
406 auto addNode(std::unique_ptr<NodeType> node) -> NodeType & {
408 nodes.push_back(std::move(node));
409 return *(
nodes.back().get());
417 auto nodeToRemoveDesc =
findNode(nodeToRemove);
418 if (nodeToRemoveDesc >=
nodes.size()) {
423 nodeToRemove.clearAllEdges();
425 nodes.erase(std::ranges::next(
nodes.begin(), nodeToRemoveDesc));
430 auto addEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType & {
431 assert(
findNode(sourceNode) <
nodes.size() &&
"Source node does not exist");
432 assert(
findNode(targetNode) <
nodes.size() &&
"Target node does not exist");
433 return sourceNode.addEdge(targetNode);
438 auto addNewEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType & {
439 assert(
findNode(sourceNode) <
nodes.size() &&
"Source node does not exist");
440 assert(
findNode(targetNode) <
nodes.size() &&
"Target node does not exist");
441 return sourceNode.addNewEdge(targetNode);
446 auto removeEdge(NodeType &sourceNode, NodeType &targetNode) ->
bool {
447 assert(
findNode(sourceNode) <
nodes.size() &&
"Source node does not exist");
448 assert(
findNode(targetNode) <
nodes.size() &&
"Target node does not exist");
449 return sourceNode.removeEdge(targetNode);
454 assert(
findNode(node) <
nodes.size() &&
"Node does not exist");
455 return node.outDegree();
459 auto inDegree(
const NodeType &node)
const ->
size_t {
460 assert(
findNode(node) <
nodes.size() &&
"Node does not exist");
461 return node.inDegree();
470 for (
auto &node :
nodes) {
471 count += node->outDegree();
auto operator=(const DirectedEdge< NodeType, EdgeType > &edge) -> DirectedEdge< NodeType, EdgeType > &=default
NodeType & sourceNode
Definition DirectedGraph.hpp:50
auto operator==(const EdgeType &E) const -> bool
Definition DirectedGraph.hpp:30
NodeType & targetNode
Definition DirectedGraph.hpp:51
auto getDerived() -> EdgeType &
Definition DirectedGraph.hpp:45
auto getDerived() const -> const EdgeType &
Definition DirectedGraph.hpp:46
auto getTargetNode() const -> NodeType &
Return the target node of this edge.
Definition DirectedGraph.hpp:38
auto isEqualTo(const EdgeType &edge) const -> bool
Definition DirectedGraph.hpp:42
DirectedEdge(NodeType &sourceNode, NodeType &targetNode)
Definition DirectedGraph.hpp:17
auto getSourceNode() const -> NodeType &
Return the source node of this edge.
Definition DirectedGraph.hpp:35
friend auto operator==(const EdgeType &A, const EdgeType &B) noexcept -> bool
Definition DirectedGraph.hpp:26
auto addNewEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType &
Definition DirectedGraph.hpp:438
std::vector< NodePtrType > NodeListType
Definition DirectedGraph.hpp:361
auto numEdges() const -> size_t
Return the number of edges in the graph.
Definition DirectedGraph.hpp:468
auto addEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType &
Add an edge between two existing nodes in the graph.
Definition DirectedGraph.hpp:430
auto inDegree(const NodeType &node) const -> size_t
Return the number of edges incident to the specified node.
Definition DirectedGraph.hpp:459
size_t node_descriptor
Definition DirectedGraph.hpp:364
auto removeNode(NodeType &nodeToRemove) -> bool
Definition DirectedGraph.hpp:416
auto addNode(std::unique_ptr< NodeType > node) -> NodeType &
Definition DirectedGraph.hpp:406
auto findNode(const NodeType &nodeToFind) const -> node_descriptor
Definition DirectedGraph.hpp:377
NodeListType nodes
Definition DirectedGraph.hpp:481
auto removeEdge(NodeType &sourceNode, NodeType &targetNode) -> bool
Definition DirectedGraph.hpp:446
auto begin() const -> const_iterator
Definition DirectedGraph.hpp:372
static const size_t null_node
Definition DirectedGraph.hpp:368
std::mutex nodesMutex
Definition DirectedGraph.hpp:479
auto outDegree(const NodeType &node) const -> size_t
Return the number of edges outgoing from the specified node.
Definition DirectedGraph.hpp:453
auto end() -> iterator
Definition DirectedGraph.hpp:375
auto addNode() -> NodeType &
Definition DirectedGraph.hpp:397
typename NodeListType::iterator iterator
Definition DirectedGraph.hpp:362
DirectedGraph< NodeType, EdgeType > DirectedGraphType
Definition DirectedGraph.hpp:366
auto begin() -> iterator
Definition DirectedGraph.hpp:374
std::unique_ptr< NodeType > NodePtrType
Definition DirectedGraph.hpp:360
auto getNode(node_descriptor node) const -> NodeType &
Given a node descriptor, return the node by reference.
Definition DirectedGraph.hpp:389
typename NodeListType::const_iterator const_iterator
Definition DirectedGraph.hpp:363
EdgeType * edge_descriptor
Definition DirectedGraph.hpp:365
auto end() const -> const_iterator
Definition DirectedGraph.hpp:373
auto numNodes() const -> size_t
Return the size of the graph.
Definition DirectedGraph.hpp:465
auto end() -> iterator
Definition DirectedGraph.hpp:83
typename OutEdgeListType::const_iterator const_iterator
Definition DirectedGraph.hpp:65
std::vector< OutEdgePtrType > OutEdgeListType
Definition DirectedGraph.hpp:62
auto getEdgesTo(const NodeType &targetNode, std::vector< EdgeType * > &result) -> bool
Definition DirectedGraph.hpp:243
auto outDegree() const -> size_t
Return the total number of edges outgoing from this node.
Definition DirectedGraph.hpp:262
typename InEdgeListType::const_iterator const_in_iterator
Definition DirectedGraph.hpp:67
typename OutEdgeListType::iterator iterator
Definition DirectedGraph.hpp:64
auto inEnd() const -> const_in_iterator
Definition DirectedGraph.hpp:89
auto operator==(const NodeType &N) const -> bool
Definition DirectedGraph.hpp:99
auto getDerived() const -> const NodeType &
Definition DirectedGraph.hpp:290
auto inBegin() -> in_iterator
Definition DirectedGraph.hpp:86
EdgeType * edge_descriptor
Definition DirectedGraph.hpp:68
friend auto operator==(NodeType const &A, NodeType const &B) noexcept -> bool
Definition DirectedGraph.hpp:94
typename InEdgeListType::iterator in_iterator
Definition DirectedGraph.hpp:66
auto removeEdge(NodeType &targetNode) -> bool
Definition DirectedGraph.hpp:198
Node(const Node &)=delete
static constexpr size_t outEdgeIndexThreshold
Definition DirectedGraph.hpp:283
auto findEdgeFrom(const NodeType &sourceNode) const -> const_in_iterator
Return an iterator to the edge connecting the source node.
Definition DirectedGraph.hpp:111
auto begin() -> iterator
Definition DirectedGraph.hpp:82
auto end() const -> const_iterator
Definition DirectedGraph.hpp:81
auto addNewEdge(NodeType &targetNode) -> EdgeType &
Definition DirectedGraph.hpp:170
auto inBegin() const -> const_in_iterator
Definition DirectedGraph.hpp:88
auto getInEdges() const -> const InEdgeListType &
Return the list of outgoing edges from this node.
Definition DirectedGraph.hpp:255
auto isEqualTo(const NodeType &node) const -> bool
Definition DirectedGraph.hpp:286
std::unique_ptr< OutEdgeIndex > outEdgeIndex
Definition DirectedGraph.hpp:279
auto inEnd() -> in_iterator
Definition DirectedGraph.hpp:87
auto begin() const -> const_iterator
Definition DirectedGraph.hpp:80
std::vector< EdgeType * > InEdgeListType
Definition DirectedGraph.hpp:63
flat_hash_map< NodeType const *, EdgeType * > OutEdgeIndex
Definition DirectedGraph.hpp:278
auto getOutEdges() const -> const OutEdgeListType &
Definition DirectedGraph.hpp:256
auto getDerived() -> NodeType &
Definition DirectedGraph.hpp:289
void clearAllEdges()
Remove all edges to/from this node.
Definition DirectedGraph.hpp:222
auto operator=(Node &&) -> Node &=delete
auto findEdgeFrom(const NodeType &sourceNode) -> in_iterator
Return an iterator to the edge connecting the source node.
Definition DirectedGraph.hpp:104
std::mutex edgeMutex
Definition DirectedGraph.hpp:268
auto addEdge(NodeType &targetNode) -> EdgeType &
Definition DirectedGraph.hpp:144
auto operator=(const Node &) -> Node &=delete
InEdgeListType inEdges
Definition DirectedGraph.hpp:270
auto findEdgeTo(const NodeType &targetNode) const -> const_iterator
Return an iterator to the edge connecting the target node.
Definition DirectedGraph.hpp:125
auto findEdgeTo(const NodeType &targetNode) -> iterator
Return an iterator to the edge connecting the target node.
Definition DirectedGraph.hpp:118
OutEdgeListType outEdges
Definition DirectedGraph.hpp:271
std::unique_ptr< EdgeType > OutEdgePtrType
Definition DirectedGraph.hpp:61
auto inDegree() const -> size_t
Return the total number of edges incoming to this node.
Definition DirectedGraph.hpp:259
Definition Utilities.hpp:16