aggregates.hh

Go to the documentation of this file.
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].