- Home
- About DUNE
- Download
- Documentation
- Community
- Development
00001 // $Id$ 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 00058 AggregationCriterion() 00059 : maxDistance_(2), minAggregateSize_(4), maxAggregateSize_(6), 00060 connectivity_(15), debugLevel_(2), skipiso_(false) 00061 {} 00062 00072 void setDefaultValuesIsotropic(std::size_t dim, std::size_t diameter=2) 00073 { 00074 maxDistance_=diameter-1; 00075 std::size_t csize=1; 00076 00077 for(;dim>0;dim--){ 00078 csize*=diameter; 00079 maxDistance_+=diameter-1; 00080 } 00081 minAggregateSize_=csize; 00082 maxAggregateSize_=static_cast<std::size_t>(csize*1.5); 00083 } 00084 00095 void setDefaultValuesAnisotropic(std::size_t dim,std::size_t diameter=2) 00096 { 00097 setDefaultValuesIsotropic(dim, diameter); 00098 maxDistance_+=dim-1; 00099 } 00107 std::size_t maxDistance() const { return maxDistance_;} 00108 00117 void setMaxDistance(std::size_t distance) { maxDistance_ = distance;} 00118 00124 bool skipIsolated() const 00125 { 00126 return skipiso_; 00127 } 00128 00134 void setSkipIsolated(bool skip) 00135 { 00136 skipiso_=skip; 00137 } 00138 00143 std::size_t minAggregateSize() const { return minAggregateSize_;} 00144 00151 void setMinAggregateSize(std::size_t size){ minAggregateSize_=size;} 00152 00157 std::size_t maxAggregateSize() const{ return maxAggregateSize_;} 00158 00165 void setMaxAggregateSize(std::size_t size){ maxAggregateSize_ = size;} 00166 00174 std::size_t maxConnectivity() const{ return connectivity_;} 00175 00183 void setMaxConnectivity(std::size_t connectivity){ connectivity_ = connectivity;} 00184 00190 void setDebugLevel(int level) 00191 { 00192 debugLevel_ = level; 00193 } 00194 00200 int debugLevel() const 00201 { 00202 return debugLevel_; 00203 } 00204 00205 00206 private: 00207 std::size_t maxDistance_, minAggregateSize_, maxAggregateSize_, connectivity_; 00208 int debugLevel_; 00209 bool skipiso_; 00210 }; 00211 00212 template<class T> 00213 std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion) 00214 { 00215 os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize=" 00216 <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize() 00217 <<" connectivity="<<criterion.maxConnectivity()<<" debugLevel="<<criterion.debugLevel()<<"}"; 00218 return os; 00219 } 00220 00224 class DependencyParameters 00225 { 00226 public: 00228 DependencyParameters() 00229 : alpha_(1.0/3.0), beta_(1.0E-5) 00230 {} 00231 00236 void setBeta(double b) 00237 { 00238 beta_ = b; 00239 } 00240 00246 double beta() const 00247 { 00248 return beta_; 00249 } 00250 00255 void setAlpha(double a) 00256 { 00257 alpha_ = a; 00258 } 00259 00264 double alpha() const 00265 { 00266 return alpha_; 00267 } 00268 00269 private: 00270 double alpha_, beta_; 00271 }; 00272 00273 00277 template<class M, class N> 00278 class Dependency : public DependencyParameters 00279 { 00280 public: 00284 typedef M Matrix; 00285 00289 typedef N Norm; 00290 00294 typedef typename Matrix::row_type Row; 00295 00299 typedef typename Matrix::ConstColIterator ColIter; 00300 00301 void init(const Matrix* matrix); 00302 00303 void initRow(const Row& row, int index); 00304 00305 void examine(const ColIter& col); 00306 00307 template<class G> 00308 void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col); 00309 00310 bool isIsolated(); 00311 private: 00313 const Matrix* matrix_; 00315 typename Matrix::field_type maxValue_; 00317 Norm norm_; 00319 int row_; 00321 typename Matrix::field_type diagonal_; 00322 }; 00323 00327 template<class M, class N> 00328 class SymmetricDependency : public DependencyParameters 00329 { 00330 public: 00334 typedef M Matrix; 00335 00339 typedef N Norm; 00340 00344 typedef typename Matrix::row_type Row; 00345 00349 typedef typename Matrix::ConstColIterator ColIter; 00350 00351 void init(const Matrix* matrix); 00352 00353 void initRow(const Row& row, int index); 00354 00355 void examine(const ColIter& col); 00356 00357 template<class G> 00358 void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col); 00359 00360 bool isIsolated(); 00361 private: 00363 const Matrix* matrix_; 00365 typename Matrix::field_type maxValue_; 00367 Norm norm_; 00369 int row_; 00371 typename Matrix::field_type diagonal_; 00372 }; 00373 00378 template<int N> 00379 class Diagonal 00380 { 00381 public: 00382 enum{ /* @brief We preserve the sign.*/ 00383 is_sign_preserving = true 00384 }; 00385 00390 template<class M> 00391 typename M::field_type operator()(const M& m) const 00392 { 00393 return m[N][N]; 00394 } 00395 }; 00396 00401 class FirstDiagonal : public Diagonal<0> 00402 {}; 00403 00409 struct RowSum 00410 { 00411 00412 enum{ /* @brief We preserve the sign.*/ 00413 is_sign_preserving = false 00414 }; 00419 template<class M> 00420 typename M::field_type operator()(const M& m) const 00421 { 00422 return m.infinity_norm(); 00423 } 00424 }; 00425 00426 struct FrobeniusNorm 00427 { 00428 00429 enum{ /* @brief We preserve the sign.*/ 00430 is_sign_preserving = false 00431 }; 00436 template<class M> 00437 typename M::field_type operator()(const M& m) const 00438 { 00439 return m.frobenius_norm(); 00440 } 00441 }; 00442 struct AlwaysOneNorm 00443 { 00444 00445 enum{ /* @brief We preserve the sign.*/ 00446 is_sign_preserving = false 00447 }; 00452 template<class M> 00453 typename M::field_type operator()(const M& m) const 00454 { 00455 return 1; 00456 } 00457 }; 00467 template<class M, class Norm> 00468 class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> > 00469 {}; 00470 00471 00483 template<class M, class Norm> 00484 class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> > 00485 {}; 00486 // forward declaration 00487 template<class G> class Aggregator; 00488 00489 00497 template<class V> 00498 class AggregatesMap 00499 { 00500 public: 00501 00505 static const V UNAGGREGATED; 00506 00510 static const V ISOLATED; 00514 typedef V VertexDescriptor; 00515 00519 typedef V AggregateDescriptor; 00520 00525 typedef PoolAllocator<VertexDescriptor,100> Allocator; 00526 00531 typedef SLList<VertexDescriptor,Allocator> VertexList; 00532 00536 class DummyEdgeVisitor 00537 { 00538 public: 00539 template<class EdgeIterator> 00540 void operator()(const EdgeIterator& egde) const 00541 {} 00542 }; 00543 00544 00548 AggregatesMap(); 00549 00555 AggregatesMap(std::size_t noVertices); 00556 00560 ~AggregatesMap(); 00561 00569 template<class M, class G, class C> 00570 tuple<int,int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion); 00571 00591 template<bool reset, class G, class F, class VM> 00592 std::size_t breadthFirstSearch(const VertexDescriptor& start, 00593 const AggregateDescriptor& aggregate, 00594 const G& graph, 00595 F& aggregateVisitor, 00596 VM& visitedMap) const; 00597 00621 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM> 00622 std::size_t breadthFirstSearch(const VertexDescriptor& start, 00623 const AggregateDescriptor& aggregate, 00624 const G& graph, L& visited, F1& aggregateVisitor, 00625 F2& nonAggregateVisitor, 00626 VM& visitedMap) const; 00627 00633 void allocate(std::size_t noVertices); 00634 00638 std::size_t noVertices() const; 00639 00643 void free(); 00644 00650 AggregateDescriptor& operator[](const VertexDescriptor& v); 00651 00657 const AggregateDescriptor& operator[](const VertexDescriptor& v) const; 00658 00659 typedef const AggregateDescriptor* const_iterator; 00660 00661 const_iterator begin() const 00662 { 00663 return aggregates_; 00664 } 00665 00666 const_iterator end() const 00667 { 00668 return aggregates_+noVertices(); 00669 } 00670 00671 typedef AggregateDescriptor* iterator; 00672 00673 iterator begin() 00674 { 00675 return aggregates_; 00676 } 00677 00678 iterator end() 00679 { 00680 return aggregates_+noVertices(); 00681 } 00682 private: 00684 AggregatesMap(const AggregatesMap<V>& map) 00685 { 00686 throw "Auch!"; 00687 } 00688 00690 AggregatesMap<V>& operator=(const AggregatesMap<V>& map) 00691 { 00692 throw "Auch!"; 00693 return this; 00694 } 00695 00699 AggregateDescriptor* aggregates_; 00700 00704 std::size_t noVertices_; 00705 }; 00706 00710 template<class G, class C> 00711 void buildDependency(G& graph, 00712 const typename C::Matrix& matrix, 00713 C criterion); 00714 00719 template<class G, class S> 00720 class Aggregate 00721 { 00722 00723 public: 00724 00725 /*** 00726 * @brief The type of the matrix graph we work with. 00727 */ 00728 typedef G MatrixGraph; 00732 typedef typename MatrixGraph::VertexDescriptor Vertex; 00733 00738 typedef PoolAllocator<Vertex,100> Allocator; 00739 00744 typedef SLList<Vertex,Allocator> VertexList; 00745 00746 00751 typedef S VertexSet; 00752 00754 typedef typename VertexList::const_iterator const_iterator; 00755 00759 typedef std::size_t* SphereMap; 00760 00768 Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates, 00769 VertexSet& connectivity); 00770 00777 void reconstruct(const Vertex& vertex); 00778 00782 void seed(const Vertex& vertex); 00783 00787 void add(const Vertex& vertex); 00788 00792 void clear(); 00793 00797 typename VertexList::size_type size(); 00801 typename VertexList::size_type connectSize(); 00802 00806 int id(); 00807 00809 const_iterator begin() const; 00810 00812 const_iterator end() const; 00813 00814 private: 00818 VertexList vertices_; 00819 00824 int id_; 00825 00829 const MatrixGraph& graph_; 00830 00834 AggregatesMap<Vertex>& aggregates_; 00835 00839 VertexSet& connected_; 00840 }; 00841 00845 template<class G> 00846 class Aggregator 00847 { 00848 public: 00849 00853 typedef G MatrixGraph; 00854 00858 typedef typename MatrixGraph::VertexDescriptor Vertex; 00859 00861 typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor; 00862 00866 Aggregator(); 00867 00871 ~Aggregator(); 00872 00885 template<class M, class C> 00886 tuple<int,int,int,int> build(const M& m, G& graph, 00887 AggregatesMap<Vertex>& aggregates, const C& c); 00888 private: 00893 typedef PoolAllocator<Vertex,100> Allocator; 00894 00898 typedef SLList<Vertex,Allocator> VertexList; 00899 00903 typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet; 00904 00908 typedef std::size_t* SphereMap; 00909 00913 MatrixGraph* graph_; 00914 00918 Aggregate<MatrixGraph,VertexSet>* aggregate_; 00919 00923 VertexList front_; 00924 00928 VertexSet connected_; 00929 00933 int size_; 00934 00938 class Stack 00939 { 00940 public: 00941 static const Vertex NullEntry; 00942 00943 Stack(const MatrixGraph& graph, 00944 const Aggregator<G>& aggregatesBuilder, 00945 const AggregatesMap<Vertex>& aggregates); 00946 ~Stack(); 00947 bool push(const Vertex& v); 00948 void fill(); 00949 Vertex pop(); 00950 private: 00951 enum{ N = 256000 }; 00952 00954 const MatrixGraph& graph_; 00956 const Aggregator<G>& aggregatesBuilder_; 00958 const AggregatesMap<Vertex>& aggregates_; 00960 int size_; 00961 int maxSize_; 00963 int head_; 00964 int filled_; 00965 00967 Vertex* vals_; 00968 00969 void localPush(const Vertex& v); 00970 }; 00971 00972 friend class Stack; 00973 00984 template<class V> 00985 void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, 00986 const AggregatesMap<Vertex>& aggregates, 00987 V& visitor) const; 00988 00993 template<class V> 00994 class AggregateVisitor 00995 { 00996 public: 01000 typedef V Visitor; 01008 AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate, 01009 Visitor& visitor); 01010 01017 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); 01018 01019 private: 01021 const AggregatesMap<Vertex>& aggregates_; 01023 AggregateDescriptor aggregate_; 01025 Visitor* visitor_; 01026 }; 01027 01031 class Counter 01032 { 01033 public: 01035 Counter(); 01037 int value(); 01038 01039 protected: 01041 void increment(); 01043 void decrement(); 01044 01045 private: 01046 int count_; 01047 }; 01048 01049 01054 class FrontNeighbourCounter : public Counter 01055 { 01056 public: 01061 FrontNeighbourCounter(const MatrixGraph& front); 01062 01063 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); 01064 01065 private: 01066 const MatrixGraph& graph_; 01067 }; 01068 01073 int noFrontNeighbours(const Vertex& vertex) const; 01074 01078 class TwoWayCounter : public Counter 01079 { 01080 public: 01081 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); 01082 }; 01083 01095 int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate, 01096 const AggregatesMap<Vertex>& aggregates) const; 01097 01101 class OneWayCounter : public Counter 01102 { 01103 public: 01104 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); 01105 }; 01106 01118 int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate, 01119 const AggregatesMap<Vertex>& aggregates) const; 01120 01127 class ConnectivityCounter : public Counter 01128 { 01129 public: 01136 ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates); 01137 01138 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); 01139 01140 private: 01142 const VertexSet& connected_; 01144 const AggregatesMap<Vertex>& aggregates_; 01145 01146 }; 01147 01159 double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const; 01167 bool connected(const Vertex& vertex, const AggregateDescriptor& aggregate, 01168 const AggregatesMap<Vertex>& aggregates) const; 01169 01177 bool connected(const Vertex& vertex, const SLList<AggregateDescriptor>& aggregateList, 01178 const AggregatesMap<Vertex>& aggregates) const; 01179 01187 class DependencyCounter: public Counter 01188 { 01189 public: 01193 DependencyCounter(); 01194 01195 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); 01196 }; 01197 01204 class FrontMarker 01205 { 01206 public: 01213 FrontMarker(VertexList& front, MatrixGraph& graph); 01214 01215 void operator()(const typename MatrixGraph::ConstEdgeIterator& edge); 01216 01217 private: 01219 VertexList& front_; 01221 MatrixGraph& graph_; 01222 }; 01223 01230 void markFront(const AggregatesMap<Vertex>& aggregates); 01231 01235 void unmarkFront(); 01236 01251 int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const; 01252 01266 std::pair<int,int> neighbours(const Vertex& vertex, 01267 const AggregateDescriptor& aggregate, 01268 const AggregatesMap<Vertex>& aggregates) const; 01285 int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const; 01286 01294 bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const; 01295 01302 void seedFromFront(Stack& stack, bool isolated); 01303 01311 std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates); 01312 01321 Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const; 01322 01331 void nonisoNeighbourAggregate(const Vertex& vertex, 01332 const AggregatesMap<Vertex>& aggregates, 01333 SLList<Vertex>& neighbours) const; 01334 01342 template<class C> 01343 void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c); 01344 template<class C> 01345 void growIsolatedAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c); 01346 }; 01347 01348 #ifndef DOXYGEN 01349 01350 template<class M, class N> 01351 inline void SymmetricDependency<M,N>::init(const Matrix* matrix) 01352 { 01353 matrix_ = matrix; 01354 } 01355 01356 template<class M, class N> 01357 inline void SymmetricDependency<M,N>::initRow(const Row& row, int index) 01358 { 01359 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min()); 01360 row_ = index; 01361 diagonal_ = norm_(matrix_->operator[](row_)[row_]); 01362 } 01363 01364 template<class M, class N> 01365 inline void SymmetricDependency<M,N>::examine(const ColIter& col) 01366 { 01367 typename Matrix::field_type eij = norm_(*col); 01368 typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]); 01369 01370 // skip positve offdiagonals if norm preserves sign of them. 01371 if(!N::is_sign_preserving || eij<0 || eji<0) 01372 maxValue_ = std::max(maxValue_, 01373 eij /diagonal_ * eji/ 01374 norm_(matrix_->operator[](col.index())[col.index()])); 01375 } 01376 01377 template<class M, class N> 01378 template<class G> 01379 inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col) 01380 { 01381 typename Matrix::field_type eij = norm_(*col); 01382 typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]); 01383 01384 // skip positve offdiagonals if norm preserves sign of them. 01385 if(!N::is_sign_preserving || (eij<0 || eji<0)) 01386 if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) * 01387 eij/ diagonal_ > alpha() * maxValue_){ 01388 edge.properties().setDepends(); 01389 edge.properties().setInfluences(); 01390 01391 typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source()); 01392 other.setInfluences(); 01393 other.setDepends(); 01394 } 01395 } 01396 01397 template<class M, class N> 01398 inline bool SymmetricDependency<M,N>::isIsolated() 01399 { 01400 return maxValue_ < beta(); 01401 } 01402 01403 01404 template<class M, class N> 01405 inline void Dependency<M,N>::init(const Matrix* matrix) 01406 { 01407 matrix_ = matrix; 01408 } 01409 01410 template<class M, class N> 01411 inline void Dependency<M,N>::initRow(const Row& row, int index) 01412 { 01413 maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min()); 01414 row_ = index; 01415 diagonal_ = norm_(matrix_->operator[](row_)[row_]); 01416 } 01417 01418 template<class M, class N> 01419 inline void Dependency<M,N>::examine(const ColIter& col) 01420 { 01421 maxValue_ = std::max(maxValue_, 01422 -norm_(*col)); 01423 } 01424 01425 template<class M, class N> 01426 template<class G> 01427 inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col) 01428 { 01429 if(-norm_(*col) >= maxValue_ * alpha()){ 01430 edge.properties().setDepends(); 01431 typedef typename G::EdgeDescriptor ED; 01432 ED e= graph.findEdge(edge.target(), edge.source()); 01433 if(e!=std::numeric_limits<ED>::max()) 01434 { 01435 typename G::EdgeProperties& other = graph.getEdgeProperties(e); 01436 other.setInfluences(); 01437 } 01438 } 01439 } 01440 01441 template<class M, class N> 01442 inline bool Dependency<M,N>::isIsolated() 01443 { 01444 return maxValue_ < beta() * diagonal_; 01445 } 01446 01447 template<class G,class S> 01448 Aggregate<G,S>::Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates, 01449 VertexSet& connected) 01450 : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates), 01451 connected_(connected) 01452 {} 01453 01454 template<class G,class S> 01455 void Aggregate<G,S>::reconstruct(const Vertex& vertex) 01456 { 01457 vertices_.push_back(vertex); 01458 typedef typename VertexList::const_iterator iterator; 01459 iterator begin = vertices_.begin(); 01460 iterator end = vertices_.end(); 01461 throw "Not yet implemented"; 01462 01463 while(begin!=end){ 01464 //for(); 01465 } 01466 01467 } 01468 01469 template<class G,class S> 01470 inline void Aggregate<G,S>::seed(const Vertex& vertex) 01471 { 01472 dvverb<<"Connected cleared"<<std::endl; 01473 connected_.clear(); 01474 vertices_.clear(); 01475 connected_.insert(vertex); 01476 dvverb << " Inserting "<<vertex<<" size="<<connected_.size(); 01477 id_ = vertex; 01478 add(vertex); 01479 } 01480 01481 01482 template<class G,class S> 01483 inline void Aggregate<G,S>::add(const Vertex& vertex) 01484 { 01485 vertices_.push_back(vertex); 01486 aggregates_[vertex]=id_; 01487 01488 typedef typename MatrixGraph::ConstEdgeIterator iterator; 01489 const iterator end = graph_.endEdges(vertex); 01490 for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge){ 01491 dvverb << " Inserting "<<aggregates_[edge.target()]; 01492 connected_.insert(aggregates_[edge.target()]); 01493 dvverb <<" size="<<connected_.size(); 01494 } 01495 dvverb <<std::endl; 01496 } 01497 template<class G,class S> 01498 inline void Aggregate<G,S>::clear() 01499 { 01500 vertices_.clear(); 01501 connected_.clear(); 01502 id_=-1; 01503 } 01504 01505 template<class G,class S> 01506 inline typename Aggregate<G,S>::VertexList::size_type 01507 Aggregate<G,S>::size() 01508 { 01509 return vertices_.size(); 01510 } 01511 01512 template<class G,class S> 01513 inline typename Aggregate<G,S>::VertexList::size_type 01514 Aggregate<G,S>::connectSize() 01515 { 01516 return connected_.size(); 01517 } 01518 01519 template<class G,class S> 01520 inline int Aggregate<G,S>::id() 01521 { 01522 return id_; 01523 } 01524 01525 template<class G,class S> 01526 inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::begin() const 01527 { 01528 return vertices_.begin(); 01529 } 01530 01531 template<class G,class S> 01532 inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const 01533 { 01534 return vertices_.end(); 01535 } 01536 01537 template<class V> 01538 const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max(); 01539 01540 template<class V> 01541 const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1; 01542 01543 template<class V> 01544 AggregatesMap<V>::AggregatesMap() 01545 : aggregates_(0) 01546 {} 01547 01548 template<class V> 01549 AggregatesMap<V>::~AggregatesMap() 01550 { 01551 if(aggregates_!=0) 01552 delete[] aggregates_; 01553 } 01554 01555 01556 template<class V> 01557 inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices) 01558 { 01559 allocate(noVertices); 01560 } 01561 01562 template<class V> 01563 inline std::size_t AggregatesMap<V>::noVertices() const 01564 { 01565 return noVertices_; 01566 } 01567 01568 template<class V> 01569 inline void AggregatesMap<V>::allocate(std::size_t noVertices) 01570 { 01571 aggregates_ = new AggregateDescriptor[noVertices]; 01572 noVertices_ = noVertices; 01573 01574 for(std::size_t i=0; i < noVertices; i++) 01575 aggregates_[i]=UNAGGREGATED; 01576 } 01577 01578 template<class V> 01579 inline void AggregatesMap<V>::free() 01580 { 01581 assert(aggregates_ != 0); 01582 delete[] aggregates_; 01583 aggregates_=0; 01584 } 01585 01586 template<class V> 01587 inline typename AggregatesMap<V>::AggregateDescriptor& 01588 AggregatesMap<V>::operator[](const VertexDescriptor& v) 01589 { 01590 return aggregates_[v]; 01591 } 01592 01593 template<class V> 01594 inline const typename AggregatesMap<V>::AggregateDescriptor& 01595 AggregatesMap<V>::operator[](const VertexDescriptor& v) const 01596 { 01597 return aggregates_[v]; 01598 } 01599 01600 template<class V> 01601 template<bool reset, class G, class F,class VM> 01602 inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start, 01603 const AggregateDescriptor& aggregate, 01604 const G& graph, F& aggregateVisitor, 01605 VM& visitedMap) const 01606 { 01607 VertexList vlist; 01608 01609 DummyEdgeVisitor dummy; 01610 return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap); 01611 } 01612 01613 template<class V> 01614 template<bool remove, bool reset, class G, class L, class F1, class F2, class VM> 01615 std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start, 01616 const AggregateDescriptor& aggregate, 01617 const G& graph, 01618 L& visited, 01619 F1& aggregateVisitor, 01620 F2& nonAggregateVisitor, 01621 VM& visitedMap) const 01622 { 01623 typedef typename L::const_iterator ListIterator; 01624 int visitedSpheres = 0; 01625 01626 visited.push_back(start); 01627 put(visitedMap, start, true); 01628 01629 ListIterator current = visited.begin(); 01630 ListIterator end = visited.end(); 01631 std::size_t i=0, size=visited.size(); 01632 01633 // visit the neighbours of all vertices of the 01634 // current sphere. 01635 while(current != end){ 01636 01637 for(;i<size; ++current, ++i){ 01638 typedef typename G::ConstEdgeIterator EdgeIterator; 01639 const EdgeIterator endEdge = graph.endEdges(*current); 01640 01641 for(EdgeIterator edge = graph.beginEdges(*current); 01642 edge != endEdge; ++edge){ 01643 01644 if(aggregates_[edge.target()]==aggregate){ 01645 if(!get(visitedMap, edge.target())){ 01646 put(visitedMap, edge.target(), true); 01647 visited.push_back(edge.target()); 01648 aggregateVisitor(edge); 01649 } 01650 }else 01651 nonAggregateVisitor(edge); 01652 } 01653 } 01654 end = visited.end(); 01655 size = visited.size(); 01656 if(current != end) 01657 visitedSpheres++; 01658 } 01659 01660 if(reset) 01661 for(current = visited.begin(); current != end; ++current) 01662 put(visitedMap, *current, false); 01663 01664 01665 if(remove) 01666 visited.clear(); 01667 01668 return visitedSpheres; 01669 } 01670 01671 template<class G> 01672 Aggregator<G>::Aggregator() 01673 : graph_(0), aggregate_(0), front_(), connected_(), size_(-1) 01674 {} 01675 01676 template<class G> 01677 Aggregator<G>::~Aggregator() 01678 { 01679 size_=-1; 01680 } 01681 01682 template<class G, class C> 01683 void buildDependency(G& graph, 01684 const typename C::Matrix& matrix, 01685 C criterion) 01686 { 01687 // The Criterion we use for building the dependency. 01688 typedef C Criterion; 01689 01690 // assert(graph.isBuilt()); 01691 typedef typename C::Matrix Matrix; 01692 typedef typename G::VertexIterator VertexIterator; 01693 01694 criterion.init(&matrix); 01695 01696 for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex){ 01697 typedef typename Matrix::row_type Row; 01698 01699 const Row& row = matrix[*vertex]; 01700 01701 // Tell the criterion what row we will examine now 01702 // This might for example be used for calculating the 01703 // maximum offdiagonal value 01704 criterion.initRow(row, *vertex); 01705 01706 // On a first path all columns are examined. After this 01707 // the calculator should know whether the vertex is isolated. 01708 typedef typename Matrix::ConstColIterator ColIterator; 01709 ColIterator end = row.end(); 01710 typename Matrix::field_type absoffdiag=0; 01711 01712 for(ColIterator col = row.begin(); col != end; ++col) 01713 if(col.index()!=*vertex){ 01714 criterion.examine(col); 01715 absoffdiag=std::max(absoffdiag, col->frobenius_norm()); 01716 } 01717 01718 if(absoffdiag==0) 01719 vertex.properties().setExcludedBorder(); 01720 01721 // reset the vertex properties 01722 //vertex.properties().reset(); 01723 01724 // Check whether the vertex is isolated. 01725 if(criterion.isIsolated()){ 01726 //std::cout<<"ISOLATED: "<<*vertex<<std::endl; 01727 vertex.properties().setIsolated(); 01728 }else{ 01729 // Examine all the edges beginning at this vertex. 01730 typedef typename G::EdgeIterator EdgeIterator; 01731 typedef typename Matrix::ConstColIterator ColIterator; 01732 EdgeIterator end = vertex.end(); 01733 ColIterator col = matrix[*vertex].begin(); 01734 01735 for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){ 01736 // Move to the right column. 01737 while(col.index()!=edge.target()) 01738 ++col; 01739 criterion.examine(graph, edge, col); 01740 } 01741 } 01742 01743 } 01744 } 01745 01746 01747 template<class G> 01748 template<class V> 01749 inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates, 01750 const AggregateDescriptor& aggregate, V& visitor) 01751 : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor) 01752 {} 01753 01754 template<class G> 01755 template<class V> 01756 inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) 01757 { 01758 if(aggregates_[edge.target()]==aggregate_) 01759 visitor_->operator()(edge); 01760 } 01761 01762 template<class G> 01763 template<class V> 01764 inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex, 01765 const AggregateDescriptor& aggregate, 01766 const AggregatesMap<Vertex>& aggregates, 01767 V& visitor) const 01768 { 01769 // Only evaluates for edge pointing to the aggregate 01770 AggregateVisitor<V> v(aggregates, aggregate, visitor); 01771 visitNeighbours(*graph_, vertex, v); 01772 } 01773 01774 01775 template<class G> 01776 inline Aggregator<G>::Counter::Counter() 01777 : count_(0) 01778 {} 01779 01780 template<class G> 01781 inline void Aggregator<G>::Counter::increment() 01782 { 01783 ++count_; 01784 } 01785 01786 template<class G> 01787 inline void Aggregator<G>::Counter::decrement() 01788 { 01789 --count_; 01790 } 01791 template<class G> 01792 inline int Aggregator<G>::Counter::value() 01793 { 01794 return count_; 01795 } 01796 01797 template<class G> 01798 inline void Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) 01799 { 01800 if(edge.properties().isTwoWay()) 01801 Counter::increment(); 01802 } 01803 01804 template<class G> 01805 int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate, 01806 const AggregatesMap<Vertex>& aggregates) const 01807 { 01808 TwoWayCounter counter; 01809 visitAggregateNeighbours(vertex, aggregate, aggregates, counter); 01810 return counter.value(); 01811 } 01812 01813 template<class G> 01814 int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate, 01815 const AggregatesMap<Vertex>& aggregates) const 01816 { 01817 OneWayCounter counter; 01818 visitAggregateNeighbours(vertex, aggregate, aggregates, counter); 01819 return counter.value(); 01820 } 01821 01822 template<class G> 01823 inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) 01824 { 01825 if(edge.properties().isOneWay()) 01826 Counter::increment(); 01827 } 01828 01829 template<class G> 01830 inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected, 01831 const AggregatesMap<Vertex>& aggregates) 01832 : Counter(), connected_(connected), aggregates_(aggregates) 01833 {} 01834 01835 01836 template<class G> 01837 inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) 01838 { 01839 if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED) 01840 // Would be a new connection 01841 Counter::increment(); 01842 else{ 01843 Counter::increment(); 01844 Counter::increment(); 01845 } 01846 } 01847 01848 template<class G> 01849 inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const 01850 { 01851 ConnectivityCounter counter(connected_, aggregates); 01852 double noNeighbours=visitNeighbours(*graph_, vertex, counter); 01853 return (double)counter.value()/noNeighbours; 01854 } 01855 01856 template<class G> 01857 inline Aggregator<G>::DependencyCounter::DependencyCounter() 01858 : Counter() 01859 {} 01860 01861 template<class G> 01862 inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) 01863 { 01864 if(edge.properties().depends()) 01865 Counter::increment(); 01866 if(edge.properties().influences()) 01867 Counter::increment(); 01868 } 01869 01870 template<class G> 01871 int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const 01872 { 01873 return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates); 01874 } 01875 01876 template<class G> 01877 std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex, 01878 const AggregateDescriptor& aggregate, 01879 const AggregatesMap<Vertex>& aggregates) const 01880 { 01881 DependencyCounter unused, aggregated; 01882 typedef AggregateVisitor<DependencyCounter> Counter; 01883 typedef tuple<Counter,Counter> CounterTuple; 01884 CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated))); 01885 visitNeighbours(*graph_, vertex, visitors); 01886 return std::make_pair(unused.value(), aggregated.value()); 01887 } 01888 01889 01890 template<class G> 01891 int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const 01892 { 01893 DependencyCounter counter; 01894 visitAggregateNeighbours(vertex, aggregate, aggregates, counter); 01895 return counter.value(); 01896 } 01897 01898 template<class G> 01899 std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) 01900 { 01901 typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_); 01902 VertexList vlist; 01903 typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy; 01904 return aggregates.template breadthFirstSearch<true,true>(vertex, 01905 aggregate_->id(), *graph_, 01906 vlist, dummy, dummy, visitedMap); 01907 } 01908 01909 template<class G> 01910 inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph) 01911 : front_(front), graph_(graph) 01912 {} 01913 01914 template<class G> 01915 inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) 01916 { 01917 Vertex target = edge.target(); 01918 01919 if(!graph_.getVertexProperties(target).front()){ 01920 front_.push_back(target); 01921 graph_.getVertexProperties(target).setFront(); 01922 } 01923 } 01924 01925 01926 template<class G> 01927 void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates) 01928 { 01929 assert(front_.size()==0); 01930 FrontMarker frontBuilder(front_, *graph_); 01931 typedef typename Aggregate<G,VertexSet>::const_iterator Iterator; 01932 01933 for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex) 01934 visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder); 01935 01936 } 01937 01938 template<class G> 01939 inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const 01940 { 01941 // Todo 01942 Dune::dvverb<<" Admissible not yet implemented!"<<std::endl; 01943 return true; 01944 //Situation 1: front node depends on two nodes. Then these 01945 // have to be strongly connected to each other 01946 01947 // Iterate over all all neighbours of front node 01948 typedef typename MatrixGraph::ConstEdgeIterator Iterator; 01949 Iterator vend = graph_->endEdges(vertex); 01950 for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge){ 01951 // if(edge.properties().depends() && !edge.properties().influences() 01952 if(edge.properties().isStrong() 01953 && aggregates[edge.target()]==aggregate) 01954 { 01955 // Search for another link to the aggregate 01956 Iterator edge1 = edge; 01957 for(++edge1; edge1 != vend; ++edge1){ 01958 //if(edge1.properties().depends() && !edge1.properties().influences() 01959 if(edge1.properties().isStrong() 01960 && aggregates[edge.target()]==aggregate) 01961 { 01962 //Search for an edge connecting the two vertices that is 01963 //strong 01964 bool found=false; 01965 Iterator v2end = graph_->endEdges(edge.target()); 01966 for(Iterator edge2 = graph_->beginEdges(edge.target()); edge2 != v2end; ++edge2){ 01967 if(edge2.target()==edge1.target() && 01968 edge2.properties().isStrong()){ 01969 found =true; 01970 break; 01971 } 01972 } 01973 if(found) 01974 return true; 01975 } 01976 } 01977 } 01978 } 01979 01980 // Situation 2: cluster node depends on front node and other cluster node 01982 vend = graph_->endEdges(vertex); 01983 for(Iterator edge = graph_->beginEdges(vertex); edge != vend; ++edge){ 01984 //if(!edge.properties().depends() && edge.properties().influences() 01985 if(edge.properties().isStrong() 01986 && aggregates[edge.target()]==aggregate) 01987 { 01988 // Search for a link from target that stays within the aggregate 01989 Iterator v1end = graph_->endEdges(edge.target()); 01990 01991 for(Iterator edge1=graph_->beginEdges(edge.target()); edge1 != v1end; ++edge1){ 01992 //if(edge1.properties().depends() && !edge1.properties().influences() 01993 if(edge1.properties().isStrong() 01994 && aggregates[edge1.target()]==aggregate) 01995 { 01996 bool found=false; 01997 // Check if front node is also connected to this one 01998 Iterator v2end = graph_->endEdges(vertex); 01999 for(Iterator edge2 = graph_->beginEdges(vertex); edge2 != v2end; ++edge2){ 02000 if(edge2.target()==edge1.target()){ 02001 if(edge2.properties().isStrong()) 02002 found=true; 02003 break; 02004 } 02005 } 02006 if(found) 02007 return true; 02008 } 02009 } 02010 } 02011 } 02012 return false; 02013 } 02014 02015 template<class G> 02016 void Aggregator<G>::unmarkFront() 02017 { 02018 typedef typename VertexList::const_iterator Iterator; 02019 02020 for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex) 02021 graph_->getVertexProperties(*vertex).resetFront(); 02022 02023 front_.clear(); 02024 } 02025 02026 template<class G> 02027 inline void 02028 Aggregator<G>::nonisoNeighbourAggregate(const Vertex& vertex, 02029 const AggregatesMap<Vertex>& aggregates, 02030 SLList<Vertex>& neighbours) const 02031 { 02032 typedef typename MatrixGraph::ConstEdgeIterator Iterator; 02033 Iterator end=graph_->beginEdges(vertex); 02034 neighbours.clear(); 02035 02036 for(Iterator edge=graph_->beginEdges(vertex); edge!=end; ++edge) 02037 { 02038 if(aggregates[edge.target()]!=AggregatesMap<Vertex>::UNAGGREGATED && graph_->getVertexProperties(edge.target()).isolated()) 02039 neighbours.push_back(aggregates[edge.target()]); 02040 } 02041 } 02042 02043 template<class G> 02044 inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const 02045 { 02046 typedef typename MatrixGraph::ConstEdgeIterator Iterator; 02047 02048 Iterator end = graph_->endEdges(vertex); 02049 for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){ 02050 if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED && 02051 graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){ 02052 if( graph_->getVertexProperties(vertex).isolated() || 02053 ((edge.properties().depends() || edge.properties().influences()) 02054 && admissible(vertex, aggregates[edge.target()], aggregates))) 02055 return edge.target(); 02056 } 02057 } 02058 return AggregatesMap<Vertex>::UNAGGREGATED; 02059 } 02060 02061 template<class G> 02062 Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph) 02063 : Counter(), graph_(graph) 02064 {} 02065 02066 template<class G> 02067 void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge) 02068 { 02069 if(graph_.getVertexProperties(edge.target()).front()) 02070 Counter::increment(); 02071 } 02072 02073 template<class G> 02074 int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const 02075 { 02076 FrontNeighbourCounter counter(*graph_); 02077 visitNeighbours(*graph_, vertex, counter); 02078 return counter.value(); 02079 } 02080 template<class G> 02081 inline bool Aggregator<G>::connected(const Vertex& vertex, 02082 const AggregateDescriptor& aggregate, 02083 const AggregatesMap<Vertex>& aggregates) const 02084 { 02085 typedef typename G::ConstEdgeIterator iterator; 02086 const iterator end = graph_->endEdges(vertex); 02087 for(iterator edge = graph_->beginEdges(vertex); edge != end; ++edge) 02088 if(aggregates[edge.target()]==aggregate) 02089 return true; 02090 return false; 02091 } 02092 template<class G> 02093 inline bool Aggregator<G>::connected(const Vertex& vertex, 02094 const SLList<AggregateDescriptor>& aggregateList, 02095 const AggregatesMap<Vertex>& aggregates) const 02096 { 02097 typedef typename SLList<AggregateDescriptor>::const_iterator Iter; 02098 for(Iter i=aggregateList.begin(); i!=aggregateList.end(); ++i) 02099 if(connected(vertex, *i, aggregates)) 02100 return true; 02101 return false; 02102 } 02103 02104 template<class G> 02105 template<class C> 02106 void Aggregator<G>::growIsolatedAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c) 02107 { 02108 SLList<Vertex> connectedAggregates; 02109 nonisoNeighbourAggregate(seed, aggregates,connectedAggregates); 02110 02111 while(aggregate_->size()< c.minAggregateSize() && aggregate_->connectSize() < c.maxConnectivity()){ 02112 double maxCon=-1; 02113 std::size_t maxFrontNeighbours=0; 02114 02115 Vertex candidate=AggregatesMap<Vertex>::UNAGGREGATED; 02116 unmarkFront(); 02117 markFront(aggregates); 02118 typedef typename VertexList::const_iterator Iterator; 02119 02120 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){ 02121 if(distance(*vertex, aggregates)>c.maxDistance()) 02122 continue; // distance of proposes aggregate too big 02123 02124 if(connectedAggregates.size()>0){ 02125 // there is already a neighbour cluster 02126 // front node must be connected to same neighbour cluster 02127 02128 if(!connected(*vertex, connectedAggregates, aggregates)) 02129 continue; 02130 } 02131 02132 double con = connectivity(*vertex, aggregates); 02133 02134 if(con == maxCon){ 02135 std::size_t frontNeighbours = noFrontNeighbours(*vertex); 02136 02137 if(frontNeighbours >= maxFrontNeighbours){ 02138 maxFrontNeighbours = frontNeighbours; 02139 candidate = *vertex; 02140 } 02141 }else if(con > maxCon){ 02142 maxCon = con; 02143 maxFrontNeighbours = noFrontNeighbours(*vertex); 02144 candidate = *vertex; 02145 } 02146 } 02147 02148 if(candidate==AggregatesMap<Vertex>::UNAGGREGATED) 02149 break; 02150 02151 aggregate_->add(candidate); 02152 } 02153 } 02154 02155 template<class G> 02156 template<class C> 02157 void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c) 02158 { 02159 while(aggregate_->size() < c.minAggregateSize()){ 02160 int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1; 02161 double maxCon=-1; 02162 02163 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED; 02164 02165 unmarkFront(); 02166 markFront(aggregates); 02167 02168 typedef typename VertexList::const_iterator Iterator; 02169 02170 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){ 02171 // Only nonisolated nodes are considered 02172 if(graph_->getVertexProperties(*vertex).isolated()) 02173 continue; 02174 02175 int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates); 02176 02177 /* The case of two way connections. */ 02178 if( maxTwoCons == twoWayCons && twoWayCons > 0){ 02179 double con = connectivity(*vertex, aggregates); 02180 02181 if(con == maxCon){ 02182 int neighbours = noFrontNeighbours(*vertex); 02183 02184 if(neighbours > maxNeighbours){ 02185 maxNeighbours = neighbours; 02186 02187 std::size_t distance_ = distance(*vertex, aggregates); 02188 02189 if(c.maxDistance() >= distance_){ 02190 candidate = *vertex; 02191 } 02192 } 02193 }else if( con > maxCon){ 02194 maxCon = con; 02195 maxNeighbours = noFrontNeighbours(*vertex); 02196 std::size_t distance_ = distance(*vertex, aggregates); 02197 02198 if(c.maxDistance() >= distance_){ 02199 candidate = *vertex; 02200 } 02201 } 02202 }else if(twoWayCons > maxTwoCons){ 02203 maxTwoCons = twoWayCons; 02204 maxCon = connectivity(*vertex, aggregates); 02205 maxNeighbours = noFrontNeighbours(*vertex); 02206 std::size_t distance_ = distance(*vertex, aggregates); 02207 02208 if(c.maxDistance() >= distance_){ 02209 candidate = *vertex; 02210 } 02211 02212 // two way connections preceed 02213 maxOneCons = std::numeric_limits<int>::max(); 02214 } 02215 02216 if(twoWayCons > 0) 02217 continue; // THis is a two-way node, skip tests for one way nodes 02218 02219 /* The one way case */ 02220 int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates); 02221 02222 if(oneWayCons==0) 02223 continue; // No strong connections, skip the tests. 02224 02225 if(!admissible(*vertex, aggregate_->id(), aggregates)) 02226 continue; 02227 02228 if( maxOneCons == oneWayCons && oneWayCons > 0){ 02229 double con = connectivity(*vertex, aggregates); 02230 02231 if(con == maxCon){ 02232 int neighbours = noFrontNeighbours(*vertex); 02233 02234 if(neighbours > maxNeighbours){ 02235 maxNeighbours = neighbours; 02236 std::size_t distance_ = distance(*vertex, aggregates); 02237 02238 if(c.maxDistance() >= distance_){ 02239 candidate = *vertex; 02240 } 02241 } 02242 }else if( con > maxCon){ 02243 maxCon = con; 02244 maxNeighbours = noFrontNeighbours(*vertex); 02245 std::size_t distance_ = distance(*vertex, aggregates); 02246 if(c.maxDistance() >= distance_){ 02247 candidate = *vertex; 02248 } 02249 } 02250 }else if(oneWayCons > maxOneCons){ 02251 maxOneCons = oneWayCons; 02252 maxCon = connectivity(*vertex, aggregates); 02253 maxNeighbours = noFrontNeighbours(*vertex); 02254 std::size_t distance_ = distance(*vertex, aggregates); 02255 02256 if(c.maxDistance() >= distance_){ 02257 candidate = *vertex; 02258 } 02259 } 02260 } 02261 02262 02263 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) 02264 break; // No more candidates found 02265 02266 aggregate_->add(candidate); 02267 } 02268 } 02269 02270 template<typename V> 02271 template<typename M, typename G, typename C> 02272 tuple<int,int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion) 02273 { 02274 Aggregator<G> aggregator; 02275 return aggregator.build(matrix, graph, *this, criterion); 02276 } 02277 02278 template<class G> 02279 template<class M, class C> 02280 tuple<int,int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c) 02281 { 02282 // Stack for fast vertex access 02283 Stack stack_(graph, *this, aggregates); 02284 02285 graph_ = &graph; 02286 02287 aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_); 02288 02289 Timer watch; 02290 watch.reset(); 02291 02292 buildDependency(graph, m, c); 02293 02294 dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl; 02295 int noAggregates, conAggregates, isoAggregates, oneAggregates; 02296 std::size_t maxA=0, minA=1000000, avg=0; 02297 int skippedAggregates; 02298 noAggregates = conAggregates = isoAggregates = oneAggregates = 02299 skippedAggregates = 0; 02300 02301 while(true){ 02302 Vertex seed = stack_.pop(); 02303 02304 if(seed == Stack::NullEntry) 02305 // No more unaggregated vertices. We are finished! 02306 break; 02307 02308 // Debugging output 02309 if((noAggregates+1)%10000 == 0) 02310 Dune::dverb<<"c"; 02311 02312 aggregate_->seed(seed); 02313 02314 if(graph.getVertexProperties(seed).excludedBorder()){ 02315 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED; 02316 ++skippedAggregates; 02317 continue; 02318 } 02319 02320 if(graph.getVertexProperties(seed).isolated()){ 02321 if(c.skipIsolated()){ 02322 // isolated vertices are not aggregated but skipped on the coarser levels. 02323 aggregates[seed]=AggregatesMap<Vertex>::ISOLATED; 02324 ++skippedAggregates; 02325 // skip rest as no agglomeration is done. 02326 continue; 02327 }else 02328 growIsolatedAggregate(seed, aggregates, c); 02329 }else 02330 growAggregate(seed, aggregates, c); 02331 02332 02333 /* The rounding step. */ 02334 while(!(graph.getVertexProperties(seed).isolated()) && aggregate_->size() < c.maxAggregateSize()){ 02335 02336 unmarkFront(); 02337 markFront(aggregates); 02338 02339 Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED; 02340 02341 typedef typename VertexList::const_iterator Iterator; 02342 02343 for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){ 02344 02345 if(graph.getVertexProperties(*vertex).isolated()) 02346 continue; // No isolated nodes here 02347 02348 if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 && 02349 (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 || 02350 !admissible( *vertex, aggregate_->id(), aggregates) )) 02351 continue; 02352 02353 std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(), 02354 aggregates); 02355 02356 //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates)) 02357 // continue; 02358 02359 if(neighbourPair.first >= neighbourPair.second) 02360 continue; 02361 02362 if(distance(*vertex, aggregates) > c.maxDistance()) 02363 continue; // Distance too far 02364 candidate = *vertex; 02365 break; 02366 } 02367 02368 if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break; // no more candidates found. 02369 02370 aggregate_->add(candidate); 02371 02372 } 02373 02374 // try to merge aggregates consisting of only one nonisolated vertex with other aggregates 02375 if(aggregate_->size()==1 && c.maxAggregateSize()>1){ 02376 if(!graph.getVertexProperties(seed).isolated()){ 02377 Vertex mergedNeighbour = mergeNeighbour(seed, aggregates); 02378 02379 if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){ 02380 // assign vertex to the neighbouring cluster 02381 aggregates[seed] = aggregates[mergedNeighbour]; 02382 }else{ 02383 minA=std::min(minA,static_cast<std::size_t>(1)); 02384 maxA=std::max(maxA,static_cast<std::size_t>(1)); 02385 ++oneAggregates; 02386 ++conAggregates; 02387 } 02388 }else{ 02389 ++avg; 02390 minA=std::min(minA,static_cast<std::size_t>(1)); 02391 maxA=std::max(maxA,static_cast<std::size_t>(1)); 02392 ++oneAggregates; 02393 ++isoAggregates; 02394 } 02395 ++avg; 02396 }else{ 02397 avg+=aggregate_->size(); 02398 minA=std::min(minA,aggregate_->size()); 02399 maxA=std::max(maxA,aggregate_->size()); 02400 if(graph.getVertexProperties(seed).isolated()) 02401 ++isoAggregates; 02402 else 02403 ++conAggregates; 02404 } 02405 unmarkFront(); 02406 markFront(aggregates); 02407 seedFromFront(stack_, graph.getVertexProperties(seed).isolated()); 02408 unmarkFront(); 02409 } 02410 02411 Dune::dinfo<<"connected aggregates: "<<conAggregates; 02412 Dune::dinfo<<" isolated aggregates: "<<isoAggregates; 02413 if(conAggregates+isoAggregates>0) 02414 Dune::dinfo<<" one node aggregates: "<<oneAggregates<<" min size=" 02415 <<minA<<" max size="<<maxA 02416 <<" avg="<<avg/(conAggregates+isoAggregates)<<std::endl; 02417 02418 delete aggregate_; 02419 return make_tuple(conAggregates+isoAggregates,isoAggregates, 02420 oneAggregates,skippedAggregates); 02421 } 02422 02423 template<class G> 02424 inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated) 02425 { 02426 typedef typename VertexList::const_iterator Iterator; 02427 02428 Iterator end= front_.end(); 02429 int count=0; 02430 for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count) 02431 if(graph_->getVertexProperties(*vertex).isolated()==isolated) 02432 stack_.push(*vertex); 02433 /* 02434 if(MINIMAL_DEBUG_LEVEL<=2 && count==0 && !isolated) 02435 Dune::dverb<< " no vertices pushed for nonisolated aggregate!"<<std::endl; 02436 */ 02437 } 02438 02439 template<class G> 02440 Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder, 02441 const AggregatesMap<Vertex>& aggregates) 02442 : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0) 02443 { 02444 vals_ = new Vertex[N]; 02445 } 02446 02447 template<class G> 02448 Aggregator<G>::Stack::~Stack() 02449 { 02450 Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl; 02451 delete[] vals_; 02452 } 02453 02454 template<class G> 02455 const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry 02456 = std::numeric_limits<typename G::VertexDescriptor>::max(); 02457 02458 template<class G> 02459 inline bool Aggregator<G>::Stack::push(const Vertex& v) 02460 { 02461 if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){ 02462 localPush(v); 02463 return true; 02464 }else 02465 return false; 02466 } 02467 02468 template<class G> 02469 inline void Aggregator<G>::Stack::localPush(const Vertex& v) 02470 { 02471 vals_[head_] = v; 02472 size_ = std::min<int>(size_+1, N); 02473 head_ = (head_+N+1)%N; 02474 } 02475 02476 template<class G> 02477 void Aggregator<G>::Stack::fill() 02478 { 02479 int isolated = 0, connected=0; 02480 int isoumin, umin; 02481 filled_++; 02482 02483 head_ = size_ = 0; 02484 isoumin = umin = std::numeric_limits<int>::max(); 02485 02486 typedef typename MatrixGraph::ConstVertexIterator Iterator; 02487 02488 const Iterator end = graph_.end(); 02489 02490 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){ 02491 // Skip already aggregated vertices 02492 if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED) 02493 continue; 02494 02495 if(vertex.properties().isolated()){ 02496 isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_)); 02497 isolated++; 02498 }else{ 02499 umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_)); 02500 connected++; 02501 } 02502 } 02503 02504 if(connected + isolated == 0) 02505 // No unaggregated vertices. 02506 return; 02507 02508 if(connected > 0){ 02509 // Connected vertices have higher priority. 02510 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex) 02511 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated() 02512 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin) 02513 localPush(*vertex); 02514 }else{ 02515 for(Iterator vertex = graph_.begin(); vertex != end; ++vertex) 02516 if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated() 02517 && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin) 02518 localPush(*vertex); 02519 } 02520 maxSize_ = std::max(size_, maxSize_); 02521 } 02522 02523 template<class G> 02524 inline typename G::VertexDescriptor Aggregator<G>::Stack::pop() 02525 { 02526 while(size_>0){ 02527 head_ = (head_ + N -1) % N; 02528 size_--; 02529 Vertex v = vals_[head_]; 02530 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED) 02531 return v; 02532 } 02533 // Stack is empty try to fill it 02534 fill(); 02535 02536 // try again 02537 while(size_>0){ 02538 head_ = (head_ + N -1) % N; 02539 size_--; 02540 Vertex v = vals_[head_]; 02541 if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED) 02542 return v; 02543 } 02544 return NullEntry; 02545 } 02546 02547 #endif // DOXYGEN 02548 02549 template<class V> 02550 void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m, std::ostream& os) 02551 { 02552 std::ios_base::fmtflags oldOpts=os.flags(); 02553 02554 os.setf(std::ios_base::right, std::ios_base::adjustfield); 02555 02556 V max=0; 02557 int width=1; 02558 02559 for(int i=0; i< n*m; i++) 02560 max=std::max(max, aggregates[i]); 02561 02562 for(int i=10; i < 1000000; i*=10) 02563 if(max/i>0) 02564 width++; 02565 else 02566 break; 02567 02568 for(int j=0, entry=0; j < m; j++){ 02569 for(int i=0; i<n; i++, entry++){ 02570 os.width(width); 02571 os<<aggregates[entry]<<" "; 02572 } 02573 02574 os<<std::endl; 02575 } 02576 os<<std::endl; 02577 os.flags(oldOpts); 02578 } 02579 02580 02581 }// namespace Amg 02582 02583 }// namespace Dune 02584 02585 02586 #endif
Generated on Fri Apr 29 2011 with Doxygen (ver 1.7.1) [doxygen-log,error-log].