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> 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 const 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 const 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 typedef const AggregateDescriptor* const_iterator;
00549
00550 const_iterator begin() const
00551 {
00552 return aggregates_;
00553 }
00554
00555 const_iterator end() const
00556 {
00557 return aggregates_+noVertices();
00558 }
00559
00560 typedef AggregateDescriptor* iterator;
00561
00562 iterator begin()
00563 {
00564 return aggregates_;
00565 }
00566
00567 iterator end()
00568 {
00569 return aggregates_+noVertices();
00570 }
00571 private:
00573 AggregatesMap(const AggregatesMap<V>& map)
00574 {
00575 throw "Auch!";
00576 }
00577
00579 AggregatesMap<V>& operator=(const AggregatesMap<V>& map)
00580 {
00581 throw "Auch!";
00582 return this;
00583 }
00584
00588 AggregateDescriptor* aggregates_;
00589
00593 std::size_t noVertices_;
00594 };
00595
00596
00601 template<class G, class S>
00602 class Aggregate
00603 {
00604
00605 public:
00606
00607
00608
00609
00610 typedef G MatrixGraph;
00614 typedef typename MatrixGraph::VertexDescriptor Vertex;
00615
00620 typedef PoolAllocator<Vertex,100> Allocator;
00621
00626 typedef SLList<Vertex,Allocator> VertexList;
00627
00628
00633 typedef S VertexSet;
00634
00636 typedef typename VertexList::const_iterator const_iterator;
00637
00641 typedef std::size_t* SphereMap;
00642
00650 Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
00651 VertexSet& connectivity);
00652
00659 void reconstruct(const Vertex& vertex);
00660
00664 void seed(const Vertex& vertex);
00665
00669 void add(const Vertex& vertex);
00670
00674 void clear();
00675
00679 typename VertexList::size_type size();
00680
00684 int id();
00685
00687 const_iterator begin() const;
00688
00690 const_iterator end() const;
00691
00692 private:
00696 VertexList vertices_;
00697
00702 int id_;
00703
00707 const MatrixGraph& graph_;
00708
00712 AggregatesMap<Vertex>& aggregates_;
00713
00717 VertexSet& connected_;
00718 };
00719
00723 template<class G>
00724 class Aggregator
00725 {
00726 public:
00727
00731 typedef G MatrixGraph;
00732
00736 typedef typename MatrixGraph::VertexDescriptor Vertex;
00737
00739 typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor;
00740
00744 Aggregator();
00745
00749 ~Aggregator();
00750
00763 template<class M, class C>
00764 tuple<int,int,int> build(const M& m, G& graph,
00765 AggregatesMap<Vertex>& aggregates, const C& c);
00766 private:
00771 typedef PoolAllocator<Vertex,1> Allocator;
00772
00776 typedef SLList<Vertex,Allocator> VertexList;
00777
00781 typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
00782
00786 typedef std::size_t* SphereMap;
00787
00791 MatrixGraph* graph_;
00792
00796 Aggregate<MatrixGraph,VertexSet>* aggregate_;
00797
00801 VertexList front_;
00802
00806 VertexSet connected_;
00807
00811 int size_;
00812
00816 class Stack
00817 {
00818 public:
00819 static const Vertex NullEntry;
00820
00821 Stack(const MatrixGraph& graph,
00822 const Aggregator<G>& aggregatesBuilder,
00823 const AggregatesMap<Vertex>& aggregates);
00824 ~Stack();
00825 bool push(const Vertex& v);
00826 void fill();
00827 Vertex pop();
00828 private:
00829 enum{ N = 256000 };
00830
00832 const MatrixGraph& graph_;
00834 const Aggregator<G>& aggregatesBuilder_;
00836 const AggregatesMap<Vertex>& aggregates_;
00838 int size_;
00839 int maxSize_;
00841 int head_;
00842 int filled_;
00843
00845 Vertex* vals_;
00846
00847 void localPush(const Vertex& v);
00848 };
00849
00850 friend class Stack;
00851
00855 template<class C>
00856 void buildDependency(MatrixGraph& graph,
00857 const typename C::Matrix& matrix,
00858 C criterion);
00859
00870 template<class V>
00871 void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,
00872 const AggregatesMap<Vertex>& aggregates,
00873 V& visitor) const;
00874
00879 template<class V>
00880 class AggregateVisitor
00881 {
00882 public:
00886 typedef V Visitor;
00894 AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
00895 Visitor& visitor);
00896
00903 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00904
00905 private:
00907 const AggregatesMap<Vertex>& aggregates_;
00909 AggregateDescriptor aggregate_;
00911 Visitor* visitor_;
00912 };
00913
00917 class Counter
00918 {
00919 public:
00921 Counter();
00923 int value();
00924
00925 protected:
00927 void increment();
00929 void decrement();
00930
00931 private:
00932 int count_;
00933 };
00934
00935
00940 class FrontNeighbourCounter : public Counter
00941 {
00942 public:
00947 FrontNeighbourCounter(const MatrixGraph& front);
00948
00949 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00950
00951 private:
00952 const MatrixGraph& graph_;
00953 };
00954
00959 int noFrontNeighbours(const Vertex& vertex) const;
00960
00964 class TwoWayCounter : public Counter
00965 {
00966 public:
00967 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00968 };
00969
00981 int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
00982 const AggregatesMap<Vertex>& aggregates) const;
00983
00987 class OneWayCounter : public Counter
00988 {
00989 public:
00990 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00991 };
00992
01004 int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,
01005 const AggregatesMap<Vertex>& aggregates) const;
01006
01013 class ConnectivityCounter : public Counter
01014 {
01015 public:
01022 ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
01023
01024 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01025
01026 private:
01028 const VertexSet& connected_;
01030 const AggregatesMap<Vertex>& aggregates_;
01031
01032 };
01033
01045 double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01046
01054 class DependencyCounter: public Counter
01055 {
01056 public:
01060 DependencyCounter();
01061
01062 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01063 };
01064
01071 class FrontMarker
01072 {
01073 public:
01080 FrontMarker(VertexList& front, MatrixGraph& graph);
01081
01082 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01083
01084 private:
01086 VertexList& front_;
01088 MatrixGraph& graph_;
01089 };
01090
01097 void markFront(const AggregatesMap<Vertex>& aggregates);
01098
01102 void unmarkFront();
01103
01118 int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01119
01133 std::pair<int,int> neighbours(const Vertex& vertex,
01134 const AggregateDescriptor& aggregate,
01135 const AggregatesMap<Vertex>& aggregates) const;
01152 int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01153
01161 bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01162
01169 void seedFromFront(Stack& stack, bool isolated);
01170
01178 std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
01179
01188 Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01189
01197 template<class C>
01198 void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
01199 };
01200
01201 template<class M, class N>
01202 inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
01203 {
01204 matrix_ = matrix;
01205 }
01206
01207 template<class M, class N>
01208 inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
01209 {
01210 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01211 row_ = index;
01212 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01213 }
01214
01215 template<class M, class N>
01216 inline void SymmetricDependency<M,N>::examine(const ColIter& col)
01217 {
01218 maxValue_ = std::max(maxValue_,
01219 (norm_(*col) * norm_(matrix_->operator[](col.index())[row_]))/
01220 (norm_(matrix_->operator[](col.index())[col.index()]) * diagonal_));
01221
01222 }
01223
01224 template<class M, class N>
01225 template<class G>
01226 inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01227 {
01228 if(norm_(matrix_->operator[](edge.target())[edge.source()]) * norm_(*col)/
01229 (norm_(matrix_->operator[](edge.target())[edge.target()]) * diagonal_) > alpha() * maxValue_){
01230 edge.properties().setDepends();
01231 edge.properties().setInfluences();
01232
01233 typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
01234 other.setInfluences();
01235 other.setDepends();
01236 }
01237 }
01238
01239 template<class M, class N>
01240 inline bool SymmetricDependency<M,N>::isIsolated()
01241 {
01242 return maxValue_ < beta();
01243 }
01244
01245
01246 template<class M, class N>
01247 inline void Dependency<M,N>::init(const Matrix* matrix)
01248 {
01249 matrix_ = matrix;
01250 }
01251
01252 template<class M, class N>
01253 inline void Dependency<M,N>::initRow(const Row& row, int index)
01254 {
01255 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01256 row_ = index;
01257 diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01258 }
01259
01260 template<class M, class N>
01261 inline void Dependency<M,N>::examine(const ColIter& col)
01262 {
01263 maxValue_ = std::max(maxValue_,
01264 -norm_(*col));
01265 }
01266
01267 template<class M, class N>
01268 template<class G>
01269 inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01270 {
01271 if(-norm_(*col) >= maxValue_ * alpha()){
01272 edge.properties().setDepends();
01273 edge.properties().setInfluences();
01274 }
01275 }
01276
01277 template<class M, class N>
01278 inline bool Dependency<M,N>::isIsolated()
01279 {
01280 return maxValue_ < beta() * diagonal_;
01281 }
01282
01283 template<class G,class S>
01284 Aggregate<G,S>::Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
01285 VertexSet& connected)
01286 : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
01287 connected_(connected)
01288 {}
01289
01290 template<class G,class S>
01291 void Aggregate<G,S>::reconstruct(const Vertex& vertex)
01292 {
01293 vertices_.push_back(vertex);
01294 typedef typename VertexList::const_iterator iterator;
01295 iterator begin = vertices_.begin();
01296 iterator end = vertices_.end();
01297 throw "Not yet implemented";
01298
01299 while(begin!=end){
01300
01301 }
01302
01303 }
01304
01305 template<class G,class S>
01306 inline void Aggregate<G,S>::seed(const Vertex& vertex)
01307 {
01308 dvverb<<"Connected cleared"<<std::endl;
01309 connected_.clear();
01310 vertices_.clear();
01311 connected_.insert(vertex);
01312 dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
01313 id_ = vertex;
01314 add(vertex);
01315 }
01316
01317
01318 template<class G,class S>
01319 inline void Aggregate<G,S>::add(const Vertex& vertex)
01320 {
01321 vertices_.push_back(vertex);
01322 aggregates_[vertex]=id_;
01323
01324 typedef typename MatrixGraph::ConstEdgeIterator iterator;
01325 const iterator end = graph_.endEdges(vertex);
01326 for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge){
01327 dvverb << " Inserting "<<aggregates_[edge.target()];
01328 connected_.insert(aggregates_[edge.target()]);
01329 dvverb <<" size="<<connected_.size();
01330 }
01331 dvverb <<std::endl;
01332 }
01333 template<class G,class S>
01334 inline void Aggregate<G,S>::clear()
01335 {
01336 vertices_.clear();
01337 connected_.clear();
01338 id_=-1;
01339 }
01340
01341 template<class G,class S>
01342 inline typename Aggregate<G,S>::VertexList::size_type
01343 Aggregate<G,S>::size()
01344 {
01345 return vertices_.size();
01346 }
01347
01348 template<class G,class S>
01349 inline int Aggregate<G,S>::id()
01350 {
01351 return id_;
01352 }
01353
01354 template<class G,class S>
01355 inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::begin() const
01356 {
01357 return vertices_.begin();
01358 }
01359
01360 template<class G,class S>
01361 inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
01362 {
01363 return vertices_.end();
01364 }
01365
01366 template<class V>
01367 const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
01368
01369 template<class V>
01370 const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
01371
01372 template<class V>
01373 AggregatesMap<V>::AggregatesMap()
01374 : aggregates_(0)
01375 {}
01376
01377 template<class V>
01378 AggregatesMap<V>::~AggregatesMap()
01379 {
01380 if(aggregates_!=0)
01381 delete[] aggregates_;
01382 }
01383
01384
01385 template<class V>
01386 inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
01387 {
01388 allocate(noVertices);
01389 }
01390
01391 template<class V>
01392 inline std::size_t AggregatesMap<V>::AggregatesMap::noVertices() const
01393 {
01394 return noVertices_;
01395 }
01396
01397 template<class V>
01398 inline void AggregatesMap<V>::allocate(std::size_t noVertices)
01399 {
01400 aggregates_ = new AggregateDescriptor[noVertices];
01401 noVertices_ = noVertices;
01402
01403 for(std::size_t i=0; i < noVertices; i++)
01404 aggregates_[i]=UNAGGREGATED;
01405 }
01406
01407 template<class V>
01408 inline void AggregatesMap<V>::free()
01409 {
01410 assert(aggregates_ != 0);
01411 delete[] aggregates_;
01412 aggregates_=0;
01413 }
01414
01415 template<class V>
01416 inline typename AggregatesMap<V>::AggregateDescriptor&
01417 AggregatesMap<V>::operator[](const VertexDescriptor& v)
01418 {
01419 return aggregates_[v];
01420 }
01421
01422 template<class V>
01423 inline const typename AggregatesMap<V>::AggregateDescriptor&
01424 AggregatesMap<V>::operator[](const VertexDescriptor& v) const
01425 {
01426 return aggregates_[v];
01427 }
01428
01429 template<class V>
01430 template<bool reset, class G, class F,class VM>
01431 inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01432 const AggregateDescriptor& aggregate,
01433 const G& graph, F& aggregateVisitor,
01434 VM& visitedMap) const
01435 {
01436 VertexList vlist;
01437
01438 DummyEdgeVisitor dummy;
01439 return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
01440 }
01441
01442 template<class V>
01443 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
01444 std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01445 const AggregateDescriptor& aggregate,
01446 const G& graph,
01447 L& visited,
01448 F1& aggregateVisitor,
01449 F2& nonAggregateVisitor,
01450 VM& visitedMap) const
01451 {
01452 typedef typename L::const_iterator ListIterator;
01453 int visitedSpheres = 0;
01454
01455 visited.push_back(start);
01456 put(visitedMap, start, true);
01457
01458 ListIterator current = visited.begin();
01459 ListIterator end = visited.end();
01460 std::size_t i=0, size=visited.size();
01461
01462
01463
01464 while(current != end){
01465
01466 for(;i<size; ++current, ++i){
01467 typedef typename G::ConstEdgeIterator EdgeIterator;
01468 const EdgeIterator endEdge = graph.endEdges(*current);
01469
01470 for(EdgeIterator edge = graph.beginEdges(*current);
01471 edge != endEdge; ++edge){
01472
01473 if(aggregates_[edge.target()]==aggregate){
01474 if(!get(visitedMap, edge.target())){
01475 put(visitedMap, edge.target(), true);
01476 visited.push_back(edge.target());
01477 aggregateVisitor(edge);
01478 }
01479 }else
01480 nonAggregateVisitor(edge);
01481 }
01482 }
01483 end = visited.end();
01484 size = visited.size();
01485 if(current != end)
01486 visitedSpheres++;
01487 }
01488
01489 if(reset)
01490 for(current = visited.begin(); current != end; ++current)
01491 put(visitedMap, *current, false);
01492
01493
01494 if(remove)
01495 visited.clear();
01496
01497 return visitedSpheres;
01498 }
01499
01500 template<class G>
01501 Aggregator<G>::Aggregator()
01502 : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
01503 {}
01504
01505 template<class G>
01506 Aggregator<G>::~Aggregator()
01507 {
01508 size_=-1;
01509 }
01510
01511 template<class G>
01512 template<class C>
01513 void Aggregator<G>::buildDependency(MatrixGraph& graph,
01514 const typename C::Matrix& matrix,
01515 C criterion)
01516 {
01517
01518 typedef C Criterion;
01519
01520
01521 typedef typename C::Matrix Matrix;
01522 typedef typename MatrixGraph::VertexIterator VertexIterator;
01523
01524 criterion.init(&matrix);
01525
01526 for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex){
01527 typedef typename Matrix::row_type Row;
01528
01529 const Row& row = matrix[*vertex];
01530
01531
01532
01533
01534 criterion.initRow(row, *vertex);
01535
01536
01537
01538 typedef typename Matrix::ConstColIterator ColIterator;
01539 ColIterator end = row.end();
01540 for(ColIterator col = row.begin(); col != end; ++col)
01541 if(col.index()!=*vertex)
01542 criterion.examine(col);
01543
01544
01545
01546
01547
01548 if(criterion.isIsolated()){
01549
01550 vertex.properties().setIsolated();
01551 }else{
01552
01553 typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01554 typedef typename Matrix::ConstColIterator ColIterator;
01555 EdgeIterator end = vertex.end();
01556 ColIterator col = matrix[*vertex].begin();
01557
01558 for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01559
01560 while(col.index()!=edge.target())
01561 ++col;
01562 criterion.examine(graph, edge, col);
01563 }
01564 }
01565
01566 }
01567 }
01568
01569
01570 template<class G>
01571 template<class V>
01572 inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
01573 const AggregateDescriptor& aggregate, V& visitor)
01574 : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01575 {}
01576
01577 template<class G>
01578 template<class V>
01579 inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01580 {
01581 if(aggregates_[edge.target()]==aggregate_)
01582 visitor_->operator()(edge);
01583 }
01584
01585 template<class G>
01586 template<class V>
01587 inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01588 const AggregateDescriptor& aggregate,
01589 const AggregatesMap<Vertex>& aggregates,
01590 V& visitor) const
01591 {
01592
01593 AggregateVisitor<V> v(aggregates, aggregate, visitor);
01594 visitNeighbours(*graph_, vertex, v);
01595 }
01596
01597
01598 template<class G>
01599 inline Aggregator<G>::Counter::Counter()
01600 : count_(0)
01601 {}
01602
01603 template<class G>
01604 inline void Aggregator<G>::Counter::increment()
01605 {
01606 ++count_;
01607 }
01608
01609 template<class G>
01610 inline void Aggregator<G>::Counter::decrement()
01611 {
01612 --count_;
01613 }
01614 template<class G>
01615 inline int Aggregator<G>::Counter::value()
01616 {
01617 return count_;
01618 }
01619
01620 template<class G>
01621 inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01622 {
01623 if(edge.properties().isTwoWay())
01624 Counter::increment();
01625 }
01626
01627 template<class G>
01628 int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01629 const AggregatesMap<Vertex>& aggregates) const
01630 {
01631 TwoWayCounter counter;
01632 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01633 return counter.value();
01634 }
01635
01636 template<class G>
01637 int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01638 const AggregatesMap<Vertex>& aggregates) const
01639 {
01640 OneWayCounter counter;
01641 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01642 return counter.value();
01643 }
01644
01645 template<class G>
01646 inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01647 {
01648 if(edge.properties().isOneWay())
01649 Counter::increment();
01650 }
01651
01652 template<class G>
01653 inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01654 const AggregatesMap<Vertex>& aggregates)
01655 : Counter(), connected_(connected), aggregates_(aggregates)
01656 {}
01657
01658
01659 template<class G>
01660 inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01661 {
01662 if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01663
01664 Counter::increment();
01665 else{
01666 Counter::increment();
01667 Counter::increment();
01668 }
01669 }
01670
01671 template<class G>
01672 inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01673 {
01674 ConnectivityCounter counter(connected_, aggregates);
01675 double noNeighbours=visitNeighbours(*graph_, vertex, counter);
01676 return (double)counter.value()/noNeighbours;
01677 }
01678
01679 template<class G>
01680 inline Aggregator<G>::DependencyCounter::DependencyCounter()
01681 : Counter()
01682 {}
01683
01684 template<class G>
01685 inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01686 {
01687 if(edge.properties().depends())
01688 Counter::increment();
01689 if(edge.properties().influences())
01690 Counter::increment();
01691 }
01692
01693 template<class G>
01694 int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01695 {
01696 return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01697 }
01698
01699 template<class G>
01700 std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01701 const AggregateDescriptor& aggregate,
01702 const AggregatesMap<Vertex>& aggregates) const
01703 {
01704 DependencyCounter unused, aggregated;
01705 typedef AggregateVisitor<DependencyCounter> Counter;
01706 typedef tuple<Counter,Counter> CounterTuple;
01707 CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
01708 return std::make_pair(unused.value(), aggregated.value());
01709 }
01710
01711
01712 template<class G>
01713 int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01714 {
01715 DependencyCounter counter;
01716 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01717 return counter.value();
01718 }
01719
01720 template<class G>
01721 std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01722 {
01723 typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01724 VertexList vlist;
01725 typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01726 return aggregates.template breadthFirstSearch<true,true>(vertex,
01727 aggregate_->id(), *graph_,
01728 vlist, dummy, dummy, visitedMap);
01729 }
01730
01731 template<class G>
01732 inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01733 : front_(front), graph_(graph)
01734 {}
01735
01736 template<class G>
01737 inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01738 {
01739 Vertex target = edge.target();
01740
01741 if(!graph_.getVertexProperties(target).front()){
01742 front_.push_back(target);
01743 graph_.getVertexProperties(target).setFront();
01744 }
01745 }
01746
01747
01748 template<class G>
01749 void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01750 {
01751 assert(front_.size()==0);
01752 FrontMarker frontBuilder(front_, *graph_);
01753 typedef typename Aggregate<G,VertexSet>::const_iterator Iterator;
01754
01755 for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01756 visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01757
01758 }
01759
01760 template<class G>
01761 inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01762 {
01763
01764 Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01765
01766 return true;
01767 }
01768
01769 template<class G>
01770 void Aggregator<G>::unmarkFront()
01771 {
01772 typedef typename VertexList::const_iterator Iterator;
01773
01774 for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01775 graph_->getVertexProperties(*vertex).resetFront();
01776
01777 front_.clear();
01778 }
01779
01780 template<class G>
01781 inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01782 {
01783 typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01784
01785 Iterator end = graph_->endEdges(vertex);
01786 for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01787 if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01788 graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01789 if( graph_->getVertexProperties(vertex).isolated() ||
01790 ((edge.properties().depends() || edge.properties().influences())
01791 && admissible(vertex, aggregates[edge.target()], aggregates)))
01792 return edge.target();
01793 }
01794 }
01795 return AggregatesMap<Vertex>::UNAGGREGATED;
01796 }
01797
01798 template<class G>
01799 Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01800 : Counter(), graph_(graph)
01801 {}
01802
01803 template<class G>
01804 void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01805 {
01806 if(graph_.getVertexProperties(edge.target()).front())
01807 Counter::increment();
01808 }
01809
01810 template<class G>
01811 int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01812 {
01813 FrontNeighbourCounter counter(*graph_);
01814 visitNeighbours(*graph_, vertex, counter);
01815 return counter.value();
01816 }
01817
01818 template<class G>
01819 template<class C>
01820 void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01821 {
01822 while(aggregate_->size() < c.minAggregateSize()){
01823 int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
01824 double maxCon=-1;
01825
01826 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01827
01828 unmarkFront();
01829 markFront(aggregates);
01830
01831 typedef typename VertexList::const_iterator Iterator;
01832
01833 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01834
01835 if(graph_->getVertexProperties(*vertex).isolated())
01836 continue;
01837
01838 int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01839
01840
01841 if( maxTwoCons == twoWayCons && twoWayCons > 0){
01842 double con = connectivity(*vertex, aggregates);
01843
01844 if(con == maxCon){
01845 int neighbours = noFrontNeighbours(*vertex);
01846
01847 if(neighbours > maxNeighbours){
01848 maxNeighbours = neighbours;
01849
01850 std::size_t distance_ = distance(*vertex, aggregates);
01851
01852 if(c.maxDistance() >= distance_){
01853 candidate = *vertex;
01854 }
01855 }
01856 }else if( con > maxCon){
01857 maxCon = con;
01858 maxNeighbours = noFrontNeighbours(*vertex);
01859 std::size_t distance_ = distance(*vertex, aggregates);
01860
01861 if(c.maxDistance() >= distance_){
01862 candidate = *vertex;
01863 }
01864 }
01865 }else if(twoWayCons > maxTwoCons){
01866 maxTwoCons = twoWayCons;
01867 maxCon = connectivity(*vertex, aggregates);
01868 maxNeighbours = noFrontNeighbours(*vertex);
01869 std::size_t distance_ = distance(*vertex, aggregates);
01870
01871 if(c.maxDistance() >= distance_){
01872 candidate = *vertex;
01873 }
01874
01875
01876 maxOneCons = std::numeric_limits<int>::max();
01877 }
01878
01879 if(twoWayCons > 0)
01880 continue;
01881
01882
01883 int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01884
01885 if(oneWayCons==0)
01886 continue;
01887
01888 if(!admissible(*vertex, aggregate_->id(), aggregates))
01889 continue;
01890
01891 if( maxOneCons == oneWayCons && oneWayCons > 0){
01892 double con = connectivity(*vertex, aggregates);
01893
01894 if(con == maxCon){
01895 int neighbours = noFrontNeighbours(*vertex);
01896
01897 if(neighbours > maxNeighbours){
01898 maxNeighbours = neighbours;
01899 std::size_t distance_ = distance(*vertex, aggregates);
01900
01901 if(c.maxDistance() >= distance_){
01902 candidate = *vertex;
01903 }
01904 }
01905 }else if( con > maxCon){
01906 maxCon = con;
01907 maxNeighbours = noFrontNeighbours(*vertex);
01908 std::size_t distance_ = distance(*vertex, aggregates);
01909 if(c.maxDistance() >= distance_){
01910 candidate = *vertex;
01911 }
01912 }
01913 }else if(oneWayCons > maxOneCons){
01914 maxOneCons = oneWayCons;
01915 maxCon = connectivity(*vertex, aggregates);
01916 maxNeighbours = noFrontNeighbours(*vertex);
01917 std::size_t distance_ = distance(*vertex, aggregates);
01918
01919 if(c.maxDistance() >= distance_){
01920 candidate = *vertex;
01921 }
01922 }
01923 }
01924
01925
01926 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01927 break;
01928
01929 aggregate_->add(candidate);
01930 }
01931 }
01932
01933 template<typename V>
01934 template<typename M, typename G, typename C>
01935 tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01936 {
01937 Aggregator<G> aggregator;
01938 return aggregator.build(matrix, graph, *this, criterion);
01939 }
01940
01941 template<class G>
01942 template<class M, class C>
01943 tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01944 {
01945
01946 Stack stack_(graph, *this, aggregates);
01947
01948 graph_ = &graph;
01949
01950 aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_);
01951
01952
01953 size_ = graph.maxVertex();
01954
01955 Timer watch;
01956 watch.reset();
01957
01958 buildDependency(graph, m, c);
01959
01960 dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01961 int noAggregates, conAggregates, isoAggregates, oneAggregates;
01962 noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01963
01964 while(true){
01965 Vertex seed = stack_.pop();
01966
01967 if(seed == Stack::NullEntry)
01968
01969 break;
01970
01971
01972 if((noAggregates+1)%10000 == 0)
01973 Dune::dverb<<"c";
01974
01975 aggregate_->seed(seed);
01976
01977
01978 if(graph.getVertexProperties(seed).isolated()){
01979
01980 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01981 ++isoAggregates;
01982
01983 continue;
01984 }else
01985 growAggregate(seed, aggregates, c);
01986
01987
01988
01989 while(aggregate_->size() < c.maxAggregateSize()){
01990
01991 unmarkFront();
01992 markFront(aggregates);
01993
01994 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01995
01996 typedef typename VertexList::const_iterator Iterator;
01997
01998 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01999
02000 if(graph.getVertexProperties(*vertex).isolated())
02001 continue;
02002
02003 if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
02004 (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
02005 !admissible( *vertex, aggregate_->id(), aggregates) ))
02006 continue;
02007
02008 std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
02009 aggregates);
02010
02011
02012
02013
02014 if(neighbourPair.first >= neighbourPair.second)
02015 continue;
02016
02017 if(distance(*vertex, aggregates) > c.maxDistance())
02018 continue;
02019 candidate = *vertex;
02020 break;
02021 }
02022
02023 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break;
02024
02025 aggregate_->add(candidate);
02026
02027 }
02028
02029
02030 if(aggregate_->size()==1)
02031 if(!graph.getVertexProperties(seed).isolated()){
02032 Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02033
02034 if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02035 aggregates[seed] = aggregates[mergedNeighbour];
02036
02037
02038
02039
02040
02041
02042
02043 }else{
02044 ++oneAggregates;
02045 ++conAggregates;
02046 }
02047
02048 }else{
02049 ++oneAggregates;
02050 ++isoAggregates;
02051 }
02052 else{
02053 if(graph.getVertexProperties(seed).isolated())
02054 ++isoAggregates;
02055 else
02056 ++conAggregates;
02057 }
02058 unmarkFront();
02059 markFront(aggregates);
02060 seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02061 unmarkFront();
02062 }
02063
02064 Dune::dinfo<<"connected aggregates: "<<conAggregates;
02065 Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02066 Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02067
02068 delete aggregate_;
02069 return make_tuple(conAggregates,isoAggregates,oneAggregates);
02070 }
02071
02072 template<class G>
02073 inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02074 {
02075 typedef typename VertexList::const_iterator Iterator;
02076
02077 Iterator end= front_.end();
02078 int count=0;
02079 for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02080 stack_.push(*vertex);
02081
02082
02083
02084
02085 }
02086
02087 template<class G>
02088 Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02089 const AggregatesMap<Vertex>& aggregates)
02090 : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02091 {
02092 vals_ = new Vertex[N];
02093 }
02094
02095 template<class G>
02096 Aggregator<G>::Stack::~Stack()
02097 {
02098 Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02099 delete[] vals_;
02100 }
02101
02102 template<class G>
02103 const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
02104 = std::numeric_limits<typename G::VertexDescriptor>::max();
02105
02106 template<class G>
02107 inline bool Aggregator<G>::Stack::push(const Vertex& v)
02108 {
02109 if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02110 localPush(v);
02111 return true;
02112 }else
02113 return false;
02114 }
02115
02116 template<class G>
02117 inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02118 {
02119 vals_[head_] = v;
02120 size_ = std::min<int>(size_+1, N);
02121 head_ = (head_+N+1)%N;
02122 }
02123
02124 template<class G>
02125 void Aggregator<G>::Stack::fill()
02126 {
02127 int isolated = 0, connected=0;
02128 int isoumin, umin;
02129 filled_++;
02130
02131 head_ = size_ = 0;
02132 isoumin = umin = std::numeric_limits<int>::max();
02133
02134 typedef typename MatrixGraph::ConstVertexIterator Iterator;
02135
02136 const Iterator end = graph_.end();
02137
02138 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02139
02140 if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02141 continue;
02142
02143 if(vertex.properties().isolated()){
02144 isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02145 isolated++;
02146 }else{
02147 umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02148 connected++;
02149 }
02150 }
02151
02152 if(connected + isolated == 0)
02153
02154 return;
02155
02156 if(connected > 0){
02157
02158 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02159 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated()
02160 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02161 localPush(*vertex);
02162 }else{
02163 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02164 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated()
02165 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02166 localPush(*vertex);
02167 }
02168 maxSize_ = std::max(size_, maxSize_);
02169 }
02170
02171 template<class G>
02172 inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02173 {
02174 while(size_>0){
02175 head_ = (head_ + N -1) % N;
02176 size_--;
02177 Vertex v = vals_[head_];
02178 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02179 return v;
02180 }
02181
02182 fill();
02183
02184
02185 while(size_>0){
02186 head_ = (head_ + N -1) % N;
02187 size_--;
02188 Vertex v = vals_[head_];
02189 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02190 return v;
02191 }
02192 return NullEntry;
02193 }
02194
02195 template<class V>
02196 void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
02197 {
02198 std::ios_base::fmtflags oldOpts=os.flags();
02199
02200 os.setf(std::ios_base::right, std::ios_base::adjustfield);
02201
02202 V max=0;
02203 int width=1;
02204
02205 for(int i=0; i< n*m; i++)
02206 max=std::max(max, aggregates[i]);
02207
02208 for(int i=10; i < 1000000; i*=10)
02209 if(max/i>0)
02210 width++;
02211 else
02212 break;
02213
02214 for(int j=0, entry=0; j < m; j++){
02215 for(int i=0; i<n; i++, entry++){
02216 os.width(width);
02217 os<<aggregates[entry]<<" ";
02218 }
02219
02220 os<<std::endl;
02221 }
02222 os<<std::endl;
02223 os.flags(oldOpts);
02224 }
02225
02226
02227 }
02228
02229 }
02230
02231
02232 #endif