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;
136 auto addEdge(NodeType &targetNode) -> EdgeType & {
137 return withEndpointsLocked(targetNode, [&] {
139 return appendEdge(targetNode);
162 return withEndpointsLocked(targetNode, [&] {
163 if (
auto *existing = lookupOutEdge(targetNode); existing !=
nullptr) {
166 return appendEdge(targetNode);
175 auto success = targetNode.removeInEdge(
getDerived());
176 assert(success &&
"No corresponding in edge reference");
181 auto survivor = std::ranges::find_if(
outEdges, [&](
auto &e) {
182 return &e->getTargetNode() == &targetNode;
187 (*outEdgeIndex)[&targetNode] = survivor->get();
208 std::vector<NodeType *> targets;
211 targets.push_back(&edge->getTargetNode());
214 if (targets.empty()) {
218 std::ranges::sort(targets);
219 targets.erase(std::ranges::unique(targets).
begin(), targets.end());
221 for (
auto *target : targets) {
222 std::erase_if(target->inEdges, [&](EdgeType *edge) {
223 return &edge->getSourceNode() == self && pred(*edge);
237 edge->getTargetNode().removeInEdge(
getDerived());
243 std::vector<NodeType *> sourceNodes;
245 sourceNodes.push_back(&edge->getSourceNode());
247 for (
auto *sourceNode : sourceNodes) {
255 auto getEdgesTo(
const NodeType &targetNode, std::vector<EdgeType *> &result)
257 assert(result.empty() &&
"Expected the results parameter to be empty");
259 if (edge->getTargetNode() == targetNode) {
260 result.push_back(edge.get());
263 return !result.empty();
304 auto isEqualTo(
const NodeType &node)
const ->
bool {
return this == &node; }
307 auto getDerived() -> NodeType & {
return *
static_cast<NodeType *
>(
this); }
309 return *
static_cast<const NodeType *
>(
this);
317 auto removeInEdge(NodeType &sourceNode) ->
bool {
332 template <
typename Fn>
333 auto withEndpointsLocked(NodeType &targetNode, Fn fn) -> EdgeType & {
335 std::lock_guard<std::mutex> lock(
edgeMutex);
338 std::scoped_lock lock(
edgeMutex, targetNode.edgeMutex);
345 auto appendEdge(NodeType &targetNode) -> EdgeType * {
346 auto edge = std::make_unique<EdgeType>(
getDerived(), targetNode);
347 auto *edgePtr = edge.get();
348 outEdges.emplace_back(std::move(edge));
349 insertOutEdgeIndex(&targetNode, edgePtr);
350 targetNode.inEdges.push_back(edgePtr);
357 auto lookupOutEdge(NodeType
const &targetNode) -> EdgeType * {
360 return it !=
outEdgeIndex->end() ? it->second :
nullptr;
363 return it !=
outEdges.end() ? it->get() :
nullptr;
368 void buildOutEdgeIndex() {
372 outEdgeIndex->try_emplace(&e->getTargetNode(), e.get());
381 void insertOutEdgeIndex(NodeType
const *targetNode, EdgeType *edgePtr) {
406 static const size_t null_node = std::numeric_limits<size_t>::max();
418 return const_cast<const NodeType &
>(*node) == nodeToFind;
420 if (it !=
nodes.end()) {
421 return it -
nodes.begin();
428 assert(node <
nodes.size() &&
"Node does not exist");
437 nodes.push_back(std::make_unique<NodeType>());
438 return *(
nodes.back().get());
444 auto addNode(std::unique_ptr<NodeType> node) -> NodeType & {
446 nodes.push_back(std::move(node));
447 return *(
nodes.back().get());
455 auto nodeToRemoveDesc =
findNode(nodeToRemove);
456 if (nodeToRemoveDesc >=
nodes.size()) {
461 nodeToRemove.clearAllEdges();
463 nodes.erase(std::ranges::next(
nodes.begin(), nodeToRemoveDesc));
469 auto getOrAddEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType & {
470 assert(
findNode(sourceNode) <
nodes.size() &&
"Source node does not exist");
471 assert(
findNode(targetNode) <
nodes.size() &&
"Target node does not exist");
472 return sourceNode.getOrAddEdge(targetNode);
477 auto addEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType & {
478 assert(
findNode(sourceNode) <
nodes.size() &&
"Source node does not exist");
479 assert(
findNode(targetNode) <
nodes.size() &&
"Target node does not exist");
480 return sourceNode.addEdge(targetNode);
485 auto removeEdge(NodeType &sourceNode, NodeType &targetNode) ->
bool {
486 assert(
findNode(sourceNode) <
nodes.size() &&
"Source node does not exist");
487 assert(
findNode(targetNode) <
nodes.size() &&
"Target node does not exist");
488 return sourceNode.removeEdge(targetNode);
493 assert(
findNode(node) <
nodes.size() &&
"Node does not exist");
494 return node.outDegree();
498 auto inDegree(
const NodeType &node)
const ->
size_t {
499 assert(
findNode(node) <
nodes.size() &&
"Node does not exist");
500 return node.inDegree();
509 for (
auto &node :
nodes) {
510 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
std::vector< NodePtrType > NodeListType
Definition DirectedGraph.hpp:399
auto numEdges() const -> size_t
Return the number of edges in the graph.
Definition DirectedGraph.hpp:507
auto getOrAddEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType &
Definition DirectedGraph.hpp:469
auto addEdge(NodeType &sourceNode, NodeType &targetNode) -> EdgeType &
Definition DirectedGraph.hpp:477
auto inDegree(const NodeType &node) const -> size_t
Return the number of edges incident to the specified node.
Definition DirectedGraph.hpp:498
size_t node_descriptor
Definition DirectedGraph.hpp:402
auto removeNode(NodeType &nodeToRemove) -> bool
Definition DirectedGraph.hpp:454
auto addNode(std::unique_ptr< NodeType > node) -> NodeType &
Definition DirectedGraph.hpp:444
auto findNode(const NodeType &nodeToFind) const -> node_descriptor
Definition DirectedGraph.hpp:415
NodeListType nodes
Definition DirectedGraph.hpp:520
auto removeEdge(NodeType &sourceNode, NodeType &targetNode) -> bool
Definition DirectedGraph.hpp:485
auto begin() const -> const_iterator
Definition DirectedGraph.hpp:410
static const size_t null_node
Definition DirectedGraph.hpp:406
std::mutex nodesMutex
Definition DirectedGraph.hpp:518
auto outDegree(const NodeType &node) const -> size_t
Return the number of edges outgoing from the specified node.
Definition DirectedGraph.hpp:492
auto end() -> iterator
Definition DirectedGraph.hpp:413
auto addNode() -> NodeType &
Definition DirectedGraph.hpp:435
typename NodeListType::iterator iterator
Definition DirectedGraph.hpp:400
DirectedGraph< NodeType, EdgeType > DirectedGraphType
Definition DirectedGraph.hpp:404
auto begin() -> iterator
Definition DirectedGraph.hpp:412
std::unique_ptr< NodeType > NodePtrType
Definition DirectedGraph.hpp:398
auto getNode(node_descriptor node) const -> NodeType &
Given a node descriptor, return the node by reference.
Definition DirectedGraph.hpp:427
typename NodeListType::const_iterator const_iterator
Definition DirectedGraph.hpp:401
EdgeType * edge_descriptor
Definition DirectedGraph.hpp:403
auto end() const -> const_iterator
Definition DirectedGraph.hpp:411
auto numNodes() const -> size_t
Return the size of the graph.
Definition DirectedGraph.hpp:504
auto end() -> iterator
Definition DirectedGraph.hpp:83
typename OutEdgeListType::const_iterator const_iterator
Definition DirectedGraph.hpp:65
void removeOutEdgesIf(Predicate pred)
Definition DirectedGraph.hpp:207
std::vector< OutEdgePtrType > OutEdgeListType
Definition DirectedGraph.hpp:62
auto getEdgesTo(const NodeType &targetNode, std::vector< EdgeType * > &result) -> bool
Definition DirectedGraph.hpp:255
auto getOrAddEdge(NodeType &targetNode) -> EdgeType &
Definition DirectedGraph.hpp:161
auto outDegree() const -> size_t
Return the total number of edges outgoing from this node.
Definition DirectedGraph.hpp:274
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
bool parallelOutEdges
Definition DirectedGraph.hpp:301
auto operator==(const NodeType &N) const -> bool
Definition DirectedGraph.hpp:99
auto getDerived() const -> const NodeType &
Definition DirectedGraph.hpp:308
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
auto mayHaveParallelOutEdges() const -> bool
Definition DirectedGraph.hpp:198
typename InEdgeListType::iterator in_iterator
Definition DirectedGraph.hpp:66
auto removeEdge(NodeType &targetNode) -> bool
Definition DirectedGraph.hpp:172
Node(const Node &)=delete
static constexpr size_t outEdgeIndexThreshold
Definition DirectedGraph.hpp:295
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 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:267
auto isEqualTo(const NodeType &node) const -> bool
Definition DirectedGraph.hpp:304
std::unique_ptr< OutEdgeIndex > outEdgeIndex
Definition DirectedGraph.hpp:291
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:290
auto getOutEdges() const -> const OutEdgeListType &
Definition DirectedGraph.hpp:268
auto getDerived() -> NodeType &
Definition DirectedGraph.hpp:307
void clearAllEdges()
Remove all edges to/from this node.
Definition DirectedGraph.hpp:234
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:280
auto addEdge(NodeType &targetNode) -> EdgeType &
Definition DirectedGraph.hpp:136
auto operator=(const Node &) -> Node &=delete
InEdgeListType inEdges
Definition DirectedGraph.hpp:282
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:283
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:271
Definition FormatBuffer.hpp:9