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 int 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
01198 (diagonal_*diagonal_));
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
01207 (diagonal_ * diagonal_) > alpha() * maxValue_){
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 vertex.properties().setIsolated();
01527 }else{
01528
01529 typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01530 typedef typename Matrix::ConstColIterator ColIterator;
01531 EdgeIterator end = vertex.end();
01532 ColIterator col = matrix[*vertex].begin();
01533
01534 for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01535
01536 while(col.index()!=edge.target())
01537 ++col;
01538 criterion.examine(graph, edge, col);
01539 }
01540 }
01541
01542 }
01543 }
01544
01545
01546 template<class G>
01547 template<class V>
01548 inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates,
01549 const AggregateDescriptor& aggregate, V& visitor)
01550 : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01551 {}
01552
01553 template<class G>
01554 template<class V>
01555 inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01556 {
01557 if(aggregates_[edge.target()]==aggregate_)
01558 visitor_->operator()(edge);
01559 }
01560
01561 template<class G>
01562 template<class V>
01563 inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01564 const AggregateDescriptor& aggregate,
01565 const AggregatesMap<Vertex>& aggregates,
01566 V& visitor) const
01567 {
01568
01569 AggregateVisitor<V> v(aggregates, aggregate, visitor);
01570 visitNeighbours(*graph_, vertex, v);
01571 }
01572
01573
01574 template<class G>
01575 inline Aggregator<G>::Counter::Counter()
01576 : count_(0)
01577 {}
01578
01579 template<class G>
01580 inline void Aggregator<G>::Counter::increment()
01581 {
01582 ++count_;
01583 }
01584
01585 template<class G>
01586 inline void Aggregator<G>::Counter::decrement()
01587 {
01588 --count_;
01589 }
01590 template<class G>
01591 inline int Aggregator<G>::Counter::value()
01592 {
01593 return count_;
01594 }
01595
01596 template<class G>
01597 inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01598 {
01599 if(edge.properties().isTwoWay())
01600 Counter::increment();
01601 }
01602
01603 template<class G>
01604 int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01605 const AggregatesMap<Vertex>& aggregates) const
01606 {
01607 TwoWayCounter counter;
01608 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01609 return counter.value();
01610 }
01611
01612 template<class G>
01613 int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01614 const AggregatesMap<Vertex>& aggregates) const
01615 {
01616 OneWayCounter counter;
01617 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01618 return counter.value();
01619 }
01620
01621 template<class G>
01622 inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01623 {
01624 if(edge.properties().isOneWay())
01625 Counter::increment();
01626 }
01627
01628 template<class G>
01629 inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01630 const AggregatesMap<Vertex>& aggregates)
01631 : Counter(), connected_(connected), aggregates_(aggregates)
01632 {}
01633
01634
01635 template<class G>
01636 inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01637 {
01638 if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01639
01640 Counter::increment();
01641 else{
01642 Counter::increment();
01643 Counter::increment();
01644 }
01645 }
01646
01647 template<class G>
01648 inline int Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01649 {
01650 ConnectivityCounter counter(connected_, aggregates);
01651 visitNeighbours(*graph_, vertex, counter);
01652 return counter.value();
01653 }
01654
01655 template<class G>
01656 inline Aggregator<G>::DependencyCounter::DependencyCounter()
01657 : Counter()
01658 {}
01659
01660 template<class G>
01661 inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01662 {
01663 if(edge.properties().depends())
01664 Counter::increment();
01665 if(edge.properties().influences())
01666 Counter::increment();
01667 }
01668
01669 template<class G>
01670 int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01671 {
01672 return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01673 }
01674
01675 template<class G>
01676 std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01677 const AggregateDescriptor& aggregate,
01678 const AggregatesMap<Vertex>& aggregates) const
01679 {
01680 DependencyCounter unused, aggregated;
01681 typedef AggregateVisitor<DependencyCounter> Counter;
01682 CombinedFunctor<Counter,Counter> visitors(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated));
01683 return std::make_pair(unused.value(), aggregated.value());
01684 }
01685
01686
01687 template<class G>
01688 int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01689 {
01690 DependencyCounter counter;
01691 visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01692 return counter.value();
01693 }
01694
01695 template<class G>
01696 std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01697 {
01698 typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01699 VertexList vlist;
01700 typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01701 return aggregates.template breadthFirstSearch<true,true>(vertex,
01702 aggregate_->id(), *graph_,
01703 vlist, dummy, dummy, visitedMap);
01704 }
01705
01706 template<class G>
01707 inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01708 : front_(front), graph_(graph)
01709 {}
01710
01711 template<class G>
01712 inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01713 {
01714 Vertex target = edge.target();
01715
01716 if(!graph_.getVertexProperties(target).front()){
01717 front_.push_back(target);
01718 graph_.getVertexProperties(target).setFront();
01719 }
01720 }
01721
01722
01723 template<class G>
01724 void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01725 {
01726 assert(front_.size()==0);
01727 FrontMarker frontBuilder(front_, *graph_);
01728 typedef typename Aggregate<G>::const_iterator Iterator;
01729
01730 for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01731 visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01732
01733 }
01734
01735 template<class G>
01736 inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01737 {
01738
01739 Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01740
01741 return true;
01742 }
01743
01744 template<class G>
01745 void Aggregator<G>::unmarkFront()
01746 {
01747 typedef typename VertexList::const_iterator Iterator;
01748
01749 for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01750 graph_->getVertexProperties(*vertex).resetFront();
01751
01752 front_.clear();
01753 }
01754
01755 template<class G>
01756 inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01757 {
01758 typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01759
01760 Iterator end = graph_->endEdges(vertex);
01761 for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01762 if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01763 graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01764 if( graph_->getVertexProperties(vertex).isolated() ||
01765 ((edge.properties().depends() || edge.properties().influences())
01766 && admissible(vertex, aggregates[edge.target()], aggregates)))
01767 return edge.target();
01768 }
01769 }
01770 return AggregatesMap<Vertex>::UNAGGREGATED;
01771 }
01772
01773 template<class G>
01774 Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01775 : Counter(), graph_(graph)
01776 {}
01777
01778 template<class G>
01779 void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01780 {
01781 if(graph_.getVertexProperties(edge.target()).front())
01782 Counter::increment();
01783 }
01784
01785 template<class G>
01786 int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01787 {
01788 FrontNeighbourCounter counter(*graph_);
01789 visitNeighbours(*graph_, vertex, counter);
01790 return counter.value();
01791 }
01792
01793 template<class G>
01794 template<class C>
01795 void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01796 {
01797 while(aggregate_->size() < c.minAggregateSize()){
01798 int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1, maxCon=-std::numeric_limits<int>::max();
01799
01800 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01801
01802 unmarkFront();
01803 markFront(aggregates);
01804
01805 typedef typename VertexList::const_iterator Iterator;
01806
01807 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01808
01809 if(graph_->getVertexProperties(*vertex).isolated())
01810 continue;
01811
01812 int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01813
01814
01815 if( maxTwoCons == twoWayCons && twoWayCons > 0){
01816 int con = connectivity(*vertex, aggregates);
01817
01818 if(con == maxCon){
01819 int neighbours = noFrontNeighbours(*vertex);
01820
01821 if(neighbours > maxNeighbours){
01822 maxNeighbours = neighbours;
01823
01824 std::size_t distance_ = distance(*vertex, aggregates);
01825
01826 if(c.maxDistance() >= distance_){
01827 candidate = *vertex;
01828 }
01829 }
01830 }else if( con > maxCon){
01831 maxCon = con;
01832 maxNeighbours = noFrontNeighbours(*vertex);
01833 std::size_t distance_ = distance(*vertex, aggregates);
01834
01835 if(c.maxDistance() >= distance_){
01836 candidate = *vertex;
01837 }
01838 }
01839 }else if(twoWayCons > maxTwoCons){
01840 maxTwoCons = twoWayCons;
01841 maxCon = connectivity(*vertex, aggregates);
01842 maxNeighbours = noFrontNeighbours(*vertex);
01843 std::size_t distance_ = distance(*vertex, aggregates);
01844
01845 if(c.maxDistance() >= distance_){
01846 candidate = *vertex;
01847 }
01848
01849
01850 maxOneCons = std::numeric_limits<int>::max();
01851 }
01852
01853 if(twoWayCons > 0)
01854 continue;
01855
01856
01857 int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01858
01859 if(oneWayCons==0)
01860 continue;
01861
01862 if(!admissible(*vertex, aggregate_->id(), aggregates))
01863 continue;
01864
01865 if( maxOneCons == oneWayCons && oneWayCons > 0){
01866 int con = connectivity(*vertex, aggregates);
01867
01868 if(con == maxCon){
01869 int neighbours = noFrontNeighbours(*vertex);
01870
01871 if(neighbours > maxNeighbours){
01872 maxNeighbours = neighbours;
01873 std::size_t distance_ = distance(*vertex, aggregates);
01874
01875 if(c.maxDistance() >= distance_){
01876 candidate = *vertex;
01877 }
01878 }
01879 }else if( con > maxCon){
01880 maxCon = con;
01881 maxNeighbours = noFrontNeighbours(*vertex);
01882 std::size_t distance_ = distance(*vertex, aggregates);
01883 if(c.maxDistance() >= distance_){
01884 candidate = *vertex;
01885 }
01886 }
01887 }else if(oneWayCons > maxOneCons){
01888 maxOneCons = oneWayCons;
01889 maxCon = connectivity(*vertex, aggregates);
01890 maxNeighbours = noFrontNeighbours(*vertex);
01891 std::size_t distance_ = distance(*vertex, aggregates);
01892
01893 if(c.maxDistance() >= distance_){
01894 candidate = *vertex;
01895 }
01896 }
01897 }
01898
01899
01900 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01901 break;
01902
01903 aggregate_->add(candidate);
01904 }
01905 }
01906
01907 template<typename V>
01908 template<typename M, typename G, typename C>
01909 Tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01910 {
01911 Aggregator<G> aggregator;
01912 return aggregator.build(matrix, graph, *this, criterion);
01913 }
01914
01915 template<class G>
01916 template<class M, class C>
01917 Tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01918 {
01919
01920 Stack stack_(graph, *this, aggregates);
01921
01922 graph_ = &graph;
01923
01924 aggregate_ = new Aggregate<G>(graph, aggregates, connected_);
01925
01926
01927 size_ = graph.maxVertex();
01928
01929 Timer watch;
01930 watch.reset();
01931
01932 buildDependency(graph, m, c);
01933
01934 dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01935 int noAggregates, conAggregates, isoAggregates, oneAggregates;
01936 noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01937
01938 while(true){
01939 Vertex seed = stack_.pop();
01940
01941 if(seed == Stack::NullEntry)
01942
01943 break;
01944
01945
01946 if((noAggregates+1)%10000 == 0)
01947 Dune::dverb<<"c";
01948
01949 aggregate_->seed(seed);
01950
01951
01952 if(graph.getVertexProperties(seed).isolated()){
01953
01954 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01955 ++isoAggregates;
01956
01957 continue;
01958 }else
01959 growAggregate(seed, aggregates, c);
01960
01961
01962
01963 while(aggregate_->size() < c.maxAggregateSize()){
01964
01965 unmarkFront();
01966 markFront(aggregates);
01967
01968 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01969
01970 typedef typename VertexList::const_iterator Iterator;
01971
01972 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01973
01974 if(graph.getVertexProperties(*vertex).isolated())
01975 continue;
01976
01977 if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 &&
01978 (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 ||
01979 !admissible( *vertex, aggregate_->id(), aggregates) ))
01980 continue;
01981
01982 std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
01983 aggregates);
01984
01985
01986
01987
01988 if(neighbourPair.first >= neighbourPair.second)
01989 continue;
01990
01991 if(distance(*vertex, aggregates) > c.maxDistance())
01992 continue;
01993 candidate = *vertex;
01994 break;
01995 }
01996
01997 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break;
01998
01999 aggregate_->add(candidate);
02000
02001 }
02002
02003
02004 if(aggregate_->size()==1)
02005 if(!graph.getVertexProperties(seed).isolated()){
02006 Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02007
02008 if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02009 aggregates[seed] = aggregates[mergedNeighbour];
02010
02011
02012
02013
02014
02015
02016
02017 }else{
02018 ++oneAggregates;
02019 ++conAggregates;
02020 }
02021
02022 }else{
02023 ++oneAggregates;
02024 ++isoAggregates;
02025 }
02026 else{
02027 if(graph.getVertexProperties(seed).isolated())
02028 ++isoAggregates;
02029 else
02030 ++conAggregates;
02031 }
02032 unmarkFront();
02033 markFront(aggregates);
02034 seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02035 unmarkFront();
02036 }
02037
02038 Dune::dinfo<<"connected aggregates: "<<conAggregates;
02039 Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02040 Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02041
02042 delete aggregate_;
02043 return Tuple<int,int,int>(conAggregates,isoAggregates,oneAggregates);
02044 }
02045
02046 template<class G>
02047 inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02048 {
02049 typedef typename VertexList::const_iterator Iterator;
02050
02051 Iterator end= front_.end();
02052 int count=0;
02053 for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02054 stack_.push(*vertex);
02055
02056
02057
02058
02059 }
02060
02061 template<class G>
02062 Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02063 const AggregatesMap<Vertex>& aggregates)
02064 : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02065 {
02066 vals_ = new Vertex[N];
02067 }
02068
02069 template<class G>
02070 Aggregator<G>::Stack::~Stack()
02071 {
02072 Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02073 delete[] vals_;
02074 }
02075
02076 template<class G>
02077 const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry
02078 = std::numeric_limits<typename G::VertexDescriptor>::max();
02079
02080 template<class G>
02081 inline bool Aggregator<G>::Stack::push(const Vertex& v)
02082 {
02083 if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02084 localPush(v);
02085 return true;
02086 }else
02087 return false;
02088 }
02089
02090 template<class G>
02091 inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02092 {
02093 vals_[head_] = v;
02094 size_ = std::min<int>(size_+1, N);
02095 head_ = (head_+N+1)%N;
02096 }
02097
02098 template<class G>
02099 void Aggregator<G>::Stack::fill()
02100 {
02101 int isolated = 0, connected=0;
02102 int isoumin, umin;
02103 filled_++;
02104
02105 head_ = size_ = 0;
02106 isoumin = umin = std::numeric_limits<int>::max();
02107
02108 typedef typename MatrixGraph::ConstVertexIterator Iterator;
02109
02110 const Iterator end = graph_.end();
02111
02112 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02113
02114 if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02115 continue;
02116
02117 if(vertex.properties().isolated()){
02118 isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02119 isolated++;
02120 }else{
02121 umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02122 connected++;
02123 }
02124 }
02125
02126 if(connected + isolated == 0)
02127
02128 return;
02129
02130 if(connected > 0){
02131
02132 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02133 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated()
02134 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02135 localPush(*vertex);
02136 }else{
02137 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02138 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated()
02139 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02140 localPush(*vertex);
02141 }
02142 maxSize_ = std::max(size_, maxSize_);
02143 }
02144
02145 template<class G>
02146 inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02147 {
02148 while(size_>0){
02149 head_ = (head_ + N -1) % N;
02150 size_--;
02151 Vertex v = vals_[head_];
02152 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02153 return v;
02154 }
02155
02156 fill();
02157
02158
02159 while(size_>0){
02160 head_ = (head_ + N -1) % N;
02161 size_--;
02162 Vertex v = vals_[head_];
02163 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02164 return v;
02165 }
02166 return NullEntry;
02167 }
02168
02169 template<class V>
02170 void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os)
02171 {
02172 std::ios_base::fmtflags oldOpts=os.flags();
02173
02174 os.setf(std::ios_base::right, std::ios_base::adjustfield);
02175
02176 V max=0;
02177 int width=1;
02178
02179 for(int i=0; i< n*m; i++)
02180 max=std::max(max, aggregates[i]);
02181
02182 for(int i=10; i < 1000000; i*=10)
02183 if(max/i>0)
02184 width++;
02185 else
02186 break;
02187
02188 for(int j=0, entry=0; j < m; j++){
02189 for(int i=0; i<n; i++, entry++){
02190 os.width(width);
02191 os<<aggregates[entry]<<" ";
02192 }
02193
02194 os<<std::endl;
02195 }
02196 os<<std::endl;
02197 os.flags(oldOpts);
02198 }
02199
02200
02201 }
02202
02203 }
02204
02205
02206 #endif