00001
00025 #ifndef GALOIS_GRAPH_LC_INOUT_GRAPH_H
00026 #define GALOIS_GRAPH_LC_INOUT_GRAPH_H
00027
00028 #include "Galois/Graph/Details.h"
00029
00030 #include <boost/iterator/iterator_facade.hpp>
00031 #include <boost/fusion/include/vector.hpp>
00032 #include <boost/fusion/include/at_c.hpp>
00033
00034 namespace Galois {
00035 namespace Graph {
00036
00041 template<typename GraphTy>
00042 class LC_InOut_Graph: public GraphTy::template with_id<true>::type {
00043 template<typename G>
00044 friend void readGraphDispatch(G&, read_lc_inout_graph_tag, const std::string&, const std::string&);
00045
00046 typedef typename GraphTy
00047 ::template with_id<true>::type Super;
00048 typedef typename GraphTy
00049 ::template with_id<true>::type
00050 ::template with_node_data<void>::type
00051 ::template with_no_lockable<true>::type InGraph;
00052 InGraph inGraph;
00053 bool asymmetric;
00054
00055 typename InGraph::GraphNode inGraphNode(typename Super::GraphNode n) {
00056 return inGraph.getNode(idFromNode(n));
00057 }
00058
00059 void createAsymmetric() { asymmetric = true; }
00060
00061 public:
00062 typedef Super out_graph_type;
00063 typedef InGraph in_graph_type;
00064 typedef typename Super::GraphNode GraphNode;
00065 typedef typename Super::edge_data_type edge_data_type;
00066 typedef typename Super::node_data_type node_data_type;
00067 typedef typename Super::edge_data_reference edge_data_reference;
00068 typedef typename Super::node_data_reference node_data_reference;
00069 typedef typename Super::edge_iterator edge_iterator;
00070 typedef typename Super::iterator iterator;
00071 typedef typename Super::const_iterator const_iterator;
00072 typedef typename Super::local_iterator local_iterator;
00073 typedef typename Super::const_local_iterator const_local_iterator;
00074 typedef read_lc_inout_graph_tag read_tag;
00075
00076
00077 class in_edge_iterator: public boost::iterator_facade<in_edge_iterator, void*, boost::forward_traversal_tag, void*> {
00078 friend class boost::iterator_core_access;
00079 friend class LC_InOut_Graph;
00080 typedef edge_iterator Iterator0;
00081 typedef typename InGraph::edge_iterator Iterator1;
00082 typedef boost::fusion::vector<Iterator0, Iterator1> Iterators;
00083
00084 Iterators its;
00085 LC_InOut_Graph* self;
00086 int type;
00087
00088 void increment() {
00089 if (type == 0)
00090 ++boost::fusion::at_c<0>(its);
00091 else
00092 ++boost::fusion::at_c<1>(its);
00093 }
00094
00095 bool equal(const in_edge_iterator& o) const {
00096 if (type != o.type)
00097 return false;
00098 if (type == 0) {
00099 return boost::fusion::at_c<0>(its) == boost::fusion::at_c<0>(o.its);
00100 } else {
00101 return boost::fusion::at_c<1>(its) == boost::fusion::at_c<1>(o.its);
00102 }
00103 }
00104
00105 void* dereference() const { return 0; }
00106
00107 public:
00108 in_edge_iterator(): type(0) { }
00109 in_edge_iterator(Iterator0 it): type(0) { boost::fusion::at_c<0>(its) = it; }
00110 in_edge_iterator(Iterator1 it, int): type(1) { boost::fusion::at_c<1>(its) = it; }
00111 };
00112
00113 LC_InOut_Graph(): asymmetric(false) { }
00114
00115 edge_data_reference getInEdgeData(in_edge_iterator ni, MethodFlag mflag = MethodFlag::NONE) {
00116 Galois::Runtime::checkWrite(mflag, false);
00117 if (ni.type == 0) {
00118 return this->getEdgeData(boost::fusion::at_c<0>(ni.its));
00119 } else {
00120 return inGraph.getEdgeData(boost::fusion::at_c<1>(ni.its));
00121 }
00122 }
00123
00124 GraphNode getInEdgeDst(in_edge_iterator ni) {
00125 if (ni.type == 0) {
00126 return this->getEdgeDst(boost::fusion::at_c<0>(ni.its));
00127 } else {
00128 return nodeFromId(inGraph.getId(inGraph.getEdgeDst(boost::fusion::at_c<1>(ni.its))));
00129 }
00130 }
00131
00132 in_edge_iterator in_edge_begin(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00133 this->acquireNode(N, mflag);
00134 if (!asymmetric) {
00135 if (Galois::Runtime::shouldLock(mflag)) {
00136 for (edge_iterator ii = this->raw_begin(N), ei = this->raw_end(N); ii != ei; ++ii) {
00137 this->acquireNode(this->getEdgeDst(ii), mflag);
00138 }
00139 }
00140 return in_edge_iterator(this->raw_begin(N));
00141 } else {
00142 if (Galois::Runtime::shouldLock(mflag)) {
00143 for (typename InGraph::edge_iterator ii = inGraph.raw_begin(inGraphNode(N)),
00144 ei = inGraph.raw_end(inGraphNode(N)); ii != ei; ++ii) {
00145 this->acquireNode(nodeFromId(inGraph.getId(inGraph.getEdgeDst(ii))), mflag);
00146 }
00147 }
00148 return in_edge_iterator(inGraph.raw_begin(inGraphNode(N)), 0);
00149 }
00150 }
00151
00152 in_edge_iterator in_edge_end(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00153 this->acquireNode(N, mflag);
00154 if (!asymmetric) {
00155 return in_edge_iterator(this->raw_end(N));
00156 } else {
00157 return in_edge_iterator(inGraph.raw_end(inGraphNode(N)), 0);
00158 }
00159 }
00160
00161 detail::InEdgesIterator<LC_InOut_Graph> in_edges(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00162 return detail::InEdgesIterator<LC_InOut_Graph>(*this, N, mflag);
00163 }
00164
00168 template<typename CompTy>
00169 void sortInEdgesByEdgeData(GraphNode N,
00170 const CompTy& comp = std::less<typename GraphTy::edge_data_type>(),
00171 MethodFlag mflag = MethodFlag::ALL) {
00172 this->acquireNode(N, mflag);
00173 if (!asymmetric) {
00174 std::sort(this->edge_sort_begin(N), this->edge_sort_end(N),
00175 detail::EdgeSortCompWrapper<EdgeSortValue<GraphNode,typename GraphTy::edge_data_type>,CompTy>(comp));
00176 } else {
00177 std::sort(inGraph.edge_sort_begin(inGraphNode(N)),
00178 inGraph.edge_sort_end(inGraphNode(N)),
00179 detail::EdgeSortCompWrapper<EdgeSortValue<GraphNode,typename GraphTy::edge_data_type>,CompTy>(comp));
00180 }
00181 }
00182
00186 template<typename CompTy>
00187 void sortInEdges(GraphNode N, const CompTy& comp, MethodFlag mflag = MethodFlag::ALL) {
00188 this->acquireNode(N, mflag);
00189 if (!asymmetric) {
00190 std::sort(this->edge_sort_begin(N), this->edge_sort_end(N), comp);
00191 } else {
00192 std::sort(inGraph.edge_sort_begin(inGraphNode(N)), inGraph.edge_sort_end(inGraphNode(N)), comp);
00193 }
00194 }
00195
00196 size_t idFromNode(GraphNode N) {
00197 return this->getId(N);
00198 }
00199
00200 GraphNode nodeFromId(size_t N) {
00201 return this->getNode(N);
00202 }
00203 };
00204
00205 }
00206 }
00207 #endif