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:
00318 enum{
00319 is_sign_preserving = true
00320 };
00321
00326 template<class M>
00327 typename M::field_type operator()(const M& m) const
00328 {
00329 return m[0][0];
00330 }
00331 };
00332
00338 struct RowSum
00339 {
00340
00341 enum{
00342 is_sign_preserving = false
00343 };
00348 template<class M>
00349 typename M::field_type operator()(const M& m) const
00350 {
00351 return m.infinity_norm();
00352 }
00353 };
00354
00364 template<class M, class Norm>
00365 class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
00366 {};
00367
00368
00380 template<class M, class Norm>
00381 class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
00382 {};
00383
00384 template<class G> class Aggregator;
00385
00386
00394 template<class V>
00395 class AggregatesMap
00396 {
00397 public:
00398
00402 static const V UNAGGREGATED;
00403
00407 static const V ISOLATED;
00411 typedef V VertexDescriptor;
00412
00416 typedef V AggregateDescriptor;
00417
00422 typedef PoolAllocator<VertexDescriptor,100> Allocator;
00423
00428 typedef SLList<VertexDescriptor,Allocator> VertexList;
00429
00433 class DummyEdgeVisitor
00434 {
00435 public:
00436 template<class EdgeIterator>
00437 void operator()(const EdgeIterator& egde) const
00438 {}
00439 };
00440
00441
00445 AggregatesMap();
00446
00452 AggregatesMap(std::size_t noVertices);
00453
00457 ~AggregatesMap();
00458
00466 template<class M, class G, class C>
00467 tuple<int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion);
00468
00488 template<bool reset, class G, class F, class VM>
00489 std::size_t breadthFirstSearch(const VertexDescriptor& start,
00490 const AggregateDescriptor& aggregate,
00491 const G& graph,
00492 F& aggregateVisitor,
00493 VM& visitedMap) const;
00494
00518 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
00519 std::size_t breadthFirstSearch(const VertexDescriptor& start,
00520 const AggregateDescriptor& aggregate,
00521 const G& graph, L& visited, F1& aggregateVisitor,
00522 F2& nonAggregateVisitor,
00523 VM& visitedMap) const;
00524
00530 void allocate(std::size_t noVertices);
00531
00535 std::size_t noVertices() const;
00536
00540 void free();
00541
00547 AggregateDescriptor& operator[](const VertexDescriptor& v);
00548
00554 const AggregateDescriptor& operator[](const VertexDescriptor& v) const;
00555
00556 typedef const AggregateDescriptor* const_iterator;
00557
00558 const_iterator begin() const
00559 {
00560 return aggregates_;
00561 }
00562
00563 const_iterator end() const
00564 {
00565 return aggregates_+noVertices();
00566 }
00567
00568 typedef AggregateDescriptor* iterator;
00569
00570 iterator begin()
00571 {
00572 return aggregates_;
00573 }
00574
00575 iterator end()
00576 {
00577 return aggregates_+noVertices();
00578 }
00579 private:
00581 AggregatesMap(const AggregatesMap<V>& map)
00582 {
00583 throw "Auch!";
00584 }
00585
00587 AggregatesMap<V>& operator=(const AggregatesMap<V>& map)
00588 {
00589 throw "Auch!";
00590 return this;
00591 }
00592
00596 AggregateDescriptor* aggregates_;
00597
00601 std::size_t noVertices_;
00602 };
00603
00604
00609 template<class G, class S>
00610 class Aggregate
00611 {
00612
00613 public:
00614
00615
00616
00617
00618 typedef G MatrixGraph;
00622 typedef typename MatrixGraph::VertexDescriptor Vertex;
00623
00628 typedef PoolAllocator<Vertex,100> Allocator;
00629
00634 typedef SLList<Vertex,Allocator> VertexList;
00635
00636
00641 typedef S VertexSet;
00642
00644 typedef typename VertexList::const_iterator const_iterator;
00645
00649 typedef std::size_t* SphereMap;
00650
00658 Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
00659 VertexSet& connectivity);
00660
00667 void reconstruct(const Vertex& vertex);
00668
00672 void seed(const Vertex& vertex);
00673
00677 void add(const Vertex& vertex);
00678
00682 void clear();
00683
00687 typename VertexList::size_type size();
00688
00692 int id();
00693
00695 const_iterator begin() const;
00696
00698 const_iterator end() const;
00699
00700 private:
00704 VertexList vertices_;
00705
00710 int id_;
00711
00715 const MatrixGraph& graph_;
00716
00720 AggregatesMap<Vertex>& aggregates_;
00721
00725 VertexSet& connected_;
00726 };
00727
00731 template<class G>
00732 class Aggregator
00733 {
00734 public:
00735
00739 typedef G MatrixGraph;
00740
00744 typedef typename MatrixGraph::VertexDescriptor Vertex;
00745
00747 typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor;
00748
00752 Aggregator();
00753
00757 ~Aggregator();
00758
00771 template<class M, class C>
00772 tuple<int,int,int> build(const M& m, G& graph,
00773 AggregatesMap<Vertex>& aggregates, const C& c);
00774 private:
00779 typedef PoolAllocator<Vertex,1> Allocator;
00780
00784 typedef SLList<Vertex,Allocator> VertexList;
00785
00789 typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
00790
00794 typedef std::size_t* SphereMap;
00795
00799 MatrixGraph* graph_;
00800
00804 Aggregate<MatrixGraph,VertexSet>* aggregate_;
00805
00809 VertexList front_;
00810
00814 VertexSet connected_;
00815
00819 int size_;
00820
00824 class Stack
00825 {
00826 public:
00827 static const Vertex NullEntry;
00828
00829 Stack(const MatrixGraph& graph,
00830 const Aggregator<G>& aggregatesBuilder,
00831 const AggregatesMap<Vertex>& aggregates);
00832 ~Stack();
00833 bool push(const Vertex& v);
00834 void fill();
00835 Vertex pop();
00836 private:
00837 enum{ N = 256000 };
00838
00840 const MatrixGraph& graph_;
00842 const Aggregator<G>& aggregatesBuilder_;
00844 const AggregatesMap<Vertex>& aggregates_;
00846 int size_;
00847 int maxSize_;
00849 int head_;
00850 int filled_;
00851
00853 Vertex* vals_;
00854
00855 void localPush(const Vertex& v);
00856 };
00857
00858 friend class Stack;
00859
00863 template<class C>
00864 void buildDependency(MatrixGraph& graph,
00865 const typename C::Matrix& matrix,
00866 C criterion);
00867
00878 template<class V>
00879 void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
00880 const AggregatesMap<Vertex>& aggregates,
00881 V& visitor) const;
00882
00887 template<class V>
00888 class AggregateVisitor
00889 {
00890 public:
00894 typedef V Visitor;
00902 AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
00903 Visitor& visitor);
00904
00911 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00912
00913 private:
00915 const AggregatesMap<Vertex>& aggregates_;
00917 AggregateDescriptor aggregate_;
00919 Visitor* visitor_;
00920 };
00921
00925 class Counter
00926 {
00927 public:
00929 Counter();
00931 int value();
00932
00933 protected:
00935 void increment();
00937 void decrement();
00938
00939 private:
00940 int count_;
00941 };
00942
00943
00948 class FrontNeighbourCounter : public Counter
00949 {
00950 public:
00955 FrontNeighbourCounter(const MatrixGraph& front);
00956
00957 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00958
00959 private:
00960 const MatrixGraph& graph_;
00961 };
00962
00967 int noFrontNeighbours(const Vertex& vertex) const;
00968
00972 class TwoWayCounter : public Counter
00973 {
00974 public:
00975 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00976 };
00977
00989 int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
00990 const AggregatesMap<Vertex>& aggregates) const;
00991
00995 class OneWayCounter : public Counter
00996 {
00997 public:
00998 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00999 };
01000
01012 int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
01013 const AggregatesMap<Vertex>& aggregates) const;
01014
01021 class ConnectivityCounter : public Counter
01022 {
01023 public:
01030 ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
01031
01032 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01033
01034 private:
01036 const VertexSet& connected_;
01038 const AggregatesMap<Vertex>& aggregates_;
01039
01040 };
01041
01053 double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01054
01062 class DependencyCounter: public Counter
01063 {
01064 public:
01068 DependencyCounter();
01069
01070 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01071 };
01072
01079 class FrontMarker
01080 {
01081 public:
01088 FrontMarker(VertexList& front, MatrixGraph& graph);
01089
01090 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01091
01092 private:
01094 VertexList& front_;
01096 MatrixGraph& graph_;
01097 };
01098
01105 void markFront(const AggregatesMap<Vertex>& aggregates);
01106
01110 void unmarkFront();
01111
01126 int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01127
01141 std::pair<int,int> neighbours(const Vertex& vertex,
01142 const AggregateDescriptor& aggregate,
01143 const AggregatesMap<Vertex>& aggregates) const;
01160 int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01161
01169 bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01170
01177 void seedFromFront(Stack& stack, bool isolated);
01178
01186 std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
01187
01196 Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01197
01205 template<class C>
01206 void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
01207 };
01208
01209 template<class M, class N>
01210 inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
01211 {
01212 matrix_ = matrix;
01213 }
01214
01215 template<class M, class N>
01216 inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
01217 {
01218 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01219 row_ = index;
01220 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01221 }
01222
01223 template<class M, class N>
01224 inline void SymmetricDependency<M,N>::examine(const ColIter& col)
01225 {
01226 typename Matrix::field_type eij = norm_(*col);
01227 typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]);
01228
01229
01230 if(!N::is_sign_preserving || eij<0 || eji<0)
01231 maxValue_ = std::max(maxValue_,
01232 eij /diagonal_ * eji/
01233 norm_(matrix_->operator[](col.index())[col.index()]));
01234 }
01235
01236 template<class M, class N>
01237 template<class G>
01238 inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01239 {
01240 typename Matrix::field_type eij = norm_(*col);
01241 typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]);
01242
01243
01244 if(!N::is_sign_preserving || (eij<0 || eji<0))
01245 if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) *
01246 eij/ diagonal_ > alpha() * maxValue_){
01247 edge.properties().setDepends();
01248 edge.properties().setInfluences();
01249
01250 typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
01251 other.setInfluences();
01252 other.setDepends();
01253 }
01254 }
01255
01256 template<class M, class N>
01257 inline bool SymmetricDependency<M,N>::isIsolated()
01258 {
01259 return maxValue_ < beta();
01260 }
01261
01262
01263 template<class M, class N>
01264 inline void Dependency<M,N>::init(const Matrix* matrix)
01265 {
01266 matrix_ = matrix;
01267 }
01268
01269 template<class M, class N>
01270 inline void Dependency<M,N>::initRow(const Row& row, int index)
01271 {
01272 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01273 row_ = index;
01274 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01275 }
01276
01277 template<class M, class N>
01278 inline void Dependency<M,N>::examine(const ColIter& col)
01279 {
01280 maxValue_ = std::max(maxValue_,
01281 -norm_(*col));
01282 }
01283
01284 template<class M, class N>
01285 template<class G>
01286 inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01287 {
01288 if(-norm_(*col) >= maxValue_ * alpha()){
01289 edge.properties().setDepends();
01290 edge.properties().setInfluences();
01291 }
01292 }
01293
01294 template<class M, class N>
01295 inline bool Dependency<M,N>::isIsolated()
01296 {
01297 return maxValue_ < beta() * diagonal_;
01298 }
01299
01300 template<class G,class S>
01301 Aggregate<G,S>::Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
01302 VertexSet& connected)
01303 : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
01304 connected_(connected)
01305 {}
01306
01307 template<class G,class S>
01308 void Aggregate<G,S>::reconstruct(const Vertex& vertex)
01309 {
01310 vertices_.push_back(vertex);
01311 typedef typename VertexList::const_iterator iterator;
01312 iterator begin = vertices_.begin();
01313 iterator end = vertices_.end();
01314 throw "Not yet implemented";
01315
01316 while(begin!=end){
01317
01318 }
01319
01320 }
01321
01322 template<class G,class S>
01323 inline void Aggregate<G,S>::seed(const Vertex& vertex)
01324 {
01325 dvverb<<"Connected cleared"<<std::endl;
01326 connected_.clear();
01327 vertices_.clear();
01328 connected_.insert(vertex);
01329 dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
01330 id_ = vertex;
01331 add(vertex);
01332 }
01333
01334
01335 template<class G,class S>
01336 inline void Aggregate<G,S>::add(const Vertex& vertex)
01337 {
01338 vertices_.push_back(vertex);
01339 aggregates_[vertex]=id_;
01340
01341 typedef typename MatrixGraph::ConstEdgeIterator iterator;
01342 const iterator end = graph_.endEdges(vertex);
01343 for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge){
01344 dvverb << " Inserting "<<aggregates_[edge.target()];
01345 connected_.insert(aggregates_[edge.target()]);
01346 dvverb <<" size="<<connected_.size();
01347 }
01348 dvverb <<std::endl;
01349 }
01350 template<class G,class S>
01351 inline void Aggregate<G,S>::clear()
01352 {
01353 vertices_.clear();
01354 connected_.clear();
01355 id_=-1;
01356 }
01357
01358 template<class G,class S>
01359 inline typename Aggregate<G,S>::VertexList::size_type
01360 Aggregate<G,S>::size()
01361 {
01362 return vertices_.size();
01363 }
01364
01365 template<class G,class S>
01366 inline int Aggregate<G,S>::id()
01367 {
01368 return id_;
01369 }
01370
01371 template<class G,class S>
01372 inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::begin() const
01373 {
01374 return vertices_.begin();
01375 }
01376
01377 template<class G,class S>
01378 inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
01379 {
01380 return vertices_.end();
01381 }
01382
01383 template<class V>
01384 const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
01385
01386 template<class V>
01387 const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
01388
01389 template<class V>
01390 AggregatesMap<V>::AggregatesMap()
01391 : aggregates_(0)
01392 {}
01393
01394 template<class V>
01395 AggregatesMap<V>::~AggregatesMap()
01396 {
01397 if(aggregates_!=0)
01398 delete[] aggregates_;
01399 }
01400
01401
01402 template<class V>
01403 inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
01404 {
01405 allocate(noVertices);
01406 }
01407
01408 template<class V>
01409 inline std::size_t AggregatesMap<V>::AggregatesMap::noVertices() const
01410 {
01411 return noVertices_;
01412 }
01413
01414 template<class V>
01415 inline void AggregatesMap<V>::allocate(std::size_t noVertices)
01416 {
01417 aggregates_ = new AggregateDescriptor[noVertices];
01418 noVertices_ = noVertices;
01419
01420 for(std::size_t i=0; i < noVertices; i++)
01421 aggregates_[i]=UNAGGREGATED;
01422 }
01423
01424 template<class V>
01425 inline void AggregatesMap<V>::free()
01426 {
01427 assert(aggregates_ != 0);
01428 delete[] aggregates_;
01429 aggregates_=0;
01430 }
01431
01432 template<class V>
01433 inline typename AggregatesMap<V>::AggregateDescriptor&
01434 AggregatesMap<V>::operator[](const VertexDescriptor& v)
01435 {
01436 return aggregates_[v];
01437 }
01438
01439 template<class V>
01440 inline const typename AggregatesMap<V>::AggregateDescriptor&
01441 AggregatesMap<V>::operator[](const VertexDescriptor& v) const
01442 {
01443 return aggregates_[v];
01444 }
01445
01446 template<class V>
01447 template<bool reset, class G, class F,class VM>
01448 inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01449 const AggregateDescriptor& aggregate,
01450 const G& graph, F& aggregateVisitor,
01451 VM& visitedMap) const
01452 {
01453 VertexList vlist;
01454
01455 DummyEdgeVisitor dummy;
01456 return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
01457 }
01458
01459 template<class V>
01460 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
01461 std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01462 const AggregateDescriptor& aggregate,
01463 const G& graph,
01464 L& visited,
01465 F1& aggregateVisitor,
01466 F2& nonAggregateVisitor,
01467 VM& visitedMap) const
01468 {
01469 typedef typename L::const_iterator ListIterator;
01470 int visitedSpheres = 0;
01471
01472 visited.push_back(start);
01473 put(visitedMap, start, true);
01474
01475 ListIterator current = visited.begin();
01476 ListIterator end = visited.end();
01477 std::size_t i=0, size=visited.size();
01478
01479
01480
01481 while(current != end){
01482
01483 for(;i<size; ++current, ++i){
01484 typedef typename G::ConstEdgeIterator EdgeIterator;
01485 const EdgeIterator endEdge = graph.endEdges(*current);
01486
01487 for(EdgeIterator edge = graph.beginEdges(*current);
01488 edge != endEdge; ++edge){
01489
01490 if(aggregates_[edge.target()]==aggregate){
01491 if(!get(visitedMap, edge.target())){
01492 put(visitedMap, edge.target(), true);
01493 visited.push_back(edge.target());
01494 aggregateVisitor(edge);
01495 }
01496 }else
01497 nonAggregateVisitor(edge);
01498 }
01499 }
01500 end = visited.end();
01501 size = visited.size();
01502 if(current != end)
01503 visitedSpheres++;
01504 }
01505
01506 if(reset)
01507 for(current = visited.begin(); current != end; ++current)
01508 put(visitedMap, *current, false);
01509
01510
01511 if(remove)
01512 visited.clear();
01513
01514 return visitedSpheres;
01515 }
01516
01517 template<class G>
01518 Aggregator<G>::Aggregator()
01519 : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
01520 {}
01521
01522 template<class G>
01523 Aggregator<G>::~Aggregator()
01524 {
01525 size_=-1;
01526 }
01527
01528 template<class G>
01529 template<class C>
01530 void Aggregator<G>::buildDependency(MatrixGraph& graph,
01531 const typename C::Matrix& matrix,
01532 C criterion)
01533 {
01534
01535 typedef C Criterion;
01536
01537
01538 typedef typename C::Matrix Matrix;
01539 typedef typename MatrixGraph::VertexIterator VertexIterator;
01540
01541 criterion.init(&matrix);
01542
01543 for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex){
01544 typedef typename Matrix::row_type Row;
01545
01546 const Row& row = matrix[*vertex];
01547
01548
01549
01550
01551 criterion.initRow(row, *vertex);
01552
01553
01554
01555 typedef typename Matrix::ConstColIterator ColIterator;
01556 ColIterator end = row.end();
01557 for(ColIterator col = row.begin(); col != end; ++col)
01558 if(col.index()!=*vertex)
01559 criterion.examine(col);
01560
01561
01562
01563
01564
01565 if(criterion.isIsolated()){
01566
01567 vertex.properties().setIsolated();
01568 }else{
01569
01570 typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01571 typedef typename Matrix::ConstColIterator ColIterator;
01572 EdgeIterator end = vertex.end();
01573 ColIterator col = matrix[*vertex].begin();
01574
01575 for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01576
01577 while(col.index()!=edge.target())
01578 ++col;
01579 criterion.examine(graph, edge, col);
01580 }
01581 }
01582
01583 }
01584 }
01585
01586
01587 template<class G>
01588 template<class V>
01589 inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
01590 const AggregateDescriptor& aggregate, V& visitor)
01591 : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01592 {}
01593
01594 template<class G>
01595 template<class V>
01596 inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01597 {
01598 if(aggregates_[edge.target()]==aggregate_)
01599 visitor_->operator()(edge);
01600 }
01601
01602 template<class G>
01603 template<class V>
01604 inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01605 const AggregateDescriptor& aggregate,
01606 const AggregatesMap<Vertex>& aggregates,
01607 V& visitor) const
01608 {
01609
01610 AggregateVisitor<V> v(aggregates, aggregate, visitor);
01611 visitNeighbours(*graph_, vertex, v);
01612 }
01613
01614
01615 template<class G>
01616 inline Aggregator<G>::Counter::Counter()
01617 : count_(0)
01618 {}
01619
01620 template<class G>
01621 inline void Aggregator<G>::Counter::increment()
01622 {
01623 ++count_;
01624 }
01625
01626 template<class G>
01627 inline void Aggregator<G>::Counter::decrement()
01628 {
01629 --count_;
01630 }
01631 template<class G>
01632 inline int Aggregator<G>::Counter::value()
01633 {
01634 return count_;
01635 }
01636
01637 template<class G>
01638 inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01639 {
01640 if(edge.properties().isTwoWay())
01641 Counter::increment();
01642 }
01643
01644 template<class G>
01645 int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01646 const AggregatesMap<Vertex>& aggregates) const
01647 {
01648 TwoWayCounter counter;
01649 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01650 return counter.value();
01651 }
01652
01653 template<class G>
01654 int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01655 const AggregatesMap<Vertex>& aggregates) const
01656 {
01657 OneWayCounter counter;
01658 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01659 return counter.value();
01660 }
01661
01662 template<class G>
01663 inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01664 {
01665 if(edge.properties().isOneWay())
01666 Counter::increment();
01667 }
01668
01669 template<class G>
01670 inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01671 const AggregatesMap<Vertex>& aggregates)
01672 : Counter(), connected_(connected), aggregates_(aggregates)
01673 {}
01674
01675
01676 template<class G>
01677 inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01678 {
01679 if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01680
01681 Counter::increment();
01682 else{
01683 Counter::increment();
01684 Counter::increment();
01685 }
01686 }
01687
01688 template<class G>
01689 inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01690 {
01691 ConnectivityCounter counter(connected_, aggregates);
01692 double noNeighbours=visitNeighbours(*graph_, vertex, counter);
01693 return (double)counter.value()/noNeighbours;
01694 }
01695
01696 template<class G>
01697 inline Aggregator<G>::DependencyCounter::DependencyCounter()
01698 : Counter()
01699 {}
01700
01701 template<class G>
01702 inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01703 {
01704 if(edge.properties().depends())
01705 Counter::increment();
01706 if(edge.properties().influences())
01707 Counter::increment();
01708 }
01709
01710 template<class G>
01711 int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01712 {
01713 return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01714 }
01715
01716 template<class G>
01717 std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01718 const AggregateDescriptor& aggregate,
01719 const AggregatesMap<Vertex>& aggregates) const
01720 {
01721 DependencyCounter unused, aggregated;
01722 typedef AggregateVisitor<DependencyCounter> Counter;
01723 typedef tuple<Counter,Counter> CounterTuple;
01724 CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
01725 return std::make_pair(unused.value(), aggregated.value());
01726 }
01727
01728
01729 template<class G>
01730 int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01731 {
01732 DependencyCounter counter;
01733 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01734 return counter.value();
01735 }
01736
01737 template<class G>
01738 std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01739 {
01740 typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01741 VertexList vlist;
01742 typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01743 return aggregates.template breadthFirstSearch<true,true>(vertex,
01744 aggregate_->id(), *graph_,
01745 vlist, dummy, dummy, visitedMap);
01746 }
01747
01748 template<class G>
01749 inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01750 : front_(front), graph_(graph)
01751 {}
01752
01753 template<class G>
01754 inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01755 {
01756 Vertex target = edge.target();
01757
01758 if(!graph_.getVertexProperties(target).front()){
01759 front_.push_back(target);
01760 graph_.getVertexProperties(target).setFront();
01761 }
01762 }
01763
01764
01765 template<class G>
01766 void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01767 {
01768 assert(front_.size()==0);
01769 FrontMarker frontBuilder(front_, *graph_);
01770 typedef typename Aggregate<G,VertexSet>::const_iterator Iterator;
01771
01772 for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01773 visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01774
01775 }
01776
01777 template<class G>
01778 inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01779 {
01780
01781 Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01782
01783 return true;
01784 }
01785
01786 template<class G>
01787 void Aggregator<G>::unmarkFront()
01788 {
01789 typedef typename VertexList::const_iterator Iterator;
01790
01791 for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01792 graph_->getVertexProperties(*vertex).resetFront();
01793
01794 front_.clear();
01795 }
01796
01797 template<class G>
01798 inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01799 {
01800 typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01801
01802 Iterator end = graph_->endEdges(vertex);
01803 for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01804 if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01805 graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01806 if( graph_->getVertexProperties(vertex).isolated() ||
01807 ((edge.properties().depends() || edge.properties().influences())
01808 && admissible(vertex, aggregates[edge.target()], aggregates)))
01809 return edge.target();
01810 }
01811 }
01812 return AggregatesMap<Vertex>::UNAGGREGATED;
01813 }
01814
01815 template<class G>
01816 Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01817 : Counter(), graph_(graph)
01818 {}
01819
01820 template<class G>
01821 void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01822 {
01823 if(graph_.getVertexProperties(edge.target()).front())
01824 Counter::increment();
01825 }
01826
01827 template<class G>
01828 int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01829 {
01830 FrontNeighbourCounter counter(*graph_);
01831 visitNeighbours(*graph_, vertex, counter);
01832 return counter.value();
01833 }
01834
01835 template<class G>
01836 template<class C>
01837 void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01838 {
01839 while(aggregate_->size() < c.minAggregateSize()){
01840 int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
01841 double maxCon=-1;
01842
01843 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01844
01845 unmarkFront();
01846 markFront(aggregates);
01847
01848 typedef typename VertexList::const_iterator Iterator;
01849
01850 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01851
01852 if(graph_->getVertexProperties(*vertex).isolated())
01853 continue;
01854
01855 int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01856
01857
01858 if( maxTwoCons == twoWayCons && twoWayCons > 0){
01859 double con = connectivity(*vertex, aggregates);
01860
01861 if(con == maxCon){
01862 int neighbours = noFrontNeighbours(*vertex);
01863
01864 if(neighbours > maxNeighbours){
01865 maxNeighbours = neighbours;
01866
01867 std::size_t distance_ = distance(*vertex, aggregates);
01868
01869 if(c.maxDistance() >= distance_){
01870 candidate = *vertex;
01871 }
01872 }
01873 }else if( con > maxCon){
01874 maxCon = con;
01875 maxNeighbours = noFrontNeighbours(*vertex);
01876 std::size_t distance_ = distance(*vertex, aggregates);
01877
01878 if(c.maxDistance() >= distance_){
01879 candidate = *vertex;
01880 }
01881 }
01882 }else if(twoWayCons > maxTwoCons){
01883 maxTwoCons = twoWayCons;
01884 maxCon = connectivity(*vertex, aggregates);
01885 maxNeighbours = noFrontNeighbours(*vertex);
01886 std::size_t distance_ = distance(*vertex, aggregates);
01887
01888 if(c.maxDistance() >= distance_){
01889 candidate = *vertex;
01890 }
01891
01892
01893 maxOneCons = std::numeric_limits<int>::max();
01894 }
01895
01896 if(twoWayCons > 0)
01897 continue;
01898
01899
01900 int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01901
01902 if(oneWayCons==0)
01903 continue;
01904
01905 if(!admissible(*vertex, aggregate_->id(), aggregates))
01906 continue;
01907
01908 if( maxOneCons == oneWayCons && oneWayCons > 0){
01909 double con = connectivity(*vertex, aggregates);
01910
01911 if(con == maxCon){
01912 int neighbours = noFrontNeighbours(*vertex);
01913
01914 if(neighbours > maxNeighbours){
01915 maxNeighbours = neighbours;
01916 std::size_t distance_ = distance(*vertex, aggregates);
01917
01918 if(c.maxDistance() >= distance_){
01919 candidate = *vertex;
01920 }
01921 }
01922 }else if( con > maxCon){
01923 maxCon = con;
01924 maxNeighbours = noFrontNeighbours(*vertex);
01925 std::size_t distance_ = distance(*vertex, aggregates);
01926 if(c.maxDistance() >= distance_){
01927 candidate = *vertex;
01928 }
01929 }
01930 }else if(oneWayCons > maxOneCons){
01931 maxOneCons = oneWayCons;
01932 maxCon = connectivity(*vertex, aggregates);
01933 maxNeighbours = noFrontNeighbours(*vertex);
01934 std::size_t distance_ = distance(*vertex, aggregates);
01935
01936 if(c.maxDistance() >= distance_){
01937 candidate = *vertex;
01938 }
01939 }
01940 }
01941
01942
01943 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01944 break;
01945
01946 aggregate_->add(candidate);
01947 }
01948 }
01949
01950 template<typename V>
01951 template<typename M, typename G, typename C>
01952 tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01953 {
01954 Aggregator<G> aggregator;
01955 return aggregator.build(matrix, graph, *this, criterion);
01956 }
01957
01958 template<class G>
01959 template<class M, class C>
01960 tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01961 {
01962
01963 Stack stack_(graph, *this, aggregates);
01964
01965 graph_ = &graph;
01966
01967 aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_);
01968
01969
01970 size_ = graph.maxVertex();
01971
01972 Timer watch;
01973 watch.reset();
01974
01975 buildDependency(graph, m, c);
01976
01977 dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01978 int noAggregates, conAggregates, isoAggregates, oneAggregates;
01979 noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01980
01981 while(true){
01982 Vertex seed = stack_.pop();
01983
01984 if(seed == Stack::NullEntry)
01985
01986 break;
01987
01988
01989 if((noAggregates+1)%10000 == 0)
01990 Dune::dverb<<"c";
01991
01992 aggregate_->seed(seed);
01993
01994
01995 if(graph.getVertexProperties(seed).isolated()){
01996
01997 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01998 ++isoAggregates;
01999
02000 continue;
02001 }else
02002 growAggregate(seed, aggregates, c);
02003
02004
02005
02006 while(aggregate_->size() < c.maxAggregateSize()){
02007
02008 unmarkFront();
02009 markFront(aggregates);
02010
02011 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
02012
02013 typedef typename VertexList::const_iterator Iterator;
02014
02015 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
02016
02017 if(graph.getVertexProperties(*vertex).isolated())
02018 continue;
02019
02020 if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
02021 (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
02022 !admissible( *vertex, aggregate_->id(), aggregates) ))
02023 continue;
02024
02025 std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
02026 aggregates);
02027
02028
02029
02030
02031 if(neighbourPair.first >= neighbourPair.second)
02032 continue;
02033
02034 if(distance(*vertex, aggregates) > c.maxDistance())
02035 continue;
02036 candidate = *vertex;
02037 break;
02038 }
02039
02040 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break;
02041
02042 aggregate_->add(candidate);
02043
02044 }
02045
02046
02047 if(aggregate_->size()==1)
02048 if(!graph.getVertexProperties(seed).isolated()){
02049 Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02050
02051 if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02052 aggregates[seed] = aggregates[mergedNeighbour];
02053
02054
02055
02056
02057
02058
02059
02060 }else{
02061 ++oneAggregates;
02062 ++conAggregates;
02063 }
02064
02065 }else{
02066 ++oneAggregates;
02067 ++isoAggregates;
02068 }
02069 else{
02070 if(graph.getVertexProperties(seed).isolated())
02071 ++isoAggregates;
02072 else
02073 ++conAggregates;
02074 }
02075 unmarkFront();
02076 markFront(aggregates);
02077 seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02078 unmarkFront();
02079 }
02080
02081 Dune::dinfo<<"connected aggregates: "<<conAggregates;
02082 Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02083 Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02084
02085 delete aggregate_;
02086 return make_tuple(conAggregates,isoAggregates,oneAggregates);
02087 }
02088
02089 template<class G>
02090 inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02091 {
02092 typedef typename VertexList::const_iterator Iterator;
02093
02094 Iterator end= front_.end();
02095 int count=0;
02096 for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02097 stack_.push(*vertex);
02098
02099
02100
02101
02102 }
02103
02104 template<class G>
02105 Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02106 const AggregatesMap<Vertex>& aggregates)
02107 : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02108 {
02109 vals_ = new Vertex[N];
02110 }
02111
02112 template<class G>
02113 Aggregator<G>::Stack::~Stack()
02114 {
02115 Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02116 delete[] vals_;
02117 }
02118
02119 template<class G>
02120 const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
02121 = std::numeric_limits<typename G::VertexDescriptor>::max();
02122
02123 template<class G>
02124 inline bool Aggregator<G>::Stack::push(const Vertex& v)
02125 {
02126 if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02127 localPush(v);
02128 return true;
02129 }else
02130 return false;
02131 }
02132
02133 template<class G>
02134 inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02135 {
02136 vals_[head_] = v;
02137 size_ = std::min<int>(size_+1, N);
02138 head_ = (head_+N+1)%N;
02139 }
02140
02141 template<class G>
02142 void Aggregator<G>::Stack::fill()
02143 {
02144 int isolated = 0, connected=0;
02145 int isoumin, umin;
02146 filled_++;
02147
02148 head_ = size_ = 0;
02149 isoumin = umin = std::numeric_limits<int>::max();
02150
02151 typedef typename MatrixGraph::ConstVertexIterator Iterator;
02152
02153 const Iterator end = graph_.end();
02154
02155 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02156
02157 if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02158 continue;
02159
02160 if(vertex.properties().isolated()){
02161 isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02162 isolated++;
02163 }else{
02164 umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02165 connected++;
02166 }
02167 }
02168
02169 if(connected + isolated == 0)
02170
02171 return;
02172
02173 if(connected > 0){
02174
02175 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02176 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated()
02177 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02178 localPush(*vertex);
02179 }else{
02180 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02181 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated()
02182 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02183 localPush(*vertex);
02184 }
02185 maxSize_ = std::max(size_, maxSize_);
02186 }
02187
02188 template<class G>
02189 inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02190 {
02191 while(size_>0){
02192 head_ = (head_ + N -1) % N;
02193 size_--;
02194 Vertex v = vals_[head_];
02195 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02196 return v;
02197 }
02198
02199 fill();
02200
02201
02202 while(size_>0){
02203 head_ = (head_ + N -1) % N;
02204 size_--;
02205 Vertex v = vals_[head_];
02206 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02207 return v;
02208 }
02209 return NullEntry;
02210 }
02211
02212 template<class V>
02213 void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
02214 {
02215 std::ios_base::fmtflags oldOpts=os.flags();
02216
02217 os.setf(std::ios_base::right, std::ios_base::adjustfield);
02218
02219 V max=0;
02220 int width=1;
02221
02222 for(int i=0; i< n*m; i++)
02223 max=std::max(max, aggregates[i]);
02224
02225 for(int i=10; i < 1000000; i*=10)
02226 if(max/i>0)
02227 width++;
02228 else
02229 break;
02230
02231 for(int j=0, entry=0; j < m; j++){
02232 for(int i=0; i<n; i++, entry++){
02233 os.width(width);
02234 os<<aggregates[entry]<<" ";
02235 }
02236
02237 os<<std::endl;
02238 }
02239 os<<std::endl;
02240 os.flags(oldOpts);
02241 }
02242
02243
02244 }
02245
02246 }
02247
02248
02249 #endif