GraphLibrary  0.0.1
A simple library that implements various graph algorithms.
 All Classes Namespaces Files Functions Variables Typedefs Macros
Graph.hpp
Go to the documentation of this file.
1 #ifndef GL_GRAPH_HPP
2 #define GL_GRAPH_HPP
3 
4 #include <fstream>
5 #include <iostream>
6 #include <algorithm>
7 #include <exception>
8 #include <type_traits>
9 #include <vector>
10 #include <string>
11 #include <queue>
12 #include <list>
13 #include <stack>
14 #include <iterator>
15 
16 #include "../gl_base.hpp"
17 #include "Color.hpp"
18 #include "Edge.hpp"
19 #include "Node.hpp"
20 #include "Property.hpp"
21 #include "../algorithms/HavelHakimi.hpp"
22 
23 namespace gl {
24 
26 // Graph Class declaration
28 
38 template <class SCALAR = int, class STORAGE_KIND = gl::List, class DIRECTION = gl::Undirected>
39 class Graph
40 {
41 
42 public:
43  using val_t = SCALAR;
47  using dest_vec_t = std::vector<std::pair<idx_t, val_t>>;
48  using idx_list_t = std::vector<idx_t>;
49  using ordered_list_t = std::list<idx_t>;
50  using visit_list_t = std::vector<bool>;
51  template <class info_t>
52  using BFS_queue_t = std::deque<info_t>;
53  using DFS_queue_t = std::stack<idx_t>;
54 
55  /* Data structure typedefs */
56  using matrix_t = std::vector<Edge>;
57  using nodeList_t = std::list<Edge>;
58  using rootList_t = std::vector<nodeList_t>;
59 
64  template <bool IsConst = true>
66  {
67  public:
68  using value_type = Edge;
69  using reference = std::conditional_t<IsConst, const Edge &, Edge &>;
70  using pointer = std::conditional_t<IsConst, const Edge *, Edge *>;
71  using iterator_category = std::forward_iterator_tag;
72  using difference_type = std::ptrdiff_t;
74  /* typedefs for data members */
75  using matrix_iterator_t = std::conditional_t<IsConst, typename matrix_t::const_iterator, typename matrix_t::iterator>;
76  using rootList_iterator_t = std::conditional_t<IsConst, typename rootList_t::const_iterator, typename rootList_t::iterator>;
77  using list_iterator_t = std::conditional_t<IsConst, typename nodeList_t::const_iterator, typename nodeList_t::iterator>;
78  using container_pointer_t = std::conditional_t<IsConst, const Graph<SCALAR, STORAGE_KIND, DIRECTION> *, Graph<SCALAR, STORAGE_KIND, DIRECTION> *>;
89 #ifndef DOXYGEN_SHOULD_SKIP_THIS
90  GL_ENABLE_IF_MATRIX
91 #endif
93  {
94  }
101 #ifndef DOXYGEN_SHOULD_SKIP_THIS
102  GL_ENABLE_IF_LIST
103 #endif
105  {
106  }
107 
112 #ifndef DOXYGEN_SHOULD_SKIP_THIS
113  GL_ENABLE_IF_MATRIX
114 #endif
116  {
117  ++ptr_;
118  while (ptr_ - data1_ < data2_->edges_.size() && !ptr_->exists())
119  {
120  ++ptr_;
121  }
122  return *this;
123  }
128 #ifndef DOXYGEN_SHOULD_SKIP_THIS
129  GL_ENABLE_IF_MATRIX
130 #endif
131  self_t operator++(int dummy)
132  {
133  self_t i = *this;
134  ++ptr_;
135  while (ptr_ - data1_ < data2_->edges_.size() && !ptr_->exists())
136  {
137  ++ptr_;
138  }
139  return i;
140  }
141 #ifndef DOXYGEN_SHOULD_SKIP_THIS
142  GL_ENABLE_IF_LIST
144  {
145  ++ptr_;
146  if (ptr_ == data1_->end() && ((data1_ + 1) != data2_->edges_.end()))
147  {
148  ++data1_;
149  while (data1_->size() == 0 && ((data1_ + 1) != data2_->edges_.end()))
150  {
151  ++data1_;
152  }
153  ptr_ = data1_->begin();
154  }
155  return *this;
156  }
157  GL_ENABLE_IF_LIST
158  self_t operator++(int dummy)
159  {
160  self_t i = *this;
161  ++ptr_;
162  if (ptr_ == data1_->end() && ((data1_ + 1) != data2_->edges_.end()))
163  {
164  ++data1_;
165  while (data1_->size() == 0 && ((data1_ + 1) != data2_->edges_.end()))
166  {
167  ++data1_;
168  }
169  ptr_ = data1_->begin();
170  }
171  return i;
172  }
173 #endif
174 
178 #ifndef DOXYGEN_SHOULD_SKIP_THIS
179  template <bool _IsConst = IsConst>
180  std::enable_if_t<_IsConst, reference>
181 #endif
182  operator*() const
183  {
184  return *ptr_;
185  }
190 #ifndef DOXYGEN_SHOULD_SKIP_THIS
191  template <bool _IsConst = IsConst>
192  std::enable_if_t<!_IsConst, reference>
193 #endif
195  {
196  return *ptr_;
197  }
202 #ifndef DOXYGEN_SHOULD_SKIP_THIS
203  template <bool _IsConst = IsConst>
204  std::enable_if_t<_IsConst, pointer>
205 #endif
206  operator->() const
207  {
208  return &operator*();
209  }
214 #ifndef DOXYGEN_SHOULD_SKIP_THIS
215  template <bool _IsConst = IsConst>
216  std::enable_if_t<!_IsConst, pointer>
217 #endif
219  {
220  return &operator*();
221  }
226  bool operator==(const self_t &rhs) { return ptr_ == rhs.ptr_ && data1_ == rhs.data1_ && data2_ == rhs.data2_; }
231  bool operator!=(const self_t &rhs) { return !operator==(rhs); }
232 
237  self_t operator=(const self_t &rhs)
238  {
239  ptr_ = rhs.ptr_;
240  data1_ = rhs.data1_;
241  data2_ = rhs.data2_;
242  }
243 
244  private:
245  std::conditional_t<std::is_same_v<STORAGE_KIND, Matrix>, matrix_iterator_t, list_iterator_t> ptr_;
246  std::conditional_t<std::is_same_v<STORAGE_KIND, Matrix>, matrix_iterator_t, rootList_iterator_t> data1_;
248  };
249 
250  /* Iterator typedefs */
253  using NodeIterator = typename std::vector<Node>::iterator;
254  using ConstNodeIterator = typename std::vector<Node>::const_iterator;
255 
256 protected:
258  std::vector<Node> nodes_;
259  std::conditional_t<std::is_same_v<STORAGE_KIND, Matrix>, matrix_t, rootList_t> edges_;
260 
261 public:
272  Graph(const idx_t &numNodes = 0, const std::string &label = "Graph") : property_(numNodes, label)
273  {
274  construct();
275  }
281  Graph(const std::string &degreeSeq, const std::string &label = "Simple Undirected Graph")
282  {
283  std::stringstream iss(degreeSeq);
284  idx_t degree;
285  std::deque<idx_t> degrees;
286  while (iss >> degree)
287  degrees.push_back(degree);
288 
289  GL_ASSERT(gl::algorithm::havelHakimi(degrees), "Degree Sequence is not graphic.")
290 
291  idx_t numNodes = degrees.size();
292  property_ = Property(numNodes, label);
293  property_.numNodes(numNodes);
294  construct();
295 
296  for (idx_t i = 0; i < numNodes; ++i)
297  {
298  for (idx_t j = i + 1; j < numNodes; ++j)
299  {
300  if (degrees[i] > 0 && degrees[j] > 0)
301  {
302  setEdge(i, j);
303  --degrees[i];
304  --degrees[j];
305  }
306  }
307  }
308  }
313  Graph(const Property &property) : property_(property)
314  {
315  construct();
316  }
318  {
319  }
320 
322  // Specialized function implementations
324 
329 #ifndef DOXYGEN_SHOULD_SKIP_THIS
330  GL_ENABLE_IF_LIST_DIRECTED
331 #endif
333  {
335  for (idx_t start = 0; start < edges_.size(); ++start)
336  {
337  for (auto &end : edges_[start])
338  {
339  out.setEdge(start, end.dest(), end.weight(), end.color());
340  }
341  }
342  return out;
343  }
344 #ifndef DOXYGEN_SHOULD_SKIP_THIS
345 
348  GL_ENABLE_IF_LIST_UNDIRECTED
350  {
352  for (idx_t start = 0; start < edges_.size(); ++start)
353  {
354  for (auto &end : edges_[start])
355  {
356  if (!out.hasEdge(start, end.dest()))
357  out.setEdge(start, end.dest(), end.weight(), end.color());
358  }
359  }
360  return out;
361  }
362 #endif
363 
368 #ifndef DOXYGEN_SHOULD_SKIP_THIS
369  GL_ENABLE_IF_MATRIX
370 #endif
372  {
374  for (auto edge = edge_cbegin(); edge != edge_cend(); ++edge)
375  {
376  out.setEdge(edge->source(), edge->dest(), edge->weight(), edge->color());
377  }
378  return out;
379  }
381 
390  inline std::string getGraphLabel() const
391  {
392  return property_.label();
393  }
398  inline void setGraphLabel(const std::string &label)
399  {
400  property_.label(label);
401  }
406  inline idx_t numNodes() const
407  {
408  return property_.numNodes();
409  }
410 
415  inline idx_t numEdges() const
416  {
417  return property_.numEdges();
418  }
419 #ifndef DOXYGEN_SHOULD_SKIP_THIS
420  GL_ENABLE_IF_UNDIRECTED
421 #endif
422 
426  inline bool isDirected() const
427  {
428  return false;
429  }
430 #ifndef DOXYGEN_SHOULD_SKIP_THIS
431 
434  GL_ENABLE_IF_DIRECTED
435  inline bool isDirected() const
436  {
437  return true;
438  }
439 #endif
440 #ifndef DOXYGEN_SHOULD_SKIP_THIS
441  GL_ENABLE_IF_UNDIRECTED
442 #endif
443 
447  inline bool isUndirected() const
448  {
449  return true;
450  }
451 #ifndef DOXYGEN_SHOULD_SKIP_THIS
452 
455  GL_ENABLE_IF_DIRECTED
456  inline bool isUndirected() const
457  {
458  return false;
459  }
460 #endif
461 
465  bool hasCycle() const
466  {
467  idx_t v = 0;
468  idx_t parent = 0;
469  std::deque<std::pair<idx_t, idx_t>> queue;
470  idx_list_t tempList;
471  visit_list_t visited(numNodes(), false);
472  queue.push_front(std::make_pair(v, parent));
473  visited[v] = true;
474 
475  while (!queue.empty())
476  {
477  v = queue.front().first;
478  parent = queue.front().second;
479  queue.pop_front();
480 
481  tempList = getNeighbours(v);
482  for (auto elem : tempList)
483  {
484  if (!visited[elem])
485  {
486  queue.push_front(std::make_pair(elem, v));
487  visited[elem] = true;
488  }
489  else if (elem != parent)
490  return true;
491  }
492  }
493  return false;
494  }
507 #ifndef DOXYGEN_SHOULD_SKIP_THIS
508  GL_ENABLE_IF_LIST_DIRECTED
509 #endif
510  void setEdge(const idx_t &start, const idx_t &end, const val_t &weight = 1, const Color &color = Color())
511  {
512  GL_ASSERT((!hasEdge(start, end)), std::string("There is already an edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
513 
514  edges_[start].push_back(Edge(start, end, weight, color, true));
516  nodes_[start].outDegreeIncrement();
517  nodes_[end].inDegreeIncrement();
518  }
519 
520 #ifndef DOXYGEN_SHOULD_SKIP_THIS
521 
524  GL_ENABLE_IF_LIST_UNDIRECTED
525  void setEdge(const idx_t &start, const idx_t &end, const val_t &weight = 1, const Color &color = Color())
526  {
527  GL_ASSERT((!hasEdge(start, end)), std::string("There is already an edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
528  edges_[start].push_back(Edge(start, end, weight, color, true));
530  nodes_[start].outDegreeIncrement();
531  nodes_[end].inDegreeIncrement();
532  if (start != end)
533  { // for avoiding double-adding self loops
534  edges_[end].push_back(Edge(end, start, weight, color, true));
535  nodes_[start].inDegreeIncrement();
536  nodes_[end].outDegreeIncrement();
537  }
538  }
539 
543  GL_ENABLE_IF_MATRIX_DIRECTED
544  void setEdge(const idx_t &start, const idx_t &end, const val_t &weight = 1, const Color &color = Color())
545  {
546  GL_ASSERT((!hasEdge(start, end)), std::string("There is already an edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
547  edges_[start * numNodes() + end].weight(weight);
548  edges_[start * numNodes() + end].exists(true);
549  edges_[start * numNodes() + end].color(color);
551  nodes_[start].outDegreeIncrement();
552  nodes_[end].inDegreeIncrement();
553  }
554 
558  GL_ENABLE_IF_MATRIX_UNDIRECTED
559  void setEdge(idx_t start, idx_t end, const val_t &weight = 1, const Color &color = {})
560  {
561  if (start > end)
562  std::swap(end, start);
563  GL_ASSERT((!hasEdge(start, end)), std::string("There is already an edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
564  edges_[start * numNodes() + end].color(color);
565  edges_[start * numNodes() + end].weight(weight);
566  if (!hasEdge(start, end))
567  {
568  edges_[start * numNodes() + end].exists(true);
570  nodes_[start].inDegreeIncrement();
571  nodes_[start].outDegreeIncrement();
572  nodes_[end].inDegreeIncrement();
573  nodes_[end].outDegreeIncrement();
574  }
575  }
576 #endif
577 
581  void setEdge(const Edge& edge)
582  {
583  setEdge(edge.source(), edge.dest(), edge.weight(), edge.color());
584  }
597  void setEdgesFromListFile(const std::string &inFile)
598  {
599  std::ifstream is;
600  is.open(inFile, std::ios::in);
601  GL_ASSERT(is.is_open(),std::string(std::string("Error: failed to open ")+inFile))
602 
603  idx_t start, end;
604  val_t weight;
605  while (!is.eof()) {
606  if (is >> start >> end >> weight)
607  {
608  setEdge(start, end, weight);
609  }
610  }
611  }
625  void setEdgesFromMatrixFile(const std::string &inFile)
626  {
627  std::ifstream is;
628  is.open(inFile, std::ios::in);
629  GL_ASSERT(is.is_open(),std::string(std::string("Error: failed to open ")+inFile))
630 
631  idx_t i = 0, j = 0;
632  val_t weight = 0;
633  std::string line;
634  std::string field;
635  while (std::getline(is,line))
636  {
637  std::stringstream ss(line);
638  while (std::getline(ss,field,','))
639  {
640  std::stringstream fs(field);
641  val_t weight;
642  if (!(fs >> weight)) {
643  fs.clear();
644  fs.ignore();
645  }
646  else {
647  if (!hasEdge(i,j)) {
648  setEdge(i, j, weight);
649  }
650  }
651  ++j;
652  if (j == numNodes()) {
653  j = 0;
654  ++i;
655  }
656  if (i == numNodes()) break;
657  }
658  }
659  }
660 
668 #ifdef DOXYGEN_SHOULD_SKIP_THIS
669  inline void updateEdge(const idx_t& start, const idx_t& end, const val_t& weight, const gl::Color& color) {}
670 #endif
671 #ifndef DOXYGEN_SHOULD_SKIP_THIS
672  template <typename ... Args, typename STORAGE = STORAGE_KIND, typename DIR = DIRECTION, GL_ENABLE_IF_LIST_DIRECTED_T>
673  inline void updateEdge(const idx_t& start, const idx_t& end, const Args&... args)
674  {
675  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
676  auto it = std::find_if(edges_[start].begin(), edges_[start].end(),
677  [&end](const Edge &node) { return node.dest() == end; });
678  updateEdgeInternal(it, args...);
679  }
680  template <typename ... Args, typename STORAGE = STORAGE_KIND, typename DIR = DIRECTION, GL_ENABLE_IF_LIST_UNDIRECTED_T>
681  inline void updateEdge(const idx_t& start, const idx_t& end, const Args&... args)
682  {
683  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
684  auto it = std::find_if(edges_[start].begin(), edges_[start].end(),
685  [&end](const Edge &node) { return node.dest() == end; });
686  updateEdgeInternal(it, args...);
687  it = std::find_if(edges_[end].begin(), edges_[end].end(),
688  [&start](const Edge &node) { return node.dest() == start; });
689  updateEdgeInternal(it, args...);
690  }
691  template <typename ... Args, typename STORAGE = STORAGE_KIND, typename DIR = DIRECTION, GL_ENABLE_IF_MATRIX_DIRECTED_T>
692  inline void updateEdge(const idx_t& start, const idx_t& end, const Args&... args)
693  {
694  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
695  updateEdgeInternal(edges_.data()+start * numNodes() + end, args...);
696  }
697  template <typename ... Args, typename STORAGE = STORAGE_KIND, typename DIR = DIRECTION, GL_ENABLE_IF_MATRIX_UNDIRECTED_T>
698  inline void updateEdge(const idx_t& start, const idx_t& end, const Args&... args)
699  {
700  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
701  updateEdgeInternal(edges_.data()+start * numNodes() + end, args...);
702  updateEdgeInternal(edges_.data()+end * numNodes() + start, args...);
703  }
704 private:
705  template <typename Target, typename First, typename ... OtherArgs>
706  inline void updateEdgeInternal (const Target& it, First arg, const OtherArgs&... rest)
707  {
708  throw std::runtime_error( std::string(__FILE__)
709  + std::string(":")
710  + std::to_string(__LINE__)
711  + std::string(" in ")
712  + std::string(__PRETTY_FUNCTION__)
713  + std::string(": Unknown argument type."));
714  }
715  template <typename Target, typename ... OtherArgs>
716  inline void updateEdgeInternal (const Target& it, const val_t& arg, const OtherArgs&... rest)
717  {
718  (*it).weight(arg);
719  updateEdgeInternal(it,rest...);
720  }
721  template <typename Target, typename ... OtherArgs>
722  inline void updateEdgeInternal (const Target& it, const gl::Color& arg, const OtherArgs&... rest)
723  {
724  (*it).color(arg);
725  updateEdgeInternal(it,rest...);
726  }
727  template <typename Target>
728  inline void updateEdgeInternal (const Target& it)
729  {
730  }
731 public:
732 #endif
733 
738 #ifndef DOXYGEN_SHOULD_SKIP_THIS
739  GL_ENABLE_IF_LIST_DIRECTED
740 #endif
741  void delEdge(const idx_t &start, const idx_t &end)
742  {
743  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
744  auto it = std::find_if(edges_[start].begin(), edges_[start].end(),
745  [&end](const Edge &node) { return node.dest() == end; });
746  edges_[start].erase(it);
748  nodes_[start].outDegreeDecrement();
749  nodes_[end].inDegreeDecrement();
750  }
751 #ifndef DOXYGEN_SHOULD_SKIP_THIS
752 
755  GL_ENABLE_IF_LIST_UNDIRECTED
756  void delEdge(const idx_t &start, const idx_t &end)
757  {
758  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
759  auto it = std::find_if(edges_[start].begin(), edges_[start].end(),
760  [&end](const Edge &node) { return node.dest() == end; });
761  edges_[start].erase(it);
763  nodes_[start].inDegreeDecrement();
764  nodes_[start].outDegreeDecrement();
765  // only do the following if the edge is not a self-loop
766  if (start != end) {
767  it = std::find_if(edges_[end].begin(), edges_[end].end(),
768  [&start](const Edge &node) { return node.dest() == start; });
769  edges_[end].erase(it);
770  nodes_[end].inDegreeDecrement();
771  nodes_[end].outDegreeDecrement();
772  }
773  }
774 
778  GL_ENABLE_IF_MATRIX_DIRECTED
779  inline void delEdge(const idx_t &start, const idx_t &end)
780  {
781  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
782  checkRange(start, end);
783  edges_[start * numNodes() + end].weight(SCALAR(0));
784  edges_[start * numNodes() + end].exists(false);
786  nodes_[start].outDegreeDecrement();
787  nodes_[end].inDegreeDecrement();
788  }
789 
793  GL_ENABLE_IF_MATRIX_UNDIRECTED
794  inline void delEdge(idx_t start, idx_t end)
795  {
796  GL_ASSERT((hasEdge(start, end)), std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end));
797  if (start > end)
798  std::swap(end, start);
799  edges_[start * numNodes() + end].weight(SCALAR(0));
800  edges_[start * numNodes() + end].exists(false);
802  nodes_[start].inDegreeDecrement();
803  nodes_[start].outDegreeDecrement();
804  nodes_[end].inDegreeDecrement();
805  nodes_[end].outDegreeDecrement();
806  }
807 #endif
808 
815 #ifndef DOXYGEN_SHOULD_SKIP_THIS
816  GL_ENABLE_IF_LIST
817 #endif
818  bool hasEdge(const idx_t &start, const idx_t &end) const
819  {
820  checkRange(start, end);
821  auto it = std::find_if(edges_[start].begin(), edges_[start].end(),
822  [&end](const Edge &node) { return node.dest() == end; });
823  return it != edges_[start].end();
824  }
825 #ifndef DOXYGEN_SHOULD_SKIP_THIS
826 
829  GL_ENABLE_IF_MATRIX_DIRECTED
830  inline bool hasEdge(const idx_t &start, const idx_t &end) const
831  {
832  checkRange(start, end);
833  return edges_[start * numNodes() + end].exists();
834  }
835 
839  GL_ENABLE_IF_MATRIX_UNDIRECTED
840  inline bool hasEdge(idx_t start, idx_t end) const
841  {
842  checkRange(start, end);
843  if (start > end)
844  std::swap(end, start);
845  return edges_[start * numNodes() + end].exists();
846  }
847 #endif
848 
855 #ifndef DOXYGEN_SHOULD_SKIP_THIS
856  GL_ENABLE_IF_LIST
857 #endif
858  val_t getEdgeWeight(const idx_t &start, const idx_t &end) const
859  {
860  GL_ASSERT(hasEdge(start, end), (std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end)))
861  auto it = std::find_if(edges_[start].begin(), edges_[start].end(),
862  [&end](const Edge &node) { return node.dest() == end; });
863  return (*it).weight();
864  }
865 #ifndef DOXYGEN_SHOULD_SKIP_THIS
866 
869  GL_ENABLE_IF_MATRIX_DIRECTED
870  inline val_t getEdgeWeight(const idx_t &start, const idx_t &end) const
871  {
872  GL_ASSERT(hasEdge(start, end), (std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end)))
873  return edges_[start * numNodes() + end].weight();
874  }
875 
879  GL_ENABLE_IF_MATRIX_UNDIRECTED
880  inline val_t getEdgeWeight(idx_t start, idx_t end) const
881  {
882  if (start > end)
883  std::swap(end, start);
884  GL_ASSERT(hasEdge(start, end), (std::string("No edge from ") + std::to_string(start) + std::string(" to ") + std::to_string(end)))
885  return edges_[start * numNodes() + end].weight();
886  }
887 #endif
888 
894 #ifndef DOXYGEN_SHOULD_SKIP_THIS
895 
898  GL_ENABLE_IF_MATRIX_DIRECTED
899 #endif
900  Color getEdgeColor(const idx_t &src, const idx_t &dest) const
901  {
902  return edges_[src * numNodes() + dest].color();
903  }
904 #ifndef DOXYGEN_SHOULD_SKIP_THIS
905 
908  GL_ENABLE_IF_MATRIX_UNDIRECTED
909  Color getEdgeColor(idx_t src, idx_t dest) const
910  {
911  if (src > dest)
912  std::swap(src, dest);
913  return edges_[src * numNodes() + dest].color();
914  }
918  GL_ENABLE_IF_LIST
919  Color getEdgeColor(const idx_t &src, const idx_t &dest) const
920  {
921  auto it = std::find_if(edges_[src].begin(), edges_[src].end(),
922  [&dest](const Edge &node) { return node.dest() == dest; });
923  return (*it).color();
924  }
925 #endif
926 
931 #ifndef DOXYGEN_SHOULD_SKIP_THIS
932  GL_ENABLE_IF_MATRIX
933 #endif
935  {
936  auto ptr = edges_.begin();
937  if (numEdges() > 0) {
938  while (!ptr->exists())
939  {
940  ++ptr;
941  }
942  }
943  else
944  {
945  ptr = edges_.end();
946  }
947  return Edge_Iterator<false>(ptr, edges_.begin(), this);
948  }
953 #ifndef DOXYGEN_SHOULD_SKIP_THIS
954  GL_ENABLE_IF_MATRIX
955 #endif
957  {
958  return Edge_Iterator<false>(edges_.end(), edges_.begin(), this);
959  }
964 #ifndef DOXYGEN_SHOULD_SKIP_THIS
965  GL_ENABLE_IF_MATRIX
966 #endif
968  {
969  auto ptr = edges_.cbegin();
970  if (numEdges() > 0) {
971  while (!ptr->exists())
972  {
973  ++ptr;
974  }
975  }
976  else
977  {
978  ptr = edges_.cend();
979  }
980  return Edge_Iterator<true>(ptr, edges_.cbegin(), this);
981  }
986 #ifndef DOXYGEN_SHOULD_SKIP_THIS
987  GL_ENABLE_IF_MATRIX
988 #endif
990  {
991  return Edge_Iterator<true>(edges_.cend(), edges_.cbegin(), this);
992  }
993 #ifndef DOXYGEN_SHOULD_SKIP_THIS
994  GL_ENABLE_IF_LIST
996  {
997  auto ptr = edges_[0].begin();
998  auto data1 = edges_.begin();
999  if (numEdges() > 0) {
1000  while (data1->size() == 0)
1001  {
1002  ++data1;
1003  }
1004  ptr = edges_[data1 - edges_.begin()].begin();
1005  }
1006  else
1007  {
1008  ptr = edges_.back().end();
1009  data1 = edges_.end()-1;
1010  }
1011  return Edge_Iterator<false>(ptr, data1, this);
1012  }
1013  GL_ENABLE_IF_LIST
1015  {
1016  return Edge_Iterator<false>(edges_.back().end(), edges_.end()-1, this);
1017  }
1018 
1019  GL_ENABLE_IF_LIST
1021  {
1022  auto ptr = edges_[0].cbegin();
1023  auto data1 = edges_.cbegin();
1024  if (numEdges() > 0) {
1025  while (data1->size() == 0)
1026  {
1027  ++data1;
1028  }
1029  ptr = edges_[data1 - edges_.cbegin()].cbegin();
1030  }
1031  else
1032  {
1033  ptr = edges_.back().cend();
1034  data1 = edges_.cend()-1;
1035  }
1036  return Edge_Iterator<true>(ptr, data1, this);
1037  }
1038  GL_ENABLE_IF_LIST
1040  {
1041  return Edge_Iterator<true>(edges_.back().cend(), edges_.cend()-1, this);
1042  }
1043 #endif
1044 
1045 
1055 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1056  GL_ENABLE_IF_LIST
1057 #endif
1058  idx_list_t getNeighbours(const idx_t &node) const
1059  {
1060  idx_list_t out;
1061  for (idx_t end = 0; end < numNodes(); ++end)
1062  {
1063  if (hasEdge(node, end))
1064  {
1065  out.push_back(end);
1066  }
1067  }
1068  return out;
1069  }
1070 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1071 
1074  GL_ENABLE_IF_MATRIX
1075  idx_list_t getNeighbours(const idx_t &node) const
1076  {
1077  idx_list_t out;
1078  for (idx_t end = 0; end < numNodes(); ++end)
1079  {
1080  if (hasEdge(node, end))
1081  out.push_back(end);
1082  }
1083  return out;
1084  }
1085 #endif
1086 
1093 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1094  GL_ENABLE_IF_LIST
1095 #endif
1096  idx_list_t getUnvisitedNeighbours(const idx_t &node, const std::vector<bool> &visited) const
1097  {
1098  idx_list_t out;
1099  for (idx_t end = 0; end < numNodes(); ++end)
1100  {
1101  if (hasEdge(node, end) && !visited[end])
1102  out.push_back(end);
1103  }
1104  return out;
1105  }
1106 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1107 
1110  GL_ENABLE_IF_MATRIX
1111  idx_list_t getUnvisitedNeighbours(const idx_t &node, const std::vector<bool> &visited) const
1112  {
1113  idx_list_t out;
1114  for (idx_t end = 0; end < numNodes(); ++end)
1115  {
1116  if (hasEdge(node, end) && !visited[end])
1117  out.push_back(end);
1118  }
1119  return out;
1120  }
1121 #endif
1122 
1128 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1129  GL_ENABLE_IF_LIST
1130 #endif
1132  {
1133  dest_vec_t out;
1134  for (const auto &edge : edges_[node])
1135  {
1136  out.push_back(std::make_pair(edge.dest(), edge.weight()));
1137  }
1138  return out;
1139  }
1140 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1141 
1144  GL_ENABLE_IF_MATRIX
1145  dest_vec_t getNeighbourWeights(const idx_t &node) const
1146  {
1147  dest_vec_t out;
1148  for (idx_t end = 0; end < numNodes(); ++end)
1149  {
1150  if (hasEdge(node, end))
1151  out.push_back(std::make_pair(end, getEdgeWeight(node, end)));
1152  }
1153  return out;
1154  }
1155 #endif
1156 
1162 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1163  GL_ENABLE_IF_LIST
1164 #endif
1165  dest_vec_t getUnvisitedNeighbourWeights(const idx_t &node, const visit_list_t &visited) const
1166  {
1167  dest_vec_t out;
1168  for (idx_t end = 0; end < numNodes(); ++end)
1169  {
1170  if (hasEdge(node, end) && !visited[end])
1171  out.push_back(std::make_pair(end, getEdgeWeight(node, end)));
1172  }
1173  return out;
1174  }
1175 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1176 
1179  GL_ENABLE_IF_MATRIX
1180  dest_vec_t getUnvisitedNeighbourWeights(const idx_t &node, const visit_list_t &visited) const
1181  {
1182  dest_vec_t out;
1183  for (idx_t end = 0; end < numNodes(); ++end)
1184  {
1185  if (hasEdge(node, end) && !visited[end])
1186  out.push_back(std::make_pair(end, getEdgeWeight(node, end)));
1187  }
1188  return out;
1189  }
1190 #endif
1191 
1199 #ifdef DOXYGEN_SHOULD_SKIP_THIS
1200  inline void updateNode(const idx_t& id, const std::string& label, const val_t& capacity, const gl::Color& color, const std::pair<float,float>& position)
1201 #endif
1202 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1203  /* Unspecialized template for error throwing */
1204  template <typename First, typename ... OtherArgs>
1205  inline void updateNode (const idx_t& id, First arg, const OtherArgs&... rest)
1206 #endif
1207  {
1208  throw std::runtime_error( std::string(__FILE__)
1209  + std::string(":")
1210  + std::to_string(__LINE__)
1211  + std::string(" in ")
1212  + std::string(__PRETTY_FUNCTION__)
1213  + std::string(": Unknown argument type."));
1214  }
1215 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1216  template <typename ... OtherArgs>
1217  inline void updateNode (const idx_t& id, const std::string& arg, const OtherArgs&... rest)
1218  {
1219  nodes_[id].label(arg);
1220  updateNode(id, rest...);
1221  }template <typename ... OtherArgs>
1222  inline void updateNode (const idx_t& id, const char* arg, const OtherArgs&... rest)
1223  {
1224  nodes_[id].label(arg);
1225  updateNode(id, rest...);
1226  }
1227  template <typename ... OtherArgs>
1228  inline void updateNode (const idx_t& id, const val_t& arg, const OtherArgs&... rest)
1229  {
1230  nodes_[id].capacity(arg);
1231  updateNode(id, rest...);
1232  }
1233  template <typename ... OtherArgs>
1234  inline void updateNode (const idx_t& id, const gl::Color& arg, const OtherArgs&... rest)
1235  {
1236  nodes_[id].color(arg);
1237  updateNode(id, rest...);
1238  }
1239  template <typename ... OtherArgs>
1240  inline void updateNode (const idx_t& id, const std::pair<float,float>& arg, const OtherArgs&... rest)
1241  {
1242  nodes_[id].position(arg);
1243  updateNode(id, rest...);
1244  }
1245  inline void updateNode (const idx_t& id)
1246  {
1247  }
1248 #endif
1249 
1255  inline std::string getNodeLabel(const idx_t &id) const
1256  {
1257  return nodes_[id].label();
1258  }
1264  inline val_t getNodeCapacity(const idx_t &id) const
1265  {
1266  return nodes_[id].capacity();
1267  }
1273  inline std::pair<float, float> getNodePosition(const idx_t &id) const
1274  {
1275  return nodes_[id].position();
1276  }
1282 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1283  GL_ENABLE_IF_LIST_UNDIRECTED
1284 #endif
1285  inline idx_t getNodeDegree(const idx_t &id) const
1286  {
1287  return edges_[id].size();
1288  }
1289 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1290 
1293  GL_ENABLE_IF_MATRIX_UNDIRECTED
1294  idx_t getNodeDegree(const idx_t &id) const
1295  {
1296  idx_t count = 0;
1297  for (idx_t end = 0; end < numNodes(); ++end)
1298  {
1299  if (hasEdge(id, end))
1300  ++count;
1301  }
1302  return count;
1303  }
1304 #endif
1305 
1309  idx_t getNodeInDegree(const idx_t &id) const
1310  {
1311  return nodes_[id].inDegree();
1312  }
1316  idx_t getNodeOutDegree(const idx_t &id) const
1317  {
1318  return nodes_[id].outDegree();
1319  }
1325  Color getNodeColor(const idx_t &id) const
1326  {
1327  return nodes_[id].color();
1328  }
1333  void readPositionsFromFile (const std::string& inFile)
1334  {
1335  std::ifstream is;
1336  is.open(inFile, std::ios::in);
1337  GL_ASSERT(is.is_open(),std::string(std::string("Error: failed to open ")+inFile))
1338 
1339  idx_t node;
1340  float x, y;
1341  while (is >> node >> x >> y)
1342  {
1343  updateNode(node,std::make_pair(x,y));
1344  }
1345  }
1346 
1352  {
1353  return NodeIterator(nodes_.begin());
1354  }
1360  {
1361  return NodeIterator(nodes_.end());
1362  }
1368  {
1369  return ConstNodeIterator(nodes_.cbegin());
1370  }
1376  {
1377  return ConstNodeIterator(nodes_.cend());
1378  }
1380 
1389  inline void checkRange(const idx_t &idx1) const
1390  {
1391  GL_ASSERT((0 <= idx1), (std::string("Negative index: ") + std::to_string(idx1) + std::string(" < 0")))
1392  GL_ASSERT((idx1 < numNodes()), ("Index " + std::to_string(idx1) + " is larger than the max: " + std::to_string(numNodes() - 1)))
1393  }
1394 
1400  inline void checkRange(const idx_t &idx1, const idx_t &idx2) const
1401  {
1402  checkRange(idx1);
1403  checkRange(idx2);
1404  }
1406 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1407  GL_ENABLE_IF_MATRIX
1408 #endif
1410  {
1411  return property_ == rhs.property_
1412  && edges_ == rhs.edges_
1413  && nodes_ == rhs.nodes_;
1414  }
1415 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1416  GL_ENABLE_IF_LIST
1418  {
1419  return property_ == rhs.property_
1420  && nodes_ == rhs.nodes_;
1421  // lists are checked more thoroughly, due to potential reordering of elements.
1422  if (edges_.size() != rhs.edges_.size()) return false;
1423  for (idx_t i = 0; i < numNodes(); ++i)
1424  {
1425  if (edges_[i].size() != rhs.edges_[i].size()) return false;
1426  }
1427  for (auto lhs_it = edge_cbegin(); lhs_it != edge_cend(); ++lhs_it)
1428  {
1429  auto rhs_it = std::find_if(rhs.edges_[lhs_it->source()].begin(), rhs.edges_[lhs_it->source()].end(),
1430  [&lhs_it](const Edge &node) {
1431  return node.dest() == lhs_it->dest()
1432  && node.weight() == lhs_it->weight()
1433  && node.color() == lhs_it->color();
1434  });
1435  if (rhs_it == rhs.edges_[lhs_it->source()].end())
1436  return false;
1437  }
1438  }
1439 #endif
1441  {
1442  return !operator==(rhs);
1443  }
1444 
1445 
1447  // Private member declarations
1449 
1450 private:
1454 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1455  // here using matrix
1456  GL_ENABLE_IF_MATRIX
1457 #endif
1458  void construct()
1459  {
1460  matrix_t matrix(numNodes() * numNodes(), Edge());
1461  for (idx_t i = 0; i < numNodes(); ++i)
1462  {
1463  for (idx_t j = 0; j < numNodes(); ++j)
1464  {
1465  matrix[i * numNodes() + j].source(i);
1466  matrix[i * numNodes() + j].dest(j);
1467  }
1468  }
1469  edges_ = matrix;
1470  std::vector<Node> nodes();
1471  for (idx_t i = 0; i < numNodes(); ++i)
1472  {
1473  nodes_.push_back(Node(i));
1474  }
1475  }
1476 
1477 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1478 
1481  GL_ENABLE_IF_LIST
1482  void construct()
1483  {
1484  rootList_t list(numNodes());
1485  edges_ = list;
1486  std::vector<Node> nodes();
1487  for (idx_t i = 0; i < numNodes(); ++i)
1488  {
1489  nodes_.push_back(Node(i));
1490  }
1491  }
1492 #endif
1493 
1494 };
1495 
1496 } /* namespace gl */
1497 
1498 #endif /* GL_GRAPH_HPP */
Graph(const idx_t &numNodes=0, const std::string &label="Graph")
Construct Graph from node count and label.
Definition: Graph.hpp:272
void setEdge(const Edge &edge)
Adds an edge directly from an Edge object.
Definition: Graph.hpp:581
operator*() const
Const dereference iterator.
Definition: Graph.hpp:182
self_t operator++()
Move Iterator to next edge (pre-increment)
Definition: Graph.hpp:115
SCALAR val_t
Value type.
Definition: Graph.hpp:43
ConstEdgeIterator edge_cbegin() const
ConstEdgeIterator to the first edge.
Definition: Graph.hpp:967
bool operator==(const Graph< SCALAR, gl::Matrix, DIRECTION > &rhs)
Definition: Graph.hpp:1409
operator*()
Non-const dereference iterator.
Definition: Graph.hpp:194
idx_t numNodes() const
Gets the number of nodes in the graph.
std::string label() const
Gets the label of the graph.
Stores an RGBA Color.
Definition: Color.hpp:21
std::deque< info_t > BFS_queue_t
BFS type.
Definition: Graph.hpp:52
void updateEdge(const idx_t &start, const idx_t &end, const val_t &weight, const gl::Color &color)
Updates edge properties. Parameters "start" & "end" mandatory, the rest optional. ...
Definition: Graph.hpp:669
dest_vec_t getNeighbourWeights(const idx_t &node) const
Returns a list of endpoints + edge weights of outgoing edges from start.
Definition: Graph.hpp:1131
bool hasCycle() const
Checks whether the given undirected graph containes cycles using an iterative BFS approach...
Definition: Graph.hpp:465
Color getEdgeColor(const idx_t &src, const idx_t &dest) const
Returns the color of the edge from src to dest.
Definition: Graph.hpp:900
operator->() const
Get underlying edge.
Definition: Graph.hpp:206
std::conditional_t< std::is_same_v< STORAGE_KIND, Matrix >, matrix_iterator_t, rootList_iterator_t > data1_
[Matrix] Iterator to first element, [List] Iterator over the rootList
Definition: Graph.hpp:246
self_t operator=(const self_t &rhs)
Construct from Assignment.
Definition: Graph.hpp:237
std::vector< idx_t > idx_list_t
Index List type.
Definition: Graph.hpp:48
gl::index_type idx_t
Index type.
Definition: Graph.hpp:44
idx_list_t getNeighbours(const idx_t &node) const
Returns a list of all endpoints of outgoing edges from start.
Definition: Graph.hpp:1058
Represents a Node in a Graph.
Definition: Node.hpp:18
Color color() const
Gets the edge's color.
Definition: Edge.hpp:208
void setEdge(const idx_t &start, const idx_t &end, const val_t &weight=1, const Color &color=Color())
Sets an edge including start/end points and weight.
Definition: Graph.hpp:510
Property property_
Stores various properties of the Graph.
Definition: Graph.hpp:257
val_t getNodeCapacity(const idx_t &id) const
Finds the flow capacity of the given node.
Definition: Graph.hpp:1264
bool operator!=(const self_t &rhs)
Check if not equal.
Definition: Graph.hpp:231
Stores and implements a Graph.
Definition: Graph.hpp:39
std::forward_iterator_tag iterator_category
Iterator category.
Definition: Graph.hpp:71
idx_t getNodeOutDegree(const idx_t &id) const
Gets the in-degree of a node (i.e. count of all outgoing edges).
Definition: Graph.hpp:1316
gl::Graph< SCALAR, gl::List, DIRECTION > toList() const
Outputs a graph in Adjacency List storage format with the same edges as this. This function only exis...
Definition: Graph.hpp:371
std::ptrdiff_t difference_type
Pointer Difference type.
Definition: Graph.hpp:72
bool hasEdge(const idx_t &start, const idx_t &end) const
Checks whether an edge exists from start to end.
Definition: Graph.hpp:818
ConstNodeIterator node_cbegin() const
ConstNodeIterator to the first node.
Definition: Graph.hpp:1367
std::conditional_t< IsConst, const Edge &, Edge & > reference
Edge reference type.
Definition: Graph.hpp:69
gl::Graph< SCALAR, gl::Matrix, DIRECTION > toMatrix() const
Outputs a graph in Adjacency Matrix storage format with the same edges as this. This function only ex...
Definition: Graph.hpp:332
Edge_Iterator< false > EdgeIterator
Edge iterator type.
Definition: Graph.hpp:251
std::conditional_t< IsConst, typename rootList_t::const_iterator, typename rootList_t::iterator > rootList_iterator_t
Definition: Graph.hpp:76
typename std::vector< Node >::const_iterator ConstNodeIterator
Node const_iterator type.
Definition: Graph.hpp:254
container_pointer_t data2_
Pointer to owner Graph.
Definition: Graph.hpp:247
ConstEdgeIterator edge_cend() const
ConstEdgeIterator to the last edge.
Definition: Graph.hpp:989
bool operator==(const self_t &rhs)
Check if equal.
Definition: Graph.hpp:226
idx_t numEdges() const
Returns the number of edges currently in the graph.
Definition: Graph.hpp:415
std::string getGraphLabel() const
Returns the label of the graph.
Definition: Graph.hpp:390
bool isDirected() const
Returns true if the graph is directed, false if not.
Definition: Graph.hpp:426
#define GL_ASSERT(EXPR, ERROR_MSG)
Custom assert that supports attaching a message.
Definition: gl_assert.hpp:14
std::conditional_t< IsConst, typename nodeList_t::const_iterator, typename nodeList_t::iterator > list_iterator_t
Definition: Graph.hpp:77
void setGraphLabel(const std::string &label)
Changes the label of the graph.
Definition: Graph.hpp:398
idx_t getNodeInDegree(const idx_t &id) const
Gets the in-degree of a node (i.e. count of all incoming edges).
Definition: Graph.hpp:1309
Graph::idx_list_t degrees(const Graph &graph)
Computes the out-degrees of all nodes in a graph.
Definition: Degrees.hpp:16
idx_t numNodes() const
Returns the number of nodes currently in the graph.
Definition: Graph.hpp:406
Edge_Iterator(matrix_iterator_t ptr, matrix_iterator_t data1, container_pointer_t data2)
Construct EdgeIterator, only used with Matrix Representation.
Definition: Graph.hpp:92
self_t operator++(int dummy)
Move Iterator to next edge (post-increment)
Definition: Graph.hpp:131
std::conditional_t< IsConst, typename matrix_t::const_iterator, typename matrix_t::iterator > matrix_iterator_t
Definition: Graph.hpp:75
std::size_t index_type
Definition: gl_base.hpp:18
std::vector< Node > nodes_
Stores information about all nodes in the Graph.
Definition: Graph.hpp:258
void checkRange(const idx_t &idx1, const idx_t &idx2) const
Two indices ("edge") that get range checked.
Definition: Graph.hpp:1400
gl::Node< val_t > Node
Node type.
Definition: Graph.hpp:46
void delEdge(const idx_t &start, const idx_t &end)
Deletes the edge going from start to end.
Definition: Graph.hpp:741
std::list< Edge > nodeList_t
ListNode Representation type.
Definition: Graph.hpp:57
Edge_Iterator()
Default constructor.
Definition: Graph.hpp:82
Color getNodeColor(const idx_t &id) const
Returns the color of a node.
Definition: Graph.hpp:1325
Edge_Iterator(list_iterator_t ptr, rootList_iterator_t data1, container_pointer_t data2)
Construct EdgeIterator, only used with List Representation.
Definition: Graph.hpp:104
dest_vec_t getUnvisitedNeighbourWeights(const idx_t &node, const visit_list_t &visited) const
Returns a list of endpoints + edge weights of unvisited outgoing edges from start.
Definition: Graph.hpp:1165
void numEdgesIncrement(const idx_t &increment=1)
Increments the number of edges in the graph.
std::list< idx_t > ordered_list_t
Ordered List type.
Definition: Graph.hpp:49
idx_t source() const
Gets the index of the source of the edge.
Definition: Edge.hpp:175
gl::Edge< val_t > Edge
Edge type.
Definition: Graph.hpp:45
Represents an Edge in a Graph.
Definition: Edge.hpp:18
std::conditional_t< IsConst, const Edge *, Edge * > pointer
Edge pointer type.
Definition: Graph.hpp:70
operator->()
Get underlying edge.
Definition: Graph.hpp:218
EdgeIterator edge_end()
EdgeIterator to behind the last edge.
Definition: Graph.hpp:956
std::vector< nodeList_t > rootList_t
ListRoot Representation type.
Definition: Graph.hpp:58
ConstNodeIterator node_cend() const
ConstNodeIterator to behind the last node.
Definition: Graph.hpp:1375
std::string getNodeLabel(const idx_t &id) const
Finds the label of the given node.
Definition: Graph.hpp:1255
void readPositionsFromFile(const std::string &inFile)
Updates node positions in the format "<id> <x-coord> <y-coord>" found in inFile.
Definition: Graph.hpp:1333
Graph(const std::string &degreeSeq, const std::string &label="Simple Undirected Graph")
Construct Graph from node count and label.
Definition: Graph.hpp:281
std::vector< bool > visit_list_t
Visited-List type.
Definition: Graph.hpp:50
void setEdgesFromMatrixFile(const std::string &inFile)
Adds edges found in inFile to the graph.
Definition: Graph.hpp:625
bool isUndirected() const
Returns true if the graph is undirected, false if not.
Definition: Graph.hpp:447
NodeIterator node_begin()
NodeIterator to the first node.
Definition: Graph.hpp:1351
idx_t dest() const
Gets the index of the destination of the edge.
Definition: Edge.hpp:186
void construct()
Auxiliary function. Creates an empty Graph using the deduced storage format.
Definition: Graph.hpp:1458
bool havelHakimi(std::deque< gl::index_type > degrees)
Uses the Havel-Hakimi algorithm to determine whether a given degree sequence is graphic.
Definition: HavelHakimi.hpp:16
void checkRange(const idx_t &idx1) const
Only one index that gets range checked.
Definition: Graph.hpp:1389
std::vector< std::pair< idx_t, val_t >> dest_vec_t
Destination-Vector type.
Definition: Graph.hpp:47
idx_t getNodeDegree(const idx_t &id) const
Finds the degree of the given node (i.e. count of all in- & outgoing edges).
Definition: Graph.hpp:1285
std::vector< Edge > matrix_t
Matrix Representation type.
Definition: Graph.hpp:56
idx_list_t getUnvisitedNeighbours(const idx_t &node, const std::vector< bool > &visited) const
Returns a list of endpoints + edge weights of outgoing edges from start.
Definition: Graph.hpp:1096
std::stack< idx_t > DFS_queue_t
DFS type.
Definition: Graph.hpp:53
Edge_Iterator class. Used to iterate over all Edges in the Graph
Definition: Graph.hpp:65
Edge_Iterator self_t
EdgeIterator type.
Definition: Graph.hpp:73
std::conditional_t< std::is_same_v< STORAGE_KIND, Matrix >, matrix_t, rootList_t > edges_
Stores information about all edges in the Graph.
Definition: Graph.hpp:259
bool operator!=(const Graph< SCALAR, STORAGE_KIND, DIRECTION > &rhs)
Definition: Graph.hpp:1440
idx_t numEdges() const
Gets the number of edges in the graph.
typename std::vector< Node >::iterator NodeIterator
Node iterator type.
Definition: Graph.hpp:253
EdgeIterator edge_begin()
EdgeIterator to the first edge.
Definition: Graph.hpp:934
~Graph()
Definition: Graph.hpp:317
std::pair< float, float > getNodePosition(const idx_t &id) const
Finds the position of the given node.
Definition: Graph.hpp:1273
void numEdgesDecrement(const idx_t &decrement=1)
Decrements the number of edges in the graph.
val_t getEdgeWeight(const idx_t &start, const idx_t &end) const
Finds the weight of the edge going from start to end.
Definition: Graph.hpp:858
Stores the properties of a Graph.
Definition: Property.hpp:14
NodeIterator node_end()
NodeIterator to behind the last node.
Definition: Graph.hpp:1359
std::conditional_t< IsConst, const Graph< SCALAR, STORAGE_KIND, DIRECTION > *, Graph< SCALAR, STORAGE_KIND, DIRECTION > * > container_pointer_t
Definition: Graph.hpp:78
Graph(const Property &property)
Construct Graph from property.
Definition: Graph.hpp:313
std::conditional_t< std::is_same_v< STORAGE_KIND, Matrix >, matrix_iterator_t, list_iterator_t > ptr_
[Matrix] Iterator to an element, [List] Iterator over the nodeLists
Definition: Graph.hpp:245
void updateNode(const idx_t &id, const std::string &label, const val_t &capacity, const gl::Color &color, const std::pair< float, float > &position)
Updates node properties. Parameter "id" mandatory, the rest optional.
Definition: Graph.hpp:1200
Edge_Iterator< true > ConstEdgeIterator
Edge const_iterator type.
Definition: Graph.hpp:252
val_t weight() const
Gets the weight of the edge.
Definition: Edge.hpp:197
void setEdgesFromListFile(const std::string &inFile)
Adds edges found in inFile to the graph.
Definition: Graph.hpp:597