epoc32/include/stdapis/boost/graph/king_ordering.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
williamr@2
     1
//=======================================================================
williamr@2
     2
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
williamr@2
     3
// Copyright 2004, 2005 Trustees of Indiana University
williamr@2
     4
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
williamr@2
     5
//          Doug Gregor, D. Kevin McGrath
williamr@2
     6
//
williamr@2
     7
// Distributed under the Boost Software License, Version 1.0. (See
williamr@2
     8
// accompanying file LICENSE_1_0.txt or copy at
williamr@2
     9
// http://www.boost.org/LICENSE_1_0.txt)
williamr@2
    10
//=======================================================================//
williamr@2
    11
#ifndef BOOST_GRAPH_KING_HPP
williamr@2
    12
#define BOOST_GRAPH_KING_HPP
williamr@2
    13
williamr@2
    14
#include <boost/config.hpp>
williamr@2
    15
#include <boost/graph/detail/sparse_ordering.hpp>
williamr@2
    16
williamr@2
    17
/*
williamr@2
    18
  King Algorithm for matrix reordering
williamr@2
    19
*/
williamr@2
    20
williamr@2
    21
namespace boost {
williamr@2
    22
  namespace detail {
williamr@2
    23
    template<typename OutputIterator, typename Buffer, typename Compare, 
williamr@2
    24
             typename PseudoDegreeMap, typename VecMap, typename VertexIndexMap>
williamr@2
    25
    class bfs_king_visitor:public default_bfs_visitor
williamr@2
    26
    {
williamr@2
    27
    public:
williamr@2
    28
      bfs_king_visitor(OutputIterator *iter, Buffer *b, Compare compare, 
williamr@2
    29
                       PseudoDegreeMap deg, std::vector<int> loc, VecMap color, 
williamr@2
    30
                       VertexIndexMap vertices): 
williamr@2
    31
        permutation(iter), Qptr(b), degree(deg), comp(compare), 
williamr@2
    32
        Qlocation(loc), colors(color), vertex_map(vertices) { }
williamr@2
    33
      
williamr@2
    34
      template <typename Vertex, typename Graph>
williamr@2
    35
      void finish_vertex(Vertex, Graph& g) {
williamr@2
    36
        typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
williamr@2
    37
        Vertex v, w;
williamr@2
    38
williamr@2
    39
        typedef typename std::deque<Vertex>::iterator iterator;
williamr@2
    40
        typedef typename std::deque<Vertex>::reverse_iterator reverse_iterator;
williamr@2
    41
williamr@2
    42
        reverse_iterator rend = Qptr->rend()-index_begin;
williamr@2
    43
        reverse_iterator rbegin = Qptr->rbegin();
williamr@2
    44
williamr@2
    45
williamr@2
    46
        //heap the vertices already there
williamr@2
    47
        std::make_heap(rbegin, rend, boost::bind<bool>(comp, _2, _1));
williamr@2
    48
williamr@2
    49
        unsigned i = 0;
williamr@2
    50
        
williamr@2
    51
        for(i = index_begin; i != Qptr->size(); ++i){
williamr@2
    52
          colors[get(vertex_map, (*Qptr)[i])] = 1;
williamr@2
    53
          Qlocation[get(vertex_map, (*Qptr)[i])] = i;
williamr@2
    54
        }
williamr@2
    55
williamr@2
    56
        i = 0;
williamr@2
    57
williamr@2
    58
        for( ; rbegin != rend; rend--){
williamr@2
    59
          percolate_down<Vertex>(i);
williamr@2
    60
          w = (*Qptr)[index_begin+i];
williamr@2
    61
          for (tie(ei, ei_end) = out_edges(w, g); ei != ei_end; ++ei) {
williamr@2
    62
            v = target(*ei, g);
williamr@2
    63
            put(degree, v, get(degree, v) - 1);
williamr@2
    64
    
williamr@2
    65
            if (colors[get(vertex_map, v)] == 1) {
williamr@2
    66
              percolate_up<Vertex>(get(vertex_map, v), i);            
williamr@2
    67
            }
williamr@2
    68
          }
williamr@2
    69
          
williamr@2
    70
          colors[get(vertex_map, w)] = 0;
williamr@2
    71
          i++;
williamr@2
    72
        }
williamr@2
    73
      }
williamr@2
    74
    
williamr@2
    75
      template <typename Vertex, typename Graph>
williamr@2
    76
      void examine_vertex(Vertex u, const Graph&) {
williamr@2
    77
        
williamr@2
    78
        *(*permutation)++ = u;
williamr@2
    79
        index_begin = Qptr->size();
williamr@2
    80
        
williamr@2
    81
      }
williamr@2
    82
    protected:
williamr@2
    83
williamr@2
    84
williamr@2
    85
      //this function replaces pop_heap, and tracks state information
williamr@2
    86
      template <typename Vertex>
williamr@2
    87
      void percolate_down(int offset){
williamr@2
    88
        typedef typename std::deque<Vertex>::reverse_iterator reverse_iterator;
williamr@2
    89
        
williamr@2
    90
        int heap_last = index_begin + offset;
williamr@2
    91
        int heap_first = Qptr->size() - 1;
williamr@2
    92
        
williamr@2
    93
        //pop_heap functionality:
williamr@2
    94
        //swap first, last
williamr@2
    95
        std::swap((*Qptr)[heap_last], (*Qptr)[heap_first]);
williamr@2
    96
        
williamr@2
    97
        //swap in the location queue
williamr@2
    98
        std::swap(Qlocation[heap_first], Qlocation[heap_last]);
williamr@2
    99
williamr@2
   100
        //set drifter, children
williamr@2
   101
        int drifter = heap_first;
williamr@2
   102
        int drifter_heap = Qptr->size() - drifter;
williamr@2
   103
williamr@2
   104
        int right_child_heap = drifter_heap * 2 + 1;
williamr@2
   105
        int right_child = Qptr->size() - right_child_heap;
williamr@2
   106
williamr@2
   107
        int left_child_heap = drifter_heap * 2;
williamr@2
   108
        int left_child = Qptr->size() - left_child_heap;
williamr@2
   109
williamr@2
   110
        //check that we are staying in the heap
williamr@2
   111
        bool valid = (right_child < heap_last) ? false : true;
williamr@2
   112
        
williamr@2
   113
        //pick smallest child of drifter, and keep in mind there might only be left child
williamr@2
   114
        int smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ? 
williamr@2
   115
          right_child : left_child;
williamr@2
   116
        
williamr@2
   117
        while(valid && smallest_child < heap_last && comp((*Qptr)[drifter], (*Qptr)[smallest_child])){
williamr@2
   118
          
williamr@2
   119
          //if smallest child smaller than drifter, swap them
williamr@2
   120
          std::swap((*Qptr)[smallest_child], (*Qptr)[drifter]);
williamr@2
   121
          std::swap(Qlocation[drifter], Qlocation[smallest_child]);
williamr@2
   122
williamr@2
   123
          //update the values, run again, as necessary
williamr@2
   124
          drifter = smallest_child;
williamr@2
   125
          drifter_heap = Qptr->size() - drifter;
williamr@2
   126
williamr@2
   127
          right_child_heap = drifter_heap * 2 + 1;
williamr@2
   128
          right_child = Qptr->size() - right_child_heap;
williamr@2
   129
williamr@2
   130
          left_child_heap = drifter_heap * 2;
williamr@2
   131
          left_child = Qptr->size() - left_child_heap;
williamr@2
   132
williamr@2
   133
          valid = (right_child < heap_last) ? false : true;
williamr@2
   134
williamr@2
   135
          smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ? 
williamr@2
   136
            right_child : left_child;
williamr@2
   137
        }
williamr@2
   138
williamr@2
   139
      }
williamr@2
   140
williamr@2
   141
williamr@2
   142
      
williamr@2
   143
      // this is like percolate down, but we always compare against the
williamr@2
   144
      // parent, as there is only a single choice
williamr@2
   145
      template <typename Vertex>
williamr@2
   146
      void percolate_up(int vertex, int offset){
williamr@2
   147
        
williamr@2
   148
        int child_location = Qlocation[vertex];
williamr@2
   149
        int heap_child_location = Qptr->size() - child_location;
williamr@2
   150
        int heap_parent_location = (int)(heap_child_location/2);
williamr@2
   151
        unsigned parent_location = Qptr->size() - heap_parent_location; 
williamr@2
   152
williamr@2
   153
        bool valid = (heap_parent_location != 0 && child_location > index_begin + offset && 
williamr@2
   154
                      parent_location < Qptr->size());
williamr@2
   155
williamr@2
   156
        while(valid && comp((*Qptr)[child_location], (*Qptr)[parent_location])){
williamr@2
   157
          
williamr@2
   158
          //swap in the heap
williamr@2
   159
          std::swap((*Qptr)[child_location], (*Qptr)[parent_location]);
williamr@2
   160
          
williamr@2
   161
          //swap in the location queue
williamr@2
   162
          std::swap(Qlocation[child_location], Qlocation[parent_location]);
williamr@2
   163
williamr@2
   164
          child_location = parent_location;
williamr@2
   165
          heap_child_location = heap_parent_location;
williamr@2
   166
          heap_parent_location = (int)(heap_child_location/2);
williamr@2
   167
          parent_location = Qptr->size() - heap_parent_location; 
williamr@2
   168
          valid = (heap_parent_location != 0 && child_location > index_begin + offset);
williamr@2
   169
        }
williamr@2
   170
      }
williamr@2
   171
      
williamr@2
   172
      OutputIterator *permutation;
williamr@2
   173
      int index_begin;
williamr@2
   174
      Buffer *Qptr;
williamr@2
   175
      PseudoDegreeMap degree;
williamr@2
   176
      Compare comp;
williamr@2
   177
      std::vector<int> Qlocation;
williamr@2
   178
      VecMap colors;
williamr@2
   179
      VertexIndexMap vertex_map;
williamr@2
   180
    };
williamr@2
   181
  
williamr@2
   182
williamr@2
   183
  } // namespace detail  
williamr@2
   184
  
williamr@2
   185
williamr@2
   186
  template<class Graph, class OutputIterator, class ColorMap, class DegreeMap,
williamr@2
   187
           typename VertexIndexMap> 
williamr@2
   188
  OutputIterator
williamr@2
   189
  king_ordering(const Graph& g,
williamr@2
   190
                std::deque< typename graph_traits<Graph>::vertex_descriptor >
williamr@2
   191
                  vertex_queue,
williamr@2
   192
                OutputIterator permutation, 
williamr@2
   193
                ColorMap color, DegreeMap degree,
williamr@2
   194
                VertexIndexMap index_map)
williamr@2
   195
  {
williamr@2
   196
    typedef typename property_traits<DegreeMap>::value_type ds_type;
williamr@2
   197
    typedef typename property_traits<ColorMap>::value_type ColorValue;
williamr@2
   198
    typedef color_traits<ColorValue> Color;
williamr@2
   199
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
williamr@2
   200
    typedef iterator_property_map<typename std::vector<ds_type>::iterator, VertexIndexMap, ds_type, ds_type&> PseudoDegreeMap;
williamr@2
   201
    typedef indirect_cmp<PseudoDegreeMap, std::less<ds_type> > Compare;
williamr@2
   202
    typedef typename boost::sparse::sparse_ordering_queue<Vertex> queue;
williamr@2
   203
    typedef typename detail::bfs_king_visitor<OutputIterator, queue, Compare,             
williamr@2
   204
      PseudoDegreeMap, std::vector<int>, VertexIndexMap > Visitor;
williamr@2
   205
    typedef typename graph_traits<Graph>::vertices_size_type
williamr@2
   206
      vertices_size_type;
williamr@2
   207
    std::vector<ds_type> pseudo_degree_vec(num_vertices(g));
williamr@2
   208
    PseudoDegreeMap pseudo_degree(pseudo_degree_vec.begin(), index_map);
williamr@2
   209
    
williamr@2
   210
    typename graph_traits<Graph>::vertex_iterator ui, ui_end;    
williamr@2
   211
    queue Q;
williamr@2
   212
    // Copy degree to pseudo_degree
williamr@2
   213
    // initialize the color map
williamr@2
   214
    for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui){
williamr@2
   215
      put(pseudo_degree, *ui, get(degree, *ui));
williamr@2
   216
      put(color, *ui, Color::white());
williamr@2
   217
    }
williamr@2
   218
    
williamr@2
   219
    Compare comp(pseudo_degree);
williamr@2
   220
    std::vector<int> colors(num_vertices(g));
williamr@2
   221
williamr@2
   222
    for(vertices_size_type i = 0; i < num_vertices(g); i++) 
williamr@2
   223
      colors[i] = 0;
williamr@2
   224
williamr@2
   225
    std::vector<int> loc(num_vertices(g));
williamr@2
   226
williamr@2
   227
    //create the visitor
williamr@2
   228
    Visitor vis(&permutation, &Q, comp, pseudo_degree, loc, colors, index_map);
williamr@2
   229
    
williamr@2
   230
    while( !vertex_queue.empty() ) {
williamr@2
   231
      Vertex s = vertex_queue.front();
williamr@2
   232
      vertex_queue.pop_front();
williamr@2
   233
      
williamr@2
   234
      //call BFS with visitor
williamr@2
   235
      breadth_first_visit(g, s, Q, vis, color);
williamr@2
   236
    }
williamr@2
   237
williamr@2
   238
    return permutation;
williamr@2
   239
  }
