OpenFPM_pdata  4.1.0 Project that contain the implementation of distributed structures
map_graph.hpp
1 /*
2  * map_graph.hpp
3  *
4  * Created on: Nov 21, 2014
5  * Author: Pietro Incardona
6  *
7  *
8  * Graph structure that store a CSR graph format
9  *
10  * This Graph format is suppose to have a list of vertex that store an index x that indicate where
11  * in the adjacency list we have the list of all the neighborhood vertex, plus an adjacency list
12  * that store all the neighborhood for each vertex:
13  *
14  * In reality inside Graph_CSR
15  *
16  * VertexList store the Vertex index that indicate the end of the neighborhood list,
17  * the start is indicated by i * v_slot (id of the vertex, v_slot maximum number of
18  * neighborhood for a vertex)
19  *
20  * EdgeList store for each vertex at position i * v_slot (id of the vertex, v_slot maximum
21  * number of neighborhood for a vertex) the list of all the neighborhood of the vertex i
22  *
23  * Example
24  *
25  * Suppose an undirected graph of 4 vertex
26  *
27  * 1 -> 2 3 4
28  * 2 -> 1
29  * 3 -> 4 1
30  * 4 -> 1 3
31  *
32  * suppose that v_slot is 4 ( each vertex has less tha 4 neighborhood )
33  *
34  * we will have
35  *
36  * Vertex list 3 5 10 14
37  * Edge list 2 3 4 0 1 0 0 0 4 1 0 0 1 3 0 0
38  *
39  * Vertex properties and edge properties are stored in a separate structure
40  *
41  */
42
43 #ifndef MAP_GRAPH_HPP_
44 #define MAP_GRAPH_HPP_
45
46 #include "Vector/map_vector.hpp"
47 #include <unordered_map>
48 #ifdef METIS_GP
49 #include "metis_util.hpp"
50 #endif
51
52 #define NO_EDGE -1
53
57 class no_edge
58 {
59 public:
60
62  typedef boost::fusion::vector<> type;
63
66
68  static const unsigned int max_prop = 0;
69
70  static inline bool noPointers()
71  {
72  return true;
73  }
74 };
75
76 template<typename V, typename E,
77  typename Memory,
78  template <typename> class layout_v_base,
79  template <typename> class layout_e_base,
80  typename grow_p>
81 class Graph_CSR;
82
90 class e_map
91 {
92 public:
93  typedef boost::fusion::vector<size_t, size_t> type;
94
95  type data;
96
97  static const unsigned int vid = 0;
98  static const unsigned int eid = 1;
99  static const unsigned int max_prop = 2;
100
101  // Setter method
102
103  inline void setvid(size_t vid_)
104  {
105  boost::fusion::at_c<0>(data) = vid_;
106  }
107
108  inline void seteid(size_t eid_)
109  {
110  boost::fusion::at_c<1>(data) = eid_;
111  }
112
113  static inline bool noPointers()
114  {
115  return true;
116  }
117 };
118
119 class edge_key
120 {
121 public:
122
124  size_t pos;
125
127  size_t pos_e;
128
134  void begin()
135  {
136  pos = 0;
137  pos_e = 0;
138  }
139
145  size_t & source()
146  {
147  return pos;
148  }
149
156  size_t & target_t()
157  {
158  return pos_e;
159  }
160 };
161
166 template<typename Graph>
168 {
170  const Graph & g;
171
172  // Actual edge key
173  edge_key ek;
174
175 public:
176
183  edge_iterator(const Graph & g) :
184  g(g)
185  {
186  ek.begin();
187  }
188
196  {
197  // Check if reach the end of the edge list
198  if (ek.pos_e + 1 >= g.getNChilds(ek.pos))
199  {
200  // increment the node position and reset
201  ek.pos++;
202  ek.pos_e = 0;
203
204  // skip every vertex without edges
205  while (ek.pos < g.getNVertex() && g.getNChilds(ek.pos) == 0)
206  {
207  ek.pos++;
208  }
209  }
210  else
211  {
212  // increment the edge position
213  ek.pos_e++;
214  }
215
216  return *this;
217  }
218
227  bool isNext()
228  {
229  if (ek.pos < g.getNVertex())
230  {
232
233  return true;
234  }
235
237  return false;
238  }
239
248  {
249  return ek;
250  }
251
257  size_t source()
258  {
259  return ek.pos;
260  }
261
267  size_t target()
268  {
269  return g.getChild(ek.pos, ek.pos_e);
270  }
271 };
272
299 template<typename V, typename E = no_edge,
300  typename Memory = HeapMemory,
301  template<typename> class layout_v_base = memory_traits_lin,
302  template<typename> class layout_e_base = memory_traits_lin,
303  typename grow_p = openfpm::grow_policy_double>
304 class Graph_CSR
305 {
307  size_t v_slot;
308
311
314
317
320
323
335  template<typename CheckPolicy = NoCheck> inline size_t addEdge_(size_t v1, size_t v2)
336  {
337  // If v1 and v2 does not satisfy some criteria return
338  if (CheckPolicy::valid(v1, v.size()) == false)
339  return (size_t)NO_EDGE;
340  if (CheckPolicy::valid(v2, v.size()) == false)
341  return (size_t)NO_EDGE;
342
343  // get the number of adjacent vertex
344  size_t id_x_end = v_l.template get<0>(v1);
345
346 #ifdef SE_CLASS1
347  // Check that v1 and v2 exist
348
349  if (v1 >= v.size() || v2 >= v.size())
350  {
351  std::cout << "Warning graph: creating an edge between vertex that does not exist" << std::endl;
352  }
353
354  // Check that the edge does not already exist
355
356  for (size_t s = 0; s < id_x_end; s++)
357  {
358  if (e_l.template get<e_map::vid>(v1 * v_slot + s) == v2)
359  {
360  std::cerr << "Error graph: the edge already exist" << std::endl;
361  }
362  }
363 #endif
364
365  // Check if there is space for another edge
366
367  if (id_x_end >= v_slot)
368  {
369  // Unfortunately there is not space we need to reallocate memory
370  // Reallocate with double slot
371
372  // Create an new Graph
373
374  Graph_CSR<V, E> g_new(2 * v_slot, v.size());
375
376  // Copy the graph
377
378  for (size_t i = 0; i < v.size(); i++)
379  {
380  // copy the property from the old graph
381
382  g_new.v.set(i, v, 2 * i);
383  }
384
385  // swap the new graph with the old one
386
387  swap(g_new);
388  }
389
390  // Here we are sure than v and e has enough slots to store a new edge
391  // Check that e_l has enough space to store new edge
392  // should be always e.size == e_l.size
393
394  if (id_x_end >= e_l.size())
395  {
396  // Resize the basic structure
397
398  e_l.resize(v.size() * v_slot);
399  }
400
401  // add in e_l the adjacent vertex for v1 and fill the edge id
402  e_l.template get<e_map::vid>(v1 * v_slot + id_x_end) = v2;
403  e_l.template get<e_map::eid>(v1 * v_slot + id_x_end) = e.size();
404
405  // add an empty edge
406  e.resize(e.size() + 1);
407
408  // Increment the ending point
409  ++v_l.template get<0>(v1);
410
411  // return the created edge
412  return e.size() - 1;
413  }
414
415 public:
416
418  typedef V V_type;
419
421  typedef E E_type;
422
425
428
439  {
440  bool ret = true;
441
442  // Check if they match
443
444  ret &= (v_slot == g.v_slot);
445  ret &= (v == g.v);
446  ret &= (v_l == g.v_l);
447  ret &= (e == g.e);
448  ret &= (e_l == g.e_l);
449
450  return ret;
451  }
452
453
460  {
462
463  dup.v_slot = v_slot;
464
466
467  dup.v.swap(v.duplicate());
468  dup.v_l.swap(v_l.duplicate());
469  dup.e.swap(e.duplicate());
470  dup.e_l.swap(e_l.duplicate());
471  dup.e_invalid.swap(e_invalid.duplicate());
472
473  return dup;
474  }
475
482  :Graph_CSR(0, 16)
483  {
484  }
485
493  Graph_CSR(size_t n_vertex) :
494  Graph_CSR(n_vertex, 16)
495  {
496  }
497
506  Graph_CSR(size_t n_vertex, size_t n_slot)
507  :v_slot(n_slot)
508  {
510  v.resize(n_vertex);
512  v_l.resize(n_vertex);
514  v_l.fill(0);
516  e_invalid.resize(1);
517  }
518
525  {
526  this->operator=(g);
527  }
528
537  {
538  size_t vs_tmp = v_slot;
539  v_slot = g.v_slot;
540  g.v_slot = vs_tmp;
541  swap(g);
542
543  return *this;
544  }
545
552  {
553  swap(g.duplicate());
554
555  v_slot = g.v_slot;
556
557  return *this;
558  }
559
570  template<unsigned int i> auto vertex_p(size_t id) -> decltype( v.template get<i>(id) )
571  {
572  return v.template get<i>(id);
573  }
574
584  template<unsigned int i> auto vertex_p(grid_key_dx<1> id) -> decltype( v.template get<i>(id) )
585  {
586  return v.template get<i>(id);
587  }
588
596  auto vertex(size_t id) -> decltype( v.get(id) )
597  {
598  return v.get(id);
599  }
600
608  auto vertex(grid_key_dx<1> id) -> decltype( v.get(id.get(0)) )
609  {
610  return v.get(id.get(0));
611  }
612
620  auto vertex(openfpm::vector_key_iterator id) -> decltype( v.get(0) )
621  {
622  return v.get(id.get());
623  }
624
632  auto vertex(size_t id) const -> const decltype( v.get(id) )
633  {
634  return v.get(id);
635  }
636
646  auto vertex(grid_key_dx<1> id) const -> const decltype( v.get(id.get(0)) )
647  {
648  return v.get(id.get(0));
649  }
650
658  auto vertex(openfpm::vector_key_iterator id) const -> const decltype( v.get(0) )
659  {
660  return v.get(id.get());
661  }
662
668  void clear()
669  {
670  v.clear();
671  e.clear();
672  v_l.clear();
673  e_l.clear();
674  e_invalid.clear();
675  }
676
677
683  void destroy()
684  {
685  v.clear();
686  v.shrink_to_fit();
687  e.clear();
688  e.shrink_to_fit();
689  v_l.clear();
690  v_l.shrink_to_fit();
691  e_l.clear();
692  e_l.shrink_to_fit();
693  e_invalid.clear();
694  e_invalid.shrink_to_fit();
695  }
696
705  template<unsigned int i> auto edge_p(grid_key_dx<1> id) -> decltype ( e.template get<i>(id) )
706  {
707  return e.template get<i>(id);
708  }
709
718  template<unsigned int i> auto edge_p(size_t id) -> decltype ( e.template get<i>(id) )
719  {
720  return e.template get<i>(id);
721  }
722
723
731  auto edge(edge_key ek) const -> const decltype ( e.get(0) )
732  {
733  return e.get(e_l.template get<e_map::eid>(ek.pos * v_slot + ek.pos_e));
734  }
735
743  auto edge(size_t id) const -> const decltype ( e.get(id) )
744  {
745  return e.get(id);
746  }
747
755  auto edge(grid_key_dx<1> id) const -> const decltype ( e.get(id.get(0)) )
756  {
757  return e.get(id.get(0));
758  }
759
768  inline size_t getNChilds(size_t c) const
769  {
770  // Get the number of childs
771
772  return v_l.template get<0>(c);
773  }
774
782  inline size_t getNChilds(typename openfpm::vector<V, Memory, layout_v_base, grow_p, openfpm::vect_isel<V>::value>::iterator_key & c)
783  {
784  // Get the number of childs
785
786  return v_l.template get<0>(c.get());
787  }
788
797  inline auto getChildEdge(size_t v, size_t v_e) -> decltype(e.get(0))
798  {
799  // Get the edge id
800  return e.get(e_l.template get<e_map::eid>(v * v_slot + v_e));
801  }
802
812  inline size_t getChild(size_t v, size_t i) const
813  {
814 #ifdef SE_CLASS1
815  if (i >= v_l.template get<0>(v))
816  {
817  std::cerr << "Error " << __FILE__ << " line: " << __LINE__ << " vertex " << v << " does not have edge " << i << std::endl;
818  }
819
820  if (i >= v_l.template get<0>(v))
821  {
822  std::cerr << "Error " << __FILE__ << " " << __LINE__ << " vertex " << v << " does not have edge "<< i << std::endl;
823  }
824 #endif
825  // Get the target vertex id
826  return e_l.template get<e_map::vid>(v * v_slot + i);
827  }
828
838  {
839 #ifdef SE_CLASS1
840  if (i >= v_l.template get<0>(v.get()))
841  {
842  std::cerr << "Error " << __FILE__ << " line: " << __LINE__ << " vertex " << v.get() << " does not have edge " << i << std::endl;
843  }
844
845  if (e.size() <= e_l.template get<e_map::eid>(v.get() * v_slot + i))
846  {
847  std::cerr << "Error " << __FILE__ << " " << __LINE__ << " vertex " << v.get() << " does not have edge "<< i << std::endl;
848  }
849 #endif
850
851  // Get the edge id
852  return e_l.template get<e_map::vid>(v.get() * v_slot + i);
853  }
854
860  inline void addVertex(const V & vrt)
861  {
862
863  v.add(vrt);
864
865  // Set the number of adjacent vertex for this vertex to 0
866
867  v_l.add(0ul);
868
869  // Add a slot for the vertex adjacency list
870
871  e_l.resize(e_l.size() + v_slot);
872  }
873
877  inline void addVertex()
878  {
879
880  v.add();
881
882  // Set the number of adjacent vertex for this vertex to 0
883
884  v_l.add(0ul);
885
886  // Add a slot for the vertex adjacency list
887
888  e_l.resize(e_l.size() + v_slot);
889  }
890
900  template<typename CheckPolicy = NoCheck> inline auto addEdge(size_t v1, size_t v2, const E & ed) -> decltype(e.get(0))
901  {
902  long int id_x_end = addEdge_<CheckPolicy>(v1, v2);
903
904  // If there is not edge return an invalid edge, is a kind of stub object
905  if (id_x_end == NO_EDGE)
906  return e_invalid.get(0);
907
908  // add in e_l the edge properties
909  e.set(id_x_end, ed);
910
911  return e.get(id_x_end);
912  }
913
924  template<typename CheckPolicy = NoCheck> inline auto addEdge(size_t v1, size_t v2) -> decltype(e.get(0))
925  {
927  long int id_x_end = addEdge_<CheckPolicy>(v1, v2);
928  // If there is not edge return an invalid edge, is a kind of stub object
929  if (id_x_end == NO_EDGE)
930  return e_invalid.get(0);
931
933  return e.get(id_x_end);
934  }
935
952  template<typename CheckPolicy = NoCheck, int sgid, int dgid> inline auto addEdge(size_t v1, size_t v2, size_t srcgid, size_t dstgid) -> decltype(e.get(0))
953  {
955  long int id_x_end = addEdge_<CheckPolicy>(v1, v2);
957  if (id_x_end == NO_EDGE)
958  return e_invalid.get(0);
959
961  e.get(id_x_end).template get<sgid>() = srcgid;
962  e.get(id_x_end).template get<dgid>() = dstgid;
963
965  return e.get(id_x_end);
966  }
967
976  inline void swap(Graph_CSR<V, E> & g)
977  {
978  // switch the memory
979
980  v.swap(g.v);
981  e.swap(g.e);
982  v_l.swap(g.v_l);
983  e_l.swap(g.e_l);
984  e_invalid.swap(g.e_invalid);
985
986  size_t v_slot_tmp = g.v_slot;
987  g.v_slot = v_slot;
988  v_slot = v_slot_tmp;
989  }
990
998  inline void swap(Graph_CSR<V, E> && g)
999  {
1000  // switch the memory
1001
1002  v.swap(g.v);
1003  e.swap(g.e);
1004  v_l.swap(g.v_l);
1005  e_l.swap(g.e_l);
1006  e_invalid.swap(g.e_invalid);
1007
1008  size_t v_slot_tmp = g.v_slot;
1009  g.v_slot = v_slot;
1010  v_slot = v_slot_tmp;
1011  }
1012
1021  inline auto getVertexIterator() const -> decltype(v.getIterator())
1022  {
1023  return v.getIterator();
1024  }
1025
1035  {
1037  }
1038
1045  inline size_t getNVertex() const
1046  {
1047  return v.size();
1048  }
1049
1056  inline size_t getNEdge() const
1057  {
1058  return e.size();
1059  }
1060 };
1061
1086 template<typename V, typename E>
1087 class Graph_CSR_s: public Graph_CSR<V, E>
1088 {
1089
1090 };
1091
1092 #endif /* MAP_GRAPH_HPP_ */
openfpm::vector< size_t, Memory, layout_v_base, grow_p, openfpm::vect_isel< size_t >::value > v_l
Structure that store the number of adjacent vertex in e_l for each vertex.
Definition: map_graph.hpp:313
static const unsigned int max_prop
no properties
Definition: map_graph.hpp:68
void begin()
Reset the counter.
Definition: map_graph.hpp:134
auto addEdge(size_t v1, size_t v2, size_t srcgid, size_t dstgid) -> decltype(e.get(0))
add edge on the graph and fill source and destination informations
Definition: map_graph.hpp:952
Graph_CSR< V, E, Memory > & operator=(const Graph_CSR< V, E, Memory > &g)
Definition: map_graph.hpp:551
const Graph & g
Graph.
Definition: map_graph.hpp:170
Transform the boost::fusion::vector into memory specification (memory_traits)
auto vertex(size_t id) -> decltype(v.get(id))
Function to access the vertex.
Definition: map_graph.hpp:596
void clear()
operator to clear the whole graph
Definition: map_graph.hpp:668
Graph_CSR(size_t n_vertex)
Constructor.
Definition: map_graph.hpp:493
Grow policy define how the vector should grow every time we exceed the size.
grid_key_dx is the key to access any element in the grid
Definition: grid_key.hpp:18
auto edge(size_t id) const -> const decltype(e.get(id))
operator to access the edge
Definition: map_graph.hpp:743
size_t getNChilds(typename openfpm::vector< V, Memory, layout_v_base, grow_p, openfpm::vect_isel< V >::value >::iterator_key &c)
Return the number of childs of a vertex.
Definition: map_graph.hpp:782
size_t getChild(typename openfpm::vector< V, Memory, layout_v_base, grow_p >::iterator_key &v, size_t i)
Get the child edge.
Definition: map_graph.hpp:837
auto edge_p(grid_key_dx< 1 > id) -> decltype(e.template get< i >(id))
Access the edge.
Definition: map_graph.hpp:705
bool isNext()
Check if there is the next element.
Definition: map_graph.hpp:227
void swap(Graph_CSR< V, E > &&g)
swap the memory of g with this graph
Definition: map_graph.hpp:998
openfpm::vector< V, Memory, layout_v_base, grow_p, openfpm::vect_isel< V >::value > v
Structure that store the vertex properties.
Definition: map_graph.hpp:310
edge_iterator< Graph_CSR< V, E, Memory > > getEdgeIterator() const
Get the vertex iterator.
Definition: map_graph.hpp:1034
edge_iterator & operator++()
Get the next element.
Definition: map_graph.hpp:195
Graph_CSR< V, E, Memory > & operator=(Graph_CSR< V, E, Memory > &&g)
Definition: map_graph.hpp:536
size_t getChild(size_t v, size_t i) const
Get the child vertex id.
Definition: map_graph.hpp:812
size_t addEdge_(size_t v1, size_t v2)
add edge on the graph
Definition: map_graph.hpp:335
auto vertex(size_t id) const -> const decltype(v.get(id))
Function to access the vertex.
Definition: map_graph.hpp:632
edge_iterator(const Graph &g)
Constructor.
Definition: map_graph.hpp:183
size_t pos
Actual source node.
Definition: map_graph.hpp:124
Graph edge iterator.
Definition: map_graph.hpp:167
size_t size()
Stub size.
Definition: map_vector.hpp:211
size_t v_slot
number of slot per vertex
Definition: map_graph.hpp:307
size_t source()
Return the source node.
Definition: map_graph.hpp:257
V V_type
Vertex typedef.
Definition: map_graph.hpp:418
auto vertex_p(size_t id) -> decltype(v.template get< i >(id))
operator to access the vertex
Definition: map_graph.hpp:570
size_t pos_e
Actual target node.
Definition: map_graph.hpp:127
auto vertex(openfpm::vector_key_iterator id) const -> const decltype(v.get(0))
operator to access the vertex
Definition: map_graph.hpp:658
This class allocate, and destroy CPU memory.
Definition: HeapMemory.hpp:39
Graph_CSR()
Constructor.
Definition: map_graph.hpp:481
auto getVertexIterator() const -> decltype(v.getIterator())
Get the vertex iterator.
Definition: map_graph.hpp:1021
openfpm::vector< e_map, Memory, layout_e_base, grow_p, openfpm::vect_isel< e_map >::value > e_l
Structure that store for each vertex the adjacent the vertex id and edge id (for property into e)
Definition: map_graph.hpp:319
size_t target()
Return the target node.
Definition: map_graph.hpp:267
auto vertex(grid_key_dx< 1 > id) const -> const decltype(v.get(id.get(0)))
Fuction to access the vertex.
Definition: map_graph.hpp:646
auto edge(grid_key_dx< 1 > id) const -> const decltype(e.get(id.get(0)))
Access the edge.
Definition: map_graph.hpp:755
auto edge(edge_key ek) const -> const decltype(e.get(0))
operator to access the edge
Definition: map_graph.hpp:731
openfpm::vector< V, Memory, layout_v_base, grow_p, openfpm::vect_isel< V >::value >::container V_container
Object container for the vertex, for example can be encap<...> (map_grid or openfpm::vector)
Definition: map_graph.hpp:424
size_t & target_t()
Return the target of this edge.
Definition: map_graph.hpp:156
auto addEdge(size_t v1, size_t v2) -> decltype(e.get(0))
add edge on the graph
Definition: map_graph.hpp:924
It analyze the type given and it select correctly the implementation for vector.
Definition: vect_isel.hpp:36
Graph_CSR< V, E, Memory, layout_v_base, layout_e_base, grow_p > duplicate() const
It duplicate the graph.
Definition: map_graph.hpp:459
class with no edge
Definition: map_graph.hpp:57
edge_key get()
Get the actual key.
Definition: map_graph.hpp:247
Structure that store a graph in CSR format or basically in compressed adjacency matrix format.
Definition: map_graph.hpp:81
type data
empty edge
Definition: map_graph.hpp:65
size_t getNVertex() const
Return the number of the vertex.
Definition: map_graph.hpp:1045
Graph_CSR(Graph_CSR< V, E, Memory > &&g)
Copy constructor.
Definition: map_graph.hpp:524
auto edge_p(size_t id) -> decltype(e.template get< i >(id))
Access the edge.
Definition: map_graph.hpp:718
E E_type
Edge typedef.
Definition: map_graph.hpp:421
void addVertex(const V &vrt)
add vertex
Definition: map_graph.hpp:860
void addVertex()
add an empty vertex
Definition: map_graph.hpp:877
size_t getNChilds(size_t c) const
Return the number of childs of a vertex.
Definition: map_graph.hpp:768
auto vertex_p(grid_key_dx< 1 > id) -> decltype(v.template get< i >(id))
Access the vertex.
Definition: map_graph.hpp:584
auto vertex(grid_key_dx< 1 > id) -> decltype(v.get(id.get(0)))
Function to access the vertex.
Definition: map_graph.hpp:608
openfpm::vector< E, Memory, layout_e_base, grow_p, openfpm::vect_isel< E >::value >::container E_container
Object container for the edge, for example can be encap<...> (map_grid or openfpm::vector)
Definition: map_graph.hpp:427
void destroy()
operator to clear the whole graph
Definition: map_graph.hpp:683
boost::fusion::vector type
type in case of no edge
Definition: map_graph.hpp:62
void swap(Graph_CSR< V, E > &g)
swap the memory of g with this graph
Definition: map_graph.hpp:976
Structure used inside GraphCSR an edge.
Definition: map_graph.hpp:90
size_t getNEdge() const
Return the number of edges.
Definition: map_graph.hpp:1056
Simplified implementation of Graph_CSR.
Definition: map_graph.hpp:1087
size_t & source()
Get the source id of this edge.
Definition: map_graph.hpp:145
auto getChildEdge(size_t v, size_t v_e) -> decltype(e.get(0))
Get the vertex edge.
Definition: map_graph.hpp:797
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:202
bool operator==(const Graph_CSR< V, E, Memory, layout_v_base, layout_e_base, grow_p > &g) const
Check if two graph exactly match.
Definition: map_graph.hpp:438
openfpm::vector< E, Memory, layout_e_base, grow_p, openfpm::vect_isel< E >::value > e
Structure that store the edge properties.
Definition: map_graph.hpp:316
Graph_CSR(size_t n_vertex, size_t n_slot)
Constructor.
Definition: map_graph.hpp:506
auto vertex(openfpm::vector_key_iterator id) -> decltype(v.get(0))
Fuction to access the vertex.
Definition: map_graph.hpp:620
auto addEdge(size_t v1, size_t v2, const E &ed) -> decltype(e.get(0))
add edge on the graph
Definition: map_graph.hpp:900
openfpm::vector< E, Memory, layout_e_base, grow_p, openfpm::vect_isel< E >::value > e_invalid
invalid edge element, when a function try to create an in valid edge this object is returned
Definition: map_graph.hpp:322