00001 #ifndef GALOIS_LIGRAEXECUTOR_H
00002 #define GALOIS_LIGRAEXECUTOR_H
00003
00004 #include "Galois/Galois.h"
00005
00006 namespace Galois {
00008 namespace Ligra {
00009
00010 namespace hidden {
00011 template<typename Graph,bool Forward>
00012 struct Transposer {
00013 typedef typename Graph::GraphNode GNode;
00014 typedef typename Graph::in_edge_iterator in_edge_iterator;
00015 typedef typename Graph::edge_iterator edge_iterator;
00016 typedef typename Graph::edge_data_reference edge_data_reference;
00017
00018 GNode getInEdgeDst(Graph& g, in_edge_iterator ii) {
00019 return g.getInEdgeDst(ii);
00020 }
00021
00022 in_edge_iterator in_edge_begin(Graph& g, GNode n) {
00023 return g.in_edge_begin(n, Galois::MethodFlag::NONE);
00024 }
00025
00026 in_edge_iterator in_edge_end(Graph& g, GNode n) {
00027 return g.in_edge_end(n, Galois::MethodFlag::NONE);
00028 }
00029
00030 edge_data_reference getInEdgeData(Graph& g, in_edge_iterator ii) {
00031 return g.getInEdgeData(ii);
00032 }
00033
00034 GNode getEdgeDst(Graph& g, edge_iterator ii) {
00035 return g.getEdgeDst(ii);
00036 }
00037
00038 edge_iterator edge_begin(Graph& g, GNode n) {
00039 return g.edge_begin(n, Galois::MethodFlag::NONE);
00040 }
00041
00042 edge_iterator edge_end(Graph& g, GNode n) {
00043 return g.edge_end(n, Galois::MethodFlag::NONE);
00044 }
00045
00046 edge_data_reference getEdgeData(Graph& g, edge_iterator ii) {
00047 return g.getEdgeData(ii);
00048 }
00049 };
00050
00051 template<typename Graph>
00052 struct Transposer<Graph,false> {
00053 typedef typename Graph::GraphNode GNode;
00054 typedef typename Graph::edge_iterator in_edge_iterator;
00055 typedef typename Graph::in_edge_iterator edge_iterator;
00056 typedef typename Graph::edge_data_reference edge_data_reference;
00057
00058 GNode getInEdgeDst(Graph& g, in_edge_iterator ii) {
00059 return g.getEdgeDst(ii);
00060 }
00061
00062 in_edge_iterator in_edge_begin(Graph& g, GNode n) {
00063 return g.edge_begin(n, Galois::MethodFlag::NONE);
00064 }
00065
00066 in_edge_iterator in_edge_end(Graph& g, GNode n) {
00067 return g.edge_end(n, Galois::MethodFlag::NONE);
00068 }
00069
00070 edge_data_reference getInEdgeData(Graph& g, in_edge_iterator ii) {
00071 return g.getEdgeData(ii);
00072 }
00073
00074 GNode getEdgeDst(Graph& g, edge_iterator ii) {
00075 return g.getInEdgeDst(ii);
00076 }
00077
00078 edge_iterator edge_begin(Graph& g, GNode n) {
00079 return g.in_edge_begin(n, Galois::MethodFlag::NONE);
00080 }
00081
00082 edge_iterator edge_end(Graph& g, GNode n) {
00083 return g.in_edge_end(n, Galois::MethodFlag::NONE);
00084 }
00085
00086 edge_data_reference getEdgeData(Graph& g, edge_iterator ii) {
00087 return g.getInEdgeData(ii);
00088 }
00089 };
00090
00091 template<typename Graph,typename Bag,typename EdgeOperator,bool Forward>
00092 struct DenseOperator: public Transposer<Graph,Forward> {
00093 typedef Transposer<Graph,Forward> Super;
00094 typedef typename Super::GNode GNode;
00095 typedef typename Super::in_edge_iterator in_edge_iterator;
00096 typedef typename Super::edge_iterator edge_iterator;
00097
00098 typedef int tt_does_not_need_aborts;
00099 typedef int tt_does_not_need_push;
00100
00101 Graph& graph;
00102 Bag& input;
00103 Bag& output;
00104 EdgeOperator op;
00105
00106 DenseOperator(Graph& g, Bag& i, Bag& o, EdgeOperator op):
00107 graph(g), input(i), output(o), op(op) { }
00108
00109 void operator()(GNode n, Galois::UserContext<GNode>&) {
00110 (*this)(n);
00111 }
00112
00113 void operator()(GNode n) {
00114 if (!op.cond(graph, n))
00115 return;
00116
00117 for (in_edge_iterator ii = this->in_edge_begin(graph, n), ei = this->in_edge_end(graph, n); ii != ei; ++ii) {
00118 GNode src = this->getInEdgeDst(graph, ii);
00119
00120 if (input.contains(graph.idFromNode(src)) && op(graph, src, n, this->getInEdgeData(graph, ii))) {
00121 output.push(graph.idFromNode(n), std::distance(this->edge_begin(graph, n), this->edge_end(graph, n)));
00122 }
00123 if (!op.cond(graph, n))
00124 return;
00125 }
00126 }
00127 };
00128
00129 template<typename Graph,typename Bag,typename EdgeOperator,bool Forward,bool IgnoreInput>
00130 struct DenseForwardOperator: public Transposer<Graph,Forward> {
00131 typedef Transposer<Graph,Forward> Super;
00132 typedef typename Super::GNode GNode;
00133 typedef typename Super::in_edge_iterator in_edge_iterator;
00134 typedef typename Super::edge_iterator edge_iterator;
00135
00136 typedef int tt_does_not_need_aborts;
00137 typedef int tt_does_not_need_push;
00138
00139 Graph& graph;
00140 Bag& input;
00141 Bag& output;
00142 EdgeOperator op;
00143
00144 DenseForwardOperator(Graph& g, Bag& i, Bag& o, EdgeOperator op):
00145 graph(g), input(i), output(o), op(op) { }
00146
00147 void operator()(GNode n, Galois::UserContext<GNode>&) {
00148 (*this)(n);
00149 }
00150
00151 void operator()(GNode n) {
00152 if (!IgnoreInput && !input.contains(graph.idFromNode(n)))
00153 return;
00154
00155 for (edge_iterator ii = this->edge_begin(graph, n), ei = this->edge_end(graph, n); ii != ei; ++ii) {
00156 GNode dst = this->getEdgeDst(graph, ii);
00157
00158 if (op.cond(graph, n) && op(graph, n, dst, this->getEdgeData(graph, ii))) {
00159 output.pushDense(graph.idFromNode(dst), std::distance(this->edge_begin(graph, dst), this->edge_end(graph, dst)));
00160 }
00161 }
00162 }
00163 };
00164
00165 template<typename Graph,typename Bag,typename EdgeOperator,bool Forward>
00166 struct SparseOperator: public Transposer<Graph,Forward> {
00167 typedef Transposer<Graph,Forward> Super;
00168 typedef typename Super::GNode GNode;
00169 typedef typename Super::in_edge_iterator in_edge_iterator;
00170 typedef typename Super::edge_iterator edge_iterator;
00171
00172 typedef int tt_does_not_need_aborts;
00173 typedef int tt_does_not_need_push;
00174
00175 Graph& graph;
00176 Bag& output;
00177 EdgeOperator op;
00178 GNode source;
00179
00180 SparseOperator(Graph& g, Bag& o, EdgeOperator op, GNode s = GNode()):
00181 graph(g), output(o), op(op), source(s) { }
00182
00183 void operator()(size_t n, Galois::UserContext<size_t>&) {
00184 (*this)(n);
00185 }
00186
00187 void operator()(size_t id) {
00188 GNode n = graph.nodeFromId(id);
00189
00190 for (edge_iterator ii = this->edge_begin(graph, n), ei = this->edge_end(graph, n); ii != ei; ++ii) {
00191 GNode dst = this->getEdgeDst(graph, ii);
00192
00193 if (op.cond(graph, dst) && op(graph, n, dst, this->getEdgeData(graph, ii))) {
00194 output.push(graph.idFromNode(dst), std::distance(this->edge_begin(graph, dst), this->edge_end(graph, dst)));
00195 }
00196 }
00197 }
00198
00199 void operator()(edge_iterator ii, Galois::UserContext<edge_iterator>&) {
00200 (*this)(ii);
00201 }
00202
00203 void operator()(edge_iterator ii) {
00204 GNode dst = this->getEdgeDst(graph, ii);
00205
00206 if (op.cond(graph, dst) && op(graph, source, dst, this->getEdgeData(graph, ii))) {
00207 output.push(graph.idFromNode(dst), std::distance(this->edge_begin(graph, dst), this->edge_end(graph, dst)));
00208 }
00209 }
00210 };
00211 }
00212
00213 template<bool Forward,typename Graph,typename EdgeOperator,typename Bag>
00214 void edgeMap(Graph& graph, EdgeOperator op, Bag& output) {
00215 output.densify();
00216 Galois::for_each_local(graph, hidden::DenseForwardOperator<Graph,Bag,EdgeOperator,Forward,true>(graph, output, output, op));
00217 }
00218
00219 template<bool Forward,typename Graph,typename EdgeOperator,typename Bag>
00220 void edgeMap(Graph& graph, EdgeOperator op, typename Graph::GraphNode single, Bag& output) {
00221 if (Forward) {
00222 Galois::for_each(graph.out_edges(single, Galois::MethodFlag::NONE).begin(),
00223 graph.out_edges(single, Galois::MethodFlag::NONE).end(),
00224 hidden::SparseOperator<Graph,Bag,EdgeOperator,true>(graph, output, op, single));
00225 } else {
00226 Galois::for_each(graph.in_edges(single, Galois::MethodFlag::NONE).begin(),
00227 graph.in_edges(single, Galois::MethodFlag::NONE).end(),
00228 hidden::SparseOperator<Graph,Bag,EdgeOperator,false>(graph, output, op, single));
00229 }
00230 }
00231
00232 template<bool Forward,typename Graph,typename EdgeOperator,typename Bag>
00233 void edgeMap(Graph& graph, EdgeOperator op, Bag& input, Bag& output, bool denseForward) {
00234 using namespace Galois::WorkList;
00235 size_t count = input.getCount();
00236
00237 if (!denseForward && count > graph.sizeEdges() / 20) {
00238
00239 input.densify();
00240 if (denseForward) {
00241 abort();
00242 output.densify();
00243 typedef dChunkedFIFO<256*4> WL;
00244 Galois::for_each_local(graph, hidden::DenseForwardOperator<Graph,Bag,EdgeOperator,Forward,false>(graph, input, output, op), Galois::wl<WL>());
00245 } else {
00246 typedef dChunkedFIFO<256> WL;
00247 Galois::for_each_local(graph, hidden::DenseOperator<Graph,Bag,EdgeOperator,Forward>(graph, input, output, op), Galois::wl<WL>());
00248 }
00249 } else {
00250
00251 typedef dChunkedFIFO<64> WL;
00252 Galois::for_each_local(input, hidden::SparseOperator<Graph,Bag,EdgeOperator,Forward>(graph, output, op), Galois::wl<WL>());
00253 }
00254 }
00255
00256 template<typename... Args>
00257 void outEdgeMap(Args&&... args) {
00258 edgeMap<true>(std::forward<Args>(args)...);
00259 }
00260
00261 template<typename... Args>
00262 void inEdgeMap(Args&&... args) {
00263 edgeMap<false>(std::forward<Args>(args)...);
00264 }
00265
00266 }
00267 }
00268
00269 #endif