williamr@2
   240
williamr@2
   241
  
williamr@2
   242
  // This is the case where only a single starting vertex is supplied.
williamr@2
   243
  template <class Graph, class OutputIterator,
williamr@2
   244
            class ColorMap, class DegreeMap, typename VertexIndexMap>
williamr@2
   245
  OutputIterator
williamr@2
   246
  king_ordering(const Graph& g,
williamr@2
   247
                typename graph_traits<Graph>::vertex_descriptor s,
williamr@2
   248
                OutputIterator permutation, 
williamr@2
   249
                ColorMap color, DegreeMap degree, VertexIndexMap index_map)
williamr@2
   250
  {
williamr@2
   251
williamr@2
   252
    std::deque< typename graph_traits<Graph>::vertex_descriptor > vertex_queue;
williamr@2
   253
    vertex_queue.push_front( s );
williamr@2
   254
    return king_ordering(g, vertex_queue, permutation, color, degree,
williamr@2
   255
                         index_map);
williamr@2
   256
  }
williamr@2
   257
williamr@2
   258
  
williamr@2
   259
  template < class Graph, class OutputIterator, 
williamr@2
   260
             class ColorMap, class DegreeMap, class VertexIndexMap>
williamr@2
   261
  OutputIterator 
williamr@2
   262
  king_ordering(const Graph& G, OutputIterator permutation, 
williamr@2
   263
                ColorMap color, DegreeMap degree, VertexIndexMap index_map)
