iMSTK
Interactive Medical Simulation Toolkit
imstkTaskGraph.h
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #pragma once
8 
9 #include "imstkTaskNode.h"
10 
11 #include <list>
12 #include <memory>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <vector>
16 
17 namespace std
18 {
23 template<>
24 struct hash<std::shared_ptr<imstk::TaskNode>>
25 {
26  std::size_t operator()(const std::shared_ptr<imstk::TaskNode>& node) const
27  {
28  using std::size_t;
29  return node->getGlobalId();
30  }
31 };
36 template<>
37 struct equal_to<std::shared_ptr<imstk::TaskNode>>
38 {
39  bool operator()(const std::shared_ptr<imstk::TaskNode>& lhs,
40  const std::shared_ptr<imstk::TaskNode>& rhs) const
41  {
42  return lhs->getGlobalId() == rhs->getGlobalId();
43  }
44 };
45 } // namespace std
46 
47 namespace imstk
48 {
49 using TaskNodeVector = std::vector<std::shared_ptr<TaskNode>>;
50 using TaskNodeList = std::list<std::shared_ptr<TaskNode>>;
51 using TaskNodeSet = std::unordered_set<std::shared_ptr<TaskNode>>;
52 using TaskNodeAdjList = std::unordered_map<std::shared_ptr<TaskNode>, TaskNodeSet>;
53 using TaskNodeNameMap = std::unordered_map<std::shared_ptr<TaskNode>, std::string>;
54 
61 class TaskGraph
62 {
63 public:
64  TaskGraph(std::string sourceName = "Source", std::string sinkName = "Sink");
65  virtual ~TaskGraph() = default;
66 
67 public:
68  std::shared_ptr<TaskNode> getSource() const { return m_source; }
69  std::shared_ptr<TaskNode> getSink() const { return m_sink; }
70 
75  TaskNodeVector& getNodes() { return m_nodes; }
76 
80  const TaskNodeAdjList& getAdjList() const { return m_adjList; }
81 
85  const TaskNodeAdjList& getInvAdjList() const { return m_invAdjList; }
86 
87 // Node operations
88 public:
92  TaskNodeVector::iterator findNode(std::string name);
93  TaskNodeVector::const_iterator findNode(std::string name) const;
97  TaskNodeVector::iterator findNode(std::shared_ptr<TaskNode> node);
98  TaskNodeVector::const_iterator findNode(std::shared_ptr<TaskNode> node) const;
99 
103  bool containsNode(std::shared_ptr<TaskNode> node) const;
104 
108  TaskNodeVector::iterator endNode() { return m_nodes.end(); }
109  TaskNodeVector::const_iterator endNode() const { return m_nodes.end(); }
113  TaskNodeVector::iterator beginNode() { return m_nodes.begin(); }
114  TaskNodeVector::const_iterator beginNode() const { return m_nodes.begin(); }
115 
120  bool addNode(std::shared_ptr<TaskNode> node);
121 
125  void addNodes(const std::vector<std::shared_ptr<TaskNode>>& nodes);
126 
130  std::shared_ptr<TaskNode> addFunction(std::string name, std::function<void()> func);
131 
136  bool removeNode(std::shared_ptr<TaskNode> node);
137 
142  bool removeNodeAndRedirect(std::shared_ptr<TaskNode> node);
143 
147  void insertAfter(std::shared_ptr<TaskNode> refNode, std::shared_ptr<TaskNode> newNode);
148 
152  void insertBefore(std::shared_ptr<TaskNode> refNode, std::shared_ptr<TaskNode> newNode);
153 
154 // Edge operations
155 public:
159  bool containsEdge(std::shared_ptr<TaskNode> srcNode, std::shared_ptr<TaskNode> destNode) const;
160 
164  void addEdge(std::shared_ptr<TaskNode> srcNode, std::shared_ptr<TaskNode> destNode);
165 
169  void addEdges(const std::vector<std::pair<std::shared_ptr<TaskNode>, std::shared_ptr<TaskNode>>>& edges);
170 
175  void nestGraph(std::shared_ptr<TaskGraph> subgraph, std::shared_ptr<TaskNode> source, std::shared_ptr<TaskNode> sink);
176 
180  void removeEdge(std::shared_ptr<TaskNode> srcNode, std::shared_ptr<TaskNode> destNode);
181 
185  bool isReachable(std::shared_ptr<TaskNode> srcNode, std::shared_ptr<TaskNode> destNode);
186 
187 public:
191  void clear();
192 
196  void clearEdges()
197  {
198  m_adjList.clear();
199  m_invAdjList.clear();
200  }
201 
202 // Graph algorithms, todo: Move into filtering module
203 public:
207  //static std::shared_ptr<TaskGraph> sum(std::shared_ptr<TaskGraph> graphA, std::shared_ptr<TaskGraph> graphB);
208 
212  static std::shared_ptr<TaskNodeList> topologicalSort(std::shared_ptr<TaskGraph> graph);
213 
218  static std::shared_ptr<TaskGraph> transitiveReduce(std::shared_ptr<TaskGraph> graph);
219 
223  static std::shared_ptr<TaskGraph> removeRedundantNodes(std::shared_ptr<TaskGraph> graph);
224 
229  static std::shared_ptr<TaskGraph> reduce(std::shared_ptr<TaskGraph> graph)
230  {
231  std::shared_ptr<TaskGraph> reducedGraph = transitiveReduce(graph);
232  if (reducedGraph != nullptr)
233  {
234  return removeRedundantNodes(reducedGraph);
235  }
236  else
237  {
238  return nullptr;
239  }
240  }
241 
242  static std::shared_ptr<TaskGraph> removeUnusedNodes(std::shared_ptr<TaskGraph> graph);
243 
247  static bool isCyclic(std::shared_ptr<TaskGraph> graph);
248 
252  static TaskNodeNameMap getUniqueNodeNames(std::shared_ptr<TaskGraph> graph, bool apply = false);
253 
257  static std::unordered_map<std::shared_ptr<TaskNode>, double> getNodeStartTimes(std::shared_ptr<TaskGraph> graph);
258 
262  static TaskNodeList getCriticalPath(std::shared_ptr<TaskGraph> graph);
263 
264 protected:
265  TaskNodeVector m_nodes;
266  TaskNodeAdjList m_adjList;
267  TaskNodeAdjList m_invAdjList;
268 
269  std::shared_ptr<TaskNode> m_source = nullptr;
270  std::shared_ptr<TaskNode> m_sink = nullptr;
271 };
272 } // namespace imstk
Base class for TaskGraph, a collection of TaskNode&#39;s. Maintains nodes, adjacencyList, and invAdjacencyList.
const TaskNodeAdjList & getAdjList() const
Get the edges belonging to this graph.
const TaskNodeAdjList & getInvAdjList() const
Get the inverse edges belonging to this graph.
TaskNodeVector::iterator endNode()
Returns the start of the node container.
TaskNodeVector & getNodes()
Get the nodes belonging to this graph HS This is bad, there are algorithms that change the nodes of t...
Compound Geometry.
static std::shared_ptr< TaskGraph > reduce(std::shared_ptr< TaskGraph > graph)
Simplifies the graph in a way that retains functionality Performs transitive reduction then redundant...
TaskNodeVector::iterator beginNode()
Returns the start of the node container.
Returns a hash value for a PointEntry.
TaskNodeAdjList m_adjList
This gives the outputs of every node.
TaskNodeAdjList m_invAdjList
This gives the inputs of every node.
void clearEdges()
Removes all edges from the graph.
Test if two points are the same or not by comparing their id and coordinates.