PageRenderTime 71ms CodeModel.GetById 14ms app.highlight 51ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/graph/sloan_ordering.hpp

http://hadesmem.googlecode.com/
C++ Header | 447 lines | 269 code | 93 blank | 85 comment | 44 complexity | 4a32a6ac561563ec052b3b374b6ebab4 MD5 | raw file
  1//
  2//=======================================================================
  3// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch)
  4// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
  5//
  6// Distributed under the Boost Software License, Version 1.0. (See
  7// accompanying file LICENSE_1_0.txt or copy at
  8// http://www.boost.org/LICENSE_1_0.txt)
  9//=======================================================================
 10//
 11
 12#ifndef BOOST_GRAPH_SLOAN_HPP
 13#define BOOST_GRAPH_SLOAN_HPP
 14
 15#define WEIGHT1 1               //default weight for the distance in the Sloan algorithm
 16#define WEIGHT2 2               //default weight for the degree in the Sloan algorithm
 17
 18#include <boost/config.hpp>
 19#include <vector>
 20#include <queue>
 21#include <algorithm>
 22#include <limits>
 23#include <boost/pending/queue.hpp>
 24#include <boost/graph/graph_traits.hpp>
 25#include <boost/graph/breadth_first_search.hpp>
 26#include <boost/graph/properties.hpp>
 27#include <boost/pending/indirect_cmp.hpp>
 28#include <boost/property_map/property_map.hpp>
 29#include <boost/graph/visitors.hpp>
 30#include <boost/graph/adjacency_list.hpp>
 31#include <boost/graph/cuthill_mckee_ordering.hpp>
 32
 33
 34////////////////////////////////////////////////////////////
 35//
 36//Sloan-Algorithm for graph reordering
 37//(optimzes profile and wavefront, not primiraly bandwidth
 38//
 39////////////////////////////////////////////////////////////
 40
 41namespace boost {
 42        
 43  /////////////////////////////////////////////////////////////////////////
 44  // Function that returns the maximum depth of 
 45  // a rooted level strucutre (RLS)
 46  //
 47  /////////////////////////////////////////////////////////////////////////
 48  template<class Distance>
 49  unsigned RLS_depth(Distance& d)
 50  {
 51    unsigned h_s = 0;
 52    typename Distance::iterator iter;
 53    
 54    for (iter = d.begin(); iter != d.end(); ++iter)
 55      {
 56        if(*iter > h_s)
 57          {
 58            h_s = *iter;
 59          }
 60      }
 61    
 62    return h_s;
 63  }
 64
 65
 66    
 67  /////////////////////////////////////////////////////////////////////////
 68  // Function that returns the width of the largest level of 
 69  // a rooted level strucutre (RLS)
 70  //
 71  /////////////////////////////////////////////////////////////////////////
 72  template<class Distance, class my_int>
 73  unsigned RLS_max_width(Distance& d, my_int depth)
 74  {
 75    
 76      //Searching for the maximum width of a level
 77      std::vector<unsigned> dummy_width(depth+1, 0);
 78      std::vector<unsigned>::iterator my_it;
 79      typename Distance::iterator iter;
 80      unsigned w_max = 0;
 81      
 82      for (iter = d.begin(); iter != d.end(); ++iter)
 83      {
 84          dummy_width[*iter]++;
 85      }
 86      
 87      for(my_it = dummy_width.begin(); my_it != dummy_width.end(); ++my_it)
 88      {
 89          if(*my_it > w_max) w_max = *my_it;
 90      }
 91      
 92      return w_max;
 93      
 94  }
 95    
 96
 97  /////////////////////////////////////////////////////////////////////////
 98  // Function for finding a good starting node for Sloan algorithm
 99  //
100  // This is to find a good starting node. "good" is in the sense
101  // of the ordering generated. 
102  /////////////////////////////////////////////////////////////////////////
103  template <class Graph, class ColorMap, class DegreeMap> 
104  typename graph_traits<Graph>::vertex_descriptor 
105  sloan_start_end_vertices(Graph& G, 
106                           typename graph_traits<Graph>::vertex_descriptor &s, 
107                           ColorMap color, 
108                           DegreeMap degree)
109  {
110    typedef typename property_traits<DegreeMap>::value_type Degree;
111    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
112    typedef typename std::vector< typename graph_traits<Graph>::vertices_size_type>::iterator vec_iter;
113    typedef typename graph_traits<Graph>::vertices_size_type size_type;
114    
115    typedef typename property_map<Graph, vertex_index_t>::const_type VertexID;
116    
117    s = *(vertices(G).first);
118    Vertex e = s;
119    Vertex i;
120    unsigned my_degree = get(degree, s ); 
121    unsigned dummy, h_i, h_s, w_i, w_e;
122    bool new_start = true;
123    unsigned maximum_degree = 0;
124    
125    //Creating a std-vector for storing the distance from the start vertex in dist
126    std::vector<typename graph_traits<Graph>::vertices_size_type> dist(num_vertices(G), 0);
127
128    //Wrap a property_map_iterator around the std::iterator
129    boost::iterator_property_map<vec_iter, VertexID, size_type, size_type&> dist_pmap(dist.begin(), get(vertex_index, G));
130    
131    //Creating a property_map for the indices of a vertex
132    typename property_map<Graph, vertex_index_t>::type index_map = get(vertex_index, G);
133    
134    //Creating a priority queue
135    typedef indirect_cmp<DegreeMap, std::greater<Degree> > Compare;
136    Compare comp(degree);
137    std::priority_queue<Vertex, std::vector<Vertex>, Compare> degree_queue(comp);
138    
139    //step 1
140    //Scan for the vertex with the smallest degree and the maximum degree
141    typename graph_traits<Graph>::vertex_iterator ui, ui_end;
142    for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
143    {
144      dummy = get(degree, *ui);
145      
146      if(dummy < my_degree)
147      {
148        my_degree = dummy;
149        s = *ui;
150      }
151      
152      if(dummy > maximum_degree)
153      {
154        maximum_degree = dummy;
155      }
156    }
157    //end 1
158    
159    do{  
160      new_start = false;     //Setting the loop repetition status to false
161      
162      //step 2
163      //initialize the the disance std-vector with 0
164      for(typename std::vector<typename graph_traits<Graph>::vertices_size_type>::iterator iter = dist.begin(); iter != dist.end(); ++iter) *iter = 0;
165      
166      //generating the RLS (rooted level structure)
167      breadth_first_search
168        (G, s, visitor
169         (
170           make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) )
171           )
172          );
173      
174      //end 2
175      
176      //step 3
177      //calculating the depth of the RLS
178      h_s = RLS_depth(dist);
179      
180      //step 4
181      //pushing one node of each degree in an ascending manner into degree_queue
182      std::vector<bool> shrink_trace(maximum_degree, false);
183      for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
184      {
185        dummy = get(degree, *ui);
186        
187        if( (dist[index_map[*ui]] == h_s ) && ( !shrink_trace[ dummy ] ) )
188        {
189          degree_queue.push(*ui);
190          shrink_trace[ dummy ] = true;
191        }
192      }
193      
194      //end 3 & 4
195
196      
197      // step 5
198      // Initializing w
199      w_e = (std::numeric_limits<unsigned>::max)();
200      //end 5
201      
202      
203      //step 6
204      //Testing for termination
205      while( !degree_queue.empty() )
206      {
207        i = degree_queue.top();       //getting the node with the lowest degree from the degree queue
208        degree_queue.pop();           //ereasing the node with the lowest degree from the degree queue
209        
210        //generating a RLS          
211        for(typename std::vector<typename graph_traits<Graph>::vertices_size_type>::iterator iter = dist.begin(); iter != dist.end(); ++iter) *iter = 0;
212        
213        breadth_first_search
214          (G, i, boost::visitor
215           (
216             make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) )
217             )
218            );
219        
220        //Calculating depth and width of the rooted level
221        h_i = RLS_depth(dist);
222        w_i = RLS_max_width(dist, h_i);
223        
224        //Testing for termination
225        if( (h_i > h_s) && (w_i < w_e) ) 
226        {
227          h_s = h_i;
228          s = i;
229          while(!degree_queue.empty()) degree_queue.pop();
230          new_start = true;         
231        }
232        else if(w_i < w_e)
233        { 
234          w_e = w_i;
235          e = i;
236        }
237      }
238      //end 6
239        
240    }while(new_start);
241    
242    return e;
243  }
244
245  //////////////////////////////////////////////////////////////////////////
246  // Sloan algorithm with a given starting Vertex.
247  //
248  // This algorithm requires user to provide a starting vertex to
249  // compute Sloan ordering.
250  //////////////////////////////////////////////////////////////////////////
251  template <class Graph, class OutputIterator,
252            class ColorMap, class DegreeMap,
253            class PriorityMap, class Weight>
254  OutputIterator
255  sloan_ordering(Graph& g,
256                 typename graph_traits<Graph>::vertex_descriptor s,
257                 typename graph_traits<Graph>::vertex_descriptor e,
258                 OutputIterator permutation, 
259                 ColorMap color, 
260                 DegreeMap degree, 
261                 PriorityMap priority, 
262                 Weight W1, 
263                 Weight W2)
264  {
265    //typedef typename property_traits<DegreeMap>::value_type Degree;
266    typedef typename property_traits<PriorityMap>::value_type Degree;
267    typedef typename property_traits<ColorMap>::value_type ColorValue;
268    typedef color_traits<ColorValue> Color;
269    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
270    typedef typename std::vector<typename graph_traits<Graph>::vertices_size_type>::iterator vec_iter;
271    typedef typename graph_traits<Graph>::vertices_size_type size_type;
272
273    typedef typename property_map<Graph, vertex_index_t>::const_type VertexID;
274
275    
276    //Creating a std-vector for storing the distance from the end vertex in it
277    typename std::vector<typename graph_traits<Graph>::vertices_size_type> dist(num_vertices(g), 0);
278    
279    //Wrap a property_map_iterator around the std::iterator
280    boost::iterator_property_map<vec_iter, VertexID, size_type, size_type&> dist_pmap(dist.begin(), get(vertex_index, g)); 
281    
282    breadth_first_search
283      (g, e, visitor
284       (
285           make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) )
286        )
287       );
288    
289    //Creating a property_map for the indices of a vertex
290    typename property_map<Graph, vertex_index_t>::type index_map = get(vertex_index, g);
291    
292    //Sets the color and priority to their initial status
293    unsigned cdeg;    
294    typename graph_traits<Graph>::vertex_iterator ui, ui_end;
295    for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
296    {
297        put(color, *ui, Color::white());
298        cdeg=get(degree, *ui)+1;
299        put(priority, *ui, W1*dist[index_map[*ui]]-W2*cdeg );  
300    }
301    
302    //Priority list
303    typedef indirect_cmp<PriorityMap, std::greater<Degree> > Compare;
304    Compare comp(priority);
305    std::list<Vertex> priority_list;
306
307    //Some more declarations
308    typename graph_traits<Graph>::out_edge_iterator ei, ei_end, ei2, ei2_end;
309    Vertex u, v, w;
310
311    put(color, s, Color::green());      //Sets the color of the starting vertex to gray
312    priority_list.push_front(s);                 //Puts s into the priority_list
313    
314    while ( !priority_list.empty() ) 
315    {  
316      priority_list.sort(comp);         //Orders the elements in the priority list in an ascending manner
317      
318      u = priority_list.front();           //Accesses the last element in the priority list
319      priority_list.pop_front();               //Removes the last element in the priority list
320      
321      if(get(color, u) == Color::green() )
322      {
323        //for-loop over all out-edges of vertex u
324        for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) 
325        {
326          v = target(*ei, g);
327          
328          put( priority, v, get(priority, v) + W2 ); //updates the priority
329          
330          if (get(color, v) == Color::white() )      //test if the vertex is inactive
331          {
332            put(color, v, Color::green() );        //giving the vertex a preactive status
333            priority_list.push_front(v);                     //writing the vertex in the priority_queue
334          }           
335        }
336      }
337      
338      //Here starts step 8
339      *permutation++ = u;                      //Puts u to the first position in the permutation-vector
340      put(color, u, Color::black() );          //Gives u an inactive status
341      
342      //for loop over all the adjacent vertices of u
343      for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
344        
345        v = target(*ei, g);     
346        
347        if (get(color, v) == Color::green() ) {      //tests if the vertex is inactive
348          
349          put(color, v, Color::red() );        //giving the vertex an active status
350          put(priority, v, get(priority, v)+W2);  //updates the priority        
351          
352          //for loop over alll adjacent vertices of v
353          for (boost::tie(ei2, ei2_end) = out_edges(v, g); ei2 != ei2_end; ++ei2) {
354            w = target(*ei2, g);
355            
356            if(get(color, w) != Color::black() ) {     //tests if vertex is postactive
357              
358              put(priority, w, get(priority, w)+W2);  //updates the priority
359              
360              if(get(color, w) == Color::white() ){
361                
362                put(color, w, Color::green() );   // gives the vertex a preactive status
363                priority_list.push_front(w);           // puts the vertex into the priority queue
364                
365              } //end if
366              
367            } //end if
368            
369          } //end for
370          
371        } //end if
372        
373      } //end for
374      
375    } //end while
376    
377    
378    return permutation;
379  }  
380  
381  /////////////////////////////////////////////////////////////////////////////////////////
382  // Same algorithm as before, but without the weights given (taking default weights
383  template <class Graph, class OutputIterator,
384            class ColorMap, class DegreeMap,
385            class PriorityMap>
386  OutputIterator
387  sloan_ordering(Graph& g,
388                 typename graph_traits<Graph>::vertex_descriptor s,
389                 typename graph_traits<Graph>::vertex_descriptor e,
390                 OutputIterator permutation, 
391                 ColorMap color, 
392                 DegreeMap degree, 
393                 PriorityMap priority)
394  {
395    return sloan_ordering(g, s, e, permutation, color, degree, priority, WEIGHT1, WEIGHT2); 
396  }
397
398
399  //////////////////////////////////////////////////////////////////////////
400  // Sloan algorithm without a given starting Vertex.
401  //
402  // This algorithm finds a good starting vertex itself to
403  // compute Sloan-ordering.
404  //////////////////////////////////////////////////////////////////////////
405 
406
407
408  template < class Graph, class OutputIterator, 
409             class Color, class Degree,
410             class Priority, class Weight>
411  inline OutputIterator
412  sloan_ordering(Graph& G, 
413                 OutputIterator permutation, 
414                 Color color, 
415                 Degree degree, 
416                 Priority priority, 
417                 Weight W1, 
418                 Weight W2 )
419  {
420    typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
421    
422    Vertex s, e;
423    e = sloan_start_end_vertices(G, s, color, degree);
424    
425    return sloan_ordering(G, s, e, permutation, color, degree, priority, W1, W2);
426  }
427
428  /////////////////////////////////////////////////////////////////////////////////////////
429  // Same as before, but without given weights (default weights are taken instead)
430  template < class Graph, class OutputIterator, 
431             class Color, class Degree,
432             class Priority >
433  inline OutputIterator
434  sloan_ordering(Graph& G, 
435                 OutputIterator permutation, 
436                 Color color, 
437                 Degree degree, 
438                 Priority priority)
439  { 
440    return sloan_ordering(G, permutation, color, degree, priority, WEIGHT1, WEIGHT2);
441  }
442  
443  
444} // namespace boost
445
446
447#endif // BOOST_GRAPH_SLOAN_HPP