DirectedGraph.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. //===- llvm/ADT/DirectedGraph.h - Directed Graph ----------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines the interface and a base class implementation for a
  10. // directed graph.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_ADT_DIRECTEDGRAPH_H
  14. #define LLVM_ADT_DIRECTEDGRAPH_H
  15. #include "llvm/ADT/GraphTraits.h"
  16. #include "llvm/ADT/SetVector.h"
  17. #include "llvm/ADT/SmallVector.h"
  18. #include "llvm/Support/Debug.h"
  19. #include "llvm/Support/raw_ostream.h"
  20. namespace llvm {
  21. /// Represent an edge in the directed graph.
  22. /// The edge contains the target node it connects to.
  23. template <class NodeType, class EdgeType> class DGEdge {
  24. public:
  25. DGEdge() = delete;
  26. /// Create an edge pointing to the given node \p N.
  27. explicit DGEdge(NodeType &N) : TargetNode(N) {}
  28. explicit DGEdge(const DGEdge<NodeType, EdgeType> &E)
  29. : TargetNode(E.TargetNode) {}
  30. DGEdge<NodeType, EdgeType> &operator=(const DGEdge<NodeType, EdgeType> &E) {
  31. TargetNode = E.TargetNode;
  32. return *this;
  33. }
  34. /// Static polymorphism: delegate implementation (via isEqualTo) to the
  35. /// derived class.
  36. bool operator==(const DGEdge &E) const {
  37. return getDerived().isEqualTo(E.getDerived());
  38. }
  39. bool operator!=(const DGEdge &E) const { return !operator==(E); }
  40. /// Retrieve the target node this edge connects to.
  41. const NodeType &getTargetNode() const { return TargetNode; }
  42. NodeType &getTargetNode() {
  43. return const_cast<NodeType &>(
  44. static_cast<const DGEdge<NodeType, EdgeType> &>(*this).getTargetNode());
  45. }
  46. /// Set the target node this edge connects to.
  47. void setTargetNode(const NodeType &N) { TargetNode = N; }
  48. protected:
  49. // As the default implementation use address comparison for equality.
  50. bool isEqualTo(const EdgeType &E) const { return this == &E; }
  51. // Cast the 'this' pointer to the derived type and return a reference.
  52. EdgeType &getDerived() { return *static_cast<EdgeType *>(this); }
  53. const EdgeType &getDerived() const {
  54. return *static_cast<const EdgeType *>(this);
  55. }
  56. // The target node this edge connects to.
  57. NodeType &TargetNode;
  58. };
  59. /// Represent a node in the directed graph.
  60. /// The node has a (possibly empty) list of outgoing edges.
  61. template <class NodeType, class EdgeType> class DGNode {
  62. public:
  63. using EdgeListTy = SetVector<EdgeType *>;
  64. using iterator = typename EdgeListTy::iterator;
  65. using const_iterator = typename EdgeListTy::const_iterator;
  66. /// Create a node with a single outgoing edge \p E.
  67. explicit DGNode(EdgeType &E) : Edges() { Edges.insert(&E); }
  68. DGNode() = default;
  69. explicit DGNode(const DGNode<NodeType, EdgeType> &N) : Edges(N.Edges) {}
  70. DGNode(DGNode<NodeType, EdgeType> &&N) : Edges(std::move(N.Edges)) {}
  71. DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &N) {
  72. Edges = N.Edges;
  73. return *this;
  74. }
  75. DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &&N) {
  76. Edges = std::move(N.Edges);
  77. return *this;
  78. }
  79. /// Static polymorphism: delegate implementation (via isEqualTo) to the
  80. /// derived class.
  81. friend bool operator==(const NodeType &M, const NodeType &N) {
  82. return M.isEqualTo(N);
  83. }
  84. friend bool operator!=(const NodeType &M, const NodeType &N) {
  85. return !(M == N);
  86. }
  87. const_iterator begin() const { return Edges.begin(); }
  88. const_iterator end() const { return Edges.end(); }
  89. iterator begin() { return Edges.begin(); }
  90. iterator end() { return Edges.end(); }
  91. const EdgeType &front() const { return *Edges.front(); }
  92. EdgeType &front() { return *Edges.front(); }
  93. const EdgeType &back() const { return *Edges.back(); }
  94. EdgeType &back() { return *Edges.back(); }
  95. /// Collect in \p EL, all the edges from this node to \p N.
  96. /// Return true if at least one edge was found, and false otherwise.
  97. /// Note that this implementation allows more than one edge to connect
  98. /// a given pair of nodes.
  99. bool findEdgesTo(const NodeType &N, SmallVectorImpl<EdgeType *> &EL) const {
  100. assert(EL.empty() && "Expected the list of edges to be empty.");
  101. for (auto *E : Edges)
  102. if (E->getTargetNode() == N)
  103. EL.push_back(E);
  104. return !EL.empty();
  105. }
  106. /// Add the given edge \p E to this node, if it doesn't exist already. Returns
  107. /// true if the edge is added and false otherwise.
  108. bool addEdge(EdgeType &E) { return Edges.insert(&E); }
  109. /// Remove the given edge \p E from this node, if it exists.
  110. void removeEdge(EdgeType &E) { Edges.remove(&E); }
  111. /// Test whether there is an edge that goes from this node to \p N.
  112. bool hasEdgeTo(const NodeType &N) const {
  113. return (findEdgeTo(N) != Edges.end());
  114. }
  115. /// Retrieve the outgoing edges for the node.
  116. const EdgeListTy &getEdges() const { return Edges; }
  117. EdgeListTy &getEdges() {
  118. return const_cast<EdgeListTy &>(
  119. static_cast<const DGNode<NodeType, EdgeType> &>(*this).Edges);
  120. }
  121. /// Clear the outgoing edges.
  122. void clear() { Edges.clear(); }
  123. protected:
  124. // As the default implementation use address comparison for equality.
  125. bool isEqualTo(const NodeType &N) const { return this == &N; }
  126. // Cast the 'this' pointer to the derived type and return a reference.
  127. NodeType &getDerived() { return *static_cast<NodeType *>(this); }
  128. const NodeType &getDerived() const {
  129. return *static_cast<const NodeType *>(this);
  130. }
  131. /// Find an edge to \p N. If more than one edge exists, this will return
  132. /// the first one in the list of edges.
  133. const_iterator findEdgeTo(const NodeType &N) const {
  134. return llvm::find_if(
  135. Edges, [&N](const EdgeType *E) { return E->getTargetNode() == N; });
  136. }
  137. // The list of outgoing edges.
  138. EdgeListTy Edges;
  139. };
  140. /// Directed graph
  141. ///
  142. /// The graph is represented by a table of nodes.
  143. /// Each node contains a (possibly empty) list of outgoing edges.
  144. /// Each edge contains the target node it connects to.
  145. template <class NodeType, class EdgeType> class DirectedGraph {
  146. protected:
  147. using NodeListTy = SmallVector<NodeType *, 10>;
  148. using EdgeListTy = SmallVector<EdgeType *, 10>;
  149. public:
  150. using iterator = typename NodeListTy::iterator;
  151. using const_iterator = typename NodeListTy::const_iterator;
  152. using DGraphType = DirectedGraph<NodeType, EdgeType>;
  153. DirectedGraph() = default;
  154. explicit DirectedGraph(NodeType &N) : Nodes() { addNode(N); }
  155. DirectedGraph(const DGraphType &G) : Nodes(G.Nodes) {}
  156. DirectedGraph(DGraphType &&RHS) : Nodes(std::move(RHS.Nodes)) {}
  157. DGraphType &operator=(const DGraphType &G) {
  158. Nodes = G.Nodes;
  159. return *this;
  160. }
  161. DGraphType &operator=(const DGraphType &&G) {
  162. Nodes = std::move(G.Nodes);
  163. return *this;
  164. }
  165. const_iterator begin() const { return Nodes.begin(); }
  166. const_iterator end() const { return Nodes.end(); }
  167. iterator begin() { return Nodes.begin(); }
  168. iterator end() { return Nodes.end(); }
  169. const NodeType &front() const { return *Nodes.front(); }
  170. NodeType &front() { return *Nodes.front(); }
  171. const NodeType &back() const { return *Nodes.back(); }
  172. NodeType &back() { return *Nodes.back(); }
  173. size_t size() const { return Nodes.size(); }
  174. /// Find the given node \p N in the table.
  175. const_iterator findNode(const NodeType &N) const {
  176. return llvm::find_if(Nodes,
  177. [&N](const NodeType *Node) { return *Node == N; });
  178. }
  179. iterator findNode(const NodeType &N) {
  180. return const_cast<iterator>(
  181. static_cast<const DGraphType &>(*this).findNode(N));
  182. }
  183. /// Add the given node \p N to the graph if it is not already present.
  184. bool addNode(NodeType &N) {
  185. if (findNode(N) != Nodes.end())
  186. return false;
  187. Nodes.push_back(&N);
  188. return true;
  189. }
  190. /// Collect in \p EL all edges that are coming into node \p N. Return true
  191. /// if at least one edge was found, and false otherwise.
  192. bool findIncomingEdgesToNode(const NodeType &N, SmallVectorImpl<EdgeType*> &EL) const {
  193. assert(EL.empty() && "Expected the list of edges to be empty.");
  194. EdgeListTy TempList;
  195. for (auto *Node : Nodes) {
  196. if (*Node == N)
  197. continue;
  198. Node->findEdgesTo(N, TempList);
  199. llvm::append_range(EL, TempList);
  200. TempList.clear();
  201. }
  202. return !EL.empty();
  203. }
  204. /// Remove the given node \p N from the graph. If the node has incoming or
  205. /// outgoing edges, they are also removed. Return true if the node was found
  206. /// and then removed, and false if the node was not found in the graph to
  207. /// begin with.
  208. bool removeNode(NodeType &N) {
  209. iterator IT = findNode(N);
  210. if (IT == Nodes.end())
  211. return false;
  212. // Remove incoming edges.
  213. EdgeListTy EL;
  214. for (auto *Node : Nodes) {
  215. if (*Node == N)
  216. continue;
  217. Node->findEdgesTo(N, EL);
  218. for (auto *E : EL)
  219. Node->removeEdge(*E);
  220. EL.clear();
  221. }
  222. N.clear();
  223. Nodes.erase(IT);
  224. return true;
  225. }
  226. /// Assuming nodes \p Src and \p Dst are already in the graph, connect node \p
  227. /// Src to node \p Dst using the provided edge \p E. Return true if \p Src is
  228. /// not already connected to \p Dst via \p E, and false otherwise.
  229. bool connect(NodeType &Src, NodeType &Dst, EdgeType &E) {
  230. assert(findNode(Src) != Nodes.end() && "Src node should be present.");
  231. assert(findNode(Dst) != Nodes.end() && "Dst node should be present.");
  232. assert((E.getTargetNode() == Dst) &&
  233. "Target of the given edge does not match Dst.");
  234. return Src.addEdge(E);
  235. }
  236. protected:
  237. // The list of nodes in the graph.
  238. NodeListTy Nodes;
  239. };
  240. } // namespace llvm
  241. #endif // LLVM_ADT_DIRECTEDGRAPH_H