DirectedGraph.h 9.8 KB

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