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