Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:34

0001 //-*-c++-*-
0002 //=======================================================================
0003 // Copyright 1997-2001 University of Notre Dame.
0004 // Authors: Lie-Quan Lee, Jeremy Siek
0005 //
0006 // Distributed under the Boost Software License, Version 1.0. (See
0007 // accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 //=======================================================================
0010 //
0011 #ifndef BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP
0012 #define BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP
0013 
0014 #include <vector>
0015 #include <boost/assert.hpp>
0016 #include <boost/config.hpp>
0017 #include <boost/pending/bucket_sorter.hpp>
0018 #include <boost/detail/numeric_traits.hpp> // for integer_traits
0019 #include <boost/graph/graph_traits.hpp>
0020 #include <boost/property_map/property_map.hpp>
0021 
0022 namespace boost
0023 {
0024 
0025 namespace detail
0026 {
0027 
0028     //
0029     // Given a set of n integers (where the integer values range from
0030     // zero to n-1), we want to keep track of a collection of stacks
0031     // of integers. It so happens that an integer will appear in at
0032     // most one stack at a time, so the stacks form disjoint sets.
0033     // Because of these restrictions, we can use one big array to
0034     // store all the stacks, intertwined with one another.
0035     // No allocation/deallocation happens in the push()/pop() methods
0036     // so this is faster than using std::stack's.
0037     //
0038     template < class SignedInteger > class Stacks
0039     {
0040         typedef SignedInteger value_type;
0041         typedef typename std::vector< value_type >::size_type size_type;
0042 
0043     public:
0044         Stacks(size_type n) : data(n) {}
0045 
0046         //: stack
0047         class stack
0048         {
0049             typedef typename std::vector< value_type >::iterator Iterator;
0050 
0051         public:
0052             stack(Iterator _data, const value_type& head)
0053             : data(_data), current(head)
0054             {
0055             }
0056 
0057             // did not use default argument here to avoid internal compiler
0058             // error in g++.
0059             stack(Iterator _data)
0060             : data(_data), current(-(std::numeric_limits< value_type >::max)())
0061             {
0062             }
0063 
0064             void pop()
0065             {
0066                 BOOST_ASSERT(!empty());
0067                 current = data[current];
0068             }
0069             void push(value_type v)
0070             {
0071                 data[v] = current;
0072                 current = v;
0073             }
0074             bool empty()
0075             {
0076                 return current == -(std::numeric_limits< value_type >::max)();
0077             }
0078             value_type& top() { return current; }
0079 
0080         private:
0081             Iterator data;
0082             value_type current;
0083         };
0084 
0085         // To return a stack object
0086         stack make_stack() { return stack(data.begin()); }
0087 
0088     protected:
0089         std::vector< value_type > data;
0090     };
0091 
0092     // marker class, a generalization of coloring.
0093     //
0094     // This class is to provide a generalization of coloring which has
0095     // complexity of amortized constant time to set all vertices' color
0096     // back to be untagged. It implemented by increasing a tag.
0097     //
0098     // The colors are:
0099     //   not tagged
0100     //   tagged
0101     //   multiple_tagged
0102     //   done
0103     //
0104     template < class SignedInteger, class Vertex, class VertexIndexMap >
0105     class Marker
0106     {
0107         typedef SignedInteger value_type;
0108         typedef typename std::vector< value_type >::size_type size_type;
0109 
0110         static value_type done()
0111         {
0112             return (std::numeric_limits< value_type >::max)() / 2;
0113         }
0114 
0115     public:
0116         Marker(size_type _num, VertexIndexMap index_map)
0117         : tag(1 - (std::numeric_limits< value_type >::max)())
0118         , data(_num, -(std::numeric_limits< value_type >::max)())
0119         , id(index_map)
0120         {
0121         }
0122 
0123         void mark_done(Vertex node) { data[get(id, node)] = done(); }
0124 
0125         bool is_done(Vertex node) { return data[get(id, node)] == done(); }
0126 
0127         void mark_tagged(Vertex node) { data[get(id, node)] = tag; }
0128 
0129         void mark_multiple_tagged(Vertex node)
0130         {
0131             data[get(id, node)] = multiple_tag;
0132         }
0133 
0134         bool is_tagged(Vertex node) const { return data[get(id, node)] >= tag; }
0135 
0136         bool is_not_tagged(Vertex node) const
0137         {
0138             return data[get(id, node)] < tag;
0139         }
0140 
0141         bool is_multiple_tagged(Vertex node) const
0142         {
0143             return data[get(id, node)] >= multiple_tag;
0144         }
0145 
0146         void increment_tag()
0147         {
0148             const size_type num = data.size();
0149             ++tag;
0150             if (tag >= done())
0151             {
0152                 tag = 1 - (std::numeric_limits< value_type >::max)();
0153                 for (size_type i = 0; i < num; ++i)
0154                     if (data[i] < done())
0155                         data[i] = -(std::numeric_limits< value_type >::max)();
0156             }
0157         }
0158 
0159         void set_multiple_tag(value_type mdeg0)
0160         {
0161             const size_type num = data.size();
0162             multiple_tag = tag + mdeg0;
0163 
0164             if (multiple_tag >= done())
0165             {
0166                 tag = 1 - (std::numeric_limits< value_type >::max)();
0167 
0168                 for (size_type i = 0; i < num; i++)
0169                     if (data[i] < done())
0170                         data[i] = -(std::numeric_limits< value_type >::max)();
0171 
0172                 multiple_tag = tag + mdeg0;
0173             }
0174         }
0175 
0176         void set_tag_as_multiple_tag() { tag = multiple_tag; }
0177 
0178     protected:
0179         value_type tag;
0180         value_type multiple_tag;
0181         std::vector< value_type > data;
0182         VertexIndexMap id;
0183     };
0184 
0185     template < class Iterator, class SignedInteger, class Vertex,
0186         class VertexIndexMap, int offset = 1 >
0187     class Numbering
0188     {
0189         typedef SignedInteger number_type;
0190         number_type num; // start from 1 instead of zero
0191         Iterator data;
0192         number_type max_num;
0193         VertexIndexMap id;
0194 
0195     public:
0196         Numbering(Iterator _data, number_type _max_num, VertexIndexMap id)
0197         : num(1), data(_data), max_num(_max_num), id(id)
0198         {
0199         }
0200         void operator()(Vertex node) { data[get(id, node)] = -num; }
0201         bool all_done(number_type i = 0) const { return num + i > max_num; }
0202         void increment(number_type i = 1) { num += i; }
0203         bool is_numbered(Vertex node) const { return data[get(id, node)] < 0; }
0204         void indistinguishable(Vertex i, Vertex j)
0205         {
0206             data[get(id, i)] = -(get(id, j) + offset);
0207         }
0208     };
0209 
0210     template < class SignedInteger, class Vertex, class VertexIndexMap >
0211     class degreelists_marker
0212     {
0213     public:
0214         typedef SignedInteger value_type;
0215         typedef typename std::vector< value_type >::size_type size_type;
0216         degreelists_marker(size_type n, VertexIndexMap id) : marks(n, 0), id(id)
0217         {
0218         }
0219         void mark_need_update(Vertex i) { marks[get(id, i)] = 1; }
0220         bool need_update(Vertex i) { return marks[get(id, i)] == 1; }
0221         bool outmatched_or_done(Vertex i) { return marks[get(id, i)] == -1; }
0222         void mark(Vertex i) { marks[get(id, i)] = -1; }
0223         void unmark(Vertex i) { marks[get(id, i)] = 0; }
0224 
0225     private:
0226         std::vector< value_type > marks;
0227         VertexIndexMap id;
0228     };
0229 
0230     // Helper function object for edge removal
0231     template < class Graph, class MarkerP, class NumberD, class Stack,
0232         class VertexIndexMap >
0233     class predicateRemoveEdge1
0234     {
0235         typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
0236         typedef typename graph_traits< Graph >::edge_descriptor edge_t;
0237 
0238     public:
0239         predicateRemoveEdge1(Graph& _g, MarkerP& _marker, NumberD _numbering,
0240             Stack& n_e, VertexIndexMap id)
0241         : g(&_g)
0242         , marker(&_marker)
0243         , numbering(_numbering)
0244         , neighbor_elements(&n_e)
0245         , id(id)
0246         {
0247         }
0248 
0249         bool operator()(edge_t e)
0250         {
0251             vertex_t dist = target(e, *g);
0252             if (marker->is_tagged(dist))
0253                 return true;
0254             marker->mark_tagged(dist);
0255             if (numbering.is_numbered(dist))
0256             {
0257                 neighbor_elements->push(get(id, dist));
0258                 return true;
0259             }
0260             return false;
0261         }
0262 
0263     private:
0264         Graph* g;
0265         MarkerP* marker;
0266         NumberD numbering;
0267         Stack* neighbor_elements;
0268         VertexIndexMap id;
0269     };
0270 
0271     // Helper function object for edge removal
0272     template < class Graph, class MarkerP > class predicate_remove_tagged_edges
0273     {
0274         typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
0275         typedef typename graph_traits< Graph >::edge_descriptor edge_t;
0276 
0277     public:
0278         predicate_remove_tagged_edges(Graph& _g, MarkerP& _marker)
0279         : g(&_g), marker(&_marker)
0280         {
0281         }
0282 
0283         bool operator()(edge_t e)
0284         {
0285             vertex_t dist = target(e, *g);
0286             if (marker->is_tagged(dist))
0287                 return true;
0288             return false;
0289         }
0290 
0291     private:
0292         Graph* g;
0293         MarkerP* marker;
0294     };
0295 
0296     template < class Graph, class DegreeMap, class InversePermutationMap,
0297         class PermutationMap, class SuperNodeMap, class VertexIndexMap >
0298     class mmd_impl
0299     {
0300         // Typedefs
0301         typedef graph_traits< Graph > Traits;
0302         typedef typename Traits::vertices_size_type size_type;
0303         typedef typename detail::integer_traits< size_type >::difference_type
0304             diff_t;
0305         typedef typename Traits::vertex_descriptor vertex_t;
0306         typedef typename Traits::adjacency_iterator adj_iter;
0307         typedef iterator_property_map< vertex_t*, identity_property_map,
0308             vertex_t, vertex_t& >
0309             IndexVertexMap;
0310         typedef detail::Stacks< diff_t > Workspace;
0311         typedef bucket_sorter< size_type, vertex_t, DegreeMap, VertexIndexMap >
0312             DegreeLists;
0313         typedef Numbering< InversePermutationMap, diff_t, vertex_t,
0314             VertexIndexMap >
0315             NumberingD;
0316         typedef degreelists_marker< diff_t, vertex_t, VertexIndexMap >
0317             DegreeListsMarker;
0318         typedef Marker< diff_t, vertex_t, VertexIndexMap > MarkerP;
0319 
0320         // Data Members
0321         bool has_no_edges;
0322 
0323         // input parameters
0324         Graph& G;
0325         int delta;
0326         DegreeMap degree;
0327         InversePermutationMap inverse_perm;
0328         PermutationMap perm;
0329         SuperNodeMap supernode_size;
0330         VertexIndexMap vertex_index_map;
0331 
0332         // internal data-structures
0333         std::vector< vertex_t > index_vertex_vec;
0334         size_type n;
0335         IndexVertexMap index_vertex_map;
0336         DegreeLists degreelists;
0337         NumberingD numbering;
0338         DegreeListsMarker degree_lists_marker;
0339         MarkerP marker;
0340         Workspace work_space;
0341 
0342     public:
0343         mmd_impl(Graph& g, size_type n_, int delta, DegreeMap degree,
0344             InversePermutationMap inverse_perm, PermutationMap perm,
0345             SuperNodeMap supernode_size, VertexIndexMap id)
0346         : has_no_edges(true)
0347         , G(g)
0348         , delta(delta)
0349         , degree(degree)
0350         , inverse_perm(inverse_perm)
0351         , perm(perm)
0352         , supernode_size(supernode_size)
0353         , vertex_index_map(id)
0354         , index_vertex_vec(n_)
0355         , n(n_)
0356         , degreelists(n_ + 1, n_, degree, id)
0357         , numbering(inverse_perm, n_, vertex_index_map)
0358         , degree_lists_marker(n_, vertex_index_map)
0359         , marker(n_, vertex_index_map)
0360         , work_space(n_)
0361         {
0362             typename graph_traits< Graph >::vertex_iterator v, vend;
0363             size_type vid = 0;
0364             for (boost::tie(v, vend) = vertices(G); v != vend; ++v, ++vid)
0365                 index_vertex_vec[vid] = *v;
0366             index_vertex_map = IndexVertexMap(&index_vertex_vec[0]);
0367 
0368             // Initialize degreelists.  Degreelists organizes the nodes
0369             // according to their degree.
0370             for (boost::tie(v, vend) = vertices(G); v != vend; ++v)
0371             {
0372                 typename Traits::degree_size_type d = out_degree(*v, G);
0373                 put(degree, *v, d);
0374                 if (0 < d)
0375                     has_no_edges = false;
0376                 degreelists.push(*v);
0377             }
0378         }
0379 
0380         void do_mmd()
0381         {
0382             // Eliminate the isolated nodes -- these are simply the nodes
0383             // with no neighbors, which are accessible as a list (really, a
0384             // stack) at location 0.  Since these don't affect any other
0385             // nodes, we can eliminate them without doing degree updates.
0386             typename DegreeLists::stack list_isolated = degreelists[0];
0387             while (!list_isolated.empty())
0388             {
0389                 vertex_t node = list_isolated.top();
0390                 marker.mark_done(node);
0391                 numbering(node);
0392                 numbering.increment();
0393                 list_isolated.pop();
0394             }
0395 
0396             if (has_no_edges)
0397             {
0398                 return;
0399             }
0400 
0401             size_type min_degree = 1;
0402             typename DegreeLists::stack list_min_degree
0403                 = degreelists[min_degree];
0404 
0405             while (list_min_degree.empty())
0406             {
0407                 ++min_degree;
0408                 list_min_degree = degreelists[min_degree];
0409             }
0410 
0411             // check if the whole eliminating process is done
0412             while (!numbering.all_done())
0413             {
0414 
0415                 size_type min_degree_limit = min_degree + delta; // WARNING
0416                 typename Workspace::stack llist = work_space.make_stack();
0417 
0418                 // multiple elimination
0419                 while (delta >= 0)
0420                 {
0421 
0422                     // Find the next non-empty degree
0423                     for (list_min_degree = degreelists[min_degree];
0424                          list_min_degree.empty()
0425                          && min_degree <= min_degree_limit;
0426                          ++min_degree,
0427                         list_min_degree = degreelists[min_degree])
0428                         ;
0429                     if (min_degree > min_degree_limit)
0430                         break;
0431 
0432                     const vertex_t node = list_min_degree.top();
0433                     const size_type node_id = get(vertex_index_map, node);
0434                     list_min_degree.pop();
0435                     numbering(node);
0436 
0437                     // check if node is the last one
0438                     if (numbering.all_done(supernode_size[node]))
0439                     {
0440                         numbering.increment(supernode_size[node]);
0441                         break;
0442                     }
0443                     marker.increment_tag();
0444                     marker.mark_tagged(node);
0445 
0446                     this->eliminate(node);
0447 
0448                     numbering.increment(supernode_size[node]);
0449                     llist.push(node_id);
0450                 } // multiple elimination
0451 
0452                 if (numbering.all_done())
0453                     break;
0454 
0455                 this->update(llist, min_degree);
0456             }
0457 
0458         } // do_mmd()
0459 
0460         void eliminate(vertex_t node)
0461         {
0462             typename Workspace::stack element_neighbor
0463                 = work_space.make_stack();
0464 
0465             // Create two function objects for edge removal
0466             typedef typename Workspace::stack WorkStack;
0467             predicateRemoveEdge1< Graph, MarkerP, NumberingD, WorkStack,
0468                 VertexIndexMap >
0469                 p(G, marker, numbering, element_neighbor, vertex_index_map);
0470 
0471             predicate_remove_tagged_edges< Graph, MarkerP > p2(G, marker);
0472 
0473             // Reconstruct the adjacent node list, push element neighbor in a
0474             // List.
0475             remove_out_edge_if(node, p, G);
0476             // during removal element neighbors are collected.
0477 
0478             while (!element_neighbor.empty())
0479             {
0480                 // element absorb
0481                 size_type e_id = element_neighbor.top();
0482                 vertex_t element = get(index_vertex_map, e_id);
0483                 adj_iter i, i_end;
0484                 for (boost::tie(i, i_end) = adjacent_vertices(element, G);
0485                      i != i_end; ++i)
0486                 {
0487                     vertex_t i_node = *i;
0488                     if (!marker.is_tagged(i_node)
0489                         && !numbering.is_numbered(i_node))
0490                     {
0491                         marker.mark_tagged(i_node);
0492                         add_edge(node, i_node, G);
0493                     }
0494                 }
0495                 element_neighbor.pop();
0496             }
0497             adj_iter v, ve;
0498             for (boost::tie(v, ve) = adjacent_vertices(node, G); v != ve; ++v)
0499             {
0500                 vertex_t v_node = *v;
0501                 if (!degree_lists_marker.need_update(v_node)
0502                     && !degree_lists_marker.outmatched_or_done(v_node))
0503                 {
0504                     degreelists.remove(v_node);
0505                 }
0506                 // update out edges of v_node
0507                 remove_out_edge_if(v_node, p2, G);
0508 
0509                 if (out_degree(v_node, G) == 0)
0510                 { // indistinguishable nodes
0511                     supernode_size[node] += supernode_size[v_node];
0512                     supernode_size[v_node] = 0;
0513                     numbering.indistinguishable(v_node, node);
0514                     marker.mark_done(v_node);
0515                     degree_lists_marker.mark(v_node);
0516                 }
0517                 else
0518                 { // not indistinguishable nodes
0519                     add_edge(v_node, node, G);
0520                     degree_lists_marker.mark_need_update(v_node);
0521                 }
0522             }
0523         } // eliminate()
0524 
0525         template < class Stack > void update(Stack llist, size_type& min_degree)
0526         {
0527             size_type min_degree0 = min_degree + delta + 1;
0528 
0529             while (!llist.empty())
0530             {
0531                 size_type deg, deg0 = 0;
0532 
0533                 marker.set_multiple_tag(min_degree0);
0534                 typename Workspace::stack q2list = work_space.make_stack();
0535                 typename Workspace::stack qxlist = work_space.make_stack();
0536 
0537                 vertex_t current = get(index_vertex_map, llist.top());
0538                 adj_iter i, ie;
0539                 for (boost::tie(i, ie) = adjacent_vertices(current, G); i != ie;
0540                      ++i)
0541                 {
0542                     vertex_t i_node = *i;
0543                     const size_type i_id = get(vertex_index_map, i_node);
0544                     if (supernode_size[i_node] != 0)
0545                     {
0546                         deg0 += supernode_size[i_node];
0547                         marker.mark_multiple_tagged(i_node);
0548                         if (degree_lists_marker.need_update(i_node))
0549                         {
0550                             if (out_degree(i_node, G) == 2)
0551                                 q2list.push(i_id);
0552                             else
0553                                 qxlist.push(i_id);
0554                         }
0555                     }
0556                 }
0557 
0558                 while (!q2list.empty())
0559                 {
0560                     const size_type u_id = q2list.top();
0561                     vertex_t u_node = get(index_vertex_map, u_id);
0562                     // if u_id is outmatched by others, no need to update degree
0563                     if (degree_lists_marker.outmatched_or_done(u_node))
0564                     {
0565                         q2list.pop();
0566                         continue;
0567                     }
0568                     marker.increment_tag();
0569                     deg = deg0;
0570 
0571                     adj_iter nu = adjacent_vertices(u_node, G).first;
0572                     vertex_t neighbor = *nu;
0573                     if (neighbor == u_node)
0574                     {
0575                         ++nu;
0576                         neighbor = *nu;
0577                     }
0578                     if (numbering.is_numbered(neighbor))
0579                     {
0580                         adj_iter i, ie;
0581                         for (boost::tie(i, ie) = adjacent_vertices(neighbor, G);
0582                              i != ie; ++i)
0583                         {
0584                             const vertex_t i_node = *i;
0585                             if (i_node == u_node || supernode_size[i_node] == 0)
0586                                 continue;
0587                             if (marker.is_tagged(i_node))
0588                             {
0589                                 if (degree_lists_marker.need_update(i_node))
0590                                 {
0591                                     if (out_degree(i_node, G) == 2)
0592                                     { // is indistinguishable
0593                                         supernode_size[u_node]
0594                                             += supernode_size[i_node];
0595                                         supernode_size[i_node] = 0;
0596                                         numbering.indistinguishable(
0597                                             i_node, u_node);
0598                                         marker.mark_done(i_node);
0599                                         degree_lists_marker.mark(i_node);
0600                                     }
0601                                     else // is outmatched
0602                                         degree_lists_marker.mark(i_node);
0603                                 }
0604                             }
0605                             else
0606                             {
0607                                 marker.mark_tagged(i_node);
0608                                 deg += supernode_size[i_node];
0609                             }
0610                         }
0611                     }
0612                     else
0613                         deg += supernode_size[neighbor];
0614 
0615                     deg -= supernode_size[u_node];
0616                     degree[u_node] = deg; // update degree
0617                     degreelists[deg].push(u_node);
0618                     // u_id has been pushed back into degreelists
0619                     degree_lists_marker.unmark(u_node);
0620                     if (min_degree > deg)
0621                         min_degree = deg;
0622                     q2list.pop();
0623                 } // while (!q2list.empty())
0624 
0625                 while (!qxlist.empty())
0626                 {
0627                     const size_type u_id = qxlist.top();
0628                     const vertex_t u_node = get(index_vertex_map, u_id);
0629 
0630                     // if u_id is outmatched by others, no need to update degree
0631                     if (degree_lists_marker.outmatched_or_done(u_node))
0632                     {
0633                         qxlist.pop();
0634                         continue;
0635                     }
0636                     marker.increment_tag();
0637                     deg = deg0;
0638                     adj_iter i, ie;
0639                     for (boost::tie(i, ie) = adjacent_vertices(u_node, G);
0640                          i != ie; ++i)
0641                     {
0642                         vertex_t i_node = *i;
0643                         if (marker.is_tagged(i_node))
0644                             continue;
0645                         marker.mark_tagged(i_node);
0646 
0647                         if (numbering.is_numbered(i_node))
0648                         {
0649                             adj_iter j, je;
0650                             for (boost::tie(j, je)
0651                                  = adjacent_vertices(i_node, G);
0652                                  j != je; ++j)
0653                             {
0654                                 const vertex_t j_node = *j;
0655                                 if (marker.is_not_tagged(j_node))
0656                                 {
0657                                     marker.mark_tagged(j_node);
0658                                     deg += supernode_size[j_node];
0659                                 }
0660                             }
0661                         }
0662                         else
0663                             deg += supernode_size[i_node];
0664                     } // for adjacent vertices of u_node
0665                     deg -= supernode_size[u_node];
0666                     degree[u_node] = deg;
0667                     degreelists[deg].push(u_node);
0668                     // u_id has been pushed back into degreelists
0669                     degree_lists_marker.unmark(u_node);
0670                     if (min_degree > deg)
0671                         min_degree = deg;
0672                     qxlist.pop();
0673                 } // while (!qxlist.empty()) {
0674 
0675                 marker.set_tag_as_multiple_tag();
0676                 llist.pop();
0677             } // while (! llist.empty())
0678 
0679         } // update()
0680 
0681         void build_permutation(InversePermutationMap next, PermutationMap prev)
0682         {
0683             // collect the permutation info
0684             size_type i;
0685             for (i = 0; i < n; ++i)
0686             {
0687                 diff_t size = supernode_size[get(index_vertex_map, i)];
0688                 if (size <= 0)
0689                 {
0690                     prev[i] = next[i];
0691                     supernode_size[get(index_vertex_map, i)]
0692                         = next[i] + 1; // record the supernode info
0693                 }
0694                 else
0695                     prev[i] = -next[i];
0696             }
0697             for (i = 1; i < n + 1; ++i)
0698             {
0699                 if (prev[i - 1] > 0)
0700                     continue;
0701                 diff_t parent = i;
0702                 while (prev[parent - 1] < 0)
0703                 {
0704                     parent = -prev[parent - 1];
0705                 }
0706 
0707                 diff_t root = parent;
0708                 diff_t num = prev[root - 1] + 1;
0709                 next[i - 1] = -num;
0710                 prev[root - 1] = num;
0711 
0712                 parent = i;
0713                 diff_t next_node = -prev[parent - 1];
0714                 while (next_node > 0)
0715                 {
0716                     prev[parent - 1] = -root;
0717                     parent = next_node;
0718                     next_node = -prev[parent - 1];
0719                 }
0720             }
0721             for (i = 0; i < n; i++)
0722             {
0723                 diff_t num = -next[i] - 1;
0724                 next[i] = num;
0725                 prev[num] = i;
0726             }
0727         } // build_permutation()
0728     };
0729 
0730 } // namespace detail
0731 
0732 // MMD algorithm
0733 //
0734 // The implementation presently includes the enhancements for mass
0735 // elimination, incomplete degree update, multiple elimination, and
0736 // external degree.
0737 //
0738 // Important Note: This implementation requires the BGL graph to be
0739 // directed.  Therefore, nonzero entry (i, j) in a symmetrical matrix
0740 // A coresponds to two directed edges (i->j and j->i).
0741 //
0742 // see Alan George and Joseph W. H. Liu, The Evolution of the Minimum
0743 // Degree Ordering Algorithm, SIAM Review, 31, 1989, Page 1-19
0744 template < class Graph, class DegreeMap, class InversePermutationMap,
0745     class PermutationMap, class SuperNodeMap, class VertexIndexMap >
0746 void minimum_degree_ordering(Graph& G, DegreeMap degree,
0747     InversePermutationMap inverse_perm, PermutationMap perm,
0748     SuperNodeMap supernode_size, int delta, VertexIndexMap vertex_index_map)
0749 {
0750     detail::mmd_impl< Graph, DegreeMap, InversePermutationMap, PermutationMap,
0751         SuperNodeMap, VertexIndexMap >
0752         impl(G, num_vertices(G), delta, degree, inverse_perm, perm,
0753             supernode_size, vertex_index_map);
0754     impl.do_mmd();
0755     impl.build_permutation(inverse_perm, perm);
0756 }
0757 
0758 } // namespace boost
0759 
0760 #endif // BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP