| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313 | //=======================================================================// Copyright (c) 2018 Yi Ji//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)////=======================================================================#ifndef BOOST_GRAPH_MAXIMUM_WEIGHTED_MATCHING_HPP#define BOOST_GRAPH_MAXIMUM_WEIGHTED_MATCHING_HPP#include <algorithm> // for std::iter_swap#include <boost/shared_ptr.hpp>#include <boost/make_shared.hpp>#include <boost/graph/max_cardinality_matching.hpp>namespace boost{template < typename Graph, typename MateMap, typename VertexIndexMap >typename property_traits<    typename property_map< Graph, edge_weight_t >::type >::value_typematching_weight_sum(const Graph& g, MateMap mate, VertexIndexMap vm){    typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;    typedef        typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;    typedef typename property_traits< typename property_map< Graph,        edge_weight_t >::type >::value_type edge_property_t;    edge_property_t weight_sum = 0;    vertex_iterator_t vi, vi_end;    for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)    {        vertex_descriptor_t v = *vi;        if (get(mate, v) != graph_traits< Graph >::null_vertex()            && get(vm, v) < get(vm, get(mate, v)))            weight_sum += get(edge_weight, g, edge(v, mate[v], g).first);    }    return weight_sum;}template < typename Graph, typename MateMap >inline typename property_traits<    typename property_map< Graph, edge_weight_t >::type >::value_typematching_weight_sum(const Graph& g, MateMap mate){    return matching_weight_sum(g, mate, get(vertex_index, g));}template < typename Graph, typename MateMap, typename VertexIndexMap >class weighted_augmenting_path_finder{public:    template < typename T > struct map_vertex_to_    {        typedef boost::iterator_property_map<            typename std::vector< T >::iterator, VertexIndexMap >            type;    };    typedef typename graph::detail::VERTEX_STATE vertex_state_t;    typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;    typedef        typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;    typedef typename std::vector< vertex_descriptor_t >::const_iterator        vertex_vec_iter_t;    typedef        typename graph_traits< Graph >::out_edge_iterator out_edge_iterator_t;    typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;    typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;    typedef typename property_traits< typename property_map< Graph,        edge_weight_t >::type >::value_type edge_property_t;    typedef std::deque< vertex_descriptor_t > vertex_list_t;    typedef std::vector< edge_descriptor_t > edge_list_t;    typedef typename map_vertex_to_< vertex_descriptor_t >::type        vertex_to_vertex_map_t;    typedef        typename map_vertex_to_< edge_property_t >::type vertex_to_weight_map_t;    typedef typename map_vertex_to_< bool >::type vertex_to_bool_map_t;    typedef typename map_vertex_to_< std::pair< vertex_descriptor_t,        vertex_descriptor_t > >::type vertex_to_pair_map_t;    typedef        typename map_vertex_to_< std::pair< edge_descriptor_t, bool > >::type            vertex_to_edge_map_t;    typedef typename map_vertex_to_< vertex_to_edge_map_t >::type        vertex_pair_to_edge_map_t;    class blossom    {    public:        typedef boost::shared_ptr< blossom > blossom_ptr_t;        std::vector< blossom_ptr_t > sub_blossoms;        edge_property_t dual_var;        blossom_ptr_t father;        blossom() : dual_var(0), father(blossom_ptr_t()) {}        // get the base vertex of a blossom by recursively getting        // its base sub-blossom, which is always the first one in        // sub_blossoms because of how we create and maintain blossoms        virtual vertex_descriptor_t get_base() const        {            const blossom* b = this;            while (!b->sub_blossoms.empty())                b = b->sub_blossoms[0].get();            return b->get_base();        }        // set a sub-blossom as a blossom's base by exchanging it        // with its first sub-blossom        void set_base(const blossom_ptr_t& sub)        {            for (blossom_iterator_t bi = sub_blossoms.begin();                 bi != sub_blossoms.end(); ++bi)            {                if (sub.get() == bi->get())                {                    std::iter_swap(sub_blossoms.begin(), bi);                    break;                }            }        }        // get all vertices inside recursively        virtual std::vector< vertex_descriptor_t > vertices() const        {            std::vector< vertex_descriptor_t > all_vertices;            for (typename std::vector< blossom_ptr_t >::const_iterator bi                 = sub_blossoms.begin();                 bi != sub_blossoms.end(); ++bi)            {                std::vector< vertex_descriptor_t > some_vertices                    = (*bi)->vertices();                all_vertices.insert(all_vertices.end(), some_vertices.begin(),                    some_vertices.end());            }            return all_vertices;        }    };    // a trivial_blossom only has one vertex and no sub-blossom;    // for each vertex v, in_blossom[v] is the trivial_blossom that contains it    // directly    class trivial_blossom : public blossom    {    public:        trivial_blossom(vertex_descriptor_t v) : trivial_vertex(v) {}        virtual vertex_descriptor_t get_base() const { return trivial_vertex; }        virtual std::vector< vertex_descriptor_t > vertices() const        {            std::vector< vertex_descriptor_t > all_vertices;            all_vertices.push_back(trivial_vertex);            return all_vertices;        }    private:        vertex_descriptor_t trivial_vertex;    };    typedef boost::shared_ptr< blossom > blossom_ptr_t;    typedef typename std::vector< blossom_ptr_t >::iterator blossom_iterator_t;    typedef        typename map_vertex_to_< blossom_ptr_t >::type vertex_to_blossom_map_t;    weighted_augmenting_path_finder(        const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm)    : g(arg_g)    , vm(arg_vm)    , null_edge(std::pair< edge_descriptor_t, bool >(          num_edges(g) == 0 ? edge_descriptor_t() : *edges(g).first, false))    , mate_vector(num_vertices(g))    , label_S_vector(num_vertices(g), graph_traits< Graph >::null_vertex())    , label_T_vector(num_vertices(g), graph_traits< Graph >::null_vertex())    , outlet_vector(num_vertices(g), graph_traits< Graph >::null_vertex())    , tau_idx_vector(num_vertices(g), graph_traits< Graph >::null_vertex())    , dual_var_vector(std::vector< edge_property_t >(          num_vertices(g), std::numeric_limits< edge_property_t >::min()))    , pi_vector(std::vector< edge_property_t >(          num_vertices(g), std::numeric_limits< edge_property_t >::max()))    , gamma_vector(std::vector< edge_property_t >(          num_vertices(g), std::numeric_limits< edge_property_t >::max()))    , tau_vector(std::vector< edge_property_t >(          num_vertices(g), std::numeric_limits< edge_property_t >::max()))    , in_blossom_vector(num_vertices(g))    , old_label_vector(num_vertices(g))    , critical_edge_vectors(num_vertices(g),          std::vector< std::pair< edge_descriptor_t, bool > >(              num_vertices(g), null_edge))    ,        mate(mate_vector.begin(), vm)    , label_S(label_S_vector.begin(), vm)    , label_T(label_T_vector.begin(), vm)    , outlet(outlet_vector.begin(), vm)    , tau_idx(tau_idx_vector.begin(), vm)    , dual_var(dual_var_vector.begin(), vm)    , pi(pi_vector.begin(), vm)    , gamma(gamma_vector.begin(), vm)    , tau(tau_vector.begin(), vm)    , in_blossom(in_blossom_vector.begin(), vm)    , old_label(old_label_vector.begin(), vm)    {        vertex_iterator_t vi, vi_end;        edge_iterator_t ei, ei_end;        edge_property_t max_weight            = std::numeric_limits< edge_property_t >::min();        for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)            max_weight = std::max(max_weight, get(edge_weight, g, *ei));        typename std::vector<            std::vector< std::pair< edge_descriptor_t, bool > > >::iterator vei;        for (boost::tie(vi, vi_end) = vertices(g),                            vei = critical_edge_vectors.begin();             vi != vi_end; ++vi, ++vei)        {            vertex_descriptor_t u = *vi;            mate[u] = get(arg_mate, u);            dual_var[u] = 2 * max_weight;            in_blossom[u] = boost::make_shared< trivial_blossom >(u);            outlet[u] = u;            critical_edge_vector.push_back(                vertex_to_edge_map_t(vei->begin(), vm));        }        critical_edge            = vertex_pair_to_edge_map_t(critical_edge_vector.begin(), vm);        init();    }    // return the top blossom where v is contained inside    blossom_ptr_t in_top_blossom(vertex_descriptor_t v) const    {        blossom_ptr_t b = in_blossom[v];        while (b->father != blossom_ptr_t())            b = b->father;        return b;    }    // check if vertex v is in blossom b    bool is_in_blossom(blossom_ptr_t b, vertex_descriptor_t v) const    {        if (v == graph_traits< Graph >::null_vertex())            return false;        blossom_ptr_t vb = in_blossom[v]->father;        while (vb != blossom_ptr_t())        {            if (vb.get() == b.get())                return true;            vb = vb->father;        }        return false;    }    // return the base vertex of the top blossom that contains v    inline vertex_descriptor_t base_vertex(vertex_descriptor_t v) const    {        return in_top_blossom(v)->get_base();    }    // add an existed top blossom of base vertex v into new top    // blossom b as its sub-blossom    void add_sub_blossom(blossom_ptr_t b, vertex_descriptor_t v)    {        blossom_ptr_t sub = in_top_blossom(v);        sub->father = b;        b->sub_blossoms.push_back(sub);        if (sub->sub_blossoms.empty())            return;        for (blossom_iterator_t bi = top_blossoms.begin();             bi != top_blossoms.end(); ++bi)        {            if (bi->get() == sub.get())            {                top_blossoms.erase(bi);                break;            }        }    }    // when a top blossom is created or its base vertex getting an S-label,    // add all edges incident to this blossom into even_edges    void bloom(blossom_ptr_t b)    {        std::vector< vertex_descriptor_t > vertices_of_b = b->vertices();        vertex_vec_iter_t vi;        for (vi = vertices_of_b.begin(); vi != vertices_of_b.end(); ++vi)        {            out_edge_iterator_t oei, oei_end;            for (boost::tie(oei, oei_end) = out_edges(*vi, g); oei != oei_end;                 ++oei)            {                if (target(*oei, g) != *vi && mate[*vi] != target(*oei, g))                    even_edges.push_back(*oei);            }        }    }    // assigning a T-label to a non S-vertex, along with outlet and updating pi    // value if updated pi[v] equals zero, augment the matching from its mate    // vertex    void put_T_label(vertex_descriptor_t v, vertex_descriptor_t T_label,        vertex_descriptor_t outlet_v, edge_property_t pi_v)    {        if (label_S[v] != graph_traits< Graph >::null_vertex())            return;        label_T[v] = T_label;        outlet[v] = outlet_v;        pi[v] = pi_v;        vertex_descriptor_t v_mate = mate[v];        if (pi[v] == 0)        {            label_T[v_mate] = graph_traits< Graph >::null_vertex();            label_S[v_mate] = v;            bloom(in_top_blossom(v_mate));        }    }    // get the missing T-label for a to-be-expanded base vertex    // the missing T-label is the last vertex of the path from outlet[v] to v    std::pair< vertex_descriptor_t, vertex_descriptor_t > missing_label(        vertex_descriptor_t b_base)    {        vertex_descriptor_t missing_outlet = outlet[b_base];        if (outlet[b_base] == b_base)            return std::make_pair(                graph_traits< Graph >::null_vertex(), missing_outlet);        vertex_iterator_t vi, vi_end;        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)            old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]);        std::pair< vertex_descriptor_t, vertex_state_t > child(            outlet[b_base], graph::detail::V_EVEN);        blossom_ptr_t b = in_blossom[child.first];        for (; b->father->father != blossom_ptr_t(); b = b->father)            ;        child.first = b->get_base();        if (child.first == b_base)            return std::make_pair(                graph_traits< Graph >::null_vertex(), missing_outlet);        while (true)        {            std::pair< vertex_descriptor_t, vertex_state_t > child_parent                = parent(child, true);            for (b = in_blossom[child_parent.first];                 b->father->father != blossom_ptr_t(); b = b->father)                ;            missing_outlet = child_parent.first;            child_parent.first = b->get_base();            if (child_parent.first == b_base)                break;            else                child = child_parent;        }        return std::make_pair(child.first, missing_outlet);    }    // expand a top blossom, put all its non-trivial sub-blossoms into    // top_blossoms    blossom_iterator_t expand_blossom(        blossom_iterator_t bi, std::vector< blossom_ptr_t >& new_ones)    {        blossom_ptr_t b = *bi;        for (blossom_iterator_t i = b->sub_blossoms.begin();             i != b->sub_blossoms.end(); ++i)        {            blossom_ptr_t sub_blossom = *i;            vertex_descriptor_t sub_base = sub_blossom->get_base();            label_S[sub_base] = label_T[sub_base]                = graph_traits< Graph >::null_vertex();            outlet[sub_base] = sub_base;            sub_blossom->father = blossom_ptr_t();            // new top blossoms cannot be pushed back into top_blossoms            // immediately, because push_back() may cause reallocation and then            // invalid iterators            if (!sub_blossom->sub_blossoms.empty())                new_ones.push_back(sub_blossom);        }        return top_blossoms.erase(bi);    }    // when expanding a T-blossom with base v, it requires more operations:    // supply the missing T-labels for new base vertices by picking the minimum    // tau from vertices of each corresponding new top-blossoms; when label_T[v]    // is null or we have a smaller tau from missing_label(v), replace T-label    // and outlet of v (but don't bloom v)    blossom_iterator_t expand_T_blossom(        blossom_iterator_t bi, std::vector< blossom_ptr_t >& new_ones)    {        blossom_ptr_t b = *bi;        vertex_descriptor_t b_base = b->get_base();        std::pair< vertex_descriptor_t, vertex_descriptor_t > T_and_outlet            = missing_label(b_base);        blossom_iterator_t next_bi = expand_blossom(bi, new_ones);        for (blossom_iterator_t i = b->sub_blossoms.begin();             i != b->sub_blossoms.end(); ++i)        {            blossom_ptr_t sub_blossom = *i;            vertex_descriptor_t sub_base = sub_blossom->get_base();            vertex_descriptor_t min_tau_v                = graph_traits< Graph >::null_vertex();            edge_property_t min_tau                = std::numeric_limits< edge_property_t >::max();            std::vector< vertex_descriptor_t > sub_vertices                = sub_blossom->vertices();            for (vertex_vec_iter_t v = sub_vertices.begin();                 v != sub_vertices.end(); ++v)            {                if (tau[*v] < min_tau)                {                    min_tau = tau[*v];                    min_tau_v = *v;                }            }            if (min_tau < std::numeric_limits< edge_property_t >::max())                put_T_label(                    sub_base, tau_idx[min_tau_v], min_tau_v, tau[min_tau_v]);        }        if (label_T[b_base] == graph_traits< Graph >::null_vertex()            || tau[old_label[b_base].second] < pi[b_base])            boost::tie(label_T[b_base], outlet[b_base]) = T_and_outlet;        return next_bi;    }    // when vertices v and w are matched to each other by augmenting,    // we must set v/w as base vertex of any blossom who contains v/w and    // is a sub-blossom of their lowest (smallest) common blossom    void adjust_blossom(vertex_descriptor_t v, vertex_descriptor_t w)    {        blossom_ptr_t vb = in_blossom[v], wb = in_blossom[w],                      lowest_common_blossom;        std::vector< blossom_ptr_t > v_ancestors, w_ancestors;        while (vb->father != blossom_ptr_t())        {            v_ancestors.push_back(vb->father);            vb = vb->father;        }        while (wb->father != blossom_ptr_t())        {            w_ancestors.push_back(wb->father);            wb = wb->father;        }        typename std::vector< blossom_ptr_t >::reverse_iterator i, j;        i = v_ancestors.rbegin();        j = w_ancestors.rbegin();        while (i != v_ancestors.rend() && j != w_ancestors.rend()            && i->get() == j->get())        {            lowest_common_blossom = *i;            ++i;            ++j;        }        vb = in_blossom[v];        wb = in_blossom[w];        while (vb->father != lowest_common_blossom)        {            vb->father->set_base(vb);            vb = vb->father;        }        while (wb->father != lowest_common_blossom)        {            wb->father->set_base(wb);            wb = wb->father;        }    }    // every edge weight is multiplied by 4 to ensure integer weights    // throughout the algorithm if all input weights are integers    inline edge_property_t slack(const edge_descriptor_t& e) const    {        vertex_descriptor_t v, w;        v = source(e, g);        w = target(e, g);        return dual_var[v] + dual_var[w] - 4 * get(edge_weight, g, e);    }    // backtrace one step on vertex v along the augmenting path    // by its labels and its vertex state;    // boolean parameter "use_old" means whether we are updating labels,    // if we are, then we use old labels to backtrace and also we    // don't jump to its base vertex when we reach an odd vertex    std::pair< vertex_descriptor_t, vertex_state_t > parent(        std::pair< vertex_descriptor_t, vertex_state_t > v,        bool use_old = false) const    {        if (v.second == graph::detail::V_EVEN)        {            // a paranoid check: label_S shoule be the same as mate in            // backtracing            if (label_S[v.first] == graph_traits< Graph >::null_vertex())                label_S[v.first] = mate[v.first];            return std::make_pair(label_S[v.first], graph::detail::V_ODD);        }        else if (v.second == graph::detail::V_ODD)        {            vertex_descriptor_t w = use_old ? old_label[v.first].first                                            : base_vertex(label_T[v.first]);            return std::make_pair(w, graph::detail::V_EVEN);        }        return std::make_pair(v.first, graph::detail::V_UNREACHED);    }    // backtrace from vertices v and w to their free (unmatched) ancesters,    // return the nearest common ancestor (null_vertex if none) of v and w    vertex_descriptor_t nearest_common_ancestor(vertex_descriptor_t v,        vertex_descriptor_t w, vertex_descriptor_t& v_free_ancestor,        vertex_descriptor_t& w_free_ancestor) const    {        std::pair< vertex_descriptor_t, vertex_state_t > v_up(            v, graph::detail::V_EVEN);        std::pair< vertex_descriptor_t, vertex_state_t > w_up(            w, graph::detail::V_EVEN);        vertex_descriptor_t nca;        nca = w_free_ancestor = v_free_ancestor            = graph_traits< Graph >::null_vertex();        std::vector< bool > ancestor_of_w_vector(num_vertices(g), false);        std::vector< bool > ancestor_of_v_vector(num_vertices(g), false);        vertex_to_bool_map_t ancestor_of_w(ancestor_of_w_vector.begin(), vm);        vertex_to_bool_map_t ancestor_of_v(ancestor_of_v_vector.begin(), vm);        while (nca == graph_traits< Graph >::null_vertex()            && (v_free_ancestor == graph_traits< Graph >::null_vertex()                || w_free_ancestor == graph_traits< Graph >::null_vertex()))        {            ancestor_of_w[w_up.first] = true;            ancestor_of_v[v_up.first] = true;            if (w_free_ancestor == graph_traits< Graph >::null_vertex())                w_up = parent(w_up);            if (v_free_ancestor == graph_traits< Graph >::null_vertex())                v_up = parent(v_up);            if (mate[v_up.first] == graph_traits< Graph >::null_vertex())                v_free_ancestor = v_up.first;            if (mate[w_up.first] == graph_traits< Graph >::null_vertex())                w_free_ancestor = w_up.first;            if (ancestor_of_w[v_up.first] == true || v_up.first == w_up.first)                nca = v_up.first;            else if (ancestor_of_v[w_up.first] == true)                nca = w_up.first;            else if (v_free_ancestor == w_free_ancestor                && v_free_ancestor != graph_traits< Graph >::null_vertex())                nca = v_up.first;        }        return nca;    }    // when a new top blossom b is created by connecting (v, w), we add    // sub-blossoms into b along backtracing from v_prime and w_prime to    // stop_vertex (the base vertex); also, we set labels and outlet for each    // base vertex we pass by    void make_blossom(blossom_ptr_t b, vertex_descriptor_t w_prime,        vertex_descriptor_t v_prime, vertex_descriptor_t stop_vertex)    {        std::pair< vertex_descriptor_t, vertex_state_t > u(            v_prime, graph::detail::V_ODD);        std::pair< vertex_descriptor_t, vertex_state_t > u_up(            w_prime, graph::detail::V_EVEN);        for (; u_up.first != stop_vertex; u = u_up, u_up = parent(u))        {            if (u_up.second == graph::detail::V_EVEN)            {                if (!in_top_blossom(u_up.first)->sub_blossoms.empty())                    outlet[u_up.first] = label_T[u.first];                label_T[u_up.first] = outlet[u.first];            }            else if (u_up.second == graph::detail::V_ODD)                label_S[u_up.first] = u.first;            add_sub_blossom(b, u_up.first);        }    }    // the design of recursively expanding augmenting path in    // (reversed_)retrieve_augmenting_path functions is inspired by same    // functions in max_cardinality_matching.hpp; except that in weighted    // matching, we use "outlet" vertices instead of "bridge" vertex pairs: if    // blossom b is the smallest non-trivial blossom that contains its base    // vertex v, then v and outlet[v] are where augmenting path enters and    // leaves b    void retrieve_augmenting_path(        vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state)    {        if (v == w)            aug_path.push_back(v);        else if (v_state == graph::detail::V_EVEN)        {            aug_path.push_back(v);            retrieve_augmenting_path(label_S[v], w, graph::detail::V_ODD);        }        else if (v_state == graph::detail::V_ODD)        {            if (outlet[v] == v)                aug_path.push_back(v);            else                reversed_retrieve_augmenting_path(                    outlet[v], v, graph::detail::V_EVEN);            retrieve_augmenting_path(label_T[v], w, graph::detail::V_EVEN);        }    }    void reversed_retrieve_augmenting_path(        vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state)    {        if (v == w)            aug_path.push_back(v);        else if (v_state == graph::detail::V_EVEN)        {            reversed_retrieve_augmenting_path(                label_S[v], w, graph::detail::V_ODD);            aug_path.push_back(v);        }        else if (v_state == graph::detail::V_ODD)        {            reversed_retrieve_augmenting_path(                label_T[v], w, graph::detail::V_EVEN);            if (outlet[v] != v)                retrieve_augmenting_path(outlet[v], v, graph::detail::V_EVEN);            else                aug_path.push_back(v);        }    }    // correct labels for vertices in the augmenting path    void relabel(vertex_descriptor_t v)    {        blossom_ptr_t b = in_blossom[v]->father;        if (!is_in_blossom(b, mate[v]))        { // if v is a new base vertex            std::pair< vertex_descriptor_t, vertex_state_t > u(                v, graph::detail::V_EVEN);            while (label_S[u.first] != u.first                && is_in_blossom(b, label_S[u.first]))                u = parent(u, true);            vertex_descriptor_t old_base = u.first;            if (label_S[old_base] != old_base)            { // if old base is not exposed                label_T[v] = label_S[old_base];                outlet[v] = old_base;            }            else            { // if old base is exposed then new label_T[v] is not in b,                // we must (i) make b2 the smallest blossom containing v but not                // as base vertex (ii) backtrace from b2's new base vertex to b                label_T[v] = graph_traits< Graph >::null_vertex();                for (b = b->father; b != blossom_ptr_t() && b->get_base() == v;                     b = b->father)                    ;                if (b != blossom_ptr_t())                {                    u = std::make_pair(b->get_base(), graph::detail::V_ODD);                    while (!is_in_blossom(                        in_blossom[v]->father, old_label[u.first].first))                        u = parent(u, true);                    label_T[v] = u.first;                    outlet[v] = old_label[u.first].first;                }            }        }        else if (label_S[v] == v || !is_in_blossom(b, label_S[v]))        { // if v is an old base vertex            // let u be the new base vertex; backtrace from u's old T-label            std::pair< vertex_descriptor_t, vertex_state_t > u(                b->get_base(), graph::detail::V_ODD);            while (                old_label[u.first].first != graph_traits< Graph >::null_vertex()                && old_label[u.first].first != v)                u = parent(u, true);            label_T[v] = old_label[u.first].second;            outlet[v] = v;        }        else // if v is neither a new nor an old base vertex            label_T[v] = label_S[v];    }    void augmenting(vertex_descriptor_t v, vertex_descriptor_t v_free_ancestor,        vertex_descriptor_t w, vertex_descriptor_t w_free_ancestor)    {        vertex_iterator_t vi, vi_end;        // retrieve the augmenting path and put it in aug_path        reversed_retrieve_augmenting_path(            v, v_free_ancestor, graph::detail::V_EVEN);        retrieve_augmenting_path(w, w_free_ancestor, graph::detail::V_EVEN);        // augment the matching along aug_path        vertex_descriptor_t a, b;        vertex_list_t reversed_aug_path;        while (!aug_path.empty())        {            a = aug_path.front();            aug_path.pop_front();            reversed_aug_path.push_back(a);            b = aug_path.front();            aug_path.pop_front();            reversed_aug_path.push_back(b);            mate[a] = b;            mate[b] = a;            // reset base vertex for every blossom in augment path            adjust_blossom(a, b);        }        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)            old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]);        // correct labels for in-blossom vertices along aug_path        while (!reversed_aug_path.empty())        {            a = reversed_aug_path.front();            reversed_aug_path.pop_front();            if (in_blossom[a]->father != blossom_ptr_t())                relabel(a);        }        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)        {            vertex_descriptor_t u = *vi;            if (mate[u] != graph_traits< Graph >::null_vertex())                label_S[u] = mate[u];        }        // expand blossoms with zero dual variables        std::vector< blossom_ptr_t > new_top_blossoms;        for (blossom_iterator_t bi = top_blossoms.begin();             bi != top_blossoms.end();)        {            if ((*bi)->dual_var <= 0)                bi = expand_blossom(bi, new_top_blossoms);            else                ++bi;        }        top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(),            new_top_blossoms.end());        init();    }    // create a new blossom and set labels for vertices inside    void blossoming(vertex_descriptor_t v, vertex_descriptor_t v_prime,        vertex_descriptor_t w, vertex_descriptor_t w_prime,        vertex_descriptor_t nca)    {        vertex_iterator_t vi, vi_end;        std::vector< bool > is_old_base_vector(num_vertices(g));        vertex_to_bool_map_t is_old_base(is_old_base_vector.begin(), vm);        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)        {            if (*vi == base_vertex(*vi))                is_old_base[*vi] = true;        }        blossom_ptr_t b = boost::make_shared< blossom >();        add_sub_blossom(b, nca);        label_T[w_prime] = v;        label_T[v_prime] = w;        outlet[w_prime] = w;        outlet[v_prime] = v;        make_blossom(b, w_prime, v_prime, nca);        make_blossom(b, v_prime, w_prime, nca);        label_T[nca] = graph_traits< Graph >::null_vertex();        outlet[nca] = nca;        top_blossoms.push_back(b);        bloom(b);        // set gamma[b_base] = min_slack{critical_edge(b_base, other_base)}        // where each critical edge is updated before, by        // argmin{slack(old_bases_in_b, other_base)};        vertex_vec_iter_t i, j;        std::vector< vertex_descriptor_t > b_vertices = b->vertices(),                                           old_base_in_b, other_base;        vertex_descriptor_t b_base = b->get_base();        for (i = b_vertices.begin(); i != b_vertices.end(); ++i)        {            if (is_old_base[*i])                old_base_in_b.push_back(*i);        }        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)        {            if (*vi != b_base && *vi == base_vertex(*vi))                other_base.push_back(*vi);        }        for (i = other_base.begin(); i != other_base.end(); ++i)        {            edge_property_t min_slack                = std::numeric_limits< edge_property_t >::max();            std::pair< edge_descriptor_t, bool > b_vi = null_edge;            for (j = old_base_in_b.begin(); j != old_base_in_b.end(); ++j)            {                if (critical_edge[*j][*i] != null_edge                    && min_slack > slack(critical_edge[*j][*i].first))                {                    min_slack = slack(critical_edge[*j][*i].first);                    b_vi = critical_edge[*j][*i];                }            }            critical_edge[b_base][*i] = critical_edge[*i][b_base] = b_vi;        }        gamma[b_base] = std::numeric_limits< edge_property_t >::max();        for (i = other_base.begin(); i != other_base.end(); ++i)        {            if (critical_edge[b_base][*i] != null_edge)                gamma[b_base] = std::min(                    gamma[b_base], slack(critical_edge[b_base][*i].first));        }    }    void init()    {        even_edges.clear();        vertex_iterator_t vi, vi_end;        typename std::vector<            std::vector< std::pair< edge_descriptor_t, bool > > >::iterator vei;        for (boost::tie(vi, vi_end) = vertices(g),                            vei = critical_edge_vectors.begin();             vi != vi_end; ++vi, ++vei)        {            vertex_descriptor_t u = *vi;            out_edge_iterator_t ei, ei_end;            gamma[u] = tau[u] = pi[u]                = std::numeric_limits< edge_property_t >::max();            std::fill(vei->begin(), vei->end(), null_edge);            if (base_vertex(u) != u)                continue;            label_S[u] = label_T[u] = graph_traits< Graph >::null_vertex();            outlet[u] = u;            if (mate[u] == graph_traits< Graph >::null_vertex())            {                label_S[u] = u;                bloom(in_top_blossom(u));            }        }    }    bool augment_matching()    {        vertex_descriptor_t v, w, w_free_ancestor, v_free_ancestor;        v = w = w_free_ancestor = v_free_ancestor            = graph_traits< Graph >::null_vertex();        bool found_alternating_path = false;        // note that we only use edges of zero slack value for augmenting        while (!even_edges.empty() && !found_alternating_path)        {            // search for augmenting paths depth-first            edge_descriptor_t current_edge = even_edges.back();            even_edges.pop_back();            v = source(current_edge, g);            w = target(current_edge, g);            vertex_descriptor_t v_prime = base_vertex(v);            vertex_descriptor_t w_prime = base_vertex(w);            // w_prime == v_prime implies that we get an edge that has been            // shrunk into a blossom            if (v_prime == w_prime)                continue;            // a paranoid check            if (label_S[v_prime] == graph_traits< Graph >::null_vertex())            {                std::swap(v_prime, w_prime);                std::swap(v, w);            }            // w_prime may be unlabeled or have a T-label; replace the existed            // T-label if the edge slack is smaller than current pi[w_prime] and            // update it. Note that a T-label is "deserved" only when pi equals            // zero. also update tau and tau_idx so that tau_idx becomes T-label            // when a T-blossom is expanded            if (label_S[w_prime] == graph_traits< Graph >::null_vertex())            {                if (slack(current_edge) < pi[w_prime])                    put_T_label(w_prime, v, w, slack(current_edge));                if (slack(current_edge) < tau[w])                {                    if (in_blossom[w]->father == blossom_ptr_t()                        || label_T[w_prime] == v                        || label_T[w_prime]                            == graph_traits< Graph >::null_vertex()                        || nearest_common_ancestor(v_prime, label_T[w_prime],                               v_free_ancestor, w_free_ancestor)                            == graph_traits< Graph >::null_vertex())                    {                        tau[w] = slack(current_edge);                        tau_idx[w] = v;                    }                }            }            else            {                if (slack(current_edge) > 0)                {                    // update gamma and critical_edges when we have a smaller                    // edge slack                    gamma[v_prime]                        = std::min(gamma[v_prime], slack(current_edge));                    gamma[w_prime]                        = std::min(gamma[w_prime], slack(current_edge));                    if (critical_edge[v_prime][w_prime] == null_edge                        || slack(critical_edge[v_prime][w_prime].first)                            > slack(current_edge))                    {                        critical_edge[v_prime][w_prime]                            = std::pair< edge_descriptor_t, bool >(                                current_edge, true);                        critical_edge[w_prime][v_prime]                            = std::pair< edge_descriptor_t, bool >(                                current_edge, true);                    }                    continue;                }                else if (slack(current_edge) == 0)                {                    // if nca is null_vertex then we have an augmenting path;                    // otherwise we have a new top blossom with nca as its base                    // vertex                    vertex_descriptor_t nca = nearest_common_ancestor(                        v_prime, w_prime, v_free_ancestor, w_free_ancestor);                    if (nca == graph_traits< Graph >::null_vertex())                        found_alternating_path                            = true; // to break out of the loop                    else                        blossoming(v, v_prime, w, w_prime, nca);                }            }        }        if (!found_alternating_path)            return false;        augmenting(v, v_free_ancestor, w, w_free_ancestor);        return true;    }    // slack the vertex and blossom dual variables when there is no augmenting    // path found according to the primal-dual method    bool adjust_dual()    {        edge_property_t delta1, delta2, delta3, delta4, delta;        delta1 = delta2 = delta3 = delta4            = std::numeric_limits< edge_property_t >::max();        vertex_iterator_t vi, vi_end;        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)        {            delta1 = std::min(delta1, dual_var[*vi]);            delta4 = pi[*vi] > 0 ? std::min(delta4, pi[*vi]) : delta4;            if (*vi == base_vertex(*vi))                delta3 = std::min(delta3, gamma[*vi] / 2);        }        for (blossom_iterator_t bi = top_blossoms.begin();             bi != top_blossoms.end(); ++bi)        {            vertex_descriptor_t b_base = (*bi)->get_base();            if (label_T[b_base] != graph_traits< Graph >::null_vertex()                && pi[b_base] == 0)                delta2 = std::min(delta2, (*bi)->dual_var / 2);        }        delta = std::min(std::min(delta1, delta2), std::min(delta3, delta4));        // start updating dual variables, note that the order is important        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)        {            vertex_descriptor_t v = *vi, v_prime = base_vertex(v);            if (label_S[v_prime] != graph_traits< Graph >::null_vertex())                dual_var[v] -= delta;            else if (label_T[v_prime] != graph_traits< Graph >::null_vertex()                && pi[v_prime] == 0)                dual_var[v] += delta;            if (v == v_prime)                gamma[v] -= 2 * delta;        }        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)        {            vertex_descriptor_t v_prime = base_vertex(*vi);            if (pi[v_prime] > 0)                tau[*vi] -= delta;        }        for (blossom_iterator_t bi = top_blossoms.begin();             bi != top_blossoms.end(); ++bi)        {            vertex_descriptor_t b_base = (*bi)->get_base();            if (label_T[b_base] != graph_traits< Graph >::null_vertex()                && pi[b_base] == 0)                (*bi)->dual_var -= 2 * delta;            if (label_S[b_base] != graph_traits< Graph >::null_vertex())                (*bi)->dual_var += 2 * delta;        }        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)        {            vertex_descriptor_t v = *vi;            if (pi[v] > 0)                pi[v] -= delta;            // when some T-vertices have zero pi value, bloom their mates so            // that matching can be further augmented            if (label_T[v] != graph_traits< Graph >::null_vertex()                && pi[v] == 0)                put_T_label(v, label_T[v], outlet[v], pi[v]);        }        // optimal solution reached, halt        if (delta == delta1)            return false;        // expand odd blossoms with zero dual variables and zero pi value of        // their base vertices        if (delta == delta2 && delta != delta3)        {            std::vector< blossom_ptr_t > new_top_blossoms;            for (blossom_iterator_t bi = top_blossoms.begin();                 bi != top_blossoms.end();)            {                const blossom_ptr_t b = *bi;                vertex_descriptor_t b_base = b->get_base();                if (b->dual_var == 0                    && label_T[b_base] != graph_traits< Graph >::null_vertex()                    && pi[b_base] == 0)                    bi = expand_T_blossom(bi, new_top_blossoms);                else                    ++bi;            }            top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(),                new_top_blossoms.end());        }        while (true)        {            // find a zero-slack critical edge (v, w) of zero gamma values            std::pair< edge_descriptor_t, bool > best_edge = null_edge;            std::vector< vertex_descriptor_t > base_nodes;            for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)            {                if (*vi == base_vertex(*vi))                    base_nodes.push_back(*vi);            }            for (vertex_vec_iter_t i = base_nodes.begin();                 i != base_nodes.end(); ++i)            {                if (gamma[*i] == 0)                {                    for (vertex_vec_iter_t j = base_nodes.begin();                         j != base_nodes.end(); ++j)                    {                        if (critical_edge[*i][*j] != null_edge                            && slack(critical_edge[*i][*j].first) == 0)                            best_edge = critical_edge[*i][*j];                    }                }            }            // if not found, continue finding other augment matching            if (best_edge == null_edge)            {                bool augmented = augment_matching();                return augmented || delta != delta1;            }            // if found, determine either augmenting or blossoming            vertex_descriptor_t v = source(best_edge.first, g),                                w = target(best_edge.first, g);            vertex_descriptor_t v_prime = base_vertex(v),                                w_prime = base_vertex(w), v_free_ancestor,                                w_free_ancestor;            vertex_descriptor_t nca = nearest_common_ancestor(                v_prime, w_prime, v_free_ancestor, w_free_ancestor);            if (nca == graph_traits< Graph >::null_vertex())            {                augmenting(v, v_free_ancestor, w, w_free_ancestor);                return true;            }            else                blossoming(v, v_prime, w, w_prime, nca);        }        return false;    }    template < typename PropertyMap > void get_current_matching(PropertyMap pm)    {        vertex_iterator_t vi, vi_end;        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)            put(pm, *vi, mate[*vi]);    }private:    const Graph& g;    VertexIndexMap vm;    const std::pair< edge_descriptor_t, bool > null_edge;    // storage for the property maps below    std::vector< vertex_descriptor_t > mate_vector;    std::vector< vertex_descriptor_t > label_S_vector, label_T_vector;    std::vector< vertex_descriptor_t > outlet_vector;    std::vector< vertex_descriptor_t > tau_idx_vector;    std::vector< edge_property_t > dual_var_vector;    std::vector< edge_property_t > pi_vector, gamma_vector, tau_vector;    std::vector< blossom_ptr_t > in_blossom_vector;    std::vector< std::pair< vertex_descriptor_t, vertex_descriptor_t > >        old_label_vector;    std::vector< vertex_to_edge_map_t > critical_edge_vector;    std::vector< std::vector< std::pair< edge_descriptor_t, bool > > >        critical_edge_vectors;    // iterator property maps    vertex_to_vertex_map_t mate;    vertex_to_vertex_map_t label_S; // v has an S-label -> v can be an even                                    // vertex, label_S[v] is its mate    vertex_to_vertex_map_t        label_T; // v has a T-label -> v can be an odd vertex, label_T[v] is its                 // predecessor in aug_path    vertex_to_vertex_map_t outlet;    vertex_to_vertex_map_t tau_idx;    vertex_to_weight_map_t dual_var;    vertex_to_weight_map_t pi, gamma, tau;    vertex_to_blossom_map_t        in_blossom; // map any vertex v to the trivial blossom containing v    vertex_to_pair_map_t old_label; // <old T-label, old outlet> before                                    // relabeling or expanding T-blossoms    vertex_pair_to_edge_map_t        critical_edge; // an not matched edge (v, w) is critical if v and w                       // belongs to different S-blossoms    vertex_list_t aug_path;    edge_list_t even_edges;    std::vector< blossom_ptr_t > top_blossoms;};template < typename Graph, typename MateMap, typename VertexIndexMap >void maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm){    empty_matching< Graph, MateMap >::find_matching(g, mate);    weighted_augmenting_path_finder< Graph, MateMap, VertexIndexMap > augmentor(        g, mate, vm);    // can have |V| times augmenting at most    for (std::size_t t = 0; t < num_vertices(g); ++t)    {        bool augmented = false;        while (!augmented)        {            augmented = augmentor.augment_matching();            if (!augmented)            {                // halt if adjusting dual variables can't bring potential                // augment                if (!augmentor.adjust_dual())                    break;            }        }        if (!augmented)            break;    }    augmentor.get_current_matching(mate);}template < typename Graph, typename MateMap >inline void maximum_weighted_matching(const Graph& g, MateMap mate){    maximum_weighted_matching(g, mate, get(vertex_index, g));}// brute-force matcher searches all possible combinations of matched edges to// get the maximum weighted matching which can be used for testing on small// graphs (within dozens vertices)template < typename Graph, typename MateMap, typename VertexIndexMap >class brute_force_matching{public:    typedef        typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;    typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;    typedef        typename std::vector< vertex_descriptor_t >::iterator vertex_vec_iter_t;    typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;    typedef boost::iterator_property_map< vertex_vec_iter_t, VertexIndexMap >        vertex_to_vertex_map_t;    brute_force_matching(        const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm)    : g(arg_g)    , vm(arg_vm)    , mate_vector(num_vertices(g))    , best_mate_vector(num_vertices(g))    , mate(mate_vector.begin(), vm)    , best_mate(best_mate_vector.begin(), vm)    {        vertex_iterator_t vi, vi_end;        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)            best_mate[*vi] = mate[*vi] = get(arg_mate, *vi);    }    template < typename PropertyMap > void find_matching(PropertyMap pm)    {        edge_iterator_t ei;        boost::tie(ei, ei_end) = edges(g);        select_edge(ei);        vertex_iterator_t vi, vi_end;        for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)            put(pm, *vi, best_mate[*vi]);    }private:    const Graph& g;    VertexIndexMap vm;    std::vector< vertex_descriptor_t > mate_vector, best_mate_vector;    vertex_to_vertex_map_t mate, best_mate;    edge_iterator_t ei_end;    void select_edge(edge_iterator_t ei)    {        if (ei == ei_end)        {            if (matching_weight_sum(g, mate)                > matching_weight_sum(g, best_mate))            {                vertex_iterator_t vi, vi_end;                for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)                    best_mate[*vi] = mate[*vi];            }            return;        }        vertex_descriptor_t v, w;        v = source(*ei, g);        w = target(*ei, g);        select_edge(++ei);        if (mate[v] == graph_traits< Graph >::null_vertex()            && mate[w] == graph_traits< Graph >::null_vertex())        {            mate[v] = w;            mate[w] = v;            select_edge(ei);            mate[v] = mate[w] = graph_traits< Graph >::null_vertex();        }    }};template < typename Graph, typename MateMap, typename VertexIndexMap >void brute_force_maximum_weighted_matching(    const Graph& g, MateMap mate, VertexIndexMap vm){    empty_matching< Graph, MateMap >::find_matching(g, mate);    brute_force_matching< Graph, MateMap, VertexIndexMap > brute_force_matcher(        g, mate, vm);    brute_force_matcher.find_matching(mate);}template < typename Graph, typename MateMap >inline void brute_force_maximum_weighted_matching(const Graph& g, MateMap mate){    brute_force_maximum_weighted_matching(g, mate, get(vertex_index, g));}}#endif
 |