• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_COMPILER_JIT_GRAPHCYCLES_GRAPHCYCLES_H_
17 #define TENSORFLOW_COMPILER_JIT_GRAPHCYCLES_GRAPHCYCLES_H_
18 
19 // GraphCycles detects the introduction of a cycle into a directed
20 // graph that is being built up incrementally.
21 //
22 // Nodes are identified by small integers.  It is not possible to
23 // record multiple edges with the same (source, destination) pair;
24 // requests to add an edge where one already exists are silently
25 // ignored.
26 //
27 // It is also not possible to introduce a cycle; an attempt to insert
28 // an edge that would introduce a cycle fails and returns false.
29 //
30 // GraphCycles uses no internal locking; calls into it should be
31 // serialized externally.
32 
33 // Performance considerations:
34 //   Works well on sparse graphs, poorly on dense graphs.
35 //   Extra information is maintained incrementally to detect cycles quickly.
36 //   InsertEdge() is very fast when the edge already exists, and reasonably fast
37 //   otherwise.
38 //   FindPath() is linear in the size of the graph.
39 // The current implementation uses O(|V|+|E|) space.
40 
41 #include <unordered_set>
42 
43 #include "tensorflow/core/platform/macros.h"
44 #include "tensorflow/core/platform/types.h"
45 
46 namespace tensorflow {
47 
48 // NOTE!!!
49 // For now a copy of this is forked to net/plaque. If you
50 // find a bug or add a feature, please inform the owners of the
51 // net/plaque copy in case it should be integrated.
52 // NOTE!!!
53 class GraphCycles {
54  public:
55   GraphCycles();
56   ~GraphCycles();
57 
58   // Allocate an unused node id and return it.
59   // The new node has a null pointer for its node data.
60   // All node identifiers passed to other routines in this interface
61   // must have been allocated by NewNode() and not yet deallocated
62   // by RemoveNode().
63   int32 NewNode();
64 
65   // Remove "node" from the graph, deleting all edges to and from it.
66   // After this call the identifier "node" it may no longer be used
67   // as an argument to any routine until it has been reallocated with
68   // NewNode().
69   void RemoveNode(int32 node);
70 
71   // Attempt to insert an edge from source_node to dest_node.  If the
72   // edge would introduce a cycle, return false without making any
73   // changes. Otherwise add the edge and return true.
74   bool InsertEdge(int32 source_node, int32 dest_node);
75 
76   // Remove any edge that exists from source_node to dest_node.
77   void RemoveEdge(int32 source_node, int32 dest_node);
78 
79   // Return whether there is an edge directly from source_node to dest_node.
80   bool HasEdge(int32 source_node, int32 dest_node) const;
81 
82   // Contracts the edge from 'a' to node 'b', merging nodes 'a' and 'b'. 'b' is
83   // removed from the graph, and edges to/from 'b' are replaced with edges
84   // to/from 'a'. If contracting the edge would create a cycle, does nothing
85   // and returns false.
86   bool ContractEdge(int32 a, int32 b);
87 
88   // Return true if can contract edge, otherwise return false.
89   bool CanContractEdge(int32 a, int32 b);
90 
91   // Return whether dest_node is reachable from source_node
92   // by following edges.
93   bool IsReachable(int32 source_node, int32 dest_node) const;
94 
95   // A faster non-thread-safe version of IsReachable.
96   bool IsReachableNonConst(int32 source_node, int32 dest_node);
97 
98   // Return or set the node data for a node.  This data is unused
99   // by the implementation.
100   void *GetNodeData(int32 node) const;
101   void SetNodeData(int32 node, void *data);
102 
103   // Find a path from "source" to "dest".  If such a path exists, place the
104   // node IDs of the nodes on the path in the array path[], and return the
105   // number of nodes on the path.  If the path is longer than max_path_len
106   // nodes, only the first max_path_len nodes are placed in path[].  The client
107   // should compare the return value with max_path_len" to see when this
108   // occurs.  If no path exists, return 0.  Any valid path stored in path[]
109   // will start with "source" and end with "dest".  There is no guarantee that
110   // the path is the shortest, but no node will appear twice in the path,
111   // except the source and destination node if they are identical; therefore,
112   // the return value is at most one greater than the number of nodes in the
113   // graph.
114   int FindPath(int32 source, int32 dest, int max_path_len, int32 path[]) const;
115 
116   // Check internal invariants. Crashes on failure, returns true on success.
117   // Expensive: should only be called from graphcycles_test.cc.
118   bool CheckInvariants() const;
119 
120   std::unordered_set<int32> Successors(int32 node);
121   std::unordered_set<int32> Predecessors(int32 node);
122 
123   // ----------------------------------------------------
124   struct Rep;
125 
126  private:
127   Rep *rep_;  // opaque representation
128   TF_DISALLOW_COPY_AND_ASSIGN(GraphCycles);
129 };
130 
131 }  // namespace tensorflow
132 #endif  // TENSORFLOW_COMPILER_JIT_GRAPHCYCLES_GRAPHCYCLES_H_
133