Parasol Planning Library (PPL)
CompositeGraph.h
Go to the documentation of this file.
1 #ifndef PPL_COMPOSITE_GRAPH_H_
2 #define PPL_COMPOSITE_GRAPH_H_
3 
7 
8 #include <containers/sequential/graph/algorithms/graph_input_output.h>
9 
10 #ifndef INVALID_ED
11 #define INVALID_ED ED{std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max()}
12 #endif
13 
14 template <typename Vertex, typename Edge> class GenericStateGraph;
15 
16 
26 template <typename Vertex, typename Edge>
27 class CompositeGraph : public GenericStateGraph<Vertex, Edge> {
28 
29  public:
30 
33 
36  typedef typename Vertex::IndividualGraph IndividualGraph;
37 
38  typedef typename BaseType::EID ED;
39  typedef typename IndividualGraph::EdgeType IndividualEdge;
40 
41  typedef typename BaseType::adj_edge_iterator adj_edge_iterator;
42  typedef typename BaseType::edge_descriptor edge_descriptor;
43  typedef typename BaseType::vertex_iterator vertex_iterator;
44  typedef typename BaseType::vertex_descriptor vertex_descriptor;
45 
46  using typename BaseType::CVI;
47  using typename BaseType::VI;
48  using typename BaseType::EI;
49  using typename BaseType::VID;
50  using typename BaseType::STAPLGraph;
51 
52  using typename BaseType::VertexHook;
53  using typename BaseType::EdgeHook;
54  using typename BaseType::HookType;
55 
59 
61  CompositeGraph(RobotGroup* const _g = nullptr, std::vector<IndividualGraph*> _graphs = {});
62 
69 
70  CompositeGraph(const CompositeGraph&) = delete;
72 
75 
79 
81  virtual RobotGroup* GetGroup();
82 
85  virtual IndividualGraph* GetIndividualGraph(const size_t _index);
86 
89  virtual const IndividualGraph* GetIndividualGraph(const size_t _index) const;
90 
92  virtual size_t GetNumRobots() const noexcept;
93 
97 
101  virtual void Write(const std::string& _filename, Environment* _env) const
102  override;
103 
107  virtual void WriteCompositeGraph(const std::string& _filename,
108  Environment* const _env) const;
109 
112  std::string PrettyPrint() const;
113 
117 
122  virtual VID AddVertex(const Vertex& _v) noexcept override;
123 
126  virtual void DeleteVertex(const VID _v) noexcept override;
127 
132  virtual ED AddEdge(const VID _source, const VID _target, const Edge& _w)
133  noexcept override;
134 
137  using BaseType::AddEdge;
138 
142  virtual void DeleteEdge(const VID _source, const VID _target) noexcept override;
143 
146  virtual void DeleteEdge(EI _iterator) noexcept override;
147 
151 
154  virtual void ClearHooks() noexcept override;
155 
157 
158  protected:
159 
162 
164 
165  std::vector<IndividualGraph*> m_graphs;
166 
167  using BaseType::m_timestamp;
168 
170 
171 };
172 
173 /*------------------------------- Construction -------------------------------*/
174 
175 template <typename Vertex, typename Edge>
176 CompositeGraph<Vertex, Edge>::
177 CompositeGraph(RobotGroup* const _g, std::vector<IndividualGraph*> _graphs) :
178  GenericStateGraph<Vertex, Edge>(nullptr), m_group(_g), m_graphs(_graphs) {
179 
180  if (m_graphs.size() != m_group->Size())
181  m_graphs.reserve(m_group->Size());
182 }
183 
184 /*-------------------------------- Accessors ---------------------------------*/
185 
186 template <typename Vertex, typename Edge>
187 inline
188 RobotGroup*
190 GetGroup() {
191  return m_group;
192 }
193 
194 
195 template <typename Vertex, typename Edge>
196 inline
199 GetIndividualGraph(const size_t _index) {
200  return m_graphs[_index];
201 }
202 
203 
204 template <typename Vertex, typename Edge>
205 inline
208 GetIndividualGraph(const size_t _index) const {
209  return m_graphs[_index];
210 }
211 
212 
213 template <typename Vertex, typename Edge>
214 size_t
216 GetNumRobots() const noexcept {
217  return m_group->Size();
218 }
219 
220 /*-------------------------------Input/Output---------------------------------*/
221 
222 template <typename Vertex, typename Edge>
223 void
225 Write(const std::string& _filename, Environment* _env) const {
228  WriteCompositeGraph(_filename, _env);
229 }
230 
231 
232 template <typename Vertex, typename Edge>
233 void
235 WriteCompositeGraph(const std::string& _filename, Environment* _env) const {
236  #ifndef VIZMO_MAP
237  throw RunTimeException(WHERE, "Cannot use this method without the vizmo map"
238  " option enabled in the Makefile!");
239  #endif
240 
241  std::ofstream ofs(_filename);
242  ofs << "#####ENVFILESTART#####" << std::endl
243  << _env->GetEnvFileName() << std::endl
244  << "#####ENVFILESTOP#####" << std::endl;
245 
246  stapl::sequential::write_graph(*this, ofs);
247 }
248 
249 
250 template <typename Vertex, typename Edge>
251 std::string
253 PrettyPrint() const {
254  std::ostringstream out;
255  out << "Number of group vertices: " << this->get_num_vertices() << std::endl;
256  out << "Vertices in each individual graph:" << std::endl << "| ";
257  for(size_t i = 0; i < GetNumRobots(); ++i) {
258  out << "(Robot " << i << ") " << GetIndividualGraph(i)->get_num_vertices() << " | ";
259  }
260  out << std::endl;
261 
262  return out.str();
263 }
264 
265 /*-------------------------------- Modifiers ---------------------------------*/
266 
267 template <typename Vertex, typename Edge>
270 AddEdge(const VID _source, const VID _target, const Edge& _lp) noexcept {
271  if(_source == _target)
272  throw RunTimeException(WHERE) << "Tried to add edge between same VID "
273  << _source << ".";
274 
275  if(_lp.GetWeight() == 0 or _lp.GetWeight() == 0)
276  throw RunTimeException(WHERE) << "Tried to add zero weight edge!";
277 
278  // We need to adjust _lp, but we still want to override the base class
279  // function, so make a local copy of the edge.
280  Edge edge = _lp;
281 
282  // Vector of edge descriptors, which are edges already in individual graphs
283  std::vector<ED>& edgeDescriptors = edge.GetEdgeDescriptors();
284 
285  const Vertex& sourceCfg = this->GetVertex(_source),
286  & targetCfg = this->GetVertex(_target);
287 
288  size_t numInactiveRobots = 0;
289 
290  // First, make sure all the local edges are in the individual graphs.
291  for(size_t i = 0; i < edgeDescriptors.size(); ++i) {
292  auto graph = m_graphs[i];
293 
294  const VID individualSourceVID = sourceCfg.GetVID(i),
295  individualTargetVID = targetCfg.GetVID(i);
296 
297  // If they are the same, it means this is an inactive robot. Record the
298  // number of these that occur so that we can ensure SOME robot(s) moved.
299  if(individualSourceVID == individualTargetVID) {
300  ++numInactiveRobots;
301  // continue;
302  }
303 
304  // Assert that the individual vertices exist.
305  const bool verticesExist =
306  graph->find_vertex(individualSourceVID) != graph->end() and
307  graph->find_vertex(individualTargetVID) != graph->end();
308  if(!verticesExist)
309  throw RunTimeException(WHERE, "Cannot add edge for non-existent vertices.");
310 
311  // If we received a valid edge descriptor, it must agree with the individual
312  // VIDs, and the individual edge must exist.
313  const bool edgeExists = graph->IsEdge(individualSourceVID,
314  individualTargetVID);
315  if(edgeDescriptors[i] != INVALID_ED) {
316  if(!edgeExists)
317  throw RunTimeException(WHERE) << "Expected edge (" << individualSourceVID
318  << ", " << individualTargetVID << ") does "
319  << "not exist for robot "
320  << graph->GetRobot()->GetLabel() << ".";
321 
322  const bool consistent = edgeDescriptors[i].source() == individualSourceVID
323  and edgeDescriptors[i].target() == individualTargetVID;
324  if(!consistent)
325  throw RunTimeException(WHERE) << "Edge descriptors are not consistent. "
326  << "Fetched from group cfg: ("
327  << individualSourceVID << ", "
328  << individualTargetVID << "), fetched from "
329  << "group edge: ("
330  << edgeDescriptors[i].source() << ", "
331  << edgeDescriptors[i].target() << ").";
332  }
333  // If not, assert that the edge to be added does not already exist and then
334  // add it.
335  else
336  throw RunTimeException(WHERE) << "Expected edge (" << individualSourceVID
337  << ", " << individualTargetVID << ") does "
338  << "not exist for robot "
339  << graph->GetRobot()->GetLabel() << ".";
340  }
341 
342  if(numInactiveRobots >= GetNumRobots())
343  throw RunTimeException(WHERE) << "No robots were moved in this edge!";
344 
345  const auto edgeDescriptor = this->add_edge(_source, _target, edge);
346  const bool notNew = edgeDescriptor.id() == INVALID_EID;
347 
348  if(notNew) {
349  std::cerr << "\nCompositeGraph::AddEdge: edge (" << _source << ", "
350  << _target << ") already exists, not adding."
351  << std::endl;
352  }
353  else {
354  // Find the edge iterator.
355  VI vi;
356  EI ei;
357  this->find_edge(edgeDescriptor, vi, ei);
358 
359  // Execute post-add hooks.
360  this->ExecuteAddEdgeHooks(ei);
361 
362  this->m_predecessors[_target].insert(_source);
363  ++m_timestamp;
364  }
365 
366  return edgeDescriptor;
367 }
368 
369 
370 template <typename Vertex, typename Edge>
373 AddVertex(const Vertex& _v) noexcept {
374  Vertex cfg; // Will be a copy of the const Vertex
375  // Check that the group map is correct.
376  if((CompositeGraphType*)_v.GetGroupGraph() != this) {
377  throw RunTimeException(WHERE) << "Composite Graph of vertex does not "
378  << "match this composite graph.";
379  }
380  else { // Graphs match, no change to attempt.
381  cfg = _v;
382  }
383 
384  // Find the vertex and ensure it does not already exist.
385  CVI vi;
386  if(this->IsVertex(cfg, vi)) {
387  std::cerr << "\nCompositeGraph::AddVertex: vertex " << vi->descriptor()
388  << " already in graph"
389  << std::endl;
390  return vi->descriptor();
391  }
392 
393  // Add each vid to individual graphs if not already present.
394  for(size_t i = 0; i < m_group->Size(); ++i) {
395  auto graph = GetIndividualGraph(i);
396  auto robot = graph->GetRobot();
397  const VID individualVID = cfg.GetVID(i);
398 
399  // If the vid is invalid, we must add the local cfg.
400  if(individualVID == INVALID_VID)
401  cfg.SetRobotCfg(robot, graph->AddVertex(cfg.GetRobotCfg(i)));
402  // If the vid was valid, make sure it exists.
403  else if(graph->find_vertex(individualVID) == graph->end())
404  throw RunTimeException(WHERE) << "Individual vertex " << individualVID
405  << " does not exist!";
406  }
407 
408  // The vertex does not exist. Add it now.
409  const VID vid = this->add_vertex(cfg);
410  this->m_predecessors[vid];
411  this->m_allVIDs.insert(vid);
412  ++m_timestamp;
413 
414  // Execute post-add hooks.
415  this->ExecuteAddVertexHooks(this->find_vertex(vid));
416 
417  return vid;
418 }
419 
420 
421 template <typename Vertex, typename Edge>
422 void
424 DeleteVertex(const VID _v) noexcept {
425  // Find the vertex and crash if it doesn't exist.
426  VI vi = this->find_vertex(_v);
427  if(vi == this->end())
428  throw RunTimeException(WHERE, "VID " + std::to_string(_v) +
429  " is not in the graph.");
430 
431  // We must manually delete the edges rather than letting STAPL do this in
432  // order to call the DeleteEdge hooks.
433 
434  // Delete the outbound edges.
435  for(auto edge = vi->begin(); edge != vi->end(); edge = vi->begin())
436  DeleteEdge(edge);
437 
438  // Delete the inbound edges.
444  for(VI vertex = this->begin(); vertex != this->end(); ++vertex) {
445  while(true) {
446  // Jump to the next edge that targets this vertex.
447  EI edge = stapl::graph_find(vertex->begin(), vertex->end(),
448  stapl::eq_target<VID>(_v));
449  if(edge == vertex->end())
450  break;
451 
452  // If we found one, delete it.
453  DeleteEdge(edge);
454  }
455  }
456 
457  // Execute pre-delete hooks and update vizmo debug.
458  this->ExecuteDeleteVertexHooks(vi);
459 
460  // Delete the group vertex.
461  this->delete_vertex(vi->descriptor());
462  this->m_allVIDs.erase(_v);
463  ++m_timestamp;
464 }
465 
466 template <typename Vertex, typename Edge>
467 void
469 DeleteEdge(const VID _source, const VID _target) noexcept {
470  // Find the edge and crash if it isn't found.
471  const ED edgeDescriptor(_source, _target);
472  VI dummy;
473  EI edgeIterator;
474 
475  const bool found = this->find_edge(edgeDescriptor, dummy, edgeIterator);
476  if(!found)
477  throw RunTimeException(WHERE) << "Edge (" << _source << ", " << _target
478  << ") does not exist.";
479 
480  DeleteEdge(edgeIterator);
481 }
482 
483 template <typename Vertex, typename Edge>
484 void
486 DeleteEdge(EI _iterator) noexcept {
487  // Execute pre-delete hooks and update vizmo debug.
488  this->ExecuteDeleteEdgeHooks(_iterator);
489 
490  // Delete the individual edges.
491  auto& edge = _iterator->property();
492  auto& descriptors = edge.GetEdgeDescriptors();
493  for(size_t i = 0; i < m_group->Size(); ++i)
494  GetIndividualGraph(i)->DeleteEdge(descriptors[i].source(), descriptors[i].target());
495 
496  // Delete the group edge.
497  this->delete_edge(_iterator->descriptor());
498 
499  // Remove predessors as appropriate.
500  const VID source = _iterator->source(),
501  target = _iterator->target();
502 
503  this->m_predecessors[target].erase(source);
504  ++m_timestamp;
505 }
506 
507 /*----------------------------------- Hooks ----------------------------------*/
508 
509 template <typename Vertex, typename Edge>
510 void
512 ClearHooks() noexcept {
514 
515  for(IndividualGraph* const map : m_graphs)
516  map->ClearHooks();
517 }
518 
519 /*----------------------------------------------------------------------------*/
520 
521 #endif
#define INVALID_ED
Definition: CompositeGraph.h:11
#define INVALID_VID
Definition: GenericStateGraph.h:23
#define INVALID_EID
Definition: GenericStateGraph.h:27
#define WHERE
Macro for retrieving info about file, function, and line number.
Definition: RuntimeUtils.h:32
Definition: CompositeGraph.h:27
virtual EID AddEdge(const VID _source, const VID _target, const Edge &_w) noexcept
Definition: GenericStateGraph.h:698
virtual VID AddVertex(const Vertex &_v) noexcept override
Definition: CompositeGraph.h:373
BaseType::vertex_descriptor vertex_descriptor
Definition: CompositeGraph.h:44
BaseType::EID ED
Definition: CompositeGraph.h:38
STAPLGraph::vertex_descriptor VID
Definition: GenericStateGraph.h:83
RobotGroup *const m_group
The robot group.
Definition: CompositeGraph.h:163
GenericStateGraph< Vertex, Edge > BaseType
Definition: CompositeGraph.h:34
virtual size_t GetNumRobots() const noexcept
Get the number of robots for the group this graph is for.
Definition: CompositeGraph.h:216
virtual void DeleteVertex(const VID _v) noexcept override
Definition: CompositeGraph.h:424
CompositeGraph & operator=(CompositeGraph &&)=delete
virtual void WriteCompositeGraph(const std::string &_filename, Environment *const _env) const
Definition: CompositeGraph.h:235
std::string PrettyPrint() const
Definition: CompositeGraph.h:253
virtual IndividualGraph * GetIndividualGraph(const size_t _index)
Definition: CompositeGraph.h:199
CompositeGraph(RobotGroup *const _g=nullptr, std::vector< IndividualGraph * > _graphs={})
Construct a composite graph.
Definition: CompositeGraph.h:177
size_t m_timestamp
Tracks the number of changes to the graph.
Definition: GenericStateGraph.h:432
CompositeGraph & operator=(const CompositeGraph &)=delete
virtual void DeleteEdge(const VID _source, const VID _target) noexcept override
Definition: CompositeGraph.h:469
virtual void ClearHooks() noexcept override
Definition: CompositeGraph.h:512
Vertex::IndividualGraph IndividualGraph
Definition: CompositeGraph.h:36
virtual RobotGroup * GetGroup()
Get the robot group.
Definition: CompositeGraph.h:190
CompositeGraph(CompositeGraph &&)=delete
std::vector< IndividualGraph * > m_graphs
The individual graphs.
Definition: CompositeGraph.h:165
virtual void Write(const std::string &_filename, Environment *_env) const override
Definition: CompositeGraph.h:225
CompositeGraph< Vertex, Edge > CompositeGraphType
Definition: CompositeGraph.h:35
CompositeGraph(const CompositeGraph &)=delete
BaseType::edge_descriptor edge_descriptor
Definition: CompositeGraph.h:42
BaseType::vertex_iterator vertex_iterator
Definition: CompositeGraph.h:43
BaseType::adj_edge_iterator adj_edge_iterator
Definition: CompositeGraph.h:41
IndividualGraph::EdgeType IndividualEdge
Definition: CompositeGraph.h:39
Definition: Environment.h:137
const std::string & GetEnvFileName() const noexcept
Get the environment file name.
Definition: Environment.cpp:332
Definition: GenericStateGraph.h:67
std::function< void(VI)> VertexHook
Definition: GenericStateGraph.h:104
STAPLGraph::vertex_descriptor VID
Definition: GenericStateGraph.h:83
VertexSet m_allVIDs
Definition: GenericStateGraph.h:458
void ExecuteAddVertexHooks(const VI _iterator) noexcept
Definition: GenericStateGraph.h:1510
virtual void ClearHooks() noexcept
Definition: GenericStateGraph.h:1317
STAPLGraph::const_vertex_iterator CVI
Definition: GenericStateGraph.h:91
void ExecuteDeleteEdgeHooks(const EI _iterator) noexcept
Definition: GenericStateGraph.h:1558
void ExecuteAddEdgeHooks(const EI _iterator) noexcept
Definition: GenericStateGraph.h:1542
STAPLGraph::vertex_iterator VI
Definition: GenericStateGraph.h:89
STAPLGraph::edge_descriptor EID
Definition: GenericStateGraph.h:84
HookType
Definition: GenericStateGraph.h:106
std::function< void(EI)> EdgeHook
Definition: GenericStateGraph.h:105
STAPLGraph::adj_edge_iterator EI
Definition: GenericStateGraph.h:90
std::unordered_map< VID, VertexSet > m_predecessors
Definition: GenericStateGraph.h:454
stapl::sequential::graph< stapl::DIRECTED, stapl::NONMULTIEDGES, Vertex, Edge > STAPLGraph
Definition: GenericStateGraph.h:80
bool IsVertex(const VID _vid) const noexcept
Definition: GenericStateGraph.h:896
VP & GetVertex(T &_t) noexcept
Retrieve a reference to a vertex property by descriptor or iterator.
Definition: GenericStateGraph.h:1034
void ExecuteDeleteVertexHooks(const VI _iterator) noexcept
Definition: GenericStateGraph.h:1526
A group of one or more robots.
Definition: RobotGroup.h:17
size_t Size() const noexcept
Get the number of robots in the group.
Definition: RobotGroup.cpp:128
Definition: PMPLExceptions.h:62