Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MorphGraph.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
26 #ifndef GALOIS_GRAPHS_MORPHGRAPH_H
27 #define GALOIS_GRAPHS_MORPHGRAPH_H
28 
29 #include <algorithm>
30 #include <map>
31 #include <set>
32 #include <type_traits>
33 #include <vector>
34 
35 #include <boost/container/small_vector.hpp>
36 #include <boost/functional.hpp>
37 #include <boost/iterator/transform_iterator.hpp>
38 #include <boost/iterator/filter_iterator.hpp>
39 #include <boost/container/small_vector.hpp>
40 
41 #include "galois/Bag.h"
42 #include "galois/config.h"
43 #include "galois/Galois.h"
45 #include "galois/graphs/Details.h"
46 #include "galois/gstl.h"
47 
48 #ifdef AUX_MAP
50 #else
53 #endif
54 
55 namespace galois {
56 namespace graphs {
57 
58 namespace internal {
62 template <typename NTy, typename ETy, bool DirectedButNotInOut>
63 struct UEdgeInfoBase;
64 
65 template <typename NTy, typename ETy>
66 struct UEdgeInfoBase<NTy, ETy, true> {
67  typedef ETy& reference;
68 
69  NTy* N;
70  ETy Ea;
71 
72  inline NTy* first() {
73  assert(N);
74  return N;
75  }
76  inline const NTy* first() const {
77  assert(N);
78  return N;
79  }
80  inline ETy* second() { return &Ea; }
81  inline const ETy* second() const { return &Ea; }
82 
83  template <typename... Args>
84  UEdgeInfoBase(NTy* n, ETy*, bool, Args&&... args)
85  : N(n), Ea(std::forward<Args>(args)...) {}
86 
87  template <typename... Args>
88  UEdgeInfoBase(NTy* n, ETy& v, bool, Args&&...) : N(n) {
89  Ea = v;
90  }
91 
92  static size_t sizeOfSecond() { return sizeof(ETy); }
93  bool isInEdge() const { return false; }
94 };
95 
96 template <typename NTy, typename ETy>
97 struct UEdgeInfoBase<NTy, ETy, false> {
98  typedef ETy& reference;
99 
100  NTy* N;
101  ETy* Ea;
102 
103  inline NTy* first() {
104  assert(N);
105  return (NTy*)((uintptr_t)N & ~1);
106  }
107  inline const NTy* first() const {
108  assert(N);
109  return (NTy*)((uintptr_t)N & ~1);
110  }
111  inline ETy* second() { return Ea; }
112  inline const ETy* second() const { return Ea; }
113  template <typename... Args>
114  UEdgeInfoBase(NTy* n, ETy* v, bool f, Args&&...)
115  : N((NTy*)((uintptr_t)n | f)), Ea(v) {}
116  static size_t sizeOfSecond() { return sizeof(ETy); }
117  bool isInEdge() const { return (uintptr_t)N & 1; }
118 };
119 
120 template <typename NTy>
121 struct UEdgeInfoBase<NTy, void, true> {
122  typedef char& reference;
123 
124  NTy* N;
125  inline NTy* first() { return N; }
126  inline const NTy* first() const { return N; }
127  inline char* second() const { return static_cast<char*>(NULL); }
128  inline char* addr() const { return second(); }
129  template <typename... Args>
130  UEdgeInfoBase(NTy* n, void*, bool, Args&&...) : N(n) {}
131  static size_t sizeOfSecond() { return 0; }
132  bool isInEdge() const { return false; }
133 };
134 
135 template <typename NTy>
136 struct UEdgeInfoBase<NTy, void, false> {
137  typedef char& reference;
138 
139  NTy* N;
140  inline NTy* first() { return (NTy*)((uintptr_t)N & ~1); }
141  inline const NTy* first() const { return (NTy*)((uintptr_t)N & ~1); }
142  inline char* second() const { return static_cast<char*>(NULL); }
143  inline char* addr() const { return second(); }
144  template <typename... Args>
145  UEdgeInfoBase(NTy* n, void*, bool f, Args&&...)
146  : N((NTy*)((uintptr_t)n | f)) {}
147  static size_t sizeOfSecond() { return 0; }
148  bool isInEdge() const { return (uintptr_t)N & 1; }
149 };
150 
151 /*
152  * Only graphs w/ in-out/symmetric edges and non-void edge data,
153  * i.e. ETy != void and DirectedNotInOut = false,
154  * need to allocate memory for edge data
155  */
156 template <typename ETy, bool DirectedNotInOut>
157 struct EdgeFactory {
159  template <typename... Args>
160  ETy* mkEdge(Args&&... args) {
161  return &mem.emplace(std::forward<Args>(args)...);
162  }
163  void delEdge(ETy*) {}
164  bool mustDel() const { return false; }
165 };
166 
167 template <typename ETy>
168 struct EdgeFactory<ETy, true> {
169  template <typename... Args>
170  ETy* mkEdge(Args&&...) {
171  return nullptr;
172  }
173  void delEdge(ETy*) {}
174  bool mustDel() const { return false; }
175 };
176 
177 template <>
178 struct EdgeFactory<void, false> {
179  template <typename... Args>
180  void* mkEdge(Args&&...) {
181  return static_cast<void*>(NULL);
182  }
183  void delEdge(void*) {}
184  bool mustDel() const { return false; }
185 };
186 
187 } // namespace internal
188 
245 template <typename NodeTy, typename EdgeTy, bool Directional,
246  bool InOut = false, bool HasNoLockable = false,
247  bool SortedNeighbors = false, typename FileEdgeTy = EdgeTy>
248 class MorphGraph : private boost::noncopyable {
249 public:
254  template <bool _has_no_lockable>
257  using type = MorphGraph<NodeTy, EdgeTy, Directional, InOut,
258  _has_no_lockable, SortedNeighbors, FileEdgeTy>;
259  };
260 
264  template <typename _node_data>
265  struct with_node_data {
267  using type = MorphGraph<_node_data, EdgeTy, Directional, InOut,
268  HasNoLockable, SortedNeighbors, FileEdgeTy>;
269  };
270 
274  template <typename _edge_data>
275  struct with_edge_data {
277  using type = MorphGraph<NodeTy, _edge_data, Directional, InOut,
278  HasNoLockable, SortedNeighbors, FileEdgeTy>;
279  };
280 
284  template <typename _file_edge_data>
287  using type = MorphGraph<NodeTy, EdgeTy, Directional, InOut, HasNoLockable,
288  SortedNeighbors, _file_edge_data>;
289  };
290 
294  template <bool _directional>
297  using type = MorphGraph<NodeTy, EdgeTy, _directional, InOut, HasNoLockable,
298  SortedNeighbors, FileEdgeTy>;
299  };
300 
304  template <bool _sorted_neighbors>
307  using type = MorphGraph<NodeTy, EdgeTy, Directional, InOut, HasNoLockable,
308  _sorted_neighbors, FileEdgeTy>;
309  };
310 
313 
314 private:
315  template <typename T>
316  struct first_eq_and_valid {
317  T N2;
318  first_eq_and_valid(T& n) : N2(n) {}
319  template <typename T2>
320  bool operator()(const T2& ii) const {
321  return ii.first() == N2 && ii.first() && ii.first()->active;
322  }
323  };
324 
325  struct first_not_valid {
326  template <typename T2>
327  bool operator()(const T2& ii) const {
328  return !ii.first() || !ii.first()->active;
329  }
330  };
331 
332  template <typename T>
333  struct first_lt {
334  template <typename T2>
335  bool operator()(const T& N2, const T2& ii) const {
336  assert(ii.first() && "UNEXPECTED: invalid item in edgelist");
337  return N2 < ii.first();
338  }
339  template <typename T2>
340  bool operator()(const T2& ii, const T& N2) const {
341  assert(ii.first() && "UNEXPECTED: invalid item in edgelist");
342  return ii.first() < N2;
343  }
344  };
345 
346  // forward declaration for graph node type
347  class gNode;
348  struct gNodeTypes
349  : public internal::NodeInfoBaseTypes<NodeTy, !HasNoLockable> {
351  using EdgeInfo =
352  internal::UEdgeInfoBase<gNode, EdgeTy, Directional & !InOut>;
353 
355  // typedef galois::gstl::Vector<EdgeInfo> EdgesTy;
356  using EdgesTy = boost::container::small_vector<
358 
359  using iterator = typename EdgesTy::iterator;
360  };
361 
362  class gNode : public internal::NodeInfoBase<NodeTy, !HasNoLockable>,
363  public gNodeTypes {
365  friend class MorphGraph;
367  using NodeInfo = internal::NodeInfoBase<NodeTy, !HasNoLockable>;
369  using iterator = typename gNode::iterator;
371  using EdgeInfo = typename gNode::EdgeInfo;
372 
374  typename gNodeTypes::EdgesTy edges;
375 
377  bool active;
378 
380  iterator begin() { return edges.begin(); }
382  iterator end() { return edges.end(); }
383 
386  void erase(iterator ii) {
387  if (SortedNeighbors) {
388  // For sorted case remove the element, moving following
389  // elements back to fill the space.
390  edges.erase(ii);
391  } else {
392  // We don't need to preserve the order, so move the last edge
393  // into this place and then remove last edge.
394  *ii = edges.back();
395  edges.pop_back();
396  }
397  }
398 
402  void erase(gNode* N, bool inEdge = false) {
403  iterator ii = find(N, inEdge);
404  if (ii != end())
405  edges.erase(ii);
406  }
407 
411  iterator find(gNode* N, bool inEdge = false) {
412  iterator ii, ei = edges.end();
413  // find starting point to start search
414  if (SortedNeighbors) {
415  assert(std::is_sorted(edges.begin(), edges.end(),
416  [=](const EdgeInfo& e1, const EdgeInfo& e2) {
417  return e1.first() < e2.first();
418  }));
419  ii =
420  std::lower_bound(edges.begin(), edges.end(), N, first_lt<gNode*>());
421  } else {
422  ii = edges.begin();
423  }
424 
425  first_eq_and_valid<gNode*> checker(N);
426  ii = std::find_if(ii, ei, checker);
427  while (ii != ei && ii->isInEdge() != inEdge) {
428  ++ii;
429  ii = std::find_if(ii, ei, checker);
430  };
431  return ii;
432  }
433 
437  void resizeEdges(size_t size) {
438  edges.resize(size, EdgeInfo(new gNode(), 0));
439  }
440 
444  template <typename... Args>
445  iterator createEdge(gNode* N, EdgeTy* v, bool inEdge, Args&&... args) {
446  iterator ii;
447  if (SortedNeighbors) {
448  // If neighbors are sorted, find appropriate insertion point.
449  // Insert before first neighbor that is too far.
450  ii =
451  std::upper_bound(edges.begin(), edges.end(), N, first_lt<gNode*>());
452  } else {
453  ii = edges.end();
454  }
455 
456  return edges.insert(ii,
457  EdgeInfo(N, v, inEdge, std::forward<Args>(args)...));
458  }
459 
464  template <typename... Args>
465  iterator createEdgeWithReuse(gNode* N, EdgeTy* v, bool inEdge,
466  Args&&... args) {
467  // First check for holes
468  iterator ii, ei;
469  if (SortedNeighbors) {
470  // If neighbors are sorted, find acceptable range for insertion.
471  ii =
472  std::lower_bound(edges.begin(), edges.end(), N, first_lt<gNode*>());
473  ei = std::upper_bound(ii, edges.end(), N, first_lt<gNode*>());
474  } else {
475  // If not sorted, we can insert anywhere in the list.
476  ii = edges.begin();
477  ei = edges.end();
478  }
479  ii = std::find_if(ii, ei, first_not_valid());
480  if (ii != ei) {
481  // FIXME: We could move elements around (short distances).
482  *ii = EdgeInfo(N, v, inEdge, std::forward<Args>(args)...);
483  return ii;
484  }
485  return edges.insert(ei,
486  EdgeInfo(N, v, inEdge, std::forward<Args>(args)...));
487  }
488 
489  template <bool _A1 = HasNoLockable>
490  void acquire(MethodFlag mflag, typename std::enable_if<!_A1>::type* = 0) {
491  galois::runtime::acquire(this, mflag);
492  }
493 
494  template <bool _A1 = HasNoLockable>
495  void acquire(MethodFlag, typename std::enable_if<_A1>::type* = 0) {}
496 
497  public:
498  template <typename... Args>
499  gNode(Args&&... args)
500  : NodeInfo(std::forward<Args>(args)...), active(false) {}
501  };
502 
503  // The graph manages the lifetimes of the data in the nodes and edges
505  using NodeListTy = galois::InsertBag<gNode>;
507  NodeListTy nodes;
508 
509  internal::EdgeFactory<EdgeTy, Directional && !InOut> edgesF;
510 
511  // Helpers for iterator classes
512  struct is_node : public std::unary_function<gNode&, bool> {
513  bool operator()(const gNode& g) const { return g.active; }
514  };
515  struct is_edge
516  : public std::unary_function<typename gNodeTypes::EdgeInfo&, bool> {
517  bool operator()(typename gNodeTypes::EdgeInfo& e) const {
518  return e.first()->active;
519  }
520  };
521  struct is_in_edge
522  : public std::unary_function<typename gNodeTypes::EdgeInfo&, bool> {
523  bool operator()(typename gNodeTypes::EdgeInfo& e) const {
524  return e.first()->active && e.isInEdge();
525  }
526  };
527  struct is_out_edge
528  : public std::unary_function<typename gNodeTypes::EdgeInfo&, bool> {
529  bool operator()(typename gNodeTypes::EdgeInfo& e) const {
530  return e.first()->active && !e.isInEdge();
531  }
532  };
533  struct makeGraphNode : public std::unary_function<gNode&, gNode*> {
534  gNode* operator()(gNode& data) const { return &data; }
535  };
536 
537 public:
538  using GraphNode = gNode*;
541  using edge_data_type = EdgeTy;
543  using file_edge_data_type = FileEdgeTy;
545  using node_data_type = NodeTy;
547  using edge_iterator =
548  typename boost::filter_iterator<is_out_edge,
549  typename gNodeTypes::iterator>;
551  using in_edge_iterator =
552  typename boost::filter_iterator<is_in_edge,
553  typename gNodeTypes::iterator>;
554 
556  using edge_data_reference = typename gNodeTypes::EdgeInfo::reference;
558  using node_data_reference = typename gNodeTypes::reference;
560  using iterator = boost::transform_iterator<
561  makeGraphNode,
562  boost::filter_iterator<is_node, typename NodeListTy::iterator>>;
563 
564 #ifdef AUX_MAP
565  struct ReadGraphAuxData {
568  LargeArray<GraphNode> nodes;
572  inNghs;
573  };
574 #else
575  struct AuxNode {
584  };
587 
590  constexpr static const bool DirectedNotInOut = (Directional && !InOut);
592  using ReadGraphAuxData =
593  typename std::conditional<DirectedNotInOut, LargeArray<GraphNode>,
595 #endif
596 
597 private:
598  template <typename... Args>
599  edge_iterator createEdgeWithReuse(GraphNode src, GraphNode dst,
600  galois::MethodFlag mflag, Args&&... args) {
601  assert(src);
602  assert(dst);
603  // galois::runtime::checkWrite(mflag, true);
604  src->acquire(mflag);
605  typename gNode::iterator ii = src->find(dst);
606  // add edge only if it doesn't already exist
607  if (ii == src->end()) {
608  if (Directional && !InOut) {
609  ii = src->createEdgeWithReuse(dst, 0, false,
610  std::forward<Args>(args)...);
611  } else {
612  dst->acquire(mflag);
613  EdgeTy* e = edgesF.mkEdge(std::forward<Args>(args)...);
614  ii = dst->createEdgeWithReuse(src, e, Directional ? true : false,
615  std::forward<Args>(args)...);
616  ii = src->createEdgeWithReuse(dst, e, false,
617  std::forward<Args>(args)...);
618  }
619  }
620  return boost::make_filter_iterator(is_out_edge(), ii, src->end());
621  }
622 
623  template <typename... Args>
624  edge_iterator createEdge(GraphNode src, GraphNode dst,
625  galois::MethodFlag mflag, Args&&... args) {
626  assert(src);
627  assert(dst);
628  // galois::runtime::checkWrite(mflag, true);
629  src->acquire(mflag);
630  typename gNode::iterator ii = src->end();
631  // add edge only if it doesn't already exist
632  if (ii == src->end()) {
633  if (Directional && !InOut) {
634  ii = src->createEdge(dst, 0, false, std::forward<Args>(args)...);
635  } else {
636  dst->acquire(mflag);
637  EdgeTy* e = edgesF.mkEdge(std::forward<Args>(args)...);
638  ii = dst->createEdge(src, e, Directional ? true : false,
639  std::forward<Args>(args)...);
640  ii = src->createEdge(dst, e, false, std::forward<Args>(args)...);
641  }
642  }
643  return boost::make_filter_iterator(is_out_edge(), ii, src->end());
644  }
645 
650  template <typename... Args>
651  EdgeTy* createOutEdge(GraphNode src, GraphNode dst, galois::MethodFlag mflag,
652  Args&&... args) {
653  assert(src);
654  assert(dst);
655 
656  src->acquire(mflag);
657  typename gNode::iterator ii = src->end();
658  if (ii == src->end()) {
659  dst->acquire(mflag);
660  EdgeTy* e = edgesF.mkEdge(std::forward<Args>(args)...);
661  ii = src->createEdge(dst, e, false, std::forward<Args>(args)...);
662  return e;
663  }
664  return nullptr;
665  }
666 
672  template <typename... Args>
673  void createInEdge(GraphNode src, GraphNode dst, EdgeTy* e,
674  galois::MethodFlag mflag, Args&&... args) {
675  assert(src);
676  assert(dst);
677 
678  dst->acquire(mflag);
679  typename gNode::iterator ii = dst->end();
680  if (ii == dst->end()) {
681  src->acquire(mflag);
682  ii = dst->createEdge(src, e, Directional ? true : false,
683  std::forward<Args>(args)...);
684  }
685  }
686 
687  template <bool _A1 = LargeArray<EdgeTy>::has_value,
688  bool _A2 = LargeArray<FileEdgeTy>::has_value>
689  EdgeTy*
690  constructOutEdgeValue(FileGraph& graph, typename FileGraph::edge_iterator nn,
691  GraphNode src, GraphNode dst,
692  typename std::enable_if<!_A1 || _A2>::type* = 0) {
693  typedef typename LargeArray<FileEdgeTy>::value_type FEDV;
694  typedef LargeArray<EdgeTy> ED;
695  if (ED::has_value) {
696  return createOutEdge(src, dst, galois::MethodFlag::UNPROTECTED,
697  graph.getEdgeData<FEDV>(nn));
698  } else {
699  return createOutEdge(src, dst, galois::MethodFlag::UNPROTECTED);
700  }
701  }
702 
703  template <bool _A1 = LargeArray<EdgeTy>::has_value,
704  bool _A2 = LargeArray<FileEdgeTy>::has_value>
705  EdgeTy*
706  constructOutEdgeValue(FileGraph&, typename FileGraph::edge_iterator,
707  GraphNode src, GraphNode dst,
708  typename std::enable_if<_A1 && !_A2>::type* = 0) {
709  return createOutEdge(src, dst, galois::MethodFlag::UNPROTECTED);
710  }
711 
712  // will reuse edge data from outgoing edges
713  void constructInEdgeValue(FileGraph&, EdgeTy* e, GraphNode src,
714  GraphNode dst) {
715  createInEdge(src, dst, e, galois::MethodFlag::UNPROTECTED);
716  }
717 
718 public
719  :
720 
727  template <typename... Args>
728  GraphNode createNode(Args&&... args) {
729  gNode* N = &(nodes.emplace(std::forward<Args>(args)...));
730  N->active = false;
731  return GraphNode(N);
732  }
733 
737  void addNode(const GraphNode& n,
739  // galois::runtime::checkWrite(mflag, true);
740  n->acquire(mflag);
741  n->active = true;
742  }
743 
746  getData(const GraphNode& n,
747  galois::MethodFlag mflag = MethodFlag::WRITE) const {
748  assert(n);
749  // galois::runtime::checkWrite(mflag, false);
750  n->acquire(mflag);
751  return n->getData();
752  }
753 
756  bool containsNode(const GraphNode& n,
757  galois::MethodFlag mflag = MethodFlag::WRITE) const {
758  assert(n);
759  n->acquire(mflag);
760  return n->active;
761  }
762 
770  assert(n);
771  // galois::runtime::checkWrite(mflag, true);
772  n->acquire(mflag);
773  gNode* N = n;
774  if (N->active) {
775  N->active = false;
776  N->edges.clear();
777  }
778  }
779 
784  void resizeEdges(GraphNode src, size_t size,
786  assert(src);
787  // galois::runtime::checkWrite(mflag, false);
788  src->acquire(mflag);
789  src->resizeEdges(size);
790  }
791 
801  return createEdgeWithReuse(src, dst, mflag);
802  }
803 
806  template <typename... Args>
808  galois::MethodFlag mflag, Args&&... args) {
809  return createEdge(src, dst, mflag, std::forward<Args>(args)...);
810  }
811 
815  assert(src);
816  // galois::runtime::checkWrite(mflag, true);
817  src->acquire(mflag);
818  if (Directional && !InOut) {
819  src->erase(dst.base());
820  } else {
821  dst->first()->acquire(mflag);
822  // EdgeTy* e = dst->second();
823  dst->first()->erase(
824  src, Directional ? true : false); // erase incoming/symmetric edge
825  src->erase(dst.base());
826  }
827  }
828 
832  assert(src);
833  assert(dst);
834  src->acquire(mflag);
835  typename gNodeTypes::iterator ii = src->find(dst), ei = src->end();
836  is_out_edge edge_predicate;
837  if (ii != ei && edge_predicate(*ii)) {
838  // After finding edge, lock dst and verify still active
839  dst->acquire(mflag);
840  if (!edge_predicate(*ii))
841  // I think we need this too, else we'll return some random iterator.
842  ii = ei;
843  } else {
844  ii = ei;
845  }
846  return boost::make_filter_iterator(edge_predicate, ii, ei);
847  }
848 
854  assert(src);
855  assert(dst);
856  src->acquire(mflag);
857  assert(std::is_sorted(src->begin(), src->end(),
858  [=](const typename gNode::EdgeInfo& e1,
859  const typename gNode::EdgeInfo& e2) {
860  return e1.first() < e2.first();
861  }));
862 
863  auto ei = src->end();
864 
865  // jump directly to edges with destination we are looking for
866  auto ii =
867  std::lower_bound(src->begin(), src->end(), dst, first_lt<gNode*>());
868 
869  first_eq_and_valid<gNode*> checker(dst);
870  ii = std::find_if(ii, ei, checker); // bug if ei set to upper_bound
871  // ignore in edges
872  while (ii != ei && ii->isInEdge()) {
873  ++ii;
874  ii = std::find_if(ii, ei, checker);
875  };
876 
877  // make sure destination node is active else return end iterator
878  is_out_edge edge_predicate;
879  if (ii != ei) {
880  dst->acquire(mflag);
881  if (!edge_predicate(*ii)) {
882  ii = ei;
883  }
884  }
885  return boost::make_filter_iterator(edge_predicate, ii, ei);
886  }
887 
890  template <bool _Undirected = !Directional>
893  typename std::enable_if<_Undirected>::type* = 0) {
894  // incoming neighbors are the same as outgoing neighbors in undirected
895  // graphs
896  return findEdge(src, dst, mflag);
897  }
898 
901  template <bool _DirectedInOut = (Directional && InOut)>
905  typename std::enable_if<_DirectedInOut>::type* = 0) {
906  assert(src);
907  assert(dst);
908  src->acquire(mflag);
909  typename gNodeTypes::iterator ii = src->find(dst, true), ei = src->end();
910  is_in_edge edge_predicate;
911  if (ii != ei && edge_predicate(*ii)) {
912  // After finding edges, lock dst and verify still active
913  dst->acquire(mflag);
914  if (!edge_predicate(*ii))
915  // need this to avoid returning a random iterator
916  ii = ei;
917  } else
918  ii = ei;
919  return boost::make_filter_iterator(edge_predicate, ii, ei);
920  }
921 
932  assert(ii->first()->active);
933  // galois::runtime::checkWrite(mflag, false);
934  ii->first()->acquire(mflag);
935  return *ii->second();
936  }
937 
944  assert(ii->first()->active);
945  // galois::runtime::checkWrite(mflag, false);
946  ii->first()->acquire(mflag);
947  return *ii->second();
948  }
949 
952  assert(ii->first()->active);
953  return GraphNode(ii->first());
954  }
955 
958  assert(ii->first()->active);
959  return GraphNode(ii->first());
960  }
961 
965  acquire(N, mflag);
966  typedef typename gNode::EdgeInfo EdgeInfo;
967  std::sort(N->begin(), N->end(),
968  [=](const EdgeInfo& e1, const EdgeInfo& e2) {
969  return e1.first() < e2.first();
970  });
971  }
972 
976  galois::iterate(*this),
977  [=](GraphNode N) { this->sortEdgesByDst(N, mflag); }, galois::steal());
978  }
979 
980  // General Things
981 
985  assert(N);
986  N->acquire(mflag);
987 
988  if (galois::runtime::shouldLock(mflag)) {
989  for (typename gNode::iterator ii = N->begin(), ee = N->end(); ii != ee;
990  ++ii) {
991  if (ii->first()->active && !ii->isInEdge())
992  ii->first()->acquire(mflag);
993  }
994  }
995  return boost::make_filter_iterator(is_out_edge(), N->begin(), N->end());
996  }
997 
999  template <bool _Undirected = !Directional>
1002  typename std::enable_if<!_Undirected>::type* = 0) {
1003  assert(N);
1004  N->acquire(mflag);
1005 
1006  if (galois::runtime::shouldLock(mflag)) {
1007  for (typename gNode::iterator ii = N->begin(), ee = N->end(); ii != ee;
1008  ++ii) {
1009  if (ii->first()->active && ii->isInEdge())
1010  ii->first()->acquire(mflag);
1011  }
1012  }
1013  return boost::make_filter_iterator(is_in_edge(), N->begin(), N->end());
1014  }
1015 
1018  template <bool _Undirected = !Directional>
1021  typename std::enable_if<_Undirected>::type* = 0) {
1022  return edge_begin(N, mflag);
1023  }
1024 
1028  galois::MethodFlag GALOIS_UNUSED(mflag) = MethodFlag::WRITE) {
1029  assert(N);
1030  // Acquiring lock is not necessary: no valid use for an end pointer should
1031  // ever require it
1032  // N->acquire(mflag);
1033  return boost::make_filter_iterator(is_out_edge(), N->end(), N->end());
1034  }
1035 
1037  template <bool _Undirected = !Directional>
1040  galois::MethodFlag GALOIS_UNUSED(mflag) = MethodFlag::WRITE,
1041  typename std::enable_if<!_Undirected>::type* = 0) {
1042  assert(N);
1043  // Acquiring lock is not necessary: no valid use for an end pointer should
1044  // ever require it
1045  // N->acquire(mflag);
1046  return boost::make_filter_iterator(is_in_edge(), N->end(), N->end());
1047  }
1048 
1050  template <bool _Undirected = !Directional>
1053  typename std::enable_if<_Undirected>::type* = 0) {
1054  return edge_end(N, mflag);
1055  }
1056 
1060  return internal::make_no_deref_range(edge_begin(N, mflag),
1061  edge_end(N, mflag));
1062  }
1063 
1065  template <bool _Undirected = !Directional>
1068  typename std::enable_if<!_Undirected>::type* = 0) {
1069  return internal::make_no_deref_range(in_edge_begin(N, mflag),
1070  in_edge_end(N, mflag));
1071  }
1072 
1075  template <bool _Undirected = !Directional>
1078  typename std::enable_if<_Undirected>::type* = 0) {
1079  return edges(N, mflag);
1080  }
1081 
1086  internal::EdgesIterator<MorphGraph>
1088  return internal::EdgesIterator<MorphGraph>(*this, N, mflag);
1089  }
1090 
1095  return boost::make_transform_iterator(
1096  boost::make_filter_iterator(is_node(), nodes.begin(), nodes.end()),
1097  makeGraphNode());
1098  }
1099 
1102  return boost::make_transform_iterator(
1103  boost::make_filter_iterator(is_node(), nodes.end(), nodes.end()),
1104  makeGraphNode());
1105  }
1106 
1109 
1112  return boost::make_transform_iterator(
1113  boost::make_filter_iterator(is_node(), nodes.local_begin(),
1114  nodes.local_end()),
1115  makeGraphNode());
1116  }
1117 
1120  return boost::make_transform_iterator(
1121  boost::make_filter_iterator(is_node(), nodes.local_end(),
1122  nodes.local_end()),
1123  makeGraphNode());
1124  }
1125 
1129  unsigned int size() { return std::distance(begin(), end()); }
1130 
1132  size_t sizeOfEdgeData() const { return gNode::EdgeInfo::sizeOfSecond(); }
1133 
1134 #ifdef AUX_MAP
1135 
1142  void allocateFrom(FileGraph& graph, ReadGraphAuxData& aux) {
1143  size_t numNodes = graph.size();
1144  aux.nodes.allocateInterleaved(numNodes);
1145  }
1146 
1156  void constructNodesFrom(FileGraph& graph, unsigned tid, unsigned total,
1157  ReadGraphAuxData& aux) {
1158  auto r = graph
1159  .divideByNode(sizeof(gNode), sizeof(typename gNode::EdgeInfo),
1160  tid, total)
1161  .first;
1162  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
1163  aux.nodes[*ii] = createNode();
1164  addNode(aux.nodes[*ii], galois::MethodFlag::UNPROTECTED);
1165  }
1166  }
1167 
1178  void constructOutEdgesFrom(FileGraph& graph, unsigned tid, unsigned total,
1179  ReadGraphAuxData& aux) {
1180  auto r = graph
1181  .divideByNode(sizeof(gNode), sizeof(typename gNode::EdgeInfo),
1182  tid, total)
1183  .first;
1184  auto& map = aux.inNghs.get();
1185 
1186  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
1187  for (FileGraph::edge_iterator nn = graph.edge_begin(*ii),
1188  en = graph.edge_end(*ii);
1189  nn != en; ++nn) {
1190  auto dstID = graph.getEdgeDst(nn);
1191  auto src = aux.nodes[*ii], dst = aux.nodes[dstID];
1192  auto e = constructOutEdgeValue(graph, nn, src, dst);
1193  if (!Directional || InOut) {
1194  map[dstID].push_back({src, e});
1195  }
1196  }
1197  }
1198  }
1199 
1210  void constructInEdgesFrom(FileGraph& graph, unsigned tid, unsigned total,
1211  const ReadGraphAuxData& aux) {
1212  // only do it if not directioal or an inout graph
1213  if (!Directional || InOut) {
1214  auto r = graph
1215  .divideByNode(sizeof(gNode),
1216  sizeof(typename gNode::EdgeInfo), tid, total)
1217  .first;
1218 
1219  for (size_t i = 0; i < aux.inNghs.numRows(); ++i) {
1220  const auto& map = aux.inNghs.get(i);
1221  auto ii = map.lower_bound(*(r.first)); // inclusive begin
1222  auto ei = map.lower_bound(*(r.second)); // exclusive end
1223  for (; ii != ei; ++ii) {
1224  auto dst = aux.nodes[ii->first];
1225  for (const auto& ie : ii->second) {
1226  constructInEdgeValue(graph, ie.second, ie.first, dst);
1227  }
1228  }
1229  }
1230  }
1231  }
1232 #else
1233 
1241  size_t numNodes = graph.size();
1242  aux.allocateInterleaved(numNodes);
1243 
1244  if (!DirectedNotInOut) {
1245  galois::do_all(galois::iterate(size_t{0}, aux.size()),
1246  [&](size_t index) { aux.constructAt(index); });
1247  }
1248  }
1249 
1260  template <bool V = DirectedNotInOut>
1261  std::enable_if_t<!V> constructNodesFrom(FileGraph& graph, unsigned tid,
1262  unsigned total,
1263  ReadGraphAuxData& aux) {
1264  auto r = graph
1265  .divideByNode(sizeof(gNode), sizeof(typename gNode::EdgeInfo),
1266  tid, total)
1267  .first;
1268  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
1269  auto& auxNode = aux[*ii].get();
1270  auxNode.n = createNode();
1272  }
1273  }
1274 
1285  template <bool V = DirectedNotInOut>
1286  std::enable_if_t<V> constructNodesFrom(FileGraph& graph, unsigned tid,
1287  unsigned total,
1288  ReadGraphAuxData& aux) {
1289  auto r = graph
1290  .divideByNode(sizeof(gNode), sizeof(typename gNode::EdgeInfo),
1291  tid, total)
1292  .first;
1293  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
1294  aux[*ii] = createNode();
1296  }
1297  }
1298 
1310  template <bool V = DirectedNotInOut>
1311  std::enable_if_t<!V> constructOutEdgesFrom(FileGraph& graph, unsigned tid,
1312  unsigned total,
1313  ReadGraphAuxData& aux) {
1314  auto r = graph
1315  .divideByNode(sizeof(gNode), sizeof(typename gNode::EdgeInfo),
1316  tid, total)
1317  .first;
1318 
1319  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
1320  for (FileGraph::edge_iterator nn = graph.edge_begin(*ii),
1321  en = graph.edge_end(*ii);
1322  nn != en; ++nn) {
1323  auto src = aux[*ii].get().n;
1324  auto& dstAux = aux[graph.getEdgeDst(nn)].get();
1325  auto e = constructOutEdgeValue(graph, nn, src, dstAux.n);
1326  dstAux.lock.lock();
1327  dstAux.inNghs.push_back({src, e});
1328  dstAux.lock.unlock();
1329  }
1330  }
1331  }
1332 
1344  template <bool V = DirectedNotInOut>
1345  std::enable_if_t<V> constructOutEdgesFrom(FileGraph& graph, unsigned tid,
1346  unsigned total,
1347  const ReadGraphAuxData& aux) {
1348  auto r = graph
1349  .divideByNode(sizeof(gNode), sizeof(typename gNode::EdgeInfo),
1350  tid, total)
1351  .first;
1352 
1353  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
1354  for (FileGraph::edge_iterator nn = graph.edge_begin(*ii),
1355  en = graph.edge_end(*ii);
1356  nn != en; ++nn) {
1357  constructOutEdgeValue(graph, nn, aux[*ii], aux[graph.getEdgeDst(nn)]);
1358  }
1359  }
1360  }
1361 
1372  template <bool V = DirectedNotInOut>
1373  std::enable_if_t<!V> constructInEdgesFrom(FileGraph& graph, unsigned tid,
1374  unsigned total,
1375  ReadGraphAuxData& aux) {
1376  auto r = graph
1377  .divideByNode(sizeof(gNode), sizeof(typename gNode::EdgeInfo),
1378  tid, total)
1379  .first;
1380 
1381  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
1382  auto& auxNode = aux[*ii].get();
1383  for (auto ie : auxNode.inNghs) {
1384  constructInEdgeValue(graph, ie.second, ie.first, auxNode.n);
1385  }
1386  }
1387  }
1388 
1391  template <bool V = DirectedNotInOut>
1392  std::enable_if_t<V> constructInEdgesFrom(FileGraph&, unsigned, unsigned,
1393  ReadGraphAuxData&) {}
1394 #endif
1395 };
1396 
1397 } // namespace graphs
1398 } // namespace galois
1399 #endif
typename std::conditional< DirectedNotInOut, LargeArray< GraphNode >, LargeArray< AuxNodePadded >>::type ReadGraphAuxData
Large array that contains auxiliary data for each node (AuxNodes)
Definition: MorphGraph.h:594
std::enable_if_t< V > constructOutEdgesFrom(FileGraph &graph, unsigned tid, unsigned total, const ReadGraphAuxData &aux)
Constructs the MorphGraph edges given a FileGraph to construct it from and already created nodes...
Definition: MorphGraph.h:1345
static constexpr const bool DirectedNotInOut
True if a node is both directional and not storing both in and out edges.
Definition: MorphGraph.h:590
void removeEdge(GraphNode src, edge_iterator dst, galois::MethodFlag mflag=MethodFlag::WRITE)
Removes an edge from the graph.
Definition: MorphGraph.h:813
typename gNodeTypes::EdgeInfo::reference edge_data_reference
Reference to edge data.
Definition: MorphGraph.h:556
void resizeEdges(GraphNode src, size_t size, galois::MethodFlag mflag=MethodFlag::WRITE)
Resize the edges of the node.
Definition: MorphGraph.h:784
in_edge_iterator in_edge_begin(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE, typename std::enable_if<!_Undirected >::type *=0)
Returns an iterator to the in-neighbors of a node.
Definition: MorphGraph.h:1001
reference emplace(Args &&...args)
Thread safe bag insertion.
Definition: Bag.h:260
unsigned int size()
Returns the number of nodes in the graph.
Definition: MorphGraph.h:1129
size_t sizeOfEdgeData() const
Returns the size of edge data.
Definition: MorphGraph.h:1132
Definition: CacheLineStorage.h:32
edge_iterator edge_begin(GraphNode N)
Returns the index to the beginning of global node N&#39;s outgoing edges in the outgoing edges array...
Definition: FileGraph.cpp:641
Contains FileGraph and FileGraphWriter class declarations.
std::enable_if_t< V > constructInEdgesFrom(FileGraph &, unsigned, unsigned, ReadGraphAuxData &)
If a directed graph and no in-edges exist (i.e.
Definition: MorphGraph.h:1392
iterator local_iterator
local iterator over nodes
Definition: MorphGraph.h:1108
iterator begin()
Definition: Bag.h:238
size_t size() const
Returns the number of nodes in the (sub)graph.
Definition: FileGraph.h:545
std::enable_if_t<!V > constructOutEdgesFrom(FileGraph &graph, unsigned tid, unsigned total, ReadGraphAuxData &aux)
Constructs the MorphGraph edges given a FileGraph to construct it from and already created nodes...
Definition: MorphGraph.h:1311
edge_iterator findEdge(GraphNode src, GraphNode dst, galois::MethodFlag mflag=MethodFlag::WRITE)
Finds if an edge between src and dst exists.
Definition: MorphGraph.h:830
boost::counting_iterator< uint64_t > iterator
uint64 boost counting iterator
Definition: FileGraph.h:408
void sortAllEdgesByDst(MethodFlag mflag=MethodFlag::WRITE)
Sort all edges by destination.
Definition: MorphGraph.h:974
typename gNodeTypes::reference node_data_reference
Reference to node data.
Definition: MorphGraph.h:558
in_edge_iterator findInEdge(GraphNode src, GraphNode dst, galois::MethodFlag mflag=MethodFlag::WRITE, typename std::enable_if< _DirectedInOut >::type *=0)
Find if an incoming edge between src and dst exists for directed in-out graphs.
Definition: MorphGraph.h:903
GraphNode getEdgeDst(edge_iterator it)
Gets the destination of some edge.
Definition: FileGraph.cpp:669
in_edge_iterator in_edge_end(GraphNode N, galois::MethodFlag GALOIS_UNUSED(mflag)=MethodFlag::WRITE, typename std::enable_if<!_Undirected >::type *=0)
Returns the end of an in-neighbor edge iterator.
Definition: MorphGraph.h:1039
GraphNode n
single graph node wrapped by this struct
Definition: MorphGraph.h:581
boost::counting_iterator< uint64_t > edge_iterator
Edge iterators (boost iterator)
Definition: FileGraph.h:248
Definition: Iterable.h:36
local_iterator local_begin()
Definition: Bag.h:243
uint64_t GraphNode
type of a node
Definition: FileGraph.h:60
bool shouldLock(const galois::MethodFlag g)
Helper function to decide if the conflict detection lock should be taken.
Definition: libgalois/include/galois/runtime/Context.h:189
node_data_reference getData(const GraphNode &n, galois::MethodFlag mflag=MethodFlag::WRITE) const
Gets the node data for a node.
Definition: MorphGraph.h:746
A graph that can have new nodes and edges added to it.
Definition: MorphGraph.h:248
edge_data_reference getEdgeData(edge_iterator ii, galois::MethodFlag mflag=MethodFlag::UNPROTECTED) const
Returns the edge data associated with the edge.
Definition: MorphGraph.h:930
local_iterator local_end()
Return the end of local range of nodes.
Definition: MorphGraph.h:1119
runtime::iterable< NoDerefIterator< in_edge_iterator > > in_edges(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE, typename std::enable_if<!_Undirected >::type *=0)
Return a range of in-edges that can be iterated over by C++ for-each.
Definition: MorphGraph.h:1067
GraphNode getEdgeDst(edge_iterator ii)
Returns the destination of an edge.
Definition: MorphGraph.h:951
galois::gstl::Vector< std::pair< GraphNode, EdgeTy * > > inNghs
stores in neighbors
Definition: MorphGraph.h:583
Struct used to define the HasNoLockable template parameter as a type in the struct.
Definition: MorphGraph.h:255
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
Definition: ParallelSTL.h:247
edge_iterator edge_end(GraphNode N, galois::MethodFlag GALOIS_UNUSED(mflag)=MethodFlag::WRITE)
Returns the end of the neighbor edge iterator.
Definition: MorphGraph.h:1027
iterator end()
Definition: Bag.h:239
internal::EdgesIterator< MorphGraph > out_edges(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
An object with begin() and end() methods to iterate over the outgoing edges of N. ...
Definition: MorphGraph.h:1087
NodeTy node_data_type
Node data type.
Definition: MorphGraph.h:545
bool containsNode(const GraphNode &n, galois::MethodFlag mflag=MethodFlag::WRITE) const
Checks if a node is in the graph.
Definition: MorphGraph.h:756
std::vector< T, Pow2Alloc< T >> Vector
[STL vector using Pow_2_VarSizeAlloc]
Definition: gstl.h:52
FileEdgeTy file_edge_data_type
Edge data type of file we are loading this graph from.
Definition: MorphGraph.h:543
edge_iterator findEdgeSortedByDst(GraphNode src, GraphNode dst, galois::MethodFlag mflag=MethodFlag::WRITE)
Find/return edge between src/dst if it exists; assumes that edges are sorted by destination.
Definition: MorphGraph.h:852
Unordered collection of elements.
Definition: Bag.h:42
typename boost::filter_iterator< is_out_edge, typename gNodeTypes::iterator > edge_iterator
(Out or Undirected) Edge iterator
Definition: MorphGraph.h:549
gNode * GraphNode
Graph node handle.
Definition: MorphGraph.h:539
void addNode(const GraphNode &n, galois::MethodFlag mflag=MethodFlag::WRITE)
Adds a node to the graph.
Definition: MorphGraph.h:737
iterator end()
Returns the end of the node iterator. Not thread-safe.
Definition: MorphGraph.h:1101
Definition: runtime/Mem.h:864
typename boost::filter_iterator< is_in_edge, typename gNodeTypes::iterator > in_edge_iterator
In Edge iterator.
Definition: MorphGraph.h:553
edge_iterator in_edge_begin(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE, typename std::enable_if< _Undirected >::type *=0)
Returns an iterator to the in-neighbors of a node; undirected case in which it&#39;s the same as a regula...
Definition: MorphGraph.h:1019
Definition: Traits.h:206
edge_data_reference getEdgeData(in_edge_iterator ii, galois::MethodFlag mflag=MethodFlag::UNPROTECTED) const
Get edge data for an in-edge.
Definition: MorphGraph.h:942
void acquire(Lockable *lockable, galois::MethodFlag m)
Master function which handles conflict detection used to acquire a lockable thing.
Definition: libgalois/include/galois/runtime/Context.h:218
Struct used to define if neighbors are sorted or not in the graph.
Definition: MorphGraph.h:305
Large array of objects with proper specialization for void type and supporting various allocation and...
Definition: LargeArray.h:53
MethodFlag
What should the runtime do when executing a method.
Definition: MethodFlags.h:34
runtime::iterable< NoDerefIterator< edge_iterator > > edges(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE)
Return a range of edges that can be iterated over by C++ for-each.
Definition: MorphGraph.h:1059
iterator begin()
Returns an iterator to all the nodes in the graph.
Definition: MorphGraph.h:1094
typename galois::substrate::CacheLineStorage< AuxNode > AuxNodePadded
Padded version of AuxNode.
Definition: MorphGraph.h:586
std::enable_if_t< V > constructNodesFrom(FileGraph &graph, unsigned tid, unsigned total, ReadGraphAuxData &aux)
Constructs the MorphGraph nodes given a FileGraph to construct it from.
Definition: MorphGraph.h:1286
void operator()(void)
Definition: Executor_ParaMeter.h:417
Struct used to define directionality of the graph.
Definition: MorphGraph.h:295
void do_all(const RangeFunc &rangeMaker, FunctionTy &&fn, const Args &...args)
Standard do-all loop.
Definition: Loops.h:71
Struct used to define the type of node data in the graph.
Definition: MorphGraph.h:265
GraphNode getEdgeDst(in_edge_iterator ii)
Returns the destination of an in-edge.
Definition: MorphGraph.h:957
EdgeTy edge_data_type
Edge data type.
Definition: MorphGraph.h:541
galois::substrate::SimpleLock lock
lock for wrapped graph node
Definition: MorphGraph.h:579
SimpleLock is a spinlock.
Definition: SimpleLock.h:36
GraphRange divideByNode(size_t nodeSize, size_t edgeSize, size_t id, size_t total)
Given a division and a total number of divisions, return a range for that particular division to work...
Definition: FileGraph.cpp:480
edge_iterator edge_end(GraphNode N)
Returns the index to the end of global node N&#39;s outgoing edges in the outgoing edges array...
Definition: FileGraph.cpp:655
edge_iterator in_edge_end(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE, typename std::enable_if< _Undirected >::type *=0)
Returns the end of an in-neighbor edge iterator, undirected case.
Definition: MorphGraph.h:1051
Struct used to define the type of file edge data in the graph.
Definition: MorphGraph.h:285
void allocateFrom(FileGraph &graph, ReadGraphAuxData &aux)
Allocate memory for nodes given a file graph with a particular number of nodes.
Definition: MorphGraph.h:1240
Definition: PerThreadContainer.h:523
void sortEdgesByDst(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE)
Sorts edge of a node by destination.
Definition: MorphGraph.h:963
Struct used to define the type of edge data in the graph.
Definition: MorphGraph.h:275
boost::transform_iterator< makeGraphNode, boost::filter_iterator< is_node, typename NodeListTy::iterator >> iterator
Node iterator.
Definition: MorphGraph.h:562
Graph that mmaps Galois gr files for access.
Definition: FileGraph.h:57
auto iterate(C &cont)
Definition: Range.h:323
std::enable_if_t<!V > constructInEdgesFrom(FileGraph &graph, unsigned tid, unsigned total, ReadGraphAuxData &aux)
Constructs the MorphGraph in-edges given a FileGraph to construct it from and already created nodes...
Definition: MorphGraph.h:1373
edge_iterator addEdge(GraphNode src, GraphNode dst, galois::MethodFlag mflag=MethodFlag::WRITE)
Adds an edge to graph, replacing existing value if edge already exists.
Definition: MorphGraph.h:799
edge_iterator addMultiEdge(GraphNode src, GraphNode dst, galois::MethodFlag mflag, Args &&...args)
Adds and initializes an edge to graph but does not check for duplicate edges.
Definition: MorphGraph.h:807
InputIterator find_if(InputIterator first, InputIterator last, Predicate pred)
Definition: ParallelSTL.h:70
local_iterator local_end()
Definition: Bag.h:246
T value_type
Definition: Executor_ParaMeter.h:111
void removeNode(GraphNode n, galois::MethodFlag mflag=MethodFlag::WRITE)
Removes a node from the graph along with all its outgoing/incoming edges for undirected graphs or out...
Definition: MorphGraph.h:769
GraphNode createNode(Args &&...args)
Creates a new node holding the indicated data.
Definition: MorphGraph.h:728
edge_iterator findInEdge(GraphNode src, GraphNode dst, galois::MethodFlag mflag=MethodFlag::WRITE, typename std::enable_if< _Undirected >::type *=0)
Find a particular in-edge: note this function activates for the undirected graph case, so it just calls the regular out-edge finding function.
Definition: MorphGraph.h:891
std::enable_if_t<!V > constructNodesFrom(FileGraph &graph, unsigned tid, unsigned total, ReadGraphAuxData &aux)
Constructs the MorphGraph nodes given a FileGraph to construct it from.
Definition: MorphGraph.h:1261
local_iterator local_begin()
Return the beginning of local range of nodes.
Definition: MorphGraph.h:1111
runtime::iterable< NoDerefIterator< edge_iterator > > in_edges(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE, typename std::enable_if< _Undirected >::type *=0)
Return a range of in-edges that can be iterated over by C++ for-each Undirected case, equivalent to out-edge iteration.
Definition: MorphGraph.h:1077
edge_iterator edge_begin(GraphNode N, galois::MethodFlag mflag=MethodFlag::WRITE)
Returns an iterator to the neighbors of a node.
Definition: MorphGraph.h:983