00001
00002 #ifndef DUNE_AMG_AGGREGATES_HH
00003 #define DUNE_AMG_AGGREGATES_HH
00004
00005 #include"graph.hh"
00006 #include"properties.hh"
00007 #include"combinedfunctor.hh"
00008
00009 #include<dune/common/timer.hh>
00010 #include<dune/common/tuples.hh>
00011 #include<dune/common/stdstreams.hh>
00012 #include<dune/common/poolallocator.hh>
00013 #include<dune/common/sllist.hh>
00014
00015 #include<utility>
00016 #include<set>
00017 #include<algorithm>
00018 #include<limits>
00019 #include<ostream>
00020
00021 namespace Dune
00022 {
00023 namespace Amg
00024 {
00025
00039 template<class T>
00040 class AggregationCriterion : public T
00041 {
00042
00043 public:
00047 typedef T DependencyPolicy;
00048
00052 AggregationCriterion()
00053 : maxDistance_(2), minAggregateSize_(4), maxAggregateSize_(6),
00054 connectivity_(15), debugLevel_(3)
00055 {}
00056
00057
00065 std::size_t maxDistance() const { return maxDistance_;}
00066
00075 void setMaxDistance(std::size_t distance) { maxDistance_ = distance;}
00076
00081 std::size_t minAggregateSize() const { return minAggregateSize_;}
00082
00089 void setMinAggregateSize(std::size_t size){ minAggregateSize_=size;}
00090
00095 std::size_t maxAggregateSize() const{ return maxAggregateSize_;}
00096
00103 void setMaxAggregateSize(std::size_t size){ maxAggregateSize_ = size;}
00104
00112 std::size_t maxConnectivity() const{ return connectivity_;}
00113
00121 void setMaxConnectivity(std::size_t connectivity){ connectivity_ = connectivity;}
00122
00128 void setDebugLevel(int level)
00129 {
00130 debugLevel_ = level;
00131 }
00132
00138 int debugLevel() const
00139 {
00140 return debugLevel_;
00141 }
00142
00143
00144 private:
00145 std::size_t maxDistance_, minAggregateSize_, maxAggregateSize_, connectivity_;
00146 int debugLevel_;
00147 };
00148
00149 template<class T>
00150 std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion)
00151 {
00152 os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize="
00153 <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize()
00154 <<" connectivity="<<criterion.connectivity()<<" debugLevel="<<criterion.debugLevel()<<"}";
00155 return os;
00156 }
00157
00161 class DependencyParameters
00162 {
00163 public:
00165 DependencyParameters()
00166 : alpha_(1.0/3.0), beta_(1.0E-5)
00167 {}
00168
00173 void setBeta(double b)
00174 {
00175 beta_ = b;
00176 }
00177
00183 double beta() const
00184 {
00185 return beta_;
00186 }
00187
00192 void setAlpha(double a)
00193 {
00194 alpha_ = a;
00195 }
00196
00201 double alpha() const
00202 {
00203 return alpha_;
00204 }
00205
00206 private:
00207 double alpha_, beta_;
00208 };
00209
00210
00214 template<class M, class N>
00215 class Dependency : public DependencyParameters
00216 {
00217 public:
00221 typedef M Matrix;
00222
00226 typedef N Norm;
00227
00231 typedef typename Matrix::row_type Row;
00232
00236 typedef typename Matrix::ConstColIterator ColIter;
00237
00238 void init(const Matrix* matrix);
00239
00240 void initRow(const Row& row, int index);
00241
00242 void examine(const ColIter& col);
00243
00244 template<class G>
00245 void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
00246
00247 bool isIsolated();
00248 private:
00250 const Matrix* matrix_;
00252 typename Matrix::field_type maxValue_;
00254 Norm norm_;
00256 int row_;
00258 typename Matrix::field_type diagonal_;
00259 };
00260
00264 template<class M, class N>
00265 class SymmetricDependency : public DependencyParameters
00266 {
00267 public:
00271 typedef M Matrix;
00272
00276 typedef N Norm;
00277
00281 typedef typename Matrix::row_type Row;
00282
00286 typedef typename Matrix::ConstColIterator ColIter;
00287
00288 void init(const Matrix* matrix);
00289
00290 void initRow(const Row& row, int index);
00291
00292 void examine(const ColIter& col);
00293
00294 template<class G>
00295 void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
00296
00297 bool isIsolated();
00298 private:
00300 const Matrix* matrix_;
00302 typename Matrix::field_type maxValue_;
00304 Norm norm_;
00306 int row_;
00308 typename Matrix::field_type diagonal_;
00309 };
00310
00315 class FirstDiagonal
00316 {
00317 public:
00322 template<class M>
00323 typename M::field_type operator()(const M& m) const
00324 {
00325 return m[0][0];
00326 }
00327 };
00328
00334 struct RowSum
00335 {
00340 template<class M>
00341 typename M::field_type operator()(const M& m) const
00342 {
00343 return m.infinity_norm();
00344 }
00345 };
00346
00356 template<class M, class Norm>
00357 class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
00358 {};
00359
00360
00372 template<class M, class Norm>
00373 class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
00374 {};
00375
00376 template<class G> class Aggregator;
00377
00378
00386 template<class V>
00387 class AggregatesMap
00388 {
00389 public:
00390
00394 static const V UNAGGREGATED;
00395
00399 static const V ISOLATED;
00403 typedef V VertexDescriptor;
00404
00408 typedef V AggregateDescriptor;
00409
00414 typedef PoolAllocator<VertexDescriptor,100*sizeof(int)> Allocator;
00415
00420 typedef SLList<VertexDescriptor,Allocator> VertexList;
00421
00425 class DummyEdgeVisitor
00426 {
00427 public:
00428 template<class EdgeIterator>
00429 void operator()(const EdgeIterator& egde) const
00430 {}
00431 };
00432
00433
00437 AggregatesMap();
00438
00444 AggregatesMap(std::size_t noVertices);
00445
00449 ~AggregatesMap();
00450
00458 template<class M, class G, class C>
00459 Tuple<int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion);
00460
00480 template<bool reset, class G, class F, class VM>
00481 std::size_t breadthFirstSearch(const VertexDescriptor& start,
00482 const AggregateDescriptor& aggregate,
00483 G& graph,
00484 F& aggregateVisitor,
00485 VM& visitedMap) const;
00486
00510 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
00511 std::size_t breadthFirstSearch(const VertexDescriptor& start,
00512 const AggregateDescriptor& aggregate,
00513 G& graph, L& visited, F1& aggregateVisitor,
00514 F2& nonAggregateVisitor,
00515 VM& visitedMap) const;
00516
00522 void allocate(std::size_t noVertices);
00523
00527 std::size_t noVertices() const;
00528
00532 void free();
00533
00539 AggregateDescriptor& operator[](const VertexDescriptor& v);
00540
00546 const AggregateDescriptor& operator[](const VertexDescriptor& v) const;
00547
00548 private:
00550 AggregatesMap(const AggregatesMap<V>& map)
00551 {
00552 throw "Auch!";
00553 }
00554
00556 AggregatesMap<V>& operator=(const AggregatesMap<V>& map)
00557 {
00558 throw "Auch!";
00559 return this;
00560 }
00561
00565 AggregateDescriptor* aggregates_;
00566
00570 std::size_t noVertices_;
00571 };
00572
00573
00578 template<class G>
00579 class Aggregate
00580 {
00581
00582 public:
00583
00584
00585
00586
00587 typedef G MatrixGraph;
00591 typedef typename MatrixGraph::VertexDescriptor Vertex;
00592
00597 typedef PoolAllocator<Vertex,100*sizeof(int)> Allocator;
00598
00603 typedef SLList<Vertex,Allocator> VertexList;
00604
00605
00610 typedef std::set<Vertex> VertexSet;
00611
00613 typedef typename VertexList::const_iterator const_iterator;
00614
00618 typedef std::size_t* SphereMap;
00619
00627 Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
00628 VertexSet& connectivity);
00629
00636 void reconstruct(const Vertex& vertex);
00637
00641 void seed(const Vertex& vertex);
00642
00646 void add(const Vertex& vertex);
00647
00651 void clear();
00652
00656 typename VertexList::size_type size();
00657
00661 int id();
00662
00664 const_iterator begin() const;
00665
00667 const_iterator end() const;
00668
00669 private:
00673 VertexList vertices_;
00674
00679 int id_;
00680
00684 const MatrixGraph& graph_;
00685
00689 AggregatesMap<Vertex>& aggregates_;
00690
00694 VertexSet& connected_;
00695 };
00696
00700 template<class G>
00701 class Aggregator
00702 {
00703 public:
00704
00708 typedef G MatrixGraph;
00709
00713 typedef typename MatrixGraph::VertexDescriptor Vertex;
00714
00716 typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor;
00717
00721 Aggregator();
00722
00726 ~Aggregator();
00727
00740 template<class M, class C>
00741 Tuple<int,int,int> build(const M& m, G& graph,
00742 AggregatesMap<Vertex>& aggregates, const C& c);
00743 private:
00748 typedef PoolAllocator<Vertex,100*sizeof(int)> Allocator;
00749
00753 typedef SLList<Vertex,Allocator> VertexList;
00754
00758 typedef std::set<Vertex> VertexSet;
00759
00763 typedef std::size_t* SphereMap;
00764
00768 MatrixGraph* graph_;
00769
00773 Aggregate<MatrixGraph>* aggregate_;
00774
00778 VertexList front_;
00779
00783 VertexSet connected_;
00784
00788 int size_;
00789
00793 class Stack
00794 {
00795 public:
00796 static const Vertex NullEntry;
00797
00798 Stack(const MatrixGraph& graph,
00799 const Aggregator<G>& aggregatesBuilder,
00800 const AggregatesMap<Vertex>& aggregates);
00801 ~Stack();
00802 bool push(const Vertex& v);
00803 void fill();
00804 Vertex pop();
00805 private:
00806 enum{ N = 256000 };
00807
00809 const MatrixGraph& graph_;
00811 const Aggregator<G>& aggregatesBuilder_;
00813 const AggregatesMap<Vertex>& aggregates_;
00815 int size_;
00816 int maxSize_;
00818 int head_;
00819 int filled_;
00820
00822 Vertex* vals_;
00823
00824 void localPush(const Vertex& v);
00825 };
00826
00827 friend class Stack;
00828
00832 template<class C>
00833 void buildDependency(MatrixGraph& graph,
00834 const typename C::Matrix& matrix,
00835 C criterion);
00836
00847 template<class V>
00848 void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
00849 const AggregatesMap<Vertex>& aggregates,
00850 V& visitor) const;
00851
00856 template<class V>
00857 class AggregateVisitor
00858 {
00859 public:
00863 typedef V Visitor;
00871 AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
00872 Visitor& visitor);
00873
00880 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00881
00882 private:
00884 const AggregatesMap<Vertex>& aggregates_;
00886 AggregateDescriptor aggregate_;
00888 Visitor* visitor_;
00889 };
00890
00894 class Counter
00895 {
00896 public:
00898 Counter();
00900 int value();
00901
00902 protected:
00904 void increment();
00906 void decrement();
00907
00908 private:
00909 int count_;
00910 };
00911
00912
00917 class FrontNeighbourCounter : public Counter
00918 {
00919 public:
00924 FrontNeighbourCounter(const MatrixGraph& front);
00925
00926 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00927
00928 private:
00929 const MatrixGraph& graph_;
00930 };
00931
00936 int noFrontNeighbours(const Vertex& vertex) const;
00937
00941 class TwoWayCounter : public Counter
00942 {
00943 public:
00944 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00945 };
00946
00958 int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
00959 const AggregatesMap<Vertex>& aggregates) const;
00960
00964 class OneWayCounter : public Counter
00965 {
00966 public:
00967 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00968 };
00969
00981 int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
00982 const AggregatesMap<Vertex>& aggregates) const;
00983
00990 class ConnectivityCounter : public Counter
00991 {
00992 public:
00999 ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
01000
01001 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01002
01003 private:
01005 const VertexSet& connected_;
01007 const AggregatesMap<Vertex>& aggregates_;
01008
01009 };
01010
01022 double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01023
01031 class DependencyCounter: public Counter
01032 {
01033 public:
01037 DependencyCounter();
01038
01039 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01040 };
01041
01048 class FrontMarker
01049 {
01050 public:
01057 FrontMarker(VertexList& front, MatrixGraph& graph);
01058
01059 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01060
01061 private:
01063 VertexList& front_;
01065 MatrixGraph& graph_;
01066 };
01067
01074 void markFront(const AggregatesMap<Vertex>& aggregates);
01075
01079 void unmarkFront();
01080
01095 int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01096
01110 std::pair<int,int> neighbours(const Vertex& vertex,
01111 const AggregateDescriptor& aggregate,
01112 const AggregatesMap<Vertex>& aggregates) const;
01129 int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01130
01138 bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01139
01146 void seedFromFront(Stack& stack, bool isolated);
01147
01155 std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
01156
01165 Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01166
01174 template<class C>
01175 void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
01176 };
01177
01178 template<class M, class N>
01179 inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
01180 {
01181 matrix_ = matrix;
01182 }
01183
01184 template<class M, class N>
01185 inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
01186 {
01187 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01188 row_ = index;
01189 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01190 }
01191
01192 template<class M, class N>
01193 inline void SymmetricDependency<M,N>::examine(const ColIter& col)
01194 {
01195 maxValue_ = std::max(maxValue_,
01196 (norm_(*col) * norm_(matrix_->operator[](col.index())[row_]))/
01197 (norm_(matrix_->operator[](col.index())[col.index()]) * diagonal_));
01198
01199 }
01200
01201 template<class M, class N>
01202 template<class G>
01203 inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01204 {
01205 if(norm_(matrix_->operator[](edge.target())[edge.source()]) * norm_(*col)/
01206 (norm_(matrix_->operator[](edge.target())[edge.target()]) * diagonal_) > alpha() * maxValue_){
01207
01208 edge.properties().setDepends();
01209 edge.properties().setInfluences();
01210
01211 typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
01212 other.setInfluences();
01213 other.setDepends();
01214 }
01215 }
01216
01217 template<class M, class N>
01218 inline bool SymmetricDependency<M,N>::isIsolated()
01219 {
01220 return maxValue_ < beta();
01221 }
01222
01223
01224 template<class M, class N>
01225 inline void Dependency<M,N>::init(const Matrix* matrix)
01226 {
01227 matrix_ = matrix;
01228 }
01229
01230 template<class M, class N>
01231 inline void Dependency<M,N>::initRow(const Row& row, int index)
01232 {
01233 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01234 row_ = index;
01235 diagonal_ = matrix_->operator[](row_)[row_];
01236 }
01237
01238 template<class M, class N>
01239 inline void Dependency<M,N>::examine(const ColIter& col)
01240 {
01241 maxValue_ = std::max(maxValue_,
01242 -*col);
01243 }
01244
01245 template<class M, class N>
01246 template<class G>
01247 inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01248 {
01249 if(-*col >= maxValue_ * alpha()){
01250 edge.properties().setDepends();
01251 edge.properties().setInfluences();
01252 }
01253 }
01254
01255 template<class M, class N>
01256 inline bool Dependency<M,N>::isIsolated()
01257 {
01258 return maxValue_ < beta() * diagonal_;
01259 }
01260
01261 template<class G>
01262 Aggregate<G>::Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
01263 VertexSet& connected)
01264 : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
01265 connected_(connected)
01266 {}
01267
01268 template<class G>
01269 void Aggregate<G>::reconstruct(const Vertex& vertex)
01270 {
01271 vertices_.push_back(vertex);
01272 typedef typename VertexList::const_iterator iterator;
01273 iterator begin = vertices_.begin();
01274 iterator end = vertices_.end();
01275 throw "Not yet implemented";
01276
01277 while(begin!=end){
01278
01279 }
01280
01281 }
01282
01283 template<class G>
01284 inline void Aggregate<G>::seed(const Vertex& vertex)
01285 {
01286 dvverb<<"Connected cleared"<<std::endl;
01287 connected_.clear();
01288 vertices_.clear();
01289 connected_.insert(vertex);
01290 dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
01291 id_ = vertex;
01292 add(vertex);
01293 }
01294
01295
01296 template<class G>
01297 inline void Aggregate<G>::add(const Vertex& vertex)
01298 {
01299 vertices_.push_back(vertex);
01300 aggregates_[vertex]=id_;
01301
01302 typedef typename MatrixGraph::ConstEdgeIterator iterator;
01303 const iterator end = graph_.endEdges(vertex);
01304 for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge){
01305 dvverb << " Inserting "<<aggregates_[edge.target()];
01306 connected_.insert(aggregates_[edge.target()]);
01307 dvverb <<" size="<<connected_.size();
01308 }
01309 dvverb <<std::endl;
01310 }
01311 template<class G>
01312 inline void Aggregate<G>::clear()
01313 {
01314 vertices_.clear();
01315 connected_.clear();
01316 id_=-1;
01317 }
01318
01319 template<class G>
01320 inline typename Aggregate<G>::VertexList::size_type
01321 Aggregate<G>::size()
01322 {
01323 return vertices_.size();
01324 }
01325
01326 template<class G>
01327 inline int Aggregate<G>::id()
01328 {
01329 return id_;
01330 }
01331
01332 template<class G>
01333 inline typename Aggregate<G>::const_iterator Aggregate<G>::begin() const
01334 {
01335 return vertices_.begin();
01336 }
01337
01338 template<class G>
01339 inline typename Aggregate<G>::const_iterator Aggregate<G>::end() const
01340 {
01341 return vertices_.end();
01342 }
01343
01344 template<class V>
01345 const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
01346
01347 template<class V>
01348 const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
01349
01350 template<class V>
01351 AggregatesMap<V>::AggregatesMap()
01352 : aggregates_(0)
01353 {}
01354
01355 template<class V>
01356 AggregatesMap<V>::~AggregatesMap()
01357 {
01358 if(aggregates_!=0)
01359 delete[] aggregates_;
01360 }
01361
01362
01363 template<class V>
01364 inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
01365 {
01366 allocate(noVertices);
01367 }
01368
01369 template<class V>
01370 inline std::size_t AggregatesMap<V>::AggregatesMap::noVertices() const
01371 {
01372 return noVertices_;
01373 }
01374
01375 template<class V>
01376 inline void AggregatesMap<V>::allocate(std::size_t noVertices)
01377 {
01378 aggregates_ = new AggregateDescriptor[noVertices];
01379 noVertices_ = noVertices;
01380
01381 for(std::size_t i=0; i < noVertices; i++)
01382 aggregates_[i]=UNAGGREGATED;
01383 }
01384
01385 template<class V>
01386 inline void AggregatesMap<V>::free()
01387 {
01388 assert(aggregates_ != 0);
01389 delete[] aggregates_;
01390 aggregates_=0;
01391 }
01392
01393 template<class V>
01394 inline typename AggregatesMap<V>::AggregateDescriptor&
01395 AggregatesMap<V>::operator[](const VertexDescriptor& v)
01396 {
01397 return aggregates_[v];
01398 }
01399
01400 template<class V>
01401 inline const typename AggregatesMap<V>::AggregateDescriptor&
01402 AggregatesMap<V>::operator[](const VertexDescriptor& v) const
01403 {
01404 return aggregates_[v];
01405 }
01406
01407 template<class V>
01408 template<bool reset, class G, class F,class VM>
01409 inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01410 const AggregateDescriptor& aggregate,
01411 G& graph, F& aggregateVisitor,
01412 VM& visitedMap) const
01413 {
01414 VertexList vlist;
01415 DummyEdgeVisitor dummy;
01416 return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
01417 }
01418
01419 template<class V>
01420 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
01421 std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01422 const AggregateDescriptor& aggregate,
01423 G& graph,
01424 L& visited,
01425 F1& aggregateVisitor,
01426 F2& nonAggregateVisitor,
01427 VM& visitedMap) const
01428 {
01429 typedef typename L::const_iterator ListIterator;
01430 int visitedSpheres = 0;
01431
01432 visited.push_back(start);
01433 put(visitedMap, start, true);
01434
01435 ListIterator current = visited.begin();
01436 ListIterator end = visited.end();
01437 std::size_t i=0, size=visited.size();
01438
01439
01440
01441 while(current != end){
01442
01443 for(;i<size; ++current, ++i){
01444 typedef typename G::ConstEdgeIterator EdgeIterator;
01445 const EdgeIterator endEdge = graph.endEdges(*current);
01446
01447 for(EdgeIterator edge = graph.beginEdges(*current);
01448 edge != endEdge; ++edge){
01449
01450 if(aggregates_[edge.target()]==aggregate){
01451 if(!get(visitedMap, edge.target())){
01452 put(visitedMap, edge.target(), true);
01453 visited.push_back(edge.target());
01454 aggregateVisitor(edge);
01455 }
01456 }else
01457 nonAggregateVisitor(edge);
01458 }
01459 }
01460 end = visited.end();
01461 size = visited.size();
01462 if(current != end)
01463 visitedSpheres++;
01464 }
01465
01466 if(reset)
01467 for(current = visited.begin(); current != end; ++current)
01468 put(visitedMap, *current, false);
01469
01470
01471 if(remove)
01472 visited.clear();
01473
01474 return visitedSpheres;
01475 }
01476
01477 template<class G>
01478 Aggregator<G>::Aggregator()
01479 : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
01480 {}
01481
01482 template<class G>
01483 Aggregator<G>::~Aggregator()
01484 {
01485 size_=-1;
01486 }
01487
01488 template<class G>
01489 template<class C>
01490 void Aggregator<G>::buildDependency(MatrixGraph& graph,
01491 const typename C::Matrix& matrix,
01492 C criterion)
01493 {
01494
01495 typedef C Criterion;
01496
01497
01498 typedef typename C::Matrix Matrix;
01499 typedef typename MatrixGraph::VertexIterator VertexIterator;
01500
01501 criterion.init(&matrix);
01502
01503 for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex){
01504 typedef typename Matrix::row_type Row;
01505
01506 Row row = matrix[*vertex];
01507
01508
01509
01510
01511 criterion.initRow(row, *vertex);
01512
01513
01514
01515 typedef typename Matrix::ConstColIterator ColIterator;
01516 ColIterator end = row.end();
01517 for(ColIterator col = row.begin(); col != end; ++col)
01518 if(col.index()!=*vertex)
01519 criterion.examine(col);
01520
01521
01522 vertex.properties().reset();
01523
01524
01525 if(criterion.isIsolated()){
01526
01527 vertex.properties().setIsolated();
01528 }else{
01529
01530 typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01531 typedef typename Matrix::ConstColIterator ColIterator;
01532 EdgeIterator end = vertex.end();
01533 ColIterator col = matrix[*vertex].begin();
01534
01535 for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01536
01537 while(col.index()!=edge.target())
01538 ++col;
01539 criterion.examine(graph, edge, col);
01540 }
01541 }
01542
01543 }
01544 }
01545
01546
01547 template<class G>
01548 template<class V>
01549 inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
01550 const AggregateDescriptor& aggregate, V& visitor)
01551 : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01552 {}
01553
01554 template<class G>
01555 template<class V>
01556 inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01557 {
01558 if(aggregates_[edge.target()]==aggregate_)
01559 visitor_->operator()(edge);
01560 }
01561
01562 template<class G>
01563 template<class V>
01564 inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01565 const AggregateDescriptor& aggregate,
01566 const AggregatesMap<Vertex>& aggregates,
01567 V& visitor) const
01568 {
01569
01570 AggregateVisitor<V> v(aggregates, aggregate, visitor);
01571 visitNeighbours(*graph_, vertex, v);
01572 }
01573
01574
01575 template<class G>
01576 inline Aggregator<G>::Counter::Counter()
01577 : count_(0)
01578 {}
01579
01580 template<class G>
01581 inline void Aggregator<G>::Counter::increment()
01582 {
01583 ++count_;
01584 }
01585
01586 template<class G>
01587 inline void Aggregator<G>::Counter::decrement()
01588 {
01589 --count_;
01590 }
01591 template<class G>
01592 inline int Aggregator<G>::Counter::value()
01593 {
01594 return count_;
01595 }
01596
01597 template<class G>
01598 inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01599 {
01600 if(edge.properties().isTwoWay())
01601 Counter::increment();
01602 }
01603
01604 template<class G>
01605 int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01606 const AggregatesMap<Vertex>& aggregates) const
01607 {
01608 TwoWayCounter counter;
01609 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01610 return counter.value();
01611 }
01612
01613 template<class G>
01614 int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01615 const AggregatesMap<Vertex>& aggregates) const
01616 {
01617 OneWayCounter counter;
01618 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01619 return counter.value();
01620 }
01621
01622 template<class G>
01623 inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01624 {
01625 if(edge.properties().isOneWay())
01626 Counter::increment();
01627 }
01628
01629 template<class G>
01630 inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01631 const AggregatesMap<Vertex>& aggregates)
01632 : Counter(), connected_(connected), aggregates_(aggregates)
01633 {}
01634
01635
01636 template<class G>
01637 inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01638 {
01639 if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01640
01641 Counter::increment();
01642 else{
01643 Counter::increment();
01644 Counter::increment();
01645 }
01646 }
01647
01648 template<class G>
01649 inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01650 {
01651 ConnectivityCounter counter(connected_, aggregates);
01652 double noNeighbours=visitNeighbours(*graph_, vertex, counter);
01653 return (double)counter.value()/noNeighbours;
01654 }
01655
01656 template<class G>
01657 inline Aggregator<G>::DependencyCounter::DependencyCounter()
01658 : Counter()
01659 {}
01660
01661 template<class G>
01662 inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01663 {
01664 if(edge.properties().depends())
01665 Counter::increment();
01666 if(edge.properties().influences())
01667 Counter::increment();
01668 }
01669
01670 template<class G>
01671 int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01672 {
01673 return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01674 }
01675
01676 template<class G>
01677 std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01678 const AggregateDescriptor& aggregate,
01679 const AggregatesMap<Vertex>& aggregates) const
01680 {
01681 DependencyCounter unused, aggregated;
01682 typedef AggregateVisitor<DependencyCounter> Counter;
01683 typedef tuple<Counter,Counter> CounterTuple;
01684 CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
01685 return std::make_pair(unused.value(), aggregated.value());
01686 }
01687
01688
01689 template<class G>
01690 int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01691 {
01692 DependencyCounter counter;
01693 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01694 return counter.value();
01695 }
01696
01697 template<class G>
01698 std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01699 {
01700 typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01701 VertexList vlist;
01702 typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01703 return aggregates.template breadthFirstSearch<true,true>(vertex,
01704 aggregate_->id(), *graph_,
01705 vlist, dummy, dummy, visitedMap);
01706 }
01707
01708 template<class G>
01709 inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01710 : front_(front), graph_(graph)
01711 {}
01712
01713 template<class G>
01714 inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01715 {
01716 Vertex target = edge.target();
01717
01718 if(!graph_.getVertexProperties(target).front()){
01719 front_.push_back(target);
01720 graph_.getVertexProperties(target).setFront();
01721 }
01722 }
01723
01724
01725 template<class G>
01726 void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01727 {
01728 assert(front_.size()==0);
01729 FrontMarker frontBuilder(front_, *graph_);
01730 typedef typename Aggregate<G>::const_iterator Iterator;
01731
01732 for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01733 visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01734
01735 }
01736
01737 template<class G>
01738 inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01739 {
01740
01741 Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01742
01743 return true;
01744 }
01745
01746 template<class G>
01747 void Aggregator<G>::unmarkFront()
01748 {
01749 typedef typename VertexList::const_iterator Iterator;
01750
01751 for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01752 graph_->getVertexProperties(*vertex).resetFront();
01753
01754 front_.clear();
01755 }
01756
01757 template<class G>
01758 inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01759 {
01760 typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01761
01762 Iterator end = graph_->endEdges(vertex);
01763 for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01764 if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01765 graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01766 if( graph_->getVertexProperties(vertex).isolated() ||
01767 ((edge.properties().depends() || edge.properties().influences())
01768 && admissible(vertex, aggregates[edge.target()], aggregates)))
01769 return edge.target();
01770 }
01771 }
01772 return AggregatesMap<Vertex>::UNAGGREGATED;
01773 }
01774
01775 template<class G>
01776 Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01777 : Counter(), graph_(graph)
01778 {}
01779
01780 template<class G>
01781 void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01782 {
01783 if(graph_.getVertexProperties(edge.target()).front())
01784 Counter::increment();
01785 }
01786
01787 template<class G>
01788 int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01789 {
01790 FrontNeighbourCounter counter(*graph_);
01791 visitNeighbours(*graph_, vertex, counter);
01792 return counter.value();
01793 }
01794
01795 template<class G>
01796 template<class C>
01797 void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01798 {
01799 while(aggregate_->size() < c.minAggregateSize()){
01800 int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
01801 double maxCon=-1;
01802
01803 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01804
01805 unmarkFront();
01806 markFront(aggregates);
01807
01808 typedef typename VertexList::const_iterator Iterator;
01809
01810 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01811
01812 if(graph_->getVertexProperties(*vertex).isolated())
01813 continue;
01814
01815 int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01816
01817
01818 if( maxTwoCons == twoWayCons && twoWayCons > 0){
01819 double con = connectivity(*vertex, aggregates);
01820
01821 if(con == maxCon){
01822 int neighbours = noFrontNeighbours(*vertex);
01823
01824 if(neighbours > maxNeighbours){
01825 maxNeighbours = neighbours;
01826
01827 std::size_t distance_ = distance(*vertex, aggregates);
01828
01829 if(c.maxDistance() >= distance_){
01830 candidate = *vertex;
01831 }
01832 }
01833 }else if( con > maxCon){
01834 maxCon = con;
01835 maxNeighbours = noFrontNeighbours(*vertex);
01836 std::size_t distance_ = distance(*vertex, aggregates);
01837
01838 if(c.maxDistance() >= distance_){
01839 candidate = *vertex;
01840 }
01841 }
01842 }else if(twoWayCons > maxTwoCons){
01843 maxTwoCons = twoWayCons;
01844 maxCon = connectivity(*vertex, aggregates);
01845 maxNeighbours = noFrontNeighbours(*vertex);
01846 std::size_t distance_ = distance(*vertex, aggregates);
01847
01848 if(c.maxDistance() >= distance_){
01849 candidate = *vertex;
01850 }
01851
01852
01853 maxOneCons = std::numeric_limits<int>::max();
01854 }
01855
01856 if(twoWayCons > 0)
01857 continue;
01858
01859
01860 int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01861
01862 if(oneWayCons==0)
01863 continue;
01864
01865 if(!admissible(*vertex, aggregate_->id(), aggregates))
01866 continue;
01867
01868 if( maxOneCons == oneWayCons && oneWayCons > 0){
01869 double con = connectivity(*vertex, aggregates);
01870
01871 if(con == maxCon){
01872 int neighbours = noFrontNeighbours(*vertex);
01873
01874 if(neighbours > maxNeighbours){
01875 maxNeighbours = neighbours;
01876 std::size_t distance_ = distance(*vertex, aggregates);
01877
01878 if(c.maxDistance() >= distance_){
01879 candidate = *vertex;
01880 }
01881 }
01882 }else if( con > maxCon){
01883 maxCon = con;
01884 maxNeighbours = noFrontNeighbours(*vertex);
01885 std::size_t distance_ = distance(*vertex, aggregates);
01886 if(c.maxDistance() >= distance_){
01887 candidate = *vertex;
01888 }
01889 }
01890 }else if(oneWayCons > maxOneCons){
01891 maxOneCons = oneWayCons;
01892 maxCon = connectivity(*vertex, aggregates);
01893 maxNeighbours = noFrontNeighbours(*vertex);
01894 std::size_t distance_ = distance(*vertex, aggregates);
01895
01896 if(c.maxDistance() >= distance_){
01897 candidate = *vertex;
01898 }
01899 }
01900 }
01901
01902
01903 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01904 break;
01905
01906 aggregate_->add(candidate);
01907 }
01908 }
01909
01910 template<typename V>
01911 template<typename M, typename G, typename C>
01912 Tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01913 {
01914 Aggregator<G> aggregator;
01915 return aggregator.build(matrix, graph, *this, criterion);
01916 }
01917
01918 template<class G>
01919 template<class M, class C>
01920 Tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01921 {
01922
01923 Stack stack_(graph, *this, aggregates);
01924
01925 graph_ = &graph;
01926
01927 aggregate_ = new Aggregate<G>(graph, aggregates, connected_);
01928
01929
01930 size_ = graph.maxVertex();
01931
01932 Timer watch;
01933 watch.reset();
01934
01935 buildDependency(graph, m, c);
01936
01937 dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01938 int noAggregates, conAggregates, isoAggregates, oneAggregates;
01939 noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01940
01941 while(true){
01942 Vertex seed = stack_.pop();
01943
01944 if(seed == Stack::NullEntry)
01945
01946 break;
01947
01948
01949 if((noAggregates+1)%10000 == 0)
01950 Dune::dverb<<"c";
01951
01952 aggregate_->seed(seed);
01953
01954
01955 if(graph.getVertexProperties(seed).isolated()){
01956
01957 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01958 ++isoAggregates;
01959
01960 continue;
01961 }else
01962 growAggregate(seed, aggregates, c);
01963
01964
01965
01966 while(aggregate_->size() < c.maxAggregateSize()){
01967
01968 unmarkFront();
01969 markFront(aggregates);
01970
01971 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01972
01973 typedef typename VertexList::const_iterator Iterator;
01974
01975 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01976
01977 if(graph.getVertexProperties(*vertex).isolated())
01978 continue;
01979
01980 if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
01981 (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
01982 !admissible( *vertex, aggregate_->id(), aggregates) ))
01983 continue;
01984
01985 std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
01986 aggregates);
01987
01988
01989
01990
01991 if(neighbourPair.first >= neighbourPair.second)
01992 continue;
01993
01994 if(distance(*vertex, aggregates) > c.maxDistance())
01995 continue;
01996 candidate = *vertex;
01997 break;
01998 }
01999
02000 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break;
02001
02002 aggregate_->add(candidate);
02003
02004 }
02005
02006
02007 if(aggregate_->size()==1)
02008 if(!graph.getVertexProperties(seed).isolated()){
02009 Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02010
02011 if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02012 aggregates[seed] = aggregates[mergedNeighbour];
02013
02014
02015
02016
02017
02018
02019
02020 }else{
02021 ++oneAggregates;
02022 ++conAggregates;
02023 }
02024
02025 }else{
02026 ++oneAggregates;
02027 ++isoAggregates;
02028 }
02029 else{
02030 if(graph.getVertexProperties(seed).isolated())
02031 ++isoAggregates;
02032 else
02033 ++conAggregates;
02034 }
02035 unmarkFront();
02036 markFront(aggregates);
02037 seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02038 unmarkFront();
02039 }
02040
02041 Dune::dinfo<<"connected aggregates: "<<conAggregates;
02042 Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02043 Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02044
02045 delete aggregate_;
02046 return Tuple<int,int,int>(conAggregates,isoAggregates,oneAggregates);
02047 }
02048
02049 template<class G>
02050 inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02051 {
02052 typedef typename VertexList::const_iterator Iterator;
02053
02054 Iterator end= front_.end();
02055 int count=0;
02056 for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02057 stack_.push(*vertex);
02058
02059
02060
02061
02062 }
02063
02064 template<class G>
02065 Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02066 const AggregatesMap<Vertex>& aggregates)
02067 : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02068 {
02069 vals_ = new Vertex[N];
02070 }
02071
02072 template<class G>
02073 Aggregator<G>::Stack::~Stack()
02074 {
02075 Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02076 delete[] vals_;
02077 }
02078
02079 template<class G>
02080 const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
02081 = std::numeric_limits<typename G::VertexDescriptor>::max();
02082
02083 template<class G>
02084 inline bool Aggregator<G>::Stack::push(const Vertex& v)
02085 {
02086 if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02087 localPush(v);
02088 return true;
02089 }else
02090 return false;
02091 }
02092
02093 template<class G>
02094 inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02095 {
02096 vals_[head_] = v;
02097 size_ = std::min<int>(size_+1, N);
02098 head_ = (head_+N+1)%N;
02099 }
02100
02101 template<class G>
02102 void Aggregator<G>::Stack::fill()
02103 {
02104 int isolated = 0, connected=0;
02105 int isoumin, umin;
02106 filled_++;
02107
02108 head_ = size_ = 0;
02109 isoumin = umin = std::numeric_limits<int>::max();
02110
02111 typedef typename MatrixGraph::ConstVertexIterator Iterator;
02112
02113 const Iterator end = graph_.end();
02114
02115 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02116
02117 if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02118 continue;
02119
02120 if(vertex.properties().isolated()){
02121 isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02122 isolated++;
02123 }else{
02124 umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02125 connected++;
02126 }
02127 }
02128
02129 if(connected + isolated == 0)
02130
02131 return;
02132
02133 if(connected > 0){
02134
02135 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02136 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated()
02137 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02138 localPush(*vertex);
02139 }else{
02140 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02141 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated()
02142 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02143 localPush(*vertex);
02144 }
02145 maxSize_ = std::max(size_, maxSize_);
02146 }
02147
02148 template<class G>
02149 inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02150 {
02151 while(size_>0){
02152 head_ = (head_ + N -1) % N;
02153 size_--;
02154 Vertex v = vals_[head_];
02155 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02156 return v;
02157 }
02158
02159 fill();
02160
02161
02162 while(size_>0){
02163 head_ = (head_ + N -1) % N;
02164 size_--;
02165 Vertex v = vals_[head_];
02166 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02167 return v;
02168 }
02169 return NullEntry;
02170 }
02171
02172 template<class V>
02173 void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
02174 {
02175 std::ios_base::fmtflags oldOpts=os.flags();
02176
02177 os.setf(std::ios_base::right, std::ios_base::adjustfield);
02178
02179 V max=0;
02180 int width=1;
02181
02182 for(int i=0; i< n*m; i++)
02183 max=std::max(max, aggregates[i]);
02184
02185 for(int i=10; i < 1000000; i*=10)
02186 if(max/i>0)
02187 width++;
02188 else
02189 break;
02190
02191 for(int j=0, entry=0; j < m; j++){
02192 for(int i=0; i<n; i++, entry++){
02193 os.width(width);
02194 os<<aggregates[entry]<<" ";
02195 }
02196
02197 os<<std::endl;
02198 }
02199 os<<std::endl;
02200 os.flags(oldOpts);
02201 }
02202
02203
02204 }
02205
02206 }
02207
02208
02209 #endif