OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
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
58{
59public:
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
76template<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>
81class Graph_CSR;
82
90class e_map
91{
92public:
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
120{
121public:
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
166template<typename Graph>
168{
170 const Graph & g;
171
172 // Actual edge key
173 edge_key ek;
174
175public:
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
299template<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>
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
415public:
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
1086template<typename V, typename E>
1087class Graph_CSR_s: public Graph_CSR<V, E>
1088{
1089
1090};
1091
1092#endif /* MAP_GRAPH_HPP_ */
Simplified implementation of Graph_CSR.
Structure that store a graph in CSR format or basically in compressed adjacency matrix format.
auto vertex(size_t id) -> decltype(v.get(id))
Function to access the vertex.
auto edge_p(grid_key_dx< 1 > id) -> decltype(e.template get< i >(id))
Access the edge.
auto vertex(grid_key_dx< 1 > id) const -> const decltype(v.get(id.get(0)))
Fuction to access the vertex.
E E_type
Edge typedef.
void addVertex(const V &vrt)
add vertex
size_t getChild(size_t v, size_t i) const
Get the child vertex id.
Graph_CSR(size_t n_vertex)
Constructor.
size_t getNEdge() const
Return the number of edges.
auto getVertexIterator() const -> decltype(v.getIterator())
Get the vertex iterator.
auto vertex(openfpm::vector_key_iterator id) const -> const decltype(v.get(0))
operator to access the vertex
auto addEdge(size_t v1, size_t v2) -> decltype(e.get(0))
add edge on the graph
V V_type
Vertex typedef.
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)
void swap(Graph_CSR< V, E > &&g)
swap the memory of g with this graph
openfpm::vector< E, Memory, layout_e_base, grow_p, openfpm::vect_isel< E >::value > e
Structure that store the edge properties.
Graph_CSR(size_t n_vertex, size_t n_slot)
Constructor.
auto vertex_p(size_t id) -> decltype(v.template get< i >(id))
operator to access the vertex
Graph_CSR< V, E, Memory > & operator=(const Graph_CSR< V, E, Memory > &g)
size_t v_slot
number of slot per vertex
auto getChildEdge(size_t v, size_t v_e) -> decltype(e.get(0))
Get the vertex edge.
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)
edge_iterator< Graph_CSR< V, E, Memory > > getEdgeIterator() const
Get the vertex iterator.
openfpm::vector< V, Memory, layout_v_base, grow_p, openfpm::vect_isel< V >::value > v
Structure that store the vertex properties.
bool operator==(const Graph_CSR< V, E, Memory, layout_v_base, layout_e_base, grow_p > &g) const
Check if two graph exactly match.
size_t getChild(typename openfpm::vector< V, Memory, layout_v_base, grow_p >::iterator_key &v, size_t i)
Get the child edge.
void addVertex()
add an empty vertex
void destroy()
operator to clear the whole graph
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
size_t getNChilds(size_t c) const
Return the number of childs of a vertex.
auto vertex_p(grid_key_dx< 1 > id) -> decltype(v.template get< i >(id))
Access the vertex.
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.
auto edge_p(size_t id) -> decltype(e.template get< i >(id))
Access the edge.
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
void clear()
operator to clear the whole graph
auto vertex(openfpm::vector_key_iterator id) -> decltype(v.get(0))
Fuction to access the vertex.
size_t addEdge_(size_t v1, size_t v2)
add edge on the graph
void swap(Graph_CSR< V, E > &g)
swap the memory of g with this graph
size_t getNVertex() const
Return the number of the vertex.
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.
auto edge(edge_key ek) const -> const decltype(e.get(0))
operator to access the edge
auto vertex(size_t id) const -> const decltype(v.get(id))
Function to access the vertex.
Graph_CSR< V, E, Memory, layout_v_base, layout_e_base, grow_p > duplicate() const
It duplicate the graph.
auto addEdge(size_t v1, size_t v2, const E &ed) -> decltype(e.get(0))
add edge on the graph
auto vertex(grid_key_dx< 1 > id) -> decltype(v.get(id.get(0)))
Function to access the vertex.
auto edge(size_t id) const -> const decltype(e.get(id))
operator to access the edge
auto edge(grid_key_dx< 1 > id) const -> const decltype(e.get(id.get(0)))
Access the edge.
Graph_CSR< V, E, Memory > & operator=(Graph_CSR< V, E, Memory > &&g)
Graph_CSR(Graph_CSR< V, E, Memory > &&g)
Copy constructor.
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)
Graph_CSR()
Constructor.
This class allocate, and destroy CPU memory.
Structure used inside GraphCSR an edge.
Definition map_graph.hpp:91
Graph edge iterator.
const Graph & g
Graph.
size_t target()
Return the target node.
bool isNext()
Check if there is the next element.
size_t source()
Return the source node.
edge_iterator & operator++()
Get the next element.
edge_iterator(const Graph &g)
Constructor.
edge_key get()
Get the actual key.
size_t pos
Actual source node.
void begin()
Reset the counter.
size_t & target_t()
Return the target of this edge.
size_t & source()
Get the source id of this edge.
size_t pos_e
Actual target node.
grid_key_dx is the key to access any element in the grid
Definition grid_key.hpp:19
class with no edge
Definition map_graph.hpp:58
static const unsigned int max_prop
no properties
Definition map_graph.hpp:68
boost::fusion::vector type
type in case of no edge
Definition map_graph.hpp:62
type data
empty edge
Definition map_graph.hpp:65
Grow policy define how the vector should grow every time we exceed the size.
Implementation of 1-D std::vector like structure.
Transform the boost::fusion::vector into memory specification (memory_traits)
It analyze the type given and it select correctly the implementation for vector.
Definition vect_isel.hpp:37