1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_AMG_DEPENDENCY_HH
4 #define DUNE_AMG_DEPENDENCY_HH
5 
6 
7 #include <bitset>
8 #include <ostream>
9 
10 #include "graph.hh"
11 #include "properties.hh"
12 #include <dune/common/propertymap.hh>
13 
14 
15 namespace Dune
16 {
17   namespace Amg
18   {
19     /**
20      * @addtogroup ISTL_PAAMG
21      *
22      * @{
23      */
24     /** @file
25      * @author Markus Blatt
26      * @brief Provides classes for initializing the link attributes of a matrix graph.
27      */
28 
29     /**
30      * @brief Class representing the properties of an ede in the matrix graph.
31      *
32      * During the coarsening process the matrix graph needs to hold different
33      * properties of its edges.
34      * This class ontains methods for getting and setting these edge attributes.
35      */
36     class EdgeProperties
37     {
38       friend std::ostream& operator<<(std::ostream& os, const EdgeProperties& props);
39     public:
40       /** @brief Flags of the link.*/
41       enum {INFLUENCE, DEPEND, SIZE};
42 
43     private:
44 
45       std::bitset<SIZE> flags_;
46     public:
47       /** @brief Constructor. */
48       EdgeProperties();
49 
50       /** @brief Access the bits directly */
51       std::bitset<SIZE>::reference operator[](std::size_t v);
52 
53       /** @brief Access the bits directly */
54       bool operator[](std::size_t v) const;
55 
56       /**
57        * @brief Checks wether the vertex the edge points to depends on
58        * the vertex the edge starts.
59        * @return True if it depends on the starting point.
60        */
61       bool depends() const;
62 
63       /**
64        * @brief Marks the edge as one of which the end point depends on
65        * the starting point.
66        */
67       void setDepends();
68 
69       /**
70        * @brief Resets the depends flag.
71        */
72       void resetDepends();
73 
74       /**
75        * @brief Checks wether the start vertex is influenced by the end vertex.
76        * @return True if it is influenced.
77        */
78       bool influences() const;
79 
80       /**
81        * @brief Marks the edge as one of which the start vertex by the end vertex.
82        */
83       void setInfluences();
84 
85       /**
86        * @brief Resets the influence flag.
87        */
88       void resetInfluences();
89 
90       /**
91        * @brief Checks wether the edge is one way.
92        * I.e. either the influence or the depends flag but is set.
93        */
94       bool isOneWay() const;
95 
96       /**
97        * @brief Checks wether the edge is two way.
98        * I.e. both the influence flag and the depends flag are that.
99        */
100       bool isTwoWay() const;
101 
102       /**
103        * @brief Checks wether the edge is strong.
104        * I.e. the influence or depends flag is set.
105        */
106       bool isStrong()  const;
107 
108       /**
109        * @brief Reset all flags.
110        */
111       void reset();
112 
113       /**
114        * @brief Prints the attributes of the edge for debugging.
115        */
116       void printFlags() const;
117     };
118 
119     /**
120      * @brief Class representing a node in the matrix graph.
121      *
122      * Contains methods for getting and setting node attributes.
123      */
124     class VertexProperties {
125       friend std::ostream& operator<<(std::ostream& os, const VertexProperties& props);
126     public:
127       enum { ISOLATED, VISITED, FRONT, BORDER, SIZE };
128     private:
129 
130       /** @brief The attribute flags. */
131       std::bitset<SIZE> flags_;
132 
133     public:
134       /** @brief Constructor. */
135       VertexProperties();
136 
137       /** @brief Access the bits directly */
138       std::bitset<SIZE>::reference operator[](std::size_t v);
139 
140       /** @brief Access the bits directly */
141       bool operator[](std::size_t v) const;
142 
143       /**
144        * @brief Marks that node as being isolated.
145        *
146        * A node is isolated if it ha not got any strong connections to other nodes
147        * in the matrix graph.
148        */
149       void setIsolated();
150 
151       /**
152        * @brief Checks wether the node is isolated.
153        */
154       bool isolated() const;
155 
156       /**
157        * @brief Resets the isolated flag.
158        */
159       void resetIsolated();
160 
161       /**
162        * @brief Mark the node as already visited.
163        */
164       void setVisited();
165 
166       /**
167        * @brief Checks wether the node is marked as visited.
168        */
169       bool visited() const;
170 
171       /**
172        * @brief Resets the visited flag.
173        */
174       void resetVisited();
175 
176       /**
177        * @brief Marks the node as belonging to the current clusters front.
178        */
179       void setFront();
180 
181       /**
182        * @brief Checks wether the node is marked as a front node.
183        */
184       bool front() const;
185 
186       /**
187        *  @brief Resets the front node flag.
188        */
189       void resetFront();
190 
191       /**
192        * @brief Marks the vertex as excluded from the aggregation.
193        */
194       void setExcludedBorder();
195 
196       /**
197        * @brief Tests whether the vertex is excluded from the aggregation.
198        * @return True if the vertex is excluded from the aggregation process.
199        */
200       bool excludedBorder() const;
201 
202       /**
203        * @brief Marks the vertex as included in the aggregation.
204        */
205       void resetExcludedBorder();
206 
207       /**
208        * @brief Reset all flags.
209        */
210       void reset();
211 
212     };
213 
214     template<typename G, std::size_t i>
215     class PropertyGraphVertexPropertyMap
216       : public RAPropertyMapHelper<typename std::bitset<VertexProperties::SIZE>::reference,
217             PropertyGraphVertexPropertyMap<G,i> >
218     {
219     public:
220 
221       typedef ReadWritePropertyMapTag Category;
222 
223       enum {
224         /** @brief the index to access in the bitset. */
225         index = i
226       };
227 
228       /**
229        * @brief The type of the graph with internal properties.
230        */
231       typedef G Graph;
232 
233       /**
234        * @brief The type of the bitset.
235        */
236       typedef std::bitset<VertexProperties::SIZE> BitSet;
237 
238       /**
239        * @brief The reference type.
240        */
241       typedef typename BitSet::reference Reference;
242 
243       /**
244        * @brief The value type.
245        */
246       typedef bool ValueType;
247 
248       /**
249        * @brief The vertex descriptor.
250        */
251       typedef typename G::VertexDescriptor Vertex;
252 
253       /**
254        * @brief Constructor.
255        * @param g The graph whose properties we access.
256        */
PropertyGraphVertexPropertyMap(G & g)257       PropertyGraphVertexPropertyMap(G& g)
258         : graph_(&g)
259       {}
260 
261       /**
262        * @brief Default constructor.
263        */
PropertyGraphVertexPropertyMap()264       PropertyGraphVertexPropertyMap()
265         : graph_(0)
266       {}
267 
268 
269       /**
270        * @brief Get the properties associated to a vertex.
271        * @param vertex The vertex whose Properties we want.
272        */
operator [](const Vertex & vertex) const273       Reference operator[](const Vertex& vertex) const
274       {
275         return graph_->getVertexProperties(vertex)[index];
276       }
277     private:
278       Graph* graph_;
279     };
280 
281   } // end namespace Amg
282 
283   template<typename G, typename EP, typename VM, typename EM>
284   struct PropertyMapTypeSelector<Amg::VertexVisitedTag,Amg::PropertiesGraph<G,Amg::VertexProperties,EP,VM,EM> >
285   {
286     typedef Amg::PropertyGraphVertexPropertyMap<Amg::PropertiesGraph<G,Amg::VertexProperties,EP,VM,EM>, Amg::VertexProperties::VISITED> Type;
287   };
288 
289   template<typename G, typename EP, typename VM, typename EM>
290   typename PropertyMapTypeSelector<Amg::VertexVisitedTag,Amg::PropertiesGraph<G,Amg::VertexProperties,EP,VM,EM> >::Type
get(const Amg::VertexVisitedTag & tag,Amg::PropertiesGraph<G,Amg::VertexProperties,EP,VM,EM> & graph)291   get([[maybe_unused]] const Amg::VertexVisitedTag& tag, Amg::PropertiesGraph<G,Amg::VertexProperties,EP,VM,EM>& graph)
292   {
293     return Amg::PropertyGraphVertexPropertyMap<Amg::PropertiesGraph<G,Amg::VertexProperties,EP,VM,EM>, Amg::VertexProperties::VISITED>(graph);
294   }
295 
296   namespace Amg
297   {
operator <<(std::ostream & os,const EdgeProperties & props)298     inline std::ostream& operator<<(std::ostream& os, const EdgeProperties& props)
299     {
300       return os << props.flags_;
301     }
302 
EdgeProperties()303     inline EdgeProperties::EdgeProperties()
304       : flags_()
305     {}
306 
307     inline std::bitset<EdgeProperties::SIZE>::reference
operator [](std::size_t v)308     EdgeProperties::operator[](std::size_t v)
309     {
310       return flags_[v];
311     }
312 
operator [](std::size_t i) const313     inline bool EdgeProperties::operator[](std::size_t i) const
314     {
315       return flags_[i];
316     }
317 
reset()318     inline void EdgeProperties::reset()
319     {
320       flags_.reset();
321     }
322 
setInfluences()323     inline void EdgeProperties::setInfluences()
324     {
325       // Set the INFLUENCE bit
326       //flags_ |= (1<<INFLUENCE);
327       flags_.set(INFLUENCE);
328     }
329 
influences() const330     inline bool EdgeProperties::influences() const
331     {
332       // Test the INFLUENCE bit
333       return flags_.test(INFLUENCE);
334     }
335 
setDepends()336     inline void EdgeProperties::setDepends()
337     {
338       // Set the first bit.
339       //flags_ |= (1<<DEPEND);
340       flags_.set(DEPEND);
341     }
342 
resetDepends()343     inline void EdgeProperties::resetDepends()
344     {
345       // reset the first bit.
346       //flags_ &= ~(1<<DEPEND);
347       flags_.reset(DEPEND);
348     }
349 
depends() const350     inline bool EdgeProperties::depends() const
351     {
352       // Return the first bit.
353       return flags_.test(DEPEND);
354     }
355 
resetInfluences()356     inline void EdgeProperties::resetInfluences()
357     {
358       // reset the second bit.
359       flags_ &= ~(1<<INFLUENCE);
360     }
361 
isOneWay() const362     inline bool EdgeProperties::isOneWay() const
363     {
364       // Test whether only the first bit is set
365       //return isStrong() && !isTwoWay();
366       return ((flags_) & std::bitset<SIZE>((1<<INFLUENCE)|(1<<DEPEND)))==(1<<DEPEND);
367     }
368 
isTwoWay() const369     inline bool EdgeProperties::isTwoWay() const
370     {
371       // Test whether the first and second bit is set
372       return ((flags_) & std::bitset<SIZE>((1<<INFLUENCE)|(1<<DEPEND)))==((1<<INFLUENCE)|(1<<DEPEND));
373     }
374 
isStrong() const375     inline bool EdgeProperties::isStrong() const
376     {
377       // Test whether the first or second bit is set
378       return ((flags_) & std::bitset<SIZE>((1<<INFLUENCE)|(1<<DEPEND))).to_ulong();
379     }
380 
381 
operator <<(std::ostream & os,const VertexProperties & props)382     inline std::ostream& operator<<(std::ostream& os, const VertexProperties& props)
383     {
384       return os << props.flags_;
385     }
386 
VertexProperties()387     inline VertexProperties::VertexProperties()
388       : flags_()
389     {}
390 
391 
392     inline std::bitset<VertexProperties::SIZE>::reference
operator [](std::size_t v)393     VertexProperties::operator[](std::size_t v)
394     {
395       return flags_[v];
396     }
397 
operator [](std::size_t v) const398     inline bool VertexProperties::operator[](std::size_t v) const
399     {
400       return flags_[v];
401     }
402 
setIsolated()403     inline void VertexProperties::setIsolated()
404     {
405       flags_.set(ISOLATED);
406     }
407 
isolated() const408     inline bool VertexProperties::isolated() const
409     {
410       return flags_.test(ISOLATED);
411     }
412 
resetIsolated()413     inline void VertexProperties::resetIsolated()
414     {
415       flags_.reset(ISOLATED);
416     }
417 
setVisited()418     inline void VertexProperties::setVisited()
419     {
420       flags_.set(VISITED);
421     }
422 
visited() const423     inline bool VertexProperties::visited() const
424     {
425       return flags_.test(VISITED);
426     }
427 
resetVisited()428     inline void VertexProperties::resetVisited()
429     {
430       flags_.reset(VISITED);
431     }
432 
setFront()433     inline void VertexProperties::setFront()
434     {
435       flags_.set(FRONT);
436     }
437 
front() const438     inline bool VertexProperties::front() const
439     {
440       return flags_.test(FRONT);
441     }
442 
resetFront()443     inline void VertexProperties::resetFront()
444     {
445       flags_.reset(FRONT);
446     }
447 
setExcludedBorder()448     inline void VertexProperties::setExcludedBorder()
449     {
450       flags_.set(BORDER);
451     }
452 
excludedBorder() const453     inline bool VertexProperties::excludedBorder() const
454     {
455       return flags_.test(BORDER);
456     }
457 
resetExcludedBorder()458     inline void VertexProperties::resetExcludedBorder()
459     {
460       flags_.reset(BORDER);
461     }
462 
reset()463     inline void VertexProperties::reset()
464     {
465       flags_.reset();
466     }
467 
468     /** @} */
469   }
470 }
471 #endif
472