williamr@2
   264
  {
williamr@2
   265
    if (vertices(G).first == vertices(G).second)
williamr@2
   266
      return permutation;
williamr@2
   267
williamr@2
   268
    typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
williamr@2
   269
    typedef typename boost::graph_traits<Graph>::vertex_iterator   VerIter;
williamr@2
   270
    typedef typename property_traits<ColorMap>::value_type ColorValue;
williamr@2
   271
    typedef color_traits<ColorValue> Color;
williamr@2
   272
williamr@2
   273
    std::deque<Vertex>      vertex_queue;
williamr@2
   274
williamr@2
   275
    // Mark everything white
williamr@2
   276
    BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white());
williamr@2
   277
williamr@2
   278
    // Find one vertex from each connected component 
williamr@2
   279
    BGL_FORALL_VERTICES_T(v, G, Graph) {
williamr@2
   280
      if (get(color, v) == Color::white()) {
williamr@2
   281
        depth_first_visit(G, v, dfs_visitor<>(), color);
williamr@2
   282
        vertex_queue.push_back(v);
williamr@2
   283
      }
williamr@2
   284
    }
williamr@2
   285
williamr@2
   286
    // Find starting nodes for all vertices
williamr@2
   287
    // TBD: How to do this with a directed graph?
williamr@2
   288
    for (typename std::deque<Vertex>::iterator i = vertex_queue.begin();
williamr@2
   289
         i != vertex_queue.end(); ++i)
williamr@2
   290
      *i = find_starting_node(G, *i, color, degree);
williamr@2
   291
    
williamr@2
   292
    return king_ordering(G, vertex_queue, permutation, color, degree,
williamr@2
   293
                         index_map);
williamr@2
   294
  }
williamr@2
   295
williamr@2
   296
  template<typename Graph, typename OutputIterator, typename VertexIndexMap>
williamr@2
   297
  OutputIterator 
williamr@2
   298
  king_ordering(const Graph& G, OutputIterator permutation, 
williamr@2
   299
                VertexIndexMap index_map)
williamr@2
   300
  {
williamr@2
   301
    if (vertices(G).first == vertices(G).second)
williamr@2
   302
      return permutation;
williamr@2
   303
williamr@2
   304
    typedef out_degree_property_map<Graph> DegreeMap;
williamr@2
   305
    std::vector<default_color_type> colors(num_vertices(G));
williamr@2
   306
    return king_ordering(G, permutation, 
williamr@2
   307
                         make_iterator_property_map(&colors[0], index_map,
williamr@2
   308
                                                    colors[0]),
williamr@2
   309
                         make_out_degree_map(G), index_map);
williamr@2
   310
  }
williamr@2
   311
williamr@2
   312
  template<typename Graph, typename OutputIterator>
williamr@2
   313
  inline OutputIterator 
williamr@2
   314
  king_ordering(const Graph& G, OutputIterator permutation)
williamr@2
   315
  { return king_ordering(G, permutation, get(vertex_index, G)); }
williamr@2
   316
williamr@2
   317
} // namespace boost
williamr@2
   318
williamr@2
   319
williamr@2
   320
#endif // BOOST_GRAPH_KING_HPP