• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=======================================================================
2 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
3 // Copyright 2004, 2005 Trustees of Indiana University
4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
5 //          Doug Gregor, D. Kevin McGrath
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //=======================================================================//
11 #ifndef BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP
12 #define BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP
13 
14 #include <boost/config.hpp>
15 #include <vector>
16 #include <queue>
17 #include <boost/pending/queue.hpp>
18 #include <boost/pending/mutable_queue.hpp>
19 #include <boost/graph/graph_traits.hpp>
20 #include <boost/graph/breadth_first_search.hpp>
21 #include <boost/graph/properties.hpp>
22 #include <boost/pending/indirect_cmp.hpp>
23 #include <boost/property_map/property_map.hpp>
24 #include <boost/bind.hpp>
25 #include <boost/graph/iteration_macros.hpp>
26 #include <boost/graph/depth_first_search.hpp>
27 
28 namespace boost
29 {
30 
31 namespace sparse
32 {
33 
34     // rcm_queue
35     //
36     // This is a custom queue type used in the
37     // *_ordering algorithms.
38     // In addition to the normal queue operations, the
39     // rcm_queue provides:
40     //
41     //   int eccentricity() const;
42     //   value_type spouse() const;
43     //
44 
45     // yes, it's a bad name...but it works, so use it
46     template < class Vertex, class DegreeMap,
47         class Container = std::deque< Vertex > >
48     class rcm_queue : public std::queue< Vertex, Container >
49     {
50         typedef std::queue< Vertex > base;
51 
52     public:
53         typedef typename base::value_type value_type;
54         typedef typename base::size_type size_type;
55 
56         /* SGI queue has not had a contructor queue(const Container&) */
rcm_queue(DegreeMap deg)57         inline rcm_queue(DegreeMap deg)
58         : _size(0), Qsize(1), eccen(-1), degree(deg)
59         {
60         }
61 
pop()62         inline void pop()
63         {
64             if (!_size)
65                 Qsize = base::size();
66 
67             base::pop();
68             if (_size == Qsize - 1)
69             {
70                 _size = 0;
71                 ++eccen;
72             }
73             else
74                 ++_size;
75         }
76 
front()77         inline value_type& front()
78         {
79             value_type& u = base::front();
80             if (_size == 0)
81                 w = u;
82             else if (get(degree, u) < get(degree, w))
83                 w = u;
84             return u;
85         }
86 
front() const87         inline const value_type& front() const
88         {
89             const value_type& u = base::front();
90             if (_size == 0)
91                 w = u;
92             else if (get(degree, u) < get(degree, w))
93                 w = u;
94             return u;
95         }
96 
top()97         inline value_type& top() { return front(); }
top() const98         inline const value_type& top() const { return front(); }
99 
size() const100         inline size_type size() const { return base::size(); }
101 
eccentricity() const102         inline size_type eccentricity() const { return eccen; }
spouse() const103         inline value_type spouse() const { return w; }
104 
105     protected:
106         size_type _size;
107         size_type Qsize;
108         int eccen;
109         mutable value_type w;
110         DegreeMap degree;
111     };
112 
113     template < typename Tp, typename Sequence = std::deque< Tp > >
114     class sparse_ordering_queue : public boost::queue< Tp, Sequence >
115     {
116     public:
117         typedef typename Sequence::iterator iterator;
118         typedef typename Sequence::reverse_iterator reverse_iterator;
119         typedef queue< Tp, Sequence > base;
120         typedef typename Sequence::size_type size_type;
121 
begin()122         inline iterator begin() { return this->c.begin(); }
rbegin()123         inline reverse_iterator rbegin() { return this->c.rbegin(); }
end()124         inline iterator end() { return this->c.end(); }
rend()125         inline reverse_iterator rend() { return this->c.rend(); }
operator [](int n)126         inline Tp& operator[](int n) { return this->c[n]; }
size()127         inline size_type size() { return this->c.size(); }
128 
129     protected:
130         // nothing
131     };
132 
133 } // namespace sparse
134 
135 // Compute Pseudo peripheral
136 //
137 // To compute an approximated peripheral for a given vertex.
138 // Used in <tt>king_ordering</tt> algorithm.
139 //
140 template < class Graph, class Vertex, class ColorMap, class DegreeMap >
pseudo_peripheral_pair(Graph const & G,const Vertex & u,int & ecc,ColorMap color,DegreeMap degree)141 Vertex pseudo_peripheral_pair(
142     Graph const& G, const Vertex& u, int& ecc, ColorMap color, DegreeMap degree)
143 {
144     typedef typename property_traits< ColorMap >::value_type ColorValue;
145     typedef color_traits< ColorValue > Color;
146 
147     sparse::rcm_queue< Vertex, DegreeMap > Q(degree);
148 
149     typename boost::graph_traits< Graph >::vertex_iterator ui, ui_end;
150     for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
151         if (get(color, *ui) != Color::red())
152             put(color, *ui, Color::white());
153     breadth_first_visit(G, u, buffer(Q).color_map(color));
154 
155     ecc = Q.eccentricity();
156     return Q.spouse();
157 }
158 
159 // Find a good starting node
160 //
161 // This is to find a good starting node for the
162 // king_ordering algorithm. "good" is in the sense
163 // of the ordering generated by RCM.
164 //
165 template < class Graph, class Vertex, class Color, class Degree >
find_starting_node(Graph const & G,Vertex r,Color color,Degree degree)166 Vertex find_starting_node(Graph const& G, Vertex r, Color color, Degree degree)
167 {
168     Vertex x, y;
169     int eccen_r, eccen_x;
170 
171     x = pseudo_peripheral_pair(G, r, eccen_r, color, degree);
172     y = pseudo_peripheral_pair(G, x, eccen_x, color, degree);
173 
174     while (eccen_x > eccen_r)
175     {
176         r = x;
177         eccen_r = eccen_x;
178         x = y;
179         y = pseudo_peripheral_pair(G, x, eccen_x, color, degree);
180     }
181     return x;
182 }
183 
184 template < typename Graph >
185 class out_degree_property_map
186 : public put_get_helper< typename graph_traits< Graph >::degree_size_type,
187       out_degree_property_map< Graph > >
188 {
189 public:
190     typedef typename graph_traits< Graph >::vertex_descriptor key_type;
191     typedef typename graph_traits< Graph >::degree_size_type value_type;
192     typedef value_type reference;
193     typedef readable_property_map_tag category;
out_degree_property_map(const Graph & g)194     out_degree_property_map(const Graph& g) : m_g(g) {}
operator [](const key_type & v) const195     value_type operator[](const key_type& v) const
196     {
197         return out_degree(v, m_g);
198     }
199 
200 private:
201     const Graph& m_g;
202 };
203 template < typename Graph >
make_out_degree_map(const Graph & g)204 inline out_degree_property_map< Graph > make_out_degree_map(const Graph& g)
205 {
206     return out_degree_property_map< Graph >(g);
207 }
208 
209 } // namespace boost
210 
211 #endif // BOOST_GRAPH_KING_HPP
212