00001
00060 #ifndef GALOIS_GRAPHS_GRAPH_H
00061 #define GALOIS_GRAPHS_GRAPH_H
00062
00063 #include <boost/iterator/transform_iterator.hpp>
00064 #include <boost/iterator/filter_iterator.hpp>
00065 #include <boost/functional.hpp>
00066
00067 #include "Galois/ConflictFlags.h"
00068 #include "Galois/Runtime/Support.h"
00069 #include "Galois/Runtime/Context.h"
00070 #include "Galois/Runtime/InsBag.h"
00071
00072 #include "LLVM/SmallVector.h"
00073
00074 using namespace GaloisRuntime;
00075
00076 namespace Galois {
00077 namespace Graph {
00078
00080
00084 template<typename T>
00085 struct VoidWrapper {
00086 typedef T type;
00087 typedef T& ref_type;
00088 typedef const T& const_ref_type;
00089 };
00090
00091 template<>
00092 struct VoidWrapper<void> {
00093 struct unit {
00094 bool operator<(const unit& a) {
00095 return true;
00096 }
00097 };
00098 typedef unit type;
00099 typedef unit ref_type;
00100 typedef const unit const_ref_type;
00101 };
00102
00104 typedef VoidWrapper<void>::unit GraphUnit;
00105
00109 template<typename NTy>
00110 struct NodeItem {
00111 NTy N;
00112 NodeItem(typename VoidWrapper<NTy>::const_ref_type n) : N(n) { }
00113 inline typename VoidWrapper<NTy>::ref_type getData() {
00114 return N;
00115 }
00116 };
00117
00118 template<>
00119 struct NodeItem<void> {
00120 NodeItem(VoidWrapper<void>::const_ref_type n) { }
00121 inline VoidWrapper<void>::ref_type getData() {
00122 return VoidWrapper<void>::ref_type();
00123 }
00124 };
00125
00129 template<typename NTy, typename ETy>
00130 struct EdgeItem {
00131 NTy N;
00132 ETy E;
00133 inline NTy getNeighbor() {
00134 return N;
00135 }
00136 inline ETy& getData() {
00137 return E;
00138 }
00139 inline EdgeItem(NTy& n) : N(n) {
00140 }
00141 inline EdgeItem(NTy& n, ETy e) : N(n), E(e) {
00142 }
00143
00144 inline EdgeItem(){ }
00145 };
00146
00147 template<typename NTy>
00148 struct EdgeItem<NTy, void> {
00149 NTy N;
00150 inline NTy getNeighbor() {
00151 return N;
00152 }
00153 inline typename VoidWrapper<void>::ref_type getData() {
00154 return VoidWrapper<void>::ref_type();
00155 }
00156 inline EdgeItem(NTy& n) : N(n) {
00157 }
00158 };
00159
00161
00169 template<typename NodeTy, typename EdgeTy, bool Directional>
00170 class FirstGraph {
00171 public:
00173 typedef typename VoidWrapper<EdgeTy>::ref_type edge_reference;
00175 typedef typename VoidWrapper<EdgeTy>::const_ref_type const_edge_reference;
00177 typedef typename VoidWrapper<NodeTy>::ref_type node_reference;
00179 typedef typename VoidWrapper<NodeTy>::const_ref_type const_node_reference;
00180
00181 private:
00182 struct gNode: public GaloisRuntime::Lockable {
00184 typedef EdgeItem<gNode*, EdgeTy> EITy;
00186 typedef NodeItem<NodeTy> NITy;
00187
00189 typedef llvm::SmallVector<EITy, 3> EdgesTy;
00190 typedef typename EdgesTy::iterator iterator;
00191
00192 EdgesTy edges;
00193 NITy data;
00194 bool active;
00195
00196 iterator begin() {
00197 return edges.begin();
00198 }
00199 iterator end() {
00200 return edges.end();
00201 }
00202
00203 struct getNeigh : public std::unary_function<EITy, gNode*> {
00204 gNode* operator()(EITy& e) const { return e.getNeighbor(); }
00205 };
00206
00207 typedef typename boost::transform_iterator<getNeigh, iterator> neighbor_iterator;
00208
00209 neighbor_iterator neighbor_begin() {
00210 return boost::make_transform_iterator(begin(), getNeigh());
00211 }
00212 neighbor_iterator neighbor_end() {
00213 return boost::make_transform_iterator(end(), getNeigh());
00214 }
00215
00216 gNode(const_node_reference d, bool a) :
00217 data(d), active(a) {
00218 }
00219
00220 void prefetch_neighbors() {
00221 for (iterator ii = begin(), ee = end(); ii != ee; ++ii)
00222 if (ii->getNeighbor())
00223 __builtin_prefetch(ii->getNeighbor());
00224 }
00225
00226 void eraseEdge(gNode* N) {
00227 for (iterator ii = begin(), ee = end(); ii != ee; ++ii) {
00228 if (ii->getNeighbor() == N) {
00229 edges.erase(ii);
00230 return;
00231 }
00232 }
00233 }
00234
00235 edge_reference getEdgeData(gNode* N) {
00236 for (iterator ii = begin(), ee = end(); ii != ee; ++ii)
00237 if (ii->getNeighbor() == N)
00238 return ii->getData();
00239 assert(0 && "Edge doesn't exist");
00240 abort();
00241 }
00242
00243 edge_reference getEdgeData(iterator ii) {
00244 return ii->getData();
00245 }
00246
00247 edge_reference getOrCreateEdge(gNode* N) {
00248 for (iterator ii = begin(), ee = end(); ii != ee; ++ii)
00249 if (ii->getNeighbor() == N)
00250 return ii->getData();
00251 edges.push_back(EITy(N));
00252 return edges.back().getData();
00253 }
00254
00255 edge_reference getOrCreateEdge(gNode* N, const_edge_reference data) {
00256 for (iterator ii = begin(), ee = end(); ii != ee; ++ii)
00257 if (ii->getNeighbor() == N)
00258 return ii->getData();
00259
00260 edges.push_back(EITy(N, data));
00261 return edges.back().getData();
00262 }
00263
00264 bool isActive() {
00265 return active;
00266 }
00267
00268 bool hasNeighbor(gNode* N) {
00269 for (iterator ii = begin(), ee = end(); ii != ee; ++ii)
00270 if (ii->getNeighbor() == N)
00271 return true;
00272 return false;
00273 }
00274 };
00275
00276
00277 typedef GaloisRuntime::galois_insert_bag<gNode> NodeListTy;
00278 NodeListTy nodes;
00279
00280
00281
00282
00283 node_reference getData(gNode* ID, Galois::MethodFlag mflag = ALL) {
00284 assert(ID);
00285 acquire(ID, mflag);
00286 return ID->data.getData();
00287 }
00288
00289 public:
00293 class GraphNode {
00294 friend class FirstGraph;
00295 FirstGraph* Parent;
00296 gNode* ID;
00297
00298 explicit GraphNode(FirstGraph* p, gNode* id) :
00299 Parent(p), ID(id) {
00300 }
00301
00302 public:
00303 GraphNode() :
00304 Parent(0), ID(0) {
00305 }
00306
00307 void prefetch_all() {
00308 if (ID)
00309 ID->prefetch_neighbors();
00310 }
00311
00312 node_reference getData(Galois::MethodFlag mflag = ALL) const {
00313 return Parent->getData(ID, mflag);
00314 }
00315
00316 FirstGraph* getGraph() const {
00317 return Parent;
00318 }
00319
00320 bool isNull() const {
00321 return !Parent;
00322 }
00323
00324 bool operator!=(const GraphNode& rhs) const {
00325 return Parent != rhs.Parent || ID != rhs.ID;
00326 }
00327
00328 bool operator==(const GraphNode& rhs) const {
00329 return Parent == rhs.Parent && ID == rhs.ID;
00330 }
00331
00332 bool operator<(const GraphNode& rhs) const {
00333 return Parent < rhs.Parent || (Parent == rhs.Parent && ID < rhs.ID);
00334 }
00335
00336 bool operator>(const GraphNode& rhs) const {
00337 return Parent > rhs.Parent || (Parent == rhs.Parent && ID > rhs.ID);
00338 }
00339
00340 bool hasNeighbor(const GraphNode& N) const {
00341 return ID->hasNeighbor(N.ID);
00342 }
00343 };
00344
00345 private:
00346
00347 class makeGraphNode: public std::unary_function<gNode, GraphNode> {
00348 FirstGraph* G;
00349 public:
00350 makeGraphNode(FirstGraph* g = 0) :
00351 G(g) {
00352 }
00353 GraphNode operator()(gNode& data) const {
00354 return GraphNode(G, &data);
00355 }
00356 };
00357
00358 class makeGraphNodePtr: public std::unary_function<gNode*, GraphNode> {
00359 FirstGraph* G;
00360 public:
00361 makeGraphNodePtr(FirstGraph* g = 0) :
00362 G(g) {
00363 }
00364 GraphNode operator()(gNode* data) const {
00365 return GraphNode(G, data);
00366 }
00367 };
00368
00369 public:
00370 typedef EdgeTy EdgeDataTy;
00371 typedef NodeTy NodeDataTy;
00372
00374
00380 GraphNode createNode(const_node_reference n) {
00381 gNode N(n, false);
00382 return GraphNode(this, &(nodes.push(N)));
00383 }
00384
00386 bool addNode(const GraphNode& n, Galois::MethodFlag mflag = ALL) {
00387 assert(n.ID);
00388 acquire(n.ID, mflag);
00389 bool oldActive = n.ID->active;
00390 if (!oldActive) {
00391 n.ID->active = true;
00392
00393 }
00394 return !oldActive;
00395 }
00396
00397
00398 bool addNode(const GraphNode& n, int maxDegree, MethodFlag mflag = ALL) {
00399 assert(n.ID);
00400 acquire(n.ID, mflag);
00401 bool oldActive = n.ID->active;
00402 if (!oldActive) {
00403 n.ID->active = true;
00404
00405 }
00406 n.ID->edges.reserve(maxDegree);
00407 return !oldActive;
00408 }
00409
00411 node_reference getData(const GraphNode& n, Galois::MethodFlag mflag = ALL) const {
00412 assert(n.ID);
00413 acquire(n.ID, mflag);
00414 return n.ID->data.getData();
00415 }
00416
00418 bool containsNode(const GraphNode& n) const {
00419 return n.ID && (n.Parent == this) && n.ID->active;
00420 }
00421
00427
00428 bool removeNode(GraphNode n, Galois::MethodFlag mflag = ALL) {
00429 assert(n.ID);
00430 acquire(n.ID, mflag);
00431 gNode* N = n.ID;
00432 bool wasActive = N->active;
00433 if (wasActive) {
00434
00435 N->active = false;
00436
00437 for (unsigned int i = 0; i < N->edges.size(); ++i) {
00438 if (N->edges[i].getNeighbor() != N)
00439 N->edges[i].getNeighbor()->eraseEdge(N);
00440 }
00441 N->edges.clear();
00442 }
00443 return wasActive;
00444 }
00445
00447
00449 void addEdge(GraphNode src, GraphNode dst,
00450 const_edge_reference data,
00451 Galois::MethodFlag mflag = ALL) {
00452 assert(src.ID);
00453 assert(dst.ID);
00454 acquire(src.ID, mflag);
00455
00456 if (Directional) {
00457 src.ID->getOrCreateEdge(dst.ID) = data;
00458 } else {
00459 acquire(dst.ID, mflag);
00460 EdgeTy& E1 = src.ID->getOrCreateEdge(dst.ID);
00461 EdgeTy& E2 = dst.ID->getOrCreateEdge(src.ID);
00462 if (src < dst)
00463 E1 = data;
00464 else
00465 E2 = data;
00466 }
00467 }
00468
00470 void addEdge(GraphNode src, GraphNode dst, Galois::MethodFlag mflag = ALL) {
00471 assert(src.ID);
00472 assert(dst.ID);
00473 acquire(src.ID, mflag);
00474 if (Directional) {
00475 src.ID->getOrCreateEdge(dst.ID);
00476 } else {
00477 acquire(dst.ID, mflag);
00478 src.ID->getOrCreateEdge(dst.ID);
00479 dst.ID->getOrCreateEdge(src.ID);
00480 }
00481 }
00482
00484 void removeEdge(GraphNode src, GraphNode dst, Galois::MethodFlag mflag = ALL) {
00485 assert(src.ID);
00486 assert(dst.ID);
00487 acquire(src.ID, mflag);
00488 if (Directional) {
00489 src.ID->eraseEdge(dst.ID);
00490 } else {
00491 acquire(dst.ID, mflag);
00492 src.ID->eraseEdge(dst.ID);
00493 dst.ID->eraseEdge(src.ID);
00494 }
00495 }
00496
00501 edge_reference getEdgeData(GraphNode src, GraphNode dst,
00502 Galois::MethodFlag mflag = ALL) const {
00503 assert(src.ID);
00504 assert(dst.ID);
00505
00506
00507 acquire(src.ID, mflag);
00508
00509 if (Directional) {
00510 return src.ID->getEdgeData(dst.ID);
00511 } else {
00512 acquire(dst.ID, mflag);
00513 if (src < dst)
00514 return src.ID->getEdgeData(dst.ID);
00515 else
00516 return dst.ID->getEdgeData(src.ID);
00517 }
00518 }
00519
00524 edge_reference getOrCreateEdge(GraphNode src, GraphNode dst,
00525 const_edge_reference data, Galois::MethodFlag mflag = ALL) const {
00526 assert(src.ID);
00527 assert(dst.ID);
00528
00529 acquire(src.ID, mflag);
00530
00531 if (Directional) {
00532 return src.ID->getOrCreateEdge(dst.ID, data);
00533 } else {
00534 acquire(dst.ID, mflag);
00535
00536 if (src < dst){
00537 dst.ID->getOrCreateEdge(src.ID, data);
00538 return src.ID->getOrCreateEdge(dst.ID, data);
00539 }
00540 else{
00541 src.ID->getOrCreateEdge(dst.ID, data);
00542 return dst.ID->getOrCreateEdge(src.ID, data);
00543
00544 }
00545 }
00546 }
00547
00549
00551 int neighborsSize(GraphNode N, Galois::MethodFlag mflag = ALL) const {
00552 assert(N.ID);
00553 acquire(N.ID, mflag);
00554 return N.ID->edges.size();
00555 }
00556
00557 typedef typename boost::transform_iterator<makeGraphNodePtr,
00558 typename gNode::neighbor_iterator>
00559 neighbor_iterator;
00560
00562 neighbor_iterator neighbor_begin(GraphNode N, Galois::MethodFlag mflag = ALL) {
00563 assert(N.ID);
00564 acquire(N.ID, mflag);
00565
00566
00567 for (typename gNode::neighbor_iterator ii = N.ID->neighbor_begin(), ee =
00568 N.ID->neighbor_end(); ii != ee; ++ii) {
00569
00570
00571 acquire(*ii, mflag);
00572 }
00573
00574 return boost::make_transform_iterator(N.ID->neighbor_begin(),
00575 makeGraphNodePtr(this));
00576 }
00577
00579 neighbor_iterator neighbor_end(GraphNode N, Galois::MethodFlag mflag = ALL) {
00580 assert(N.ID);
00581
00582
00583
00584
00585 return boost::make_transform_iterator(N.ID->neighbor_end(),
00586 makeGraphNodePtr(this));
00587 }
00588
00589 edge_reference getEdgeData(GraphNode src, neighbor_iterator dst,
00590 Galois::MethodFlag mflag = ALL) {
00591 assert(src.ID);
00592
00593
00594 acquire(src.ID, mflag);
00595
00596 if (Directional) {
00597 return src.ID->getEdgeData(dst.base().base());
00598 } else {
00599 if (src.ID < dst.base().base()->getNeighbor())
00600 return src.ID->getEdgeData(dst.base().base()->getNeighbor());
00601 else
00602 return dst.base().base()->getNeighbor()->getEdgeData(src.ID);
00603 }
00604 }
00605
00606
00607 typedef boost::transform_iterator<makeGraphNode,
00608 boost::filter_iterator<std::mem_fun_ref_t<bool, gNode>,
00609 typename NodeListTy::iterator> > active_iterator;
00610
00614 active_iterator active_begin() {
00615 return boost::make_transform_iterator(
00616 boost::make_filter_iterator(
00617 std::mem_fun_ref(&gNode::isActive), nodes.begin(), nodes.end()),
00618 makeGraphNode(this));
00619 }
00620
00622 active_iterator active_end() {
00623 return boost::make_transform_iterator(
00624 boost::make_filter_iterator(
00625 std::mem_fun_ref(&gNode::isActive), nodes.end(), nodes.end()),
00626 makeGraphNode(this));
00627 }
00628
00632 unsigned int size() {
00633 return std::distance(active_begin(), active_end());
00634 }
00635
00636 FirstGraph() {
00637 reportStatSum("NodeSize", sizeof(gNode));
00638 }
00639 };
00640
00641 }
00642 }
00643 #endif