1.1 --- a/doc/groups.dox Tue Apr 21 10:34:49 2009 +0100
1.2 +++ b/doc/groups.dox Tue Apr 21 13:08:19 2009 +0100
1.3 @@ -435,9 +435,10 @@
1.4 @ingroup algs
1.5 \brief Algorithms for finding matchings in graphs and bipartite graphs.
1.6
1.7 -This group contains algorithm objects and functions to calculate
1.8 +This group contains the algorithms for calculating
1.9 matchings in graphs and bipartite graphs. The general matching problem is
1.10 -finding a subset of the arcs which does not shares common endpoints.
1.11 +finding a subset of the edges for which each node has at most one incident
1.12 +edge.
1.13
1.14 There are several different algorithms for calculate matchings in
1.15 graphs. The matching problems in bipartite graphs are generally
2.1 --- a/lemon/Makefile.am Tue Apr 21 10:34:49 2009 +0100
2.2 +++ b/lemon/Makefile.am Tue Apr 21 13:08:19 2009 +0100
2.3 @@ -89,8 +89,8 @@
2.4 lemon/lp_skeleton.h \
2.5 lemon/list_graph.h \
2.6 lemon/maps.h \
2.7 + lemon/matching.h \
2.8 lemon/math.h \
2.9 - lemon/max_matching.h \
2.10 lemon/min_cost_arborescence.h \
2.11 lemon/nauty_reader.h \
2.12 lemon/path.h \
3.1 --- a/lemon/euler.h Tue Apr 21 10:34:49 2009 +0100
3.2 +++ b/lemon/euler.h Tue Apr 21 13:08:19 2009 +0100
3.3 @@ -26,33 +26,31 @@
3.4
3.5 /// \ingroup graph_properties
3.6 /// \file
3.7 -/// \brief Euler tour
3.8 +/// \brief Euler tour iterators and a function for checking the \e Eulerian
3.9 +/// property.
3.10 ///
3.11 -///This file provides an Euler tour iterator and ways to check
3.12 -///if a digraph is euler.
3.13 -
3.14 +///This file provides Euler tour iterators and a function to check
3.15 +///if a (di)graph is \e Eulerian.
3.16
3.17 namespace lemon {
3.18
3.19 - ///Euler iterator for digraphs.
3.20 + ///Euler tour iterator for digraphs.
3.21
3.22 - /// \ingroup graph_properties
3.23 - ///This iterator converts to the \c Arc type of the digraph and using
3.24 - ///operator ++, it provides an Euler tour of a \e directed
3.25 - ///graph (if there exists).
3.26 + /// \ingroup graph_prop
3.27 + ///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
3.28 + ///graph (if there exists) and it converts to the \c Arc type of the digraph.
3.29 ///
3.30 - ///For example
3.31 - ///if the given digraph is Euler (i.e it has only one nontrivial component
3.32 - ///and the in-degree is equal to the out-degree for all nodes),
3.33 - ///the following code will put the arcs of \c g
3.34 - ///to the vector \c et according to an
3.35 - ///Euler tour of \c g.
3.36 + ///For example, if the given digraph has an Euler tour (i.e it has only one
3.37 + ///non-trivial component and the in-degree is equal to the out-degree
3.38 + ///for all nodes), then the following code will put the arcs of \c g
3.39 + ///to the vector \c et according to an Euler tour of \c g.
3.40 ///\code
3.41 /// std::vector<ListDigraph::Arc> et;
3.42 - /// for(DiEulerIt<ListDigraph> e(g),e!=INVALID;++e)
3.43 + /// for(DiEulerIt<ListDigraph> e(g); e!=INVALID; ++e)
3.44 /// et.push_back(e);
3.45 ///\endcode
3.46 - ///If \c g is not Euler then the resulted tour will not be full or closed.
3.47 + ///If \c g has no Euler tour, then the resulted walk will not be closed
3.48 + ///or not contain all arcs.
3.49 ///\sa EulerIt
3.50 template<typename GR>
3.51 class DiEulerIt
3.52 @@ -65,53 +63,65 @@
3.53 typedef typename GR::InArcIt InArcIt;
3.54
3.55 const GR &g;
3.56 - typename GR::template NodeMap<OutArcIt> nedge;
3.57 + typename GR::template NodeMap<OutArcIt> narc;
3.58 std::list<Arc> euler;
3.59
3.60 public:
3.61
3.62 ///Constructor
3.63
3.64 + ///Constructor.
3.65 ///\param gr A digraph.
3.66 - ///\param start The starting point of the tour. If it is not given
3.67 - /// the tour will start from the first node.
3.68 + ///\param start The starting point of the tour. If it is not given,
3.69 + ///the tour will start from the first node that has an outgoing arc.
3.70 DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
3.71 - : g(gr), nedge(g)
3.72 + : g(gr), narc(g)
3.73 {
3.74 - if(start==INVALID) start=NodeIt(g);
3.75 - for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
3.76 - while(nedge[start]!=INVALID) {
3.77 - euler.push_back(nedge[start]);
3.78 - Node next=g.target(nedge[start]);
3.79 - ++nedge[start];
3.80 - start=next;
3.81 + if (start==INVALID) {
3.82 + NodeIt n(g);
3.83 + while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
3.84 + start=n;
3.85 + }
3.86 + if (start!=INVALID) {
3.87 + for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
3.88 + while (narc[start]!=INVALID) {
3.89 + euler.push_back(narc[start]);
3.90 + Node next=g.target(narc[start]);
3.91 + ++narc[start];
3.92 + start=next;
3.93 + }
3.94 }
3.95 }
3.96
3.97 - ///Arc Conversion
3.98 + ///Arc conversion
3.99 operator Arc() { return euler.empty()?INVALID:euler.front(); }
3.100 + ///Compare with \c INVALID
3.101 bool operator==(Invalid) { return euler.empty(); }
3.102 + ///Compare with \c INVALID
3.103 bool operator!=(Invalid) { return !euler.empty(); }
3.104
3.105 ///Next arc of the tour
3.106 +
3.107 + ///Next arc of the tour
3.108 + ///
3.109 DiEulerIt &operator++() {
3.110 Node s=g.target(euler.front());
3.111 euler.pop_front();
3.112 - //This produces a warning.Strange.
3.113 - //std::list<Arc>::iterator next=euler.begin();
3.114 typename std::list<Arc>::iterator next=euler.begin();
3.115 - while(nedge[s]!=INVALID) {
3.116 - euler.insert(next,nedge[s]);
3.117 - Node n=g.target(nedge[s]);
3.118 - ++nedge[s];
3.119 + while(narc[s]!=INVALID) {
3.120 + euler.insert(next,narc[s]);
3.121 + Node n=g.target(narc[s]);
3.122 + ++narc[s];
3.123 s=n;
3.124 }
3.125 return *this;
3.126 }
3.127 ///Postfix incrementation
3.128
3.129 + /// Postfix incrementation.
3.130 + ///
3.131 ///\warning This incrementation
3.132 - ///returns an \c Arc, not an \ref DiEulerIt, as one may
3.133 + ///returns an \c Arc, not a \ref DiEulerIt, as one may
3.134 ///expect.
3.135 Arc operator++(int)
3.136 {
3.137 @@ -121,30 +131,28 @@
3.138 }
3.139 };
3.140
3.141 - ///Euler iterator for graphs.
3.142 + ///Euler tour iterator for graphs.
3.143
3.144 /// \ingroup graph_properties
3.145 - ///This iterator converts to the \c Arc (or \c Edge)
3.146 - ///type of the digraph and using
3.147 - ///operator ++, it provides an Euler tour of an undirected
3.148 - ///digraph (if there exists).
3.149 + ///This iterator provides an Euler tour (Eulerian circuit) of an
3.150 + ///\e undirected graph (if there exists) and it converts to the \c Arc
3.151 + ///and \c Edge types of the graph.
3.152 ///
3.153 - ///For example
3.154 - ///if the given digraph if Euler (i.e it has only one nontrivial component
3.155 - ///and the degree of each node is even),
3.156 + ///For example, if the given graph has an Euler tour (i.e it has only one
3.157 + ///non-trivial component and the degree of each node is even),
3.158 ///the following code will print the arc IDs according to an
3.159 ///Euler tour of \c g.
3.160 ///\code
3.161 - /// for(EulerIt<ListGraph> e(g),e!=INVALID;++e) {
3.162 + /// for(EulerIt<ListGraph> e(g); e!=INVALID; ++e) {
3.163 /// std::cout << g.id(Edge(e)) << std::eol;
3.164 /// }
3.165 ///\endcode
3.166 - ///Although the iterator provides an Euler tour of an graph,
3.167 - ///it still returns Arcs in order to indicate the direction of the tour.
3.168 - ///(But Arc will convert to Edges, of course).
3.169 + ///Although this iterator is for undirected graphs, it still returns
3.170 + ///arcs in order to indicate the direction of the tour.
3.171 + ///(But arcs convert to edges, of course.)
3.172 ///
3.173 - ///If \c g is not Euler then the resulted tour will not be full or closed.
3.174 - ///\sa EulerIt
3.175 + ///If \c g has no Euler tour, then the resulted walk will not be closed
3.176 + ///or not contain all edges.
3.177 template<typename GR>
3.178 class EulerIt
3.179 {
3.180 @@ -157,7 +165,7 @@
3.181 typedef typename GR::InArcIt InArcIt;
3.182
3.183 const GR &g;
3.184 - typename GR::template NodeMap<OutArcIt> nedge;
3.185 + typename GR::template NodeMap<OutArcIt> narc;
3.186 typename GR::template EdgeMap<bool> visited;
3.187 std::list<Arc> euler;
3.188
3.189 @@ -165,47 +173,56 @@
3.190
3.191 ///Constructor
3.192
3.193 - ///\param gr An graph.
3.194 - ///\param start The starting point of the tour. If it is not given
3.195 - /// the tour will start from the first node.
3.196 + ///Constructor.
3.197 + ///\param gr A graph.
3.198 + ///\param start The starting point of the tour. If it is not given,
3.199 + ///the tour will start from the first node that has an incident edge.
3.200 EulerIt(const GR &gr, typename GR::Node start = INVALID)
3.201 - : g(gr), nedge(g), visited(g, false)
3.202 + : g(gr), narc(g), visited(g, false)
3.203 {
3.204 - if(start==INVALID) start=NodeIt(g);
3.205 - for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
3.206 - while(nedge[start]!=INVALID) {
3.207 - euler.push_back(nedge[start]);
3.208 - visited[nedge[start]]=true;
3.209 - Node next=g.target(nedge[start]);
3.210 - ++nedge[start];
3.211 - start=next;
3.212 - while(nedge[start]!=INVALID && visited[nedge[start]]) ++nedge[start];
3.213 + if (start==INVALID) {
3.214 + NodeIt n(g);
3.215 + while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
3.216 + start=n;
3.217 + }
3.218 + if (start!=INVALID) {
3.219 + for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
3.220 + while(narc[start]!=INVALID) {
3.221 + euler.push_back(narc[start]);
3.222 + visited[narc[start]]=true;
3.223 + Node next=g.target(narc[start]);
3.224 + ++narc[start];
3.225 + start=next;
3.226 + while(narc[start]!=INVALID && visited[narc[start]]) ++narc[start];
3.227 + }
3.228 }
3.229 }
3.230
3.231 - ///Arc Conversion
3.232 + ///Arc conversion
3.233 operator Arc() const { return euler.empty()?INVALID:euler.front(); }
3.234 - ///Arc Conversion
3.235 + ///Edge conversion
3.236 operator Edge() const { return euler.empty()?INVALID:euler.front(); }
3.237 - ///\e
3.238 + ///Compare with \c INVALID
3.239 bool operator==(Invalid) const { return euler.empty(); }
3.240 - ///\e
3.241 + ///Compare with \c INVALID
3.242 bool operator!=(Invalid) const { return !euler.empty(); }
3.243
3.244 ///Next arc of the tour
3.245 +
3.246 + ///Next arc of the tour
3.247 + ///
3.248 EulerIt &operator++() {
3.249 Node s=g.target(euler.front());
3.250 euler.pop_front();
3.251 typename std::list<Arc>::iterator next=euler.begin();
3.252 -
3.253 - while(nedge[s]!=INVALID) {
3.254 - while(nedge[s]!=INVALID && visited[nedge[s]]) ++nedge[s];
3.255 - if(nedge[s]==INVALID) break;
3.256 + while(narc[s]!=INVALID) {
3.257 + while(narc[s]!=INVALID && visited[narc[s]]) ++narc[s];
3.258 + if(narc[s]==INVALID) break;
3.259 else {
3.260 - euler.insert(next,nedge[s]);
3.261 - visited[nedge[s]]=true;
3.262 - Node n=g.target(nedge[s]);
3.263 - ++nedge[s];
3.264 + euler.insert(next,narc[s]);
3.265 + visited[narc[s]]=true;
3.266 + Node n=g.target(narc[s]);
3.267 + ++narc[s];
3.268 s=n;
3.269 }
3.270 }
3.271 @@ -214,9 +231,10 @@
3.272
3.273 ///Postfix incrementation
3.274
3.275 - ///\warning This incrementation
3.276 - ///returns an \c Arc, not an \ref EulerIt, as one may
3.277 - ///expect.
3.278 + /// Postfix incrementation.
3.279 + ///
3.280 + ///\warning This incrementation returns an \c Arc (which converts to
3.281 + ///an \c Edge), not an \ref EulerIt, as one may expect.
3.282 Arc operator++(int)
3.283 {
3.284 Arc e=*this;
3.285 @@ -226,18 +244,23 @@
3.286 };
3.287
3.288
3.289 - ///Checks if the graph is Eulerian
3.290 + ///Check if the given graph is \e Eulerian
3.291
3.292 /// \ingroup graph_properties
3.293 - ///Checks if the graph is Eulerian. It works for both directed and undirected
3.294 - ///graphs.
3.295 - ///\note By definition, a digraph is called \e Eulerian if
3.296 - ///and only if it is connected and the number of its incoming and outgoing
3.297 + ///This function checks if the given graph is \e Eulerian.
3.298 + ///It works for both directed and undirected graphs.
3.299 + ///
3.300 + ///By definition, a digraph is called \e Eulerian if
3.301 + ///and only if it is connected and the number of incoming and outgoing
3.302 ///arcs are the same for each node.
3.303 ///Similarly, an undirected graph is called \e Eulerian if
3.304 - ///and only if it is connected and the number of incident arcs is even
3.305 - ///for each node. <em>Therefore, there are digraphs which are not Eulerian,
3.306 - ///but still have an Euler tour</em>.
3.307 + ///and only if it is connected and the number of incident edges is even
3.308 + ///for each node.
3.309 + ///
3.310 + ///\note There are (di)graphs that are not Eulerian, but still have an
3.311 + /// Euler tour, since they may contain isolated nodes.
3.312 + ///
3.313 + ///\sa DiEulerIt, EulerIt
3.314 template<typename GR>
3.315 #ifdef DOXYGEN
3.316 bool
3.317 @@ -256,7 +279,7 @@
3.318 {
3.319 for(typename GR::NodeIt n(g);n!=INVALID;++n)
3.320 if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
3.321 - return connected(Undirector<const GR>(g));
3.322 + return connected(undirector(g));
3.323 }
3.324
3.325 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/lemon/matching.h Tue Apr 21 13:08:19 2009 +0100
4.3 @@ -0,0 +1,3244 @@
4.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
4.5 + *
4.6 + * This file is a part of LEMON, a generic C++ optimization library.
4.7 + *
4.8 + * Copyright (C) 2003-2009
4.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
4.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
4.11 + *
4.12 + * Permission to use, modify and distribute this software is granted
4.13 + * provided that this copyright notice appears in all copies. For
4.14 + * precise terms see the accompanying LICENSE file.
4.15 + *
4.16 + * This software is provided "AS IS" with no warranty of any kind,
4.17 + * express or implied, and with no claim as to its suitability for any
4.18 + * purpose.
4.19 + *
4.20 + */
4.21 +
4.22 +#ifndef LEMON_MAX_MATCHING_H
4.23 +#define LEMON_MAX_MATCHING_H
4.24 +
4.25 +#include <vector>
4.26 +#include <queue>
4.27 +#include <set>
4.28 +#include <limits>
4.29 +
4.30 +#include <lemon/core.h>
4.31 +#include <lemon/unionfind.h>
4.32 +#include <lemon/bin_heap.h>
4.33 +#include <lemon/maps.h>
4.34 +
4.35 +///\ingroup matching
4.36 +///\file
4.37 +///\brief Maximum matching algorithms in general graphs.
4.38 +
4.39 +namespace lemon {
4.40 +
4.41 + /// \ingroup matching
4.42 + ///
4.43 + /// \brief Maximum cardinality matching in general graphs
4.44 + ///
4.45 + /// This class implements Edmonds' alternating forest matching algorithm
4.46 + /// for finding a maximum cardinality matching in a general undirected graph.
4.47 + /// It can be started from an arbitrary initial matching
4.48 + /// (the default is the empty one).
4.49 + ///
4.50 + /// The dual solution of the problem is a map of the nodes to
4.51 + /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
4.52 + /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
4.53 + /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
4.54 + /// with factor-critical components, the nodes in \c ODD/A form the
4.55 + /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
4.56 + /// a perfect matching. The number of the factor-critical components
4.57 + /// minus the number of barrier nodes is a lower bound on the
4.58 + /// unmatched nodes, and the matching is optimal if and only if this bound is
4.59 + /// tight. This decomposition can be obtained using \ref status() or
4.60 + /// \ref statusMap() after running the algorithm.
4.61 + ///
4.62 + /// \tparam GR The undirected graph type the algorithm runs on.
4.63 + template <typename GR>
4.64 + class MaxMatching {
4.65 + public:
4.66 +
4.67 + /// The graph type of the algorithm
4.68 + typedef GR Graph;
4.69 + /// The type of the matching map
4.70 + typedef typename Graph::template NodeMap<typename Graph::Arc>
4.71 + MatchingMap;
4.72 +
4.73 + ///\brief Status constants for Gallai-Edmonds decomposition.
4.74 + ///
4.75 + ///These constants are used for indicating the Gallai-Edmonds
4.76 + ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
4.77 + ///induce a subgraph with factor-critical components, the nodes with
4.78 + ///status \c ODD (or \c A) form the canonical barrier, and the nodes
4.79 + ///with status \c MATCHED (or \c C) induce a subgraph having a
4.80 + ///perfect matching.
4.81 + enum Status {
4.82 + EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.)
4.83 + D = 1,
4.84 + MATCHED = 0, ///< = 0. (\c C is an alias for \c MATCHED.)
4.85 + C = 0,
4.86 + ODD = -1, ///< = -1. (\c A is an alias for \c ODD.)
4.87 + A = -1,
4.88 + UNMATCHED = -2 ///< = -2.
4.89 + };
4.90 +
4.91 + /// The type of the status map
4.92 + typedef typename Graph::template NodeMap<Status> StatusMap;
4.93 +
4.94 + private:
4.95 +
4.96 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
4.97 +
4.98 + typedef UnionFindEnum<IntNodeMap> BlossomSet;
4.99 + typedef ExtendFindEnum<IntNodeMap> TreeSet;
4.100 + typedef RangeMap<Node> NodeIntMap;
4.101 + typedef MatchingMap EarMap;
4.102 + typedef std::vector<Node> NodeQueue;
4.103 +
4.104 + const Graph& _graph;
4.105 + MatchingMap* _matching;
4.106 + StatusMap* _status;
4.107 +
4.108 + EarMap* _ear;
4.109 +
4.110 + IntNodeMap* _blossom_set_index;
4.111 + BlossomSet* _blossom_set;
4.112 + NodeIntMap* _blossom_rep;
4.113 +
4.114 + IntNodeMap* _tree_set_index;
4.115 + TreeSet* _tree_set;
4.116 +
4.117 + NodeQueue _node_queue;
4.118 + int _process, _postpone, _last;
4.119 +
4.120 + int _node_num;
4.121 +
4.122 + private:
4.123 +
4.124 + void createStructures() {
4.125 + _node_num = countNodes(_graph);
4.126 + if (!_matching) {
4.127 + _matching = new MatchingMap(_graph);
4.128 + }
4.129 + if (!_status) {
4.130 + _status = new StatusMap(_graph);
4.131 + }
4.132 + if (!_ear) {
4.133 + _ear = new EarMap(_graph);
4.134 + }
4.135 + if (!_blossom_set) {
4.136 + _blossom_set_index = new IntNodeMap(_graph);
4.137 + _blossom_set = new BlossomSet(*_blossom_set_index);
4.138 + }
4.139 + if (!_blossom_rep) {
4.140 + _blossom_rep = new NodeIntMap(_node_num);
4.141 + }
4.142 + if (!_tree_set) {
4.143 + _tree_set_index = new IntNodeMap(_graph);
4.144 + _tree_set = new TreeSet(*_tree_set_index);
4.145 + }
4.146 + _node_queue.resize(_node_num);
4.147 + }
4.148 +
4.149 + void destroyStructures() {
4.150 + if (_matching) {
4.151 + delete _matching;
4.152 + }
4.153 + if (_status) {
4.154 + delete _status;
4.155 + }
4.156 + if (_ear) {
4.157 + delete _ear;
4.158 + }
4.159 + if (_blossom_set) {
4.160 + delete _blossom_set;
4.161 + delete _blossom_set_index;
4.162 + }
4.163 + if (_blossom_rep) {
4.164 + delete _blossom_rep;
4.165 + }
4.166 + if (_tree_set) {
4.167 + delete _tree_set_index;
4.168 + delete _tree_set;
4.169 + }
4.170 + }
4.171 +
4.172 + void processDense(const Node& n) {
4.173 + _process = _postpone = _last = 0;
4.174 + _node_queue[_last++] = n;
4.175 +
4.176 + while (_process != _last) {
4.177 + Node u = _node_queue[_process++];
4.178 + for (OutArcIt a(_graph, u); a != INVALID; ++a) {
4.179 + Node v = _graph.target(a);
4.180 + if ((*_status)[v] == MATCHED) {
4.181 + extendOnArc(a);
4.182 + } else if ((*_status)[v] == UNMATCHED) {
4.183 + augmentOnArc(a);
4.184 + return;
4.185 + }
4.186 + }
4.187 + }
4.188 +
4.189 + while (_postpone != _last) {
4.190 + Node u = _node_queue[_postpone++];
4.191 +
4.192 + for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
4.193 + Node v = _graph.target(a);
4.194 +
4.195 + if ((*_status)[v] == EVEN) {
4.196 + if (_blossom_set->find(u) != _blossom_set->find(v)) {
4.197 + shrinkOnEdge(a);
4.198 + }
4.199 + }
4.200 +
4.201 + while (_process != _last) {
4.202 + Node w = _node_queue[_process++];
4.203 + for (OutArcIt b(_graph, w); b != INVALID; ++b) {
4.204 + Node x = _graph.target(b);
4.205 + if ((*_status)[x] == MATCHED) {
4.206 + extendOnArc(b);
4.207 + } else if ((*_status)[x] == UNMATCHED) {
4.208 + augmentOnArc(b);
4.209 + return;
4.210 + }
4.211 + }
4.212 + }
4.213 + }
4.214 + }
4.215 + }
4.216 +
4.217 + void processSparse(const Node& n) {
4.218 + _process = _last = 0;
4.219 + _node_queue[_last++] = n;
4.220 + while (_process != _last) {
4.221 + Node u = _node_queue[_process++];
4.222 + for (OutArcIt a(_graph, u); a != INVALID; ++a) {
4.223 + Node v = _graph.target(a);
4.224 +
4.225 + if ((*_status)[v] == EVEN) {
4.226 + if (_blossom_set->find(u) != _blossom_set->find(v)) {
4.227 + shrinkOnEdge(a);
4.228 + }
4.229 + } else if ((*_status)[v] == MATCHED) {
4.230 + extendOnArc(a);
4.231 + } else if ((*_status)[v] == UNMATCHED) {
4.232 + augmentOnArc(a);
4.233 + return;
4.234 + }
4.235 + }
4.236 + }
4.237 + }
4.238 +
4.239 + void shrinkOnEdge(const Edge& e) {
4.240 + Node nca = INVALID;
4.241 +
4.242 + {
4.243 + std::set<Node> left_set, right_set;
4.244 +
4.245 + Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
4.246 + left_set.insert(left);
4.247 +
4.248 + Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
4.249 + right_set.insert(right);
4.250 +
4.251 + while (true) {
4.252 + if ((*_matching)[left] == INVALID) break;
4.253 + left = _graph.target((*_matching)[left]);
4.254 + left = (*_blossom_rep)[_blossom_set->
4.255 + find(_graph.target((*_ear)[left]))];
4.256 + if (right_set.find(left) != right_set.end()) {
4.257 + nca = left;
4.258 + break;
4.259 + }
4.260 + left_set.insert(left);
4.261 +
4.262 + if ((*_matching)[right] == INVALID) break;
4.263 + right = _graph.target((*_matching)[right]);
4.264 + right = (*_blossom_rep)[_blossom_set->
4.265 + find(_graph.target((*_ear)[right]))];
4.266 + if (left_set.find(right) != left_set.end()) {
4.267 + nca = right;
4.268 + break;
4.269 + }
4.270 + right_set.insert(right);
4.271 + }
4.272 +
4.273 + if (nca == INVALID) {
4.274 + if ((*_matching)[left] == INVALID) {
4.275 + nca = right;
4.276 + while (left_set.find(nca) == left_set.end()) {
4.277 + nca = _graph.target((*_matching)[nca]);
4.278 + nca =(*_blossom_rep)[_blossom_set->
4.279 + find(_graph.target((*_ear)[nca]))];
4.280 + }
4.281 + } else {
4.282 + nca = left;
4.283 + while (right_set.find(nca) == right_set.end()) {
4.284 + nca = _graph.target((*_matching)[nca]);
4.285 + nca = (*_blossom_rep)[_blossom_set->
4.286 + find(_graph.target((*_ear)[nca]))];
4.287 + }
4.288 + }
4.289 + }
4.290 + }
4.291 +
4.292 + {
4.293 +
4.294 + Node node = _graph.u(e);
4.295 + Arc arc = _graph.direct(e, true);
4.296 + Node base = (*_blossom_rep)[_blossom_set->find(node)];
4.297 +
4.298 + while (base != nca) {
4.299 + (*_ear)[node] = arc;
4.300 +
4.301 + Node n = node;
4.302 + while (n != base) {
4.303 + n = _graph.target((*_matching)[n]);
4.304 + Arc a = (*_ear)[n];
4.305 + n = _graph.target(a);
4.306 + (*_ear)[n] = _graph.oppositeArc(a);
4.307 + }
4.308 + node = _graph.target((*_matching)[base]);
4.309 + _tree_set->erase(base);
4.310 + _tree_set->erase(node);
4.311 + _blossom_set->insert(node, _blossom_set->find(base));
4.312 + (*_status)[node] = EVEN;
4.313 + _node_queue[_last++] = node;
4.314 + arc = _graph.oppositeArc((*_ear)[node]);
4.315 + node = _graph.target((*_ear)[node]);
4.316 + base = (*_blossom_rep)[_blossom_set->find(node)];
4.317 + _blossom_set->join(_graph.target(arc), base);
4.318 + }
4.319 + }
4.320 +
4.321 + (*_blossom_rep)[_blossom_set->find(nca)] = nca;
4.322 +
4.323 + {
4.324 +
4.325 + Node node = _graph.v(e);
4.326 + Arc arc = _graph.direct(e, false);
4.327 + Node base = (*_blossom_rep)[_blossom_set->find(node)];
4.328 +
4.329 + while (base != nca) {
4.330 + (*_ear)[node] = arc;
4.331 +
4.332 + Node n = node;
4.333 + while (n != base) {
4.334 + n = _graph.target((*_matching)[n]);
4.335 + Arc a = (*_ear)[n];
4.336 + n = _graph.target(a);
4.337 + (*_ear)[n] = _graph.oppositeArc(a);
4.338 + }
4.339 + node = _graph.target((*_matching)[base]);
4.340 + _tree_set->erase(base);
4.341 + _tree_set->erase(node);
4.342 + _blossom_set->insert(node, _blossom_set->find(base));
4.343 + (*_status)[node] = EVEN;
4.344 + _node_queue[_last++] = node;
4.345 + arc = _graph.oppositeArc((*_ear)[node]);
4.346 + node = _graph.target((*_ear)[node]);
4.347 + base = (*_blossom_rep)[_blossom_set->find(node)];
4.348 + _blossom_set->join(_graph.target(arc), base);
4.349 + }
4.350 + }
4.351 +
4.352 + (*_blossom_rep)[_blossom_set->find(nca)] = nca;
4.353 + }
4.354 +
4.355 + void extendOnArc(const Arc& a) {
4.356 + Node base = _graph.source(a);
4.357 + Node odd = _graph.target(a);
4.358 +
4.359 + (*_ear)[odd] = _graph.oppositeArc(a);
4.360 + Node even = _graph.target((*_matching)[odd]);
4.361 + (*_blossom_rep)[_blossom_set->insert(even)] = even;
4.362 + (*_status)[odd] = ODD;
4.363 + (*_status)[even] = EVEN;
4.364 + int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
4.365 + _tree_set->insert(odd, tree);
4.366 + _tree_set->insert(even, tree);
4.367 + _node_queue[_last++] = even;
4.368 +
4.369 + }
4.370 +
4.371 + void augmentOnArc(const Arc& a) {
4.372 + Node even = _graph.source(a);
4.373 + Node odd = _graph.target(a);
4.374 +
4.375 + int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
4.376 +
4.377 + (*_matching)[odd] = _graph.oppositeArc(a);
4.378 + (*_status)[odd] = MATCHED;
4.379 +
4.380 + Arc arc = (*_matching)[even];
4.381 + (*_matching)[even] = a;
4.382 +
4.383 + while (arc != INVALID) {
4.384 + odd = _graph.target(arc);
4.385 + arc = (*_ear)[odd];
4.386 + even = _graph.target(arc);
4.387 + (*_matching)[odd] = arc;
4.388 + arc = (*_matching)[even];
4.389 + (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
4.390 + }
4.391 +
4.392 + for (typename TreeSet::ItemIt it(*_tree_set, tree);
4.393 + it != INVALID; ++it) {
4.394 + if ((*_status)[it] == ODD) {
4.395 + (*_status)[it] = MATCHED;
4.396 + } else {
4.397 + int blossom = _blossom_set->find(it);
4.398 + for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
4.399 + jt != INVALID; ++jt) {
4.400 + (*_status)[jt] = MATCHED;
4.401 + }
4.402 + _blossom_set->eraseClass(blossom);
4.403 + }
4.404 + }
4.405 + _tree_set->eraseClass(tree);
4.406 +
4.407 + }
4.408 +
4.409 + public:
4.410 +
4.411 + /// \brief Constructor
4.412 + ///
4.413 + /// Constructor.
4.414 + MaxMatching(const Graph& graph)
4.415 + : _graph(graph), _matching(0), _status(0), _ear(0),
4.416 + _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
4.417 + _tree_set_index(0), _tree_set(0) {}
4.418 +
4.419 + ~MaxMatching() {
4.420 + destroyStructures();
4.421 + }
4.422 +
4.423 + /// \name Execution Control
4.424 + /// The simplest way to execute the algorithm is to use the
4.425 + /// \c run() member function.\n
4.426 + /// If you need better control on the execution, you have to call
4.427 + /// one of the functions \ref init(), \ref greedyInit() or
4.428 + /// \ref matchingInit() first, then you can start the algorithm with
4.429 + /// \ref startSparse() or \ref startDense().
4.430 +
4.431 + ///@{
4.432 +
4.433 + /// \brief Set the initial matching to the empty matching.
4.434 + ///
4.435 + /// This function sets the initial matching to the empty matching.
4.436 + void init() {
4.437 + createStructures();
4.438 + for(NodeIt n(_graph); n != INVALID; ++n) {
4.439 + (*_matching)[n] = INVALID;
4.440 + (*_status)[n] = UNMATCHED;
4.441 + }
4.442 + }
4.443 +
4.444 + /// \brief Find an initial matching in a greedy way.
4.445 + ///
4.446 + /// This function finds an initial matching in a greedy way.
4.447 + void greedyInit() {
4.448 + createStructures();
4.449 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.450 + (*_matching)[n] = INVALID;
4.451 + (*_status)[n] = UNMATCHED;
4.452 + }
4.453 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.454 + if ((*_matching)[n] == INVALID) {
4.455 + for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
4.456 + Node v = _graph.target(a);
4.457 + if ((*_matching)[v] == INVALID && v != n) {
4.458 + (*_matching)[n] = a;
4.459 + (*_status)[n] = MATCHED;
4.460 + (*_matching)[v] = _graph.oppositeArc(a);
4.461 + (*_status)[v] = MATCHED;
4.462 + break;
4.463 + }
4.464 + }
4.465 + }
4.466 + }
4.467 + }
4.468 +
4.469 +
4.470 + /// \brief Initialize the matching from a map.
4.471 + ///
4.472 + /// This function initializes the matching from a \c bool valued edge
4.473 + /// map. This map should have the property that there are no two incident
4.474 + /// edges with \c true value, i.e. it really contains a matching.
4.475 + /// \return \c true if the map contains a matching.
4.476 + template <typename MatchingMap>
4.477 + bool matchingInit(const MatchingMap& matching) {
4.478 + createStructures();
4.479 +
4.480 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.481 + (*_matching)[n] = INVALID;
4.482 + (*_status)[n] = UNMATCHED;
4.483 + }
4.484 + for(EdgeIt e(_graph); e!=INVALID; ++e) {
4.485 + if (matching[e]) {
4.486 +
4.487 + Node u = _graph.u(e);
4.488 + if ((*_matching)[u] != INVALID) return false;
4.489 + (*_matching)[u] = _graph.direct(e, true);
4.490 + (*_status)[u] = MATCHED;
4.491 +
4.492 + Node v = _graph.v(e);
4.493 + if ((*_matching)[v] != INVALID) return false;
4.494 + (*_matching)[v] = _graph.direct(e, false);
4.495 + (*_status)[v] = MATCHED;
4.496 + }
4.497 + }
4.498 + return true;
4.499 + }
4.500 +
4.501 + /// \brief Start Edmonds' algorithm
4.502 + ///
4.503 + /// This function runs the original Edmonds' algorithm.
4.504 + ///
4.505 + /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
4.506 + /// called before using this function.
4.507 + void startSparse() {
4.508 + for(NodeIt n(_graph); n != INVALID; ++n) {
4.509 + if ((*_status)[n] == UNMATCHED) {
4.510 + (*_blossom_rep)[_blossom_set->insert(n)] = n;
4.511 + _tree_set->insert(n);
4.512 + (*_status)[n] = EVEN;
4.513 + processSparse(n);
4.514 + }
4.515 + }
4.516 + }
4.517 +
4.518 + /// \brief Start Edmonds' algorithm with a heuristic improvement
4.519 + /// for dense graphs
4.520 + ///
4.521 + /// This function runs Edmonds' algorithm with a heuristic of postponing
4.522 + /// shrinks, therefore resulting in a faster algorithm for dense graphs.
4.523 + ///
4.524 + /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
4.525 + /// called before using this function.
4.526 + void startDense() {
4.527 + for(NodeIt n(_graph); n != INVALID; ++n) {
4.528 + if ((*_status)[n] == UNMATCHED) {
4.529 + (*_blossom_rep)[_blossom_set->insert(n)] = n;
4.530 + _tree_set->insert(n);
4.531 + (*_status)[n] = EVEN;
4.532 + processDense(n);
4.533 + }
4.534 + }
4.535 + }
4.536 +
4.537 +
4.538 + /// \brief Run Edmonds' algorithm
4.539 + ///
4.540 + /// This function runs Edmonds' algorithm. An additional heuristic of
4.541 + /// postponing shrinks is used for relatively dense graphs
4.542 + /// (for which <tt>m>=2*n</tt> holds).
4.543 + void run() {
4.544 + if (countEdges(_graph) < 2 * countNodes(_graph)) {
4.545 + greedyInit();
4.546 + startSparse();
4.547 + } else {
4.548 + init();
4.549 + startDense();
4.550 + }
4.551 + }
4.552 +
4.553 + /// @}
4.554 +
4.555 + /// \name Primal Solution
4.556 + /// Functions to get the primal solution, i.e. the maximum matching.
4.557 +
4.558 + /// @{
4.559 +
4.560 + /// \brief Return the size (cardinality) of the matching.
4.561 + ///
4.562 + /// This function returns the size (cardinality) of the current matching.
4.563 + /// After run() it returns the size of the maximum matching in the graph.
4.564 + int matchingSize() const {
4.565 + int size = 0;
4.566 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.567 + if ((*_matching)[n] != INVALID) {
4.568 + ++size;
4.569 + }
4.570 + }
4.571 + return size / 2;
4.572 + }
4.573 +
4.574 + /// \brief Return \c true if the given edge is in the matching.
4.575 + ///
4.576 + /// This function returns \c true if the given edge is in the current
4.577 + /// matching.
4.578 + bool matching(const Edge& edge) const {
4.579 + return edge == (*_matching)[_graph.u(edge)];
4.580 + }
4.581 +
4.582 + /// \brief Return the matching arc (or edge) incident to the given node.
4.583 + ///
4.584 + /// This function returns the matching arc (or edge) incident to the
4.585 + /// given node in the current matching or \c INVALID if the node is
4.586 + /// not covered by the matching.
4.587 + Arc matching(const Node& n) const {
4.588 + return (*_matching)[n];
4.589 + }
4.590 +
4.591 + /// \brief Return a const reference to the matching map.
4.592 + ///
4.593 + /// This function returns a const reference to a node map that stores
4.594 + /// the matching arc (or edge) incident to each node.
4.595 + const MatchingMap& matchingMap() const {
4.596 + return *_matching;
4.597 + }
4.598 +
4.599 + /// \brief Return the mate of the given node.
4.600 + ///
4.601 + /// This function returns the mate of the given node in the current
4.602 + /// matching or \c INVALID if the node is not covered by the matching.
4.603 + Node mate(const Node& n) const {
4.604 + return (*_matching)[n] != INVALID ?
4.605 + _graph.target((*_matching)[n]) : INVALID;
4.606 + }
4.607 +
4.608 + /// @}
4.609 +
4.610 + /// \name Dual Solution
4.611 + /// Functions to get the dual solution, i.e. the Gallai-Edmonds
4.612 + /// decomposition.
4.613 +
4.614 + /// @{
4.615 +
4.616 + /// \brief Return the status of the given node in the Edmonds-Gallai
4.617 + /// decomposition.
4.618 + ///
4.619 + /// This function returns the \ref Status "status" of the given node
4.620 + /// in the Edmonds-Gallai decomposition.
4.621 + Status status(const Node& n) const {
4.622 + return (*_status)[n];
4.623 + }
4.624 +
4.625 + /// \brief Return a const reference to the status map, which stores
4.626 + /// the Edmonds-Gallai decomposition.
4.627 + ///
4.628 + /// This function returns a const reference to a node map that stores the
4.629 + /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
4.630 + const StatusMap& statusMap() const {
4.631 + return *_status;
4.632 + }
4.633 +
4.634 + /// \brief Return \c true if the given node is in the barrier.
4.635 + ///
4.636 + /// This function returns \c true if the given node is in the barrier.
4.637 + bool barrier(const Node& n) const {
4.638 + return (*_status)[n] == ODD;
4.639 + }
4.640 +
4.641 + /// @}
4.642 +
4.643 + };
4.644 +
4.645 + /// \ingroup matching
4.646 + ///
4.647 + /// \brief Weighted matching in general graphs
4.648 + ///
4.649 + /// This class provides an efficient implementation of Edmond's
4.650 + /// maximum weighted matching algorithm. The implementation is based
4.651 + /// on extensive use of priority queues and provides
4.652 + /// \f$O(nm\log n)\f$ time complexity.
4.653 + ///
4.654 + /// The maximum weighted matching problem is to find a subset of the
4.655 + /// edges in an undirected graph with maximum overall weight for which
4.656 + /// each node has at most one incident edge.
4.657 + /// It can be formulated with the following linear program.
4.658 + /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
4.659 + /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
4.660 + \quad \forall B\in\mathcal{O}\f] */
4.661 + /// \f[x_e \ge 0\quad \forall e\in E\f]
4.662 + /// \f[\max \sum_{e\in E}x_ew_e\f]
4.663 + /// where \f$\delta(X)\f$ is the set of edges incident to a node in
4.664 + /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
4.665 + /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
4.666 + /// subsets of the nodes.
4.667 + ///
4.668 + /// The algorithm calculates an optimal matching and a proof of the
4.669 + /// optimality. The solution of the dual problem can be used to check
4.670 + /// the result of the algorithm. The dual linear problem is the
4.671 + /// following.
4.672 + /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
4.673 + z_B \ge w_{uv} \quad \forall uv\in E\f] */
4.674 + /// \f[y_u \ge 0 \quad \forall u \in V\f]
4.675 + /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
4.676 + /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
4.677 + \frac{\vert B \vert - 1}{2}z_B\f] */
4.678 + ///
4.679 + /// The algorithm can be executed with the run() function.
4.680 + /// After it the matching (the primal solution) and the dual solution
4.681 + /// can be obtained using the query functions and the
4.682 + /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
4.683 + /// which is able to iterate on the nodes of a blossom.
4.684 + /// If the value type is integer, then the dual solution is multiplied
4.685 + /// by \ref MaxWeightedMatching::dualScale "4".
4.686 + ///
4.687 + /// \tparam GR The undirected graph type the algorithm runs on.
4.688 + /// \tparam WM The type edge weight map. The default type is
4.689 + /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
4.690 +#ifdef DOXYGEN
4.691 + template <typename GR, typename WM>
4.692 +#else
4.693 + template <typename GR,
4.694 + typename WM = typename GR::template EdgeMap<int> >
4.695 +#endif
4.696 + class MaxWeightedMatching {
4.697 + public:
4.698 +
4.699 + /// The graph type of the algorithm
4.700 + typedef GR Graph;
4.701 + /// The type of the edge weight map
4.702 + typedef WM WeightMap;
4.703 + /// The value type of the edge weights
4.704 + typedef typename WeightMap::Value Value;
4.705 +
4.706 + /// The type of the matching map
4.707 + typedef typename Graph::template NodeMap<typename Graph::Arc>
4.708 + MatchingMap;
4.709 +
4.710 + /// \brief Scaling factor for dual solution
4.711 + ///
4.712 + /// Scaling factor for dual solution. It is equal to 4 or 1
4.713 + /// according to the value type.
4.714 + static const int dualScale =
4.715 + std::numeric_limits<Value>::is_integer ? 4 : 1;
4.716 +
4.717 + private:
4.718 +
4.719 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
4.720 +
4.721 + typedef typename Graph::template NodeMap<Value> NodePotential;
4.722 + typedef std::vector<Node> BlossomNodeList;
4.723 +
4.724 + struct BlossomVariable {
4.725 + int begin, end;
4.726 + Value value;
4.727 +
4.728 + BlossomVariable(int _begin, int _end, Value _value)
4.729 + : begin(_begin), end(_end), value(_value) {}
4.730 +
4.731 + };
4.732 +
4.733 + typedef std::vector<BlossomVariable> BlossomPotential;
4.734 +
4.735 + const Graph& _graph;
4.736 + const WeightMap& _weight;
4.737 +
4.738 + MatchingMap* _matching;
4.739 +
4.740 + NodePotential* _node_potential;
4.741 +
4.742 + BlossomPotential _blossom_potential;
4.743 + BlossomNodeList _blossom_node_list;
4.744 +
4.745 + int _node_num;
4.746 + int _blossom_num;
4.747 +
4.748 + typedef RangeMap<int> IntIntMap;
4.749 +
4.750 + enum Status {
4.751 + EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
4.752 + };
4.753 +
4.754 + typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
4.755 + struct BlossomData {
4.756 + int tree;
4.757 + Status status;
4.758 + Arc pred, next;
4.759 + Value pot, offset;
4.760 + Node base;
4.761 + };
4.762 +
4.763 + IntNodeMap *_blossom_index;
4.764 + BlossomSet *_blossom_set;
4.765 + RangeMap<BlossomData>* _blossom_data;
4.766 +
4.767 + IntNodeMap *_node_index;
4.768 + IntArcMap *_node_heap_index;
4.769 +
4.770 + struct NodeData {
4.771 +
4.772 + NodeData(IntArcMap& node_heap_index)
4.773 + : heap(node_heap_index) {}
4.774 +
4.775 + int blossom;
4.776 + Value pot;
4.777 + BinHeap<Value, IntArcMap> heap;
4.778 + std::map<int, Arc> heap_index;
4.779 +
4.780 + int tree;
4.781 + };
4.782 +
4.783 + RangeMap<NodeData>* _node_data;
4.784 +
4.785 + typedef ExtendFindEnum<IntIntMap> TreeSet;
4.786 +
4.787 + IntIntMap *_tree_set_index;
4.788 + TreeSet *_tree_set;
4.789 +
4.790 + IntNodeMap *_delta1_index;
4.791 + BinHeap<Value, IntNodeMap> *_delta1;
4.792 +
4.793 + IntIntMap *_delta2_index;
4.794 + BinHeap<Value, IntIntMap> *_delta2;
4.795 +
4.796 + IntEdgeMap *_delta3_index;
4.797 + BinHeap<Value, IntEdgeMap> *_delta3;
4.798 +
4.799 + IntIntMap *_delta4_index;
4.800 + BinHeap<Value, IntIntMap> *_delta4;
4.801 +
4.802 + Value _delta_sum;
4.803 +
4.804 + void createStructures() {
4.805 + _node_num = countNodes(_graph);
4.806 + _blossom_num = _node_num * 3 / 2;
4.807 +
4.808 + if (!_matching) {
4.809 + _matching = new MatchingMap(_graph);
4.810 + }
4.811 + if (!_node_potential) {
4.812 + _node_potential = new NodePotential(_graph);
4.813 + }
4.814 + if (!_blossom_set) {
4.815 + _blossom_index = new IntNodeMap(_graph);
4.816 + _blossom_set = new BlossomSet(*_blossom_index);
4.817 + _blossom_data = new RangeMap<BlossomData>(_blossom_num);
4.818 + }
4.819 +
4.820 + if (!_node_index) {
4.821 + _node_index = new IntNodeMap(_graph);
4.822 + _node_heap_index = new IntArcMap(_graph);
4.823 + _node_data = new RangeMap<NodeData>(_node_num,
4.824 + NodeData(*_node_heap_index));
4.825 + }
4.826 +
4.827 + if (!_tree_set) {
4.828 + _tree_set_index = new IntIntMap(_blossom_num);
4.829 + _tree_set = new TreeSet(*_tree_set_index);
4.830 + }
4.831 + if (!_delta1) {
4.832 + _delta1_index = new IntNodeMap(_graph);
4.833 + _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
4.834 + }
4.835 + if (!_delta2) {
4.836 + _delta2_index = new IntIntMap(_blossom_num);
4.837 + _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
4.838 + }
4.839 + if (!_delta3) {
4.840 + _delta3_index = new IntEdgeMap(_graph);
4.841 + _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
4.842 + }
4.843 + if (!_delta4) {
4.844 + _delta4_index = new IntIntMap(_blossom_num);
4.845 + _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
4.846 + }
4.847 + }
4.848 +
4.849 + void destroyStructures() {
4.850 + _node_num = countNodes(_graph);
4.851 + _blossom_num = _node_num * 3 / 2;
4.852 +
4.853 + if (_matching) {
4.854 + delete _matching;
4.855 + }
4.856 + if (_node_potential) {
4.857 + delete _node_potential;
4.858 + }
4.859 + if (_blossom_set) {
4.860 + delete _blossom_index;
4.861 + delete _blossom_set;
4.862 + delete _blossom_data;
4.863 + }
4.864 +
4.865 + if (_node_index) {
4.866 + delete _node_index;
4.867 + delete _node_heap_index;
4.868 + delete _node_data;
4.869 + }
4.870 +
4.871 + if (_tree_set) {
4.872 + delete _tree_set_index;
4.873 + delete _tree_set;
4.874 + }
4.875 + if (_delta1) {
4.876 + delete _delta1_index;
4.877 + delete _delta1;
4.878 + }
4.879 + if (_delta2) {
4.880 + delete _delta2_index;
4.881 + delete _delta2;
4.882 + }
4.883 + if (_delta3) {
4.884 + delete _delta3_index;
4.885 + delete _delta3;
4.886 + }
4.887 + if (_delta4) {
4.888 + delete _delta4_index;
4.889 + delete _delta4;
4.890 + }
4.891 + }
4.892 +
4.893 + void matchedToEven(int blossom, int tree) {
4.894 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
4.895 + _delta2->erase(blossom);
4.896 + }
4.897 +
4.898 + if (!_blossom_set->trivial(blossom)) {
4.899 + (*_blossom_data)[blossom].pot -=
4.900 + 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
4.901 + }
4.902 +
4.903 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.904 + n != INVALID; ++n) {
4.905 +
4.906 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
4.907 + int ni = (*_node_index)[n];
4.908 +
4.909 + (*_node_data)[ni].heap.clear();
4.910 + (*_node_data)[ni].heap_index.clear();
4.911 +
4.912 + (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
4.913 +
4.914 + _delta1->push(n, (*_node_data)[ni].pot);
4.915 +
4.916 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
4.917 + Node v = _graph.source(e);
4.918 + int vb = _blossom_set->find(v);
4.919 + int vi = (*_node_index)[v];
4.920 +
4.921 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.922 + dualScale * _weight[e];
4.923 +
4.924 + if ((*_blossom_data)[vb].status == EVEN) {
4.925 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
4.926 + _delta3->push(e, rw / 2);
4.927 + }
4.928 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
4.929 + if (_delta3->state(e) != _delta3->IN_HEAP) {
4.930 + _delta3->push(e, rw);
4.931 + }
4.932 + } else {
4.933 + typename std::map<int, Arc>::iterator it =
4.934 + (*_node_data)[vi].heap_index.find(tree);
4.935 +
4.936 + if (it != (*_node_data)[vi].heap_index.end()) {
4.937 + if ((*_node_data)[vi].heap[it->second] > rw) {
4.938 + (*_node_data)[vi].heap.replace(it->second, e);
4.939 + (*_node_data)[vi].heap.decrease(e, rw);
4.940 + it->second = e;
4.941 + }
4.942 + } else {
4.943 + (*_node_data)[vi].heap.push(e, rw);
4.944 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
4.945 + }
4.946 +
4.947 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
4.948 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
4.949 +
4.950 + if ((*_blossom_data)[vb].status == MATCHED) {
4.951 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
4.952 + _delta2->push(vb, _blossom_set->classPrio(vb) -
4.953 + (*_blossom_data)[vb].offset);
4.954 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
4.955 + (*_blossom_data)[vb].offset){
4.956 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
4.957 + (*_blossom_data)[vb].offset);
4.958 + }
4.959 + }
4.960 + }
4.961 + }
4.962 + }
4.963 + }
4.964 + (*_blossom_data)[blossom].offset = 0;
4.965 + }
4.966 +
4.967 + void matchedToOdd(int blossom) {
4.968 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
4.969 + _delta2->erase(blossom);
4.970 + }
4.971 + (*_blossom_data)[blossom].offset += _delta_sum;
4.972 + if (!_blossom_set->trivial(blossom)) {
4.973 + _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
4.974 + (*_blossom_data)[blossom].offset);
4.975 + }
4.976 + }
4.977 +
4.978 + void evenToMatched(int blossom, int tree) {
4.979 + if (!_blossom_set->trivial(blossom)) {
4.980 + (*_blossom_data)[blossom].pot += 2 * _delta_sum;
4.981 + }
4.982 +
4.983 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.984 + n != INVALID; ++n) {
4.985 + int ni = (*_node_index)[n];
4.986 + (*_node_data)[ni].pot -= _delta_sum;
4.987 +
4.988 + _delta1->erase(n);
4.989 +
4.990 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
4.991 + Node v = _graph.source(e);
4.992 + int vb = _blossom_set->find(v);
4.993 + int vi = (*_node_index)[v];
4.994 +
4.995 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.996 + dualScale * _weight[e];
4.997 +
4.998 + if (vb == blossom) {
4.999 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.1000 + _delta3->erase(e);
4.1001 + }
4.1002 + } else if ((*_blossom_data)[vb].status == EVEN) {
4.1003 +
4.1004 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.1005 + _delta3->erase(e);
4.1006 + }
4.1007 +
4.1008 + int vt = _tree_set->find(vb);
4.1009 +
4.1010 + if (vt != tree) {
4.1011 +
4.1012 + Arc r = _graph.oppositeArc(e);
4.1013 +
4.1014 + typename std::map<int, Arc>::iterator it =
4.1015 + (*_node_data)[ni].heap_index.find(vt);
4.1016 +
4.1017 + if (it != (*_node_data)[ni].heap_index.end()) {
4.1018 + if ((*_node_data)[ni].heap[it->second] > rw) {
4.1019 + (*_node_data)[ni].heap.replace(it->second, r);
4.1020 + (*_node_data)[ni].heap.decrease(r, rw);
4.1021 + it->second = r;
4.1022 + }
4.1023 + } else {
4.1024 + (*_node_data)[ni].heap.push(r, rw);
4.1025 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
4.1026 + }
4.1027 +
4.1028 + if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
4.1029 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
4.1030 +
4.1031 + if (_delta2->state(blossom) != _delta2->IN_HEAP) {
4.1032 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
4.1033 + (*_blossom_data)[blossom].offset);
4.1034 + } else if ((*_delta2)[blossom] >
4.1035 + _blossom_set->classPrio(blossom) -
4.1036 + (*_blossom_data)[blossom].offset){
4.1037 + _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
4.1038 + (*_blossom_data)[blossom].offset);
4.1039 + }
4.1040 + }
4.1041 + }
4.1042 +
4.1043 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
4.1044 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.1045 + _delta3->erase(e);
4.1046 + }
4.1047 + } else {
4.1048 +
4.1049 + typename std::map<int, Arc>::iterator it =
4.1050 + (*_node_data)[vi].heap_index.find(tree);
4.1051 +
4.1052 + if (it != (*_node_data)[vi].heap_index.end()) {
4.1053 + (*_node_data)[vi].heap.erase(it->second);
4.1054 + (*_node_data)[vi].heap_index.erase(it);
4.1055 + if ((*_node_data)[vi].heap.empty()) {
4.1056 + _blossom_set->increase(v, std::numeric_limits<Value>::max());
4.1057 + } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
4.1058 + _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
4.1059 + }
4.1060 +
4.1061 + if ((*_blossom_data)[vb].status == MATCHED) {
4.1062 + if (_blossom_set->classPrio(vb) ==
4.1063 + std::numeric_limits<Value>::max()) {
4.1064 + _delta2->erase(vb);
4.1065 + } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
4.1066 + (*_blossom_data)[vb].offset) {
4.1067 + _delta2->increase(vb, _blossom_set->classPrio(vb) -
4.1068 + (*_blossom_data)[vb].offset);
4.1069 + }
4.1070 + }
4.1071 + }
4.1072 + }
4.1073 + }
4.1074 + }
4.1075 + }
4.1076 +
4.1077 + void oddToMatched(int blossom) {
4.1078 + (*_blossom_data)[blossom].offset -= _delta_sum;
4.1079 +
4.1080 + if (_blossom_set->classPrio(blossom) !=
4.1081 + std::numeric_limits<Value>::max()) {
4.1082 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
4.1083 + (*_blossom_data)[blossom].offset);
4.1084 + }
4.1085 +
4.1086 + if (!_blossom_set->trivial(blossom)) {
4.1087 + _delta4->erase(blossom);
4.1088 + }
4.1089 + }
4.1090 +
4.1091 + void oddToEven(int blossom, int tree) {
4.1092 + if (!_blossom_set->trivial(blossom)) {
4.1093 + _delta4->erase(blossom);
4.1094 + (*_blossom_data)[blossom].pot -=
4.1095 + 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
4.1096 + }
4.1097 +
4.1098 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.1099 + n != INVALID; ++n) {
4.1100 + int ni = (*_node_index)[n];
4.1101 +
4.1102 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
4.1103 +
4.1104 + (*_node_data)[ni].heap.clear();
4.1105 + (*_node_data)[ni].heap_index.clear();
4.1106 + (*_node_data)[ni].pot +=
4.1107 + 2 * _delta_sum - (*_blossom_data)[blossom].offset;
4.1108 +
4.1109 + _delta1->push(n, (*_node_data)[ni].pot);
4.1110 +
4.1111 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
4.1112 + Node v = _graph.source(e);
4.1113 + int vb = _blossom_set->find(v);
4.1114 + int vi = (*_node_index)[v];
4.1115 +
4.1116 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.1117 + dualScale * _weight[e];
4.1118 +
4.1119 + if ((*_blossom_data)[vb].status == EVEN) {
4.1120 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
4.1121 + _delta3->push(e, rw / 2);
4.1122 + }
4.1123 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
4.1124 + if (_delta3->state(e) != _delta3->IN_HEAP) {
4.1125 + _delta3->push(e, rw);
4.1126 + }
4.1127 + } else {
4.1128 +
4.1129 + typename std::map<int, Arc>::iterator it =
4.1130 + (*_node_data)[vi].heap_index.find(tree);
4.1131 +
4.1132 + if (it != (*_node_data)[vi].heap_index.end()) {
4.1133 + if ((*_node_data)[vi].heap[it->second] > rw) {
4.1134 + (*_node_data)[vi].heap.replace(it->second, e);
4.1135 + (*_node_data)[vi].heap.decrease(e, rw);
4.1136 + it->second = e;
4.1137 + }
4.1138 + } else {
4.1139 + (*_node_data)[vi].heap.push(e, rw);
4.1140 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
4.1141 + }
4.1142 +
4.1143 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
4.1144 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
4.1145 +
4.1146 + if ((*_blossom_data)[vb].status == MATCHED) {
4.1147 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
4.1148 + _delta2->push(vb, _blossom_set->classPrio(vb) -
4.1149 + (*_blossom_data)[vb].offset);
4.1150 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
4.1151 + (*_blossom_data)[vb].offset) {
4.1152 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
4.1153 + (*_blossom_data)[vb].offset);
4.1154 + }
4.1155 + }
4.1156 + }
4.1157 + }
4.1158 + }
4.1159 + }
4.1160 + (*_blossom_data)[blossom].offset = 0;
4.1161 + }
4.1162 +
4.1163 +
4.1164 + void matchedToUnmatched(int blossom) {
4.1165 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
4.1166 + _delta2->erase(blossom);
4.1167 + }
4.1168 +
4.1169 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.1170 + n != INVALID; ++n) {
4.1171 + int ni = (*_node_index)[n];
4.1172 +
4.1173 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
4.1174 +
4.1175 + (*_node_data)[ni].heap.clear();
4.1176 + (*_node_data)[ni].heap_index.clear();
4.1177 +
4.1178 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
4.1179 + Node v = _graph.target(e);
4.1180 + int vb = _blossom_set->find(v);
4.1181 + int vi = (*_node_index)[v];
4.1182 +
4.1183 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.1184 + dualScale * _weight[e];
4.1185 +
4.1186 + if ((*_blossom_data)[vb].status == EVEN) {
4.1187 + if (_delta3->state(e) != _delta3->IN_HEAP) {
4.1188 + _delta3->push(e, rw);
4.1189 + }
4.1190 + }
4.1191 + }
4.1192 + }
4.1193 + }
4.1194 +
4.1195 + void unmatchedToMatched(int blossom) {
4.1196 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.1197 + n != INVALID; ++n) {
4.1198 + int ni = (*_node_index)[n];
4.1199 +
4.1200 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
4.1201 + Node v = _graph.source(e);
4.1202 + int vb = _blossom_set->find(v);
4.1203 + int vi = (*_node_index)[v];
4.1204 +
4.1205 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.1206 + dualScale * _weight[e];
4.1207 +
4.1208 + if (vb == blossom) {
4.1209 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.1210 + _delta3->erase(e);
4.1211 + }
4.1212 + } else if ((*_blossom_data)[vb].status == EVEN) {
4.1213 +
4.1214 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.1215 + _delta3->erase(e);
4.1216 + }
4.1217 +
4.1218 + int vt = _tree_set->find(vb);
4.1219 +
4.1220 + Arc r = _graph.oppositeArc(e);
4.1221 +
4.1222 + typename std::map<int, Arc>::iterator it =
4.1223 + (*_node_data)[ni].heap_index.find(vt);
4.1224 +
4.1225 + if (it != (*_node_data)[ni].heap_index.end()) {
4.1226 + if ((*_node_data)[ni].heap[it->second] > rw) {
4.1227 + (*_node_data)[ni].heap.replace(it->second, r);
4.1228 + (*_node_data)[ni].heap.decrease(r, rw);
4.1229 + it->second = r;
4.1230 + }
4.1231 + } else {
4.1232 + (*_node_data)[ni].heap.push(r, rw);
4.1233 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
4.1234 + }
4.1235 +
4.1236 + if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
4.1237 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
4.1238 +
4.1239 + if (_delta2->state(blossom) != _delta2->IN_HEAP) {
4.1240 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
4.1241 + (*_blossom_data)[blossom].offset);
4.1242 + } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
4.1243 + (*_blossom_data)[blossom].offset){
4.1244 + _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
4.1245 + (*_blossom_data)[blossom].offset);
4.1246 + }
4.1247 + }
4.1248 +
4.1249 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
4.1250 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.1251 + _delta3->erase(e);
4.1252 + }
4.1253 + }
4.1254 + }
4.1255 + }
4.1256 + }
4.1257 +
4.1258 + void alternatePath(int even, int tree) {
4.1259 + int odd;
4.1260 +
4.1261 + evenToMatched(even, tree);
4.1262 + (*_blossom_data)[even].status = MATCHED;
4.1263 +
4.1264 + while ((*_blossom_data)[even].pred != INVALID) {
4.1265 + odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
4.1266 + (*_blossom_data)[odd].status = MATCHED;
4.1267 + oddToMatched(odd);
4.1268 + (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
4.1269 +
4.1270 + even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
4.1271 + (*_blossom_data)[even].status = MATCHED;
4.1272 + evenToMatched(even, tree);
4.1273 + (*_blossom_data)[even].next =
4.1274 + _graph.oppositeArc((*_blossom_data)[odd].pred);
4.1275 + }
4.1276 +
4.1277 + }
4.1278 +
4.1279 + void destroyTree(int tree) {
4.1280 + for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
4.1281 + if ((*_blossom_data)[b].status == EVEN) {
4.1282 + (*_blossom_data)[b].status = MATCHED;
4.1283 + evenToMatched(b, tree);
4.1284 + } else if ((*_blossom_data)[b].status == ODD) {
4.1285 + (*_blossom_data)[b].status = MATCHED;
4.1286 + oddToMatched(b);
4.1287 + }
4.1288 + }
4.1289 + _tree_set->eraseClass(tree);
4.1290 + }
4.1291 +
4.1292 +
4.1293 + void unmatchNode(const Node& node) {
4.1294 + int blossom = _blossom_set->find(node);
4.1295 + int tree = _tree_set->find(blossom);
4.1296 +
4.1297 + alternatePath(blossom, tree);
4.1298 + destroyTree(tree);
4.1299 +
4.1300 + (*_blossom_data)[blossom].status = UNMATCHED;
4.1301 + (*_blossom_data)[blossom].base = node;
4.1302 + matchedToUnmatched(blossom);
4.1303 + }
4.1304 +
4.1305 +
4.1306 + void augmentOnEdge(const Edge& edge) {
4.1307 +
4.1308 + int left = _blossom_set->find(_graph.u(edge));
4.1309 + int right = _blossom_set->find(_graph.v(edge));
4.1310 +
4.1311 + if ((*_blossom_data)[left].status == EVEN) {
4.1312 + int left_tree = _tree_set->find(left);
4.1313 + alternatePath(left, left_tree);
4.1314 + destroyTree(left_tree);
4.1315 + } else {
4.1316 + (*_blossom_data)[left].status = MATCHED;
4.1317 + unmatchedToMatched(left);
4.1318 + }
4.1319 +
4.1320 + if ((*_blossom_data)[right].status == EVEN) {
4.1321 + int right_tree = _tree_set->find(right);
4.1322 + alternatePath(right, right_tree);
4.1323 + destroyTree(right_tree);
4.1324 + } else {
4.1325 + (*_blossom_data)[right].status = MATCHED;
4.1326 + unmatchedToMatched(right);
4.1327 + }
4.1328 +
4.1329 + (*_blossom_data)[left].next = _graph.direct(edge, true);
4.1330 + (*_blossom_data)[right].next = _graph.direct(edge, false);
4.1331 + }
4.1332 +
4.1333 + void extendOnArc(const Arc& arc) {
4.1334 + int base = _blossom_set->find(_graph.target(arc));
4.1335 + int tree = _tree_set->find(base);
4.1336 +
4.1337 + int odd = _blossom_set->find(_graph.source(arc));
4.1338 + _tree_set->insert(odd, tree);
4.1339 + (*_blossom_data)[odd].status = ODD;
4.1340 + matchedToOdd(odd);
4.1341 + (*_blossom_data)[odd].pred = arc;
4.1342 +
4.1343 + int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
4.1344 + (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
4.1345 + _tree_set->insert(even, tree);
4.1346 + (*_blossom_data)[even].status = EVEN;
4.1347 + matchedToEven(even, tree);
4.1348 + }
4.1349 +
4.1350 + void shrinkOnEdge(const Edge& edge, int tree) {
4.1351 + int nca = -1;
4.1352 + std::vector<int> left_path, right_path;
4.1353 +
4.1354 + {
4.1355 + std::set<int> left_set, right_set;
4.1356 + int left = _blossom_set->find(_graph.u(edge));
4.1357 + left_path.push_back(left);
4.1358 + left_set.insert(left);
4.1359 +
4.1360 + int right = _blossom_set->find(_graph.v(edge));
4.1361 + right_path.push_back(right);
4.1362 + right_set.insert(right);
4.1363 +
4.1364 + while (true) {
4.1365 +
4.1366 + if ((*_blossom_data)[left].pred == INVALID) break;
4.1367 +
4.1368 + left =
4.1369 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
4.1370 + left_path.push_back(left);
4.1371 + left =
4.1372 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
4.1373 + left_path.push_back(left);
4.1374 +
4.1375 + left_set.insert(left);
4.1376 +
4.1377 + if (right_set.find(left) != right_set.end()) {
4.1378 + nca = left;
4.1379 + break;
4.1380 + }
4.1381 +
4.1382 + if ((*_blossom_data)[right].pred == INVALID) break;
4.1383 +
4.1384 + right =
4.1385 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
4.1386 + right_path.push_back(right);
4.1387 + right =
4.1388 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
4.1389 + right_path.push_back(right);
4.1390 +
4.1391 + right_set.insert(right);
4.1392 +
4.1393 + if (left_set.find(right) != left_set.end()) {
4.1394 + nca = right;
4.1395 + break;
4.1396 + }
4.1397 +
4.1398 + }
4.1399 +
4.1400 + if (nca == -1) {
4.1401 + if ((*_blossom_data)[left].pred == INVALID) {
4.1402 + nca = right;
4.1403 + while (left_set.find(nca) == left_set.end()) {
4.1404 + nca =
4.1405 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.1406 + right_path.push_back(nca);
4.1407 + nca =
4.1408 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.1409 + right_path.push_back(nca);
4.1410 + }
4.1411 + } else {
4.1412 + nca = left;
4.1413 + while (right_set.find(nca) == right_set.end()) {
4.1414 + nca =
4.1415 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.1416 + left_path.push_back(nca);
4.1417 + nca =
4.1418 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.1419 + left_path.push_back(nca);
4.1420 + }
4.1421 + }
4.1422 + }
4.1423 + }
4.1424 +
4.1425 + std::vector<int> subblossoms;
4.1426 + Arc prev;
4.1427 +
4.1428 + prev = _graph.direct(edge, true);
4.1429 + for (int i = 0; left_path[i] != nca; i += 2) {
4.1430 + subblossoms.push_back(left_path[i]);
4.1431 + (*_blossom_data)[left_path[i]].next = prev;
4.1432 + _tree_set->erase(left_path[i]);
4.1433 +
4.1434 + subblossoms.push_back(left_path[i + 1]);
4.1435 + (*_blossom_data)[left_path[i + 1]].status = EVEN;
4.1436 + oddToEven(left_path[i + 1], tree);
4.1437 + _tree_set->erase(left_path[i + 1]);
4.1438 + prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
4.1439 + }
4.1440 +
4.1441 + int k = 0;
4.1442 + while (right_path[k] != nca) ++k;
4.1443 +
4.1444 + subblossoms.push_back(nca);
4.1445 + (*_blossom_data)[nca].next = prev;
4.1446 +
4.1447 + for (int i = k - 2; i >= 0; i -= 2) {
4.1448 + subblossoms.push_back(right_path[i + 1]);
4.1449 + (*_blossom_data)[right_path[i + 1]].status = EVEN;
4.1450 + oddToEven(right_path[i + 1], tree);
4.1451 + _tree_set->erase(right_path[i + 1]);
4.1452 +
4.1453 + (*_blossom_data)[right_path[i + 1]].next =
4.1454 + (*_blossom_data)[right_path[i + 1]].pred;
4.1455 +
4.1456 + subblossoms.push_back(right_path[i]);
4.1457 + _tree_set->erase(right_path[i]);
4.1458 + }
4.1459 +
4.1460 + int surface =
4.1461 + _blossom_set->join(subblossoms.begin(), subblossoms.end());
4.1462 +
4.1463 + for (int i = 0; i < int(subblossoms.size()); ++i) {
4.1464 + if (!_blossom_set->trivial(subblossoms[i])) {
4.1465 + (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
4.1466 + }
4.1467 + (*_blossom_data)[subblossoms[i]].status = MATCHED;
4.1468 + }
4.1469 +
4.1470 + (*_blossom_data)[surface].pot = -2 * _delta_sum;
4.1471 + (*_blossom_data)[surface].offset = 0;
4.1472 + (*_blossom_data)[surface].status = EVEN;
4.1473 + (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
4.1474 + (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
4.1475 +
4.1476 + _tree_set->insert(surface, tree);
4.1477 + _tree_set->erase(nca);
4.1478 + }
4.1479 +
4.1480 + void splitBlossom(int blossom) {
4.1481 + Arc next = (*_blossom_data)[blossom].next;
4.1482 + Arc pred = (*_blossom_data)[blossom].pred;
4.1483 +
4.1484 + int tree = _tree_set->find(blossom);
4.1485 +
4.1486 + (*_blossom_data)[blossom].status = MATCHED;
4.1487 + oddToMatched(blossom);
4.1488 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
4.1489 + _delta2->erase(blossom);
4.1490 + }
4.1491 +
4.1492 + std::vector<int> subblossoms;
4.1493 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
4.1494 +
4.1495 + Value offset = (*_blossom_data)[blossom].offset;
4.1496 + int b = _blossom_set->find(_graph.source(pred));
4.1497 + int d = _blossom_set->find(_graph.source(next));
4.1498 +
4.1499 + int ib = -1, id = -1;
4.1500 + for (int i = 0; i < int(subblossoms.size()); ++i) {
4.1501 + if (subblossoms[i] == b) ib = i;
4.1502 + if (subblossoms[i] == d) id = i;
4.1503 +
4.1504 + (*_blossom_data)[subblossoms[i]].offset = offset;
4.1505 + if (!_blossom_set->trivial(subblossoms[i])) {
4.1506 + (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
4.1507 + }
4.1508 + if (_blossom_set->classPrio(subblossoms[i]) !=
4.1509 + std::numeric_limits<Value>::max()) {
4.1510 + _delta2->push(subblossoms[i],
4.1511 + _blossom_set->classPrio(subblossoms[i]) -
4.1512 + (*_blossom_data)[subblossoms[i]].offset);
4.1513 + }
4.1514 + }
4.1515 +
4.1516 + if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
4.1517 + for (int i = (id + 1) % subblossoms.size();
4.1518 + i != ib; i = (i + 2) % subblossoms.size()) {
4.1519 + int sb = subblossoms[i];
4.1520 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.1521 + (*_blossom_data)[sb].next =
4.1522 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.1523 + }
4.1524 +
4.1525 + for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
4.1526 + int sb = subblossoms[i];
4.1527 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.1528 + int ub = subblossoms[(i + 2) % subblossoms.size()];
4.1529 +
4.1530 + (*_blossom_data)[sb].status = ODD;
4.1531 + matchedToOdd(sb);
4.1532 + _tree_set->insert(sb, tree);
4.1533 + (*_blossom_data)[sb].pred = pred;
4.1534 + (*_blossom_data)[sb].next =
4.1535 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.1536 +
4.1537 + pred = (*_blossom_data)[ub].next;
4.1538 +
4.1539 + (*_blossom_data)[tb].status = EVEN;
4.1540 + matchedToEven(tb, tree);
4.1541 + _tree_set->insert(tb, tree);
4.1542 + (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
4.1543 + }
4.1544 +
4.1545 + (*_blossom_data)[subblossoms[id]].status = ODD;
4.1546 + matchedToOdd(subblossoms[id]);
4.1547 + _tree_set->insert(subblossoms[id], tree);
4.1548 + (*_blossom_data)[subblossoms[id]].next = next;
4.1549 + (*_blossom_data)[subblossoms[id]].pred = pred;
4.1550 +
4.1551 + } else {
4.1552 +
4.1553 + for (int i = (ib + 1) % subblossoms.size();
4.1554 + i != id; i = (i + 2) % subblossoms.size()) {
4.1555 + int sb = subblossoms[i];
4.1556 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.1557 + (*_blossom_data)[sb].next =
4.1558 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.1559 + }
4.1560 +
4.1561 + for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
4.1562 + int sb = subblossoms[i];
4.1563 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.1564 + int ub = subblossoms[(i + 2) % subblossoms.size()];
4.1565 +
4.1566 + (*_blossom_data)[sb].status = ODD;
4.1567 + matchedToOdd(sb);
4.1568 + _tree_set->insert(sb, tree);
4.1569 + (*_blossom_data)[sb].next = next;
4.1570 + (*_blossom_data)[sb].pred =
4.1571 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.1572 +
4.1573 + (*_blossom_data)[tb].status = EVEN;
4.1574 + matchedToEven(tb, tree);
4.1575 + _tree_set->insert(tb, tree);
4.1576 + (*_blossom_data)[tb].pred =
4.1577 + (*_blossom_data)[tb].next =
4.1578 + _graph.oppositeArc((*_blossom_data)[ub].next);
4.1579 + next = (*_blossom_data)[ub].next;
4.1580 + }
4.1581 +
4.1582 + (*_blossom_data)[subblossoms[ib]].status = ODD;
4.1583 + matchedToOdd(subblossoms[ib]);
4.1584 + _tree_set->insert(subblossoms[ib], tree);
4.1585 + (*_blossom_data)[subblossoms[ib]].next = next;
4.1586 + (*_blossom_data)[subblossoms[ib]].pred = pred;
4.1587 + }
4.1588 + _tree_set->erase(blossom);
4.1589 + }
4.1590 +
4.1591 + void extractBlossom(int blossom, const Node& base, const Arc& matching) {
4.1592 + if (_blossom_set->trivial(blossom)) {
4.1593 + int bi = (*_node_index)[base];
4.1594 + Value pot = (*_node_data)[bi].pot;
4.1595 +
4.1596 + (*_matching)[base] = matching;
4.1597 + _blossom_node_list.push_back(base);
4.1598 + (*_node_potential)[base] = pot;
4.1599 + } else {
4.1600 +
4.1601 + Value pot = (*_blossom_data)[blossom].pot;
4.1602 + int bn = _blossom_node_list.size();
4.1603 +
4.1604 + std::vector<int> subblossoms;
4.1605 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
4.1606 + int b = _blossom_set->find(base);
4.1607 + int ib = -1;
4.1608 + for (int i = 0; i < int(subblossoms.size()); ++i) {
4.1609 + if (subblossoms[i] == b) { ib = i; break; }
4.1610 + }
4.1611 +
4.1612 + for (int i = 1; i < int(subblossoms.size()); i += 2) {
4.1613 + int sb = subblossoms[(ib + i) % subblossoms.size()];
4.1614 + int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
4.1615 +
4.1616 + Arc m = (*_blossom_data)[tb].next;
4.1617 + extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
4.1618 + extractBlossom(tb, _graph.source(m), m);
4.1619 + }
4.1620 + extractBlossom(subblossoms[ib], base, matching);
4.1621 +
4.1622 + int en = _blossom_node_list.size();
4.1623 +
4.1624 + _blossom_potential.push_back(BlossomVariable(bn, en, pot));
4.1625 + }
4.1626 + }
4.1627 +
4.1628 + void extractMatching() {
4.1629 + std::vector<int> blossoms;
4.1630 + for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
4.1631 + blossoms.push_back(c);
4.1632 + }
4.1633 +
4.1634 + for (int i = 0; i < int(blossoms.size()); ++i) {
4.1635 + if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
4.1636 +
4.1637 + Value offset = (*_blossom_data)[blossoms[i]].offset;
4.1638 + (*_blossom_data)[blossoms[i]].pot += 2 * offset;
4.1639 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
4.1640 + n != INVALID; ++n) {
4.1641 + (*_node_data)[(*_node_index)[n]].pot -= offset;
4.1642 + }
4.1643 +
4.1644 + Arc matching = (*_blossom_data)[blossoms[i]].next;
4.1645 + Node base = _graph.source(matching);
4.1646 + extractBlossom(blossoms[i], base, matching);
4.1647 + } else {
4.1648 + Node base = (*_blossom_data)[blossoms[i]].base;
4.1649 + extractBlossom(blossoms[i], base, INVALID);
4.1650 + }
4.1651 + }
4.1652 + }
4.1653 +
4.1654 + public:
4.1655 +
4.1656 + /// \brief Constructor
4.1657 + ///
4.1658 + /// Constructor.
4.1659 + MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
4.1660 + : _graph(graph), _weight(weight), _matching(0),
4.1661 + _node_potential(0), _blossom_potential(), _blossom_node_list(),
4.1662 + _node_num(0), _blossom_num(0),
4.1663 +
4.1664 + _blossom_index(0), _blossom_set(0), _blossom_data(0),
4.1665 + _node_index(0), _node_heap_index(0), _node_data(0),
4.1666 + _tree_set_index(0), _tree_set(0),
4.1667 +
4.1668 + _delta1_index(0), _delta1(0),
4.1669 + _delta2_index(0), _delta2(0),
4.1670 + _delta3_index(0), _delta3(0),
4.1671 + _delta4_index(0), _delta4(0),
4.1672 +
4.1673 + _delta_sum() {}
4.1674 +
4.1675 + ~MaxWeightedMatching() {
4.1676 + destroyStructures();
4.1677 + }
4.1678 +
4.1679 + /// \name Execution Control
4.1680 + /// The simplest way to execute the algorithm is to use the
4.1681 + /// \ref run() member function.
4.1682 +
4.1683 + ///@{
4.1684 +
4.1685 + /// \brief Initialize the algorithm
4.1686 + ///
4.1687 + /// This function initializes the algorithm.
4.1688 + void init() {
4.1689 + createStructures();
4.1690 +
4.1691 + for (ArcIt e(_graph); e != INVALID; ++e) {
4.1692 + (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
4.1693 + }
4.1694 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.1695 + (*_delta1_index)[n] = _delta1->PRE_HEAP;
4.1696 + }
4.1697 + for (EdgeIt e(_graph); e != INVALID; ++e) {
4.1698 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
4.1699 + }
4.1700 + for (int i = 0; i < _blossom_num; ++i) {
4.1701 + (*_delta2_index)[i] = _delta2->PRE_HEAP;
4.1702 + (*_delta4_index)[i] = _delta4->PRE_HEAP;
4.1703 + }
4.1704 +
4.1705 + int index = 0;
4.1706 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.1707 + Value max = 0;
4.1708 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
4.1709 + if (_graph.target(e) == n) continue;
4.1710 + if ((dualScale * _weight[e]) / 2 > max) {
4.1711 + max = (dualScale * _weight[e]) / 2;
4.1712 + }
4.1713 + }
4.1714 + (*_node_index)[n] = index;
4.1715 + (*_node_data)[index].pot = max;
4.1716 + _delta1->push(n, max);
4.1717 + int blossom =
4.1718 + _blossom_set->insert(n, std::numeric_limits<Value>::max());
4.1719 +
4.1720 + _tree_set->insert(blossom);
4.1721 +
4.1722 + (*_blossom_data)[blossom].status = EVEN;
4.1723 + (*_blossom_data)[blossom].pred = INVALID;
4.1724 + (*_blossom_data)[blossom].next = INVALID;
4.1725 + (*_blossom_data)[blossom].pot = 0;
4.1726 + (*_blossom_data)[blossom].offset = 0;
4.1727 + ++index;
4.1728 + }
4.1729 + for (EdgeIt e(_graph); e != INVALID; ++e) {
4.1730 + int si = (*_node_index)[_graph.u(e)];
4.1731 + int ti = (*_node_index)[_graph.v(e)];
4.1732 + if (_graph.u(e) != _graph.v(e)) {
4.1733 + _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
4.1734 + dualScale * _weight[e]) / 2);
4.1735 + }
4.1736 + }
4.1737 + }
4.1738 +
4.1739 + /// \brief Start the algorithm
4.1740 + ///
4.1741 + /// This function starts the algorithm.
4.1742 + ///
4.1743 + /// \pre \ref init() must be called before using this function.
4.1744 + void start() {
4.1745 + enum OpType {
4.1746 + D1, D2, D3, D4
4.1747 + };
4.1748 +
4.1749 + int unmatched = _node_num;
4.1750 + while (unmatched > 0) {
4.1751 + Value d1 = !_delta1->empty() ?
4.1752 + _delta1->prio() : std::numeric_limits<Value>::max();
4.1753 +
4.1754 + Value d2 = !_delta2->empty() ?
4.1755 + _delta2->prio() : std::numeric_limits<Value>::max();
4.1756 +
4.1757 + Value d3 = !_delta3->empty() ?
4.1758 + _delta3->prio() : std::numeric_limits<Value>::max();
4.1759 +
4.1760 + Value d4 = !_delta4->empty() ?
4.1761 + _delta4->prio() : std::numeric_limits<Value>::max();
4.1762 +
4.1763 + _delta_sum = d1; OpType ot = D1;
4.1764 + if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
4.1765 + if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
4.1766 + if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
4.1767 +
4.1768 +
4.1769 + switch (ot) {
4.1770 + case D1:
4.1771 + {
4.1772 + Node n = _delta1->top();
4.1773 + unmatchNode(n);
4.1774 + --unmatched;
4.1775 + }
4.1776 + break;
4.1777 + case D2:
4.1778 + {
4.1779 + int blossom = _delta2->top();
4.1780 + Node n = _blossom_set->classTop(blossom);
4.1781 + Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
4.1782 + extendOnArc(e);
4.1783 + }
4.1784 + break;
4.1785 + case D3:
4.1786 + {
4.1787 + Edge e = _delta3->top();
4.1788 +
4.1789 + int left_blossom = _blossom_set->find(_graph.u(e));
4.1790 + int right_blossom = _blossom_set->find(_graph.v(e));
4.1791 +
4.1792 + if (left_blossom == right_blossom) {
4.1793 + _delta3->pop();
4.1794 + } else {
4.1795 + int left_tree;
4.1796 + if ((*_blossom_data)[left_blossom].status == EVEN) {
4.1797 + left_tree = _tree_set->find(left_blossom);
4.1798 + } else {
4.1799 + left_tree = -1;
4.1800 + ++unmatched;
4.1801 + }
4.1802 + int right_tree;
4.1803 + if ((*_blossom_data)[right_blossom].status == EVEN) {
4.1804 + right_tree = _tree_set->find(right_blossom);
4.1805 + } else {
4.1806 + right_tree = -1;
4.1807 + ++unmatched;
4.1808 + }
4.1809 +
4.1810 + if (left_tree == right_tree) {
4.1811 + shrinkOnEdge(e, left_tree);
4.1812 + } else {
4.1813 + augmentOnEdge(e);
4.1814 + unmatched -= 2;
4.1815 + }
4.1816 + }
4.1817 + } break;
4.1818 + case D4:
4.1819 + splitBlossom(_delta4->top());
4.1820 + break;
4.1821 + }
4.1822 + }
4.1823 + extractMatching();
4.1824 + }
4.1825 +
4.1826 + /// \brief Run the algorithm.
4.1827 + ///
4.1828 + /// This method runs the \c %MaxWeightedMatching algorithm.
4.1829 + ///
4.1830 + /// \note mwm.run() is just a shortcut of the following code.
4.1831 + /// \code
4.1832 + /// mwm.init();
4.1833 + /// mwm.start();
4.1834 + /// \endcode
4.1835 + void run() {
4.1836 + init();
4.1837 + start();
4.1838 + }
4.1839 +
4.1840 + /// @}
4.1841 +
4.1842 + /// \name Primal Solution
4.1843 + /// Functions to get the primal solution, i.e. the maximum weighted
4.1844 + /// matching.\n
4.1845 + /// Either \ref run() or \ref start() function should be called before
4.1846 + /// using them.
4.1847 +
4.1848 + /// @{
4.1849 +
4.1850 + /// \brief Return the weight of the matching.
4.1851 + ///
4.1852 + /// This function returns the weight of the found matching.
4.1853 + ///
4.1854 + /// \pre Either run() or start() must be called before using this function.
4.1855 + Value matchingWeight() const {
4.1856 + Value sum = 0;
4.1857 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.1858 + if ((*_matching)[n] != INVALID) {
4.1859 + sum += _weight[(*_matching)[n]];
4.1860 + }
4.1861 + }
4.1862 + return sum /= 2;
4.1863 + }
4.1864 +
4.1865 + /// \brief Return the size (cardinality) of the matching.
4.1866 + ///
4.1867 + /// This function returns the size (cardinality) of the found matching.
4.1868 + ///
4.1869 + /// \pre Either run() or start() must be called before using this function.
4.1870 + int matchingSize() const {
4.1871 + int num = 0;
4.1872 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.1873 + if ((*_matching)[n] != INVALID) {
4.1874 + ++num;
4.1875 + }
4.1876 + }
4.1877 + return num /= 2;
4.1878 + }
4.1879 +
4.1880 + /// \brief Return \c true if the given edge is in the matching.
4.1881 + ///
4.1882 + /// This function returns \c true if the given edge is in the found
4.1883 + /// matching.
4.1884 + ///
4.1885 + /// \pre Either run() or start() must be called before using this function.
4.1886 + bool matching(const Edge& edge) const {
4.1887 + return edge == (*_matching)[_graph.u(edge)];
4.1888 + }
4.1889 +
4.1890 + /// \brief Return the matching arc (or edge) incident to the given node.
4.1891 + ///
4.1892 + /// This function returns the matching arc (or edge) incident to the
4.1893 + /// given node in the found matching or \c INVALID if the node is
4.1894 + /// not covered by the matching.
4.1895 + ///
4.1896 + /// \pre Either run() or start() must be called before using this function.
4.1897 + Arc matching(const Node& node) const {
4.1898 + return (*_matching)[node];
4.1899 + }
4.1900 +
4.1901 + /// \brief Return a const reference to the matching map.
4.1902 + ///
4.1903 + /// This function returns a const reference to a node map that stores
4.1904 + /// the matching arc (or edge) incident to each node.
4.1905 + const MatchingMap& matchingMap() const {
4.1906 + return *_matching;
4.1907 + }
4.1908 +
4.1909 + /// \brief Return the mate of the given node.
4.1910 + ///
4.1911 + /// This function returns the mate of the given node in the found
4.1912 + /// matching or \c INVALID if the node is not covered by the matching.
4.1913 + ///
4.1914 + /// \pre Either run() or start() must be called before using this function.
4.1915 + Node mate(const Node& node) const {
4.1916 + return (*_matching)[node] != INVALID ?
4.1917 + _graph.target((*_matching)[node]) : INVALID;
4.1918 + }
4.1919 +
4.1920 + /// @}
4.1921 +
4.1922 + /// \name Dual Solution
4.1923 + /// Functions to get the dual solution.\n
4.1924 + /// Either \ref run() or \ref start() function should be called before
4.1925 + /// using them.
4.1926 +
4.1927 + /// @{
4.1928 +
4.1929 + /// \brief Return the value of the dual solution.
4.1930 + ///
4.1931 + /// This function returns the value of the dual solution.
4.1932 + /// It should be equal to the primal value scaled by \ref dualScale
4.1933 + /// "dual scale".
4.1934 + ///
4.1935 + /// \pre Either run() or start() must be called before using this function.
4.1936 + Value dualValue() const {
4.1937 + Value sum = 0;
4.1938 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.1939 + sum += nodeValue(n);
4.1940 + }
4.1941 + for (int i = 0; i < blossomNum(); ++i) {
4.1942 + sum += blossomValue(i) * (blossomSize(i) / 2);
4.1943 + }
4.1944 + return sum;
4.1945 + }
4.1946 +
4.1947 + /// \brief Return the dual value (potential) of the given node.
4.1948 + ///
4.1949 + /// This function returns the dual value (potential) of the given node.
4.1950 + ///
4.1951 + /// \pre Either run() or start() must be called before using this function.
4.1952 + Value nodeValue(const Node& n) const {
4.1953 + return (*_node_potential)[n];
4.1954 + }
4.1955 +
4.1956 + /// \brief Return the number of the blossoms in the basis.
4.1957 + ///
4.1958 + /// This function returns the number of the blossoms in the basis.
4.1959 + ///
4.1960 + /// \pre Either run() or start() must be called before using this function.
4.1961 + /// \see BlossomIt
4.1962 + int blossomNum() const {
4.1963 + return _blossom_potential.size();
4.1964 + }
4.1965 +
4.1966 + /// \brief Return the number of the nodes in the given blossom.
4.1967 + ///
4.1968 + /// This function returns the number of the nodes in the given blossom.
4.1969 + ///
4.1970 + /// \pre Either run() or start() must be called before using this function.
4.1971 + /// \see BlossomIt
4.1972 + int blossomSize(int k) const {
4.1973 + return _blossom_potential[k].end - _blossom_potential[k].begin;
4.1974 + }
4.1975 +
4.1976 + /// \brief Return the dual value (ptential) of the given blossom.
4.1977 + ///
4.1978 + /// This function returns the dual value (ptential) of the given blossom.
4.1979 + ///
4.1980 + /// \pre Either run() or start() must be called before using this function.
4.1981 + Value blossomValue(int k) const {
4.1982 + return _blossom_potential[k].value;
4.1983 + }
4.1984 +
4.1985 + /// \brief Iterator for obtaining the nodes of a blossom.
4.1986 + ///
4.1987 + /// This class provides an iterator for obtaining the nodes of the
4.1988 + /// given blossom. It lists a subset of the nodes.
4.1989 + /// Before using this iterator, you must allocate a
4.1990 + /// MaxWeightedMatching class and execute it.
4.1991 + class BlossomIt {
4.1992 + public:
4.1993 +
4.1994 + /// \brief Constructor.
4.1995 + ///
4.1996 + /// Constructor to get the nodes of the given variable.
4.1997 + ///
4.1998 + /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
4.1999 + /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
4.2000 + /// called before initializing this iterator.
4.2001 + BlossomIt(const MaxWeightedMatching& algorithm, int variable)
4.2002 + : _algorithm(&algorithm)
4.2003 + {
4.2004 + _index = _algorithm->_blossom_potential[variable].begin;
4.2005 + _last = _algorithm->_blossom_potential[variable].end;
4.2006 + }
4.2007 +
4.2008 + /// \brief Conversion to \c Node.
4.2009 + ///
4.2010 + /// Conversion to \c Node.
4.2011 + operator Node() const {
4.2012 + return _algorithm->_blossom_node_list[_index];
4.2013 + }
4.2014 +
4.2015 + /// \brief Increment operator.
4.2016 + ///
4.2017 + /// Increment operator.
4.2018 + BlossomIt& operator++() {
4.2019 + ++_index;
4.2020 + return *this;
4.2021 + }
4.2022 +
4.2023 + /// \brief Validity checking
4.2024 + ///
4.2025 + /// Checks whether the iterator is invalid.
4.2026 + bool operator==(Invalid) const { return _index == _last; }
4.2027 +
4.2028 + /// \brief Validity checking
4.2029 + ///
4.2030 + /// Checks whether the iterator is valid.
4.2031 + bool operator!=(Invalid) const { return _index != _last; }
4.2032 +
4.2033 + private:
4.2034 + const MaxWeightedMatching* _algorithm;
4.2035 + int _last;
4.2036 + int _index;
4.2037 + };
4.2038 +
4.2039 + /// @}
4.2040 +
4.2041 + };
4.2042 +
4.2043 + /// \ingroup matching
4.2044 + ///
4.2045 + /// \brief Weighted perfect matching in general graphs
4.2046 + ///
4.2047 + /// This class provides an efficient implementation of Edmond's
4.2048 + /// maximum weighted perfect matching algorithm. The implementation
4.2049 + /// is based on extensive use of priority queues and provides
4.2050 + /// \f$O(nm\log n)\f$ time complexity.
4.2051 + ///
4.2052 + /// The maximum weighted perfect matching problem is to find a subset of
4.2053 + /// the edges in an undirected graph with maximum overall weight for which
4.2054 + /// each node has exactly one incident edge.
4.2055 + /// It can be formulated with the following linear program.
4.2056 + /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
4.2057 + /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
4.2058 + \quad \forall B\in\mathcal{O}\f] */
4.2059 + /// \f[x_e \ge 0\quad \forall e\in E\f]
4.2060 + /// \f[\max \sum_{e\in E}x_ew_e\f]
4.2061 + /// where \f$\delta(X)\f$ is the set of edges incident to a node in
4.2062 + /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
4.2063 + /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
4.2064 + /// subsets of the nodes.
4.2065 + ///
4.2066 + /// The algorithm calculates an optimal matching and a proof of the
4.2067 + /// optimality. The solution of the dual problem can be used to check
4.2068 + /// the result of the algorithm. The dual linear problem is the
4.2069 + /// following.
4.2070 + /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
4.2071 + w_{uv} \quad \forall uv\in E\f] */
4.2072 + /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
4.2073 + /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
4.2074 + \frac{\vert B \vert - 1}{2}z_B\f] */
4.2075 + ///
4.2076 + /// The algorithm can be executed with the run() function.
4.2077 + /// After it the matching (the primal solution) and the dual solution
4.2078 + /// can be obtained using the query functions and the
4.2079 + /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
4.2080 + /// which is able to iterate on the nodes of a blossom.
4.2081 + /// If the value type is integer, then the dual solution is multiplied
4.2082 + /// by \ref MaxWeightedMatching::dualScale "4".
4.2083 + ///
4.2084 + /// \tparam GR The undirected graph type the algorithm runs on.
4.2085 + /// \tparam WM The type edge weight map. The default type is
4.2086 + /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
4.2087 +#ifdef DOXYGEN
4.2088 + template <typename GR, typename WM>
4.2089 +#else
4.2090 + template <typename GR,
4.2091 + typename WM = typename GR::template EdgeMap<int> >
4.2092 +#endif
4.2093 + class MaxWeightedPerfectMatching {
4.2094 + public:
4.2095 +
4.2096 + /// The graph type of the algorithm
4.2097 + typedef GR Graph;
4.2098 + /// The type of the edge weight map
4.2099 + typedef WM WeightMap;
4.2100 + /// The value type of the edge weights
4.2101 + typedef typename WeightMap::Value Value;
4.2102 +
4.2103 + /// \brief Scaling factor for dual solution
4.2104 + ///
4.2105 + /// Scaling factor for dual solution, it is equal to 4 or 1
4.2106 + /// according to the value type.
4.2107 + static const int dualScale =
4.2108 + std::numeric_limits<Value>::is_integer ? 4 : 1;
4.2109 +
4.2110 + /// The type of the matching map
4.2111 + typedef typename Graph::template NodeMap<typename Graph::Arc>
4.2112 + MatchingMap;
4.2113 +
4.2114 + private:
4.2115 +
4.2116 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
4.2117 +
4.2118 + typedef typename Graph::template NodeMap<Value> NodePotential;
4.2119 + typedef std::vector<Node> BlossomNodeList;
4.2120 +
4.2121 + struct BlossomVariable {
4.2122 + int begin, end;
4.2123 + Value value;
4.2124 +
4.2125 + BlossomVariable(int _begin, int _end, Value _value)
4.2126 + : begin(_begin), end(_end), value(_value) {}
4.2127 +
4.2128 + };
4.2129 +
4.2130 + typedef std::vector<BlossomVariable> BlossomPotential;
4.2131 +
4.2132 + const Graph& _graph;
4.2133 + const WeightMap& _weight;
4.2134 +
4.2135 + MatchingMap* _matching;
4.2136 +
4.2137 + NodePotential* _node_potential;
4.2138 +
4.2139 + BlossomPotential _blossom_potential;
4.2140 + BlossomNodeList _blossom_node_list;
4.2141 +
4.2142 + int _node_num;
4.2143 + int _blossom_num;
4.2144 +
4.2145 + typedef RangeMap<int> IntIntMap;
4.2146 +
4.2147 + enum Status {
4.2148 + EVEN = -1, MATCHED = 0, ODD = 1
4.2149 + };
4.2150 +
4.2151 + typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
4.2152 + struct BlossomData {
4.2153 + int tree;
4.2154 + Status status;
4.2155 + Arc pred, next;
4.2156 + Value pot, offset;
4.2157 + };
4.2158 +
4.2159 + IntNodeMap *_blossom_index;
4.2160 + BlossomSet *_blossom_set;
4.2161 + RangeMap<BlossomData>* _blossom_data;
4.2162 +
4.2163 + IntNodeMap *_node_index;
4.2164 + IntArcMap *_node_heap_index;
4.2165 +
4.2166 + struct NodeData {
4.2167 +
4.2168 + NodeData(IntArcMap& node_heap_index)
4.2169 + : heap(node_heap_index) {}
4.2170 +
4.2171 + int blossom;
4.2172 + Value pot;
4.2173 + BinHeap<Value, IntArcMap> heap;
4.2174 + std::map<int, Arc> heap_index;
4.2175 +
4.2176 + int tree;
4.2177 + };
4.2178 +
4.2179 + RangeMap<NodeData>* _node_data;
4.2180 +
4.2181 + typedef ExtendFindEnum<IntIntMap> TreeSet;
4.2182 +
4.2183 + IntIntMap *_tree_set_index;
4.2184 + TreeSet *_tree_set;
4.2185 +
4.2186 + IntIntMap *_delta2_index;
4.2187 + BinHeap<Value, IntIntMap> *_delta2;
4.2188 +
4.2189 + IntEdgeMap *_delta3_index;
4.2190 + BinHeap<Value, IntEdgeMap> *_delta3;
4.2191 +
4.2192 + IntIntMap *_delta4_index;
4.2193 + BinHeap<Value, IntIntMap> *_delta4;
4.2194 +
4.2195 + Value _delta_sum;
4.2196 +
4.2197 + void createStructures() {
4.2198 + _node_num = countNodes(_graph);
4.2199 + _blossom_num = _node_num * 3 / 2;
4.2200 +
4.2201 + if (!_matching) {
4.2202 + _matching = new MatchingMap(_graph);
4.2203 + }
4.2204 + if (!_node_potential) {
4.2205 + _node_potential = new NodePotential(_graph);
4.2206 + }
4.2207 + if (!_blossom_set) {
4.2208 + _blossom_index = new IntNodeMap(_graph);
4.2209 + _blossom_set = new BlossomSet(*_blossom_index);
4.2210 + _blossom_data = new RangeMap<BlossomData>(_blossom_num);
4.2211 + }
4.2212 +
4.2213 + if (!_node_index) {
4.2214 + _node_index = new IntNodeMap(_graph);
4.2215 + _node_heap_index = new IntArcMap(_graph);
4.2216 + _node_data = new RangeMap<NodeData>(_node_num,
4.2217 + NodeData(*_node_heap_index));
4.2218 + }
4.2219 +
4.2220 + if (!_tree_set) {
4.2221 + _tree_set_index = new IntIntMap(_blossom_num);
4.2222 + _tree_set = new TreeSet(*_tree_set_index);
4.2223 + }
4.2224 + if (!_delta2) {
4.2225 + _delta2_index = new IntIntMap(_blossom_num);
4.2226 + _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
4.2227 + }
4.2228 + if (!_delta3) {
4.2229 + _delta3_index = new IntEdgeMap(_graph);
4.2230 + _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
4.2231 + }
4.2232 + if (!_delta4) {
4.2233 + _delta4_index = new IntIntMap(_blossom_num);
4.2234 + _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
4.2235 + }
4.2236 + }
4.2237 +
4.2238 + void destroyStructures() {
4.2239 + _node_num = countNodes(_graph);
4.2240 + _blossom_num = _node_num * 3 / 2;
4.2241 +
4.2242 + if (_matching) {
4.2243 + delete _matching;
4.2244 + }
4.2245 + if (_node_potential) {
4.2246 + delete _node_potential;
4.2247 + }
4.2248 + if (_blossom_set) {
4.2249 + delete _blossom_index;
4.2250 + delete _blossom_set;
4.2251 + delete _blossom_data;
4.2252 + }
4.2253 +
4.2254 + if (_node_index) {
4.2255 + delete _node_index;
4.2256 + delete _node_heap_index;
4.2257 + delete _node_data;
4.2258 + }
4.2259 +
4.2260 + if (_tree_set) {
4.2261 + delete _tree_set_index;
4.2262 + delete _tree_set;
4.2263 + }
4.2264 + if (_delta2) {
4.2265 + delete _delta2_index;
4.2266 + delete _delta2;
4.2267 + }
4.2268 + if (_delta3) {
4.2269 + delete _delta3_index;
4.2270 + delete _delta3;
4.2271 + }
4.2272 + if (_delta4) {
4.2273 + delete _delta4_index;
4.2274 + delete _delta4;
4.2275 + }
4.2276 + }
4.2277 +
4.2278 + void matchedToEven(int blossom, int tree) {
4.2279 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
4.2280 + _delta2->erase(blossom);
4.2281 + }
4.2282 +
4.2283 + if (!_blossom_set->trivial(blossom)) {
4.2284 + (*_blossom_data)[blossom].pot -=
4.2285 + 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
4.2286 + }
4.2287 +
4.2288 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.2289 + n != INVALID; ++n) {
4.2290 +
4.2291 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
4.2292 + int ni = (*_node_index)[n];
4.2293 +
4.2294 + (*_node_data)[ni].heap.clear();
4.2295 + (*_node_data)[ni].heap_index.clear();
4.2296 +
4.2297 + (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
4.2298 +
4.2299 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
4.2300 + Node v = _graph.source(e);
4.2301 + int vb = _blossom_set->find(v);
4.2302 + int vi = (*_node_index)[v];
4.2303 +
4.2304 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.2305 + dualScale * _weight[e];
4.2306 +
4.2307 + if ((*_blossom_data)[vb].status == EVEN) {
4.2308 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
4.2309 + _delta3->push(e, rw / 2);
4.2310 + }
4.2311 + } else {
4.2312 + typename std::map<int, Arc>::iterator it =
4.2313 + (*_node_data)[vi].heap_index.find(tree);
4.2314 +
4.2315 + if (it != (*_node_data)[vi].heap_index.end()) {
4.2316 + if ((*_node_data)[vi].heap[it->second] > rw) {
4.2317 + (*_node_data)[vi].heap.replace(it->second, e);
4.2318 + (*_node_data)[vi].heap.decrease(e, rw);
4.2319 + it->second = e;
4.2320 + }
4.2321 + } else {
4.2322 + (*_node_data)[vi].heap.push(e, rw);
4.2323 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
4.2324 + }
4.2325 +
4.2326 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
4.2327 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
4.2328 +
4.2329 + if ((*_blossom_data)[vb].status == MATCHED) {
4.2330 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
4.2331 + _delta2->push(vb, _blossom_set->classPrio(vb) -
4.2332 + (*_blossom_data)[vb].offset);
4.2333 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
4.2334 + (*_blossom_data)[vb].offset){
4.2335 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
4.2336 + (*_blossom_data)[vb].offset);
4.2337 + }
4.2338 + }
4.2339 + }
4.2340 + }
4.2341 + }
4.2342 + }
4.2343 + (*_blossom_data)[blossom].offset = 0;
4.2344 + }
4.2345 +
4.2346 + void matchedToOdd(int blossom) {
4.2347 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
4.2348 + _delta2->erase(blossom);
4.2349 + }
4.2350 + (*_blossom_data)[blossom].offset += _delta_sum;
4.2351 + if (!_blossom_set->trivial(blossom)) {
4.2352 + _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
4.2353 + (*_blossom_data)[blossom].offset);
4.2354 + }
4.2355 + }
4.2356 +
4.2357 + void evenToMatched(int blossom, int tree) {
4.2358 + if (!_blossom_set->trivial(blossom)) {
4.2359 + (*_blossom_data)[blossom].pot += 2 * _delta_sum;
4.2360 + }
4.2361 +
4.2362 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.2363 + n != INVALID; ++n) {
4.2364 + int ni = (*_node_index)[n];
4.2365 + (*_node_data)[ni].pot -= _delta_sum;
4.2366 +
4.2367 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
4.2368 + Node v = _graph.source(e);
4.2369 + int vb = _blossom_set->find(v);
4.2370 + int vi = (*_node_index)[v];
4.2371 +
4.2372 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.2373 + dualScale * _weight[e];
4.2374 +
4.2375 + if (vb == blossom) {
4.2376 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.2377 + _delta3->erase(e);
4.2378 + }
4.2379 + } else if ((*_blossom_data)[vb].status == EVEN) {
4.2380 +
4.2381 + if (_delta3->state(e) == _delta3->IN_HEAP) {
4.2382 + _delta3->erase(e);
4.2383 + }
4.2384 +
4.2385 + int vt = _tree_set->find(vb);
4.2386 +
4.2387 + if (vt != tree) {
4.2388 +
4.2389 + Arc r = _graph.oppositeArc(e);
4.2390 +
4.2391 + typename std::map<int, Arc>::iterator it =
4.2392 + (*_node_data)[ni].heap_index.find(vt);
4.2393 +
4.2394 + if (it != (*_node_data)[ni].heap_index.end()) {
4.2395 + if ((*_node_data)[ni].heap[it->second] > rw) {
4.2396 + (*_node_data)[ni].heap.replace(it->second, r);
4.2397 + (*_node_data)[ni].heap.decrease(r, rw);
4.2398 + it->second = r;
4.2399 + }
4.2400 + } else {
4.2401 + (*_node_data)[ni].heap.push(r, rw);
4.2402 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
4.2403 + }
4.2404 +
4.2405 + if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
4.2406 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
4.2407 +
4.2408 + if (_delta2->state(blossom) != _delta2->IN_HEAP) {
4.2409 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
4.2410 + (*_blossom_data)[blossom].offset);
4.2411 + } else if ((*_delta2)[blossom] >
4.2412 + _blossom_set->classPrio(blossom) -
4.2413 + (*_blossom_data)[blossom].offset){
4.2414 + _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
4.2415 + (*_blossom_data)[blossom].offset);
4.2416 + }
4.2417 + }
4.2418 + }
4.2419 + } else {
4.2420 +
4.2421 + typename std::map<int, Arc>::iterator it =
4.2422 + (*_node_data)[vi].heap_index.find(tree);
4.2423 +
4.2424 + if (it != (*_node_data)[vi].heap_index.end()) {
4.2425 + (*_node_data)[vi].heap.erase(it->second);
4.2426 + (*_node_data)[vi].heap_index.erase(it);
4.2427 + if ((*_node_data)[vi].heap.empty()) {
4.2428 + _blossom_set->increase(v, std::numeric_limits<Value>::max());
4.2429 + } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
4.2430 + _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
4.2431 + }
4.2432 +
4.2433 + if ((*_blossom_data)[vb].status == MATCHED) {
4.2434 + if (_blossom_set->classPrio(vb) ==
4.2435 + std::numeric_limits<Value>::max()) {
4.2436 + _delta2->erase(vb);
4.2437 + } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
4.2438 + (*_blossom_data)[vb].offset) {
4.2439 + _delta2->increase(vb, _blossom_set->classPrio(vb) -
4.2440 + (*_blossom_data)[vb].offset);
4.2441 + }
4.2442 + }
4.2443 + }
4.2444 + }
4.2445 + }
4.2446 + }
4.2447 + }
4.2448 +
4.2449 + void oddToMatched(int blossom) {
4.2450 + (*_blossom_data)[blossom].offset -= _delta_sum;
4.2451 +
4.2452 + if (_blossom_set->classPrio(blossom) !=
4.2453 + std::numeric_limits<Value>::max()) {
4.2454 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
4.2455 + (*_blossom_data)[blossom].offset);
4.2456 + }
4.2457 +
4.2458 + if (!_blossom_set->trivial(blossom)) {
4.2459 + _delta4->erase(blossom);
4.2460 + }
4.2461 + }
4.2462 +
4.2463 + void oddToEven(int blossom, int tree) {
4.2464 + if (!_blossom_set->trivial(blossom)) {
4.2465 + _delta4->erase(blossom);
4.2466 + (*_blossom_data)[blossom].pot -=
4.2467 + 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
4.2468 + }
4.2469 +
4.2470 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
4.2471 + n != INVALID; ++n) {
4.2472 + int ni = (*_node_index)[n];
4.2473 +
4.2474 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
4.2475 +
4.2476 + (*_node_data)[ni].heap.clear();
4.2477 + (*_node_data)[ni].heap_index.clear();
4.2478 + (*_node_data)[ni].pot +=
4.2479 + 2 * _delta_sum - (*_blossom_data)[blossom].offset;
4.2480 +
4.2481 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
4.2482 + Node v = _graph.source(e);
4.2483 + int vb = _blossom_set->find(v);
4.2484 + int vi = (*_node_index)[v];
4.2485 +
4.2486 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
4.2487 + dualScale * _weight[e];
4.2488 +
4.2489 + if ((*_blossom_data)[vb].status == EVEN) {
4.2490 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
4.2491 + _delta3->push(e, rw / 2);
4.2492 + }
4.2493 + } else {
4.2494 +
4.2495 + typename std::map<int, Arc>::iterator it =
4.2496 + (*_node_data)[vi].heap_index.find(tree);
4.2497 +
4.2498 + if (it != (*_node_data)[vi].heap_index.end()) {
4.2499 + if ((*_node_data)[vi].heap[it->second] > rw) {
4.2500 + (*_node_data)[vi].heap.replace(it->second, e);
4.2501 + (*_node_data)[vi].heap.decrease(e, rw);
4.2502 + it->second = e;
4.2503 + }
4.2504 + } else {
4.2505 + (*_node_data)[vi].heap.push(e, rw);
4.2506 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
4.2507 + }
4.2508 +
4.2509 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
4.2510 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
4.2511 +
4.2512 + if ((*_blossom_data)[vb].status == MATCHED) {
4.2513 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
4.2514 + _delta2->push(vb, _blossom_set->classPrio(vb) -
4.2515 + (*_blossom_data)[vb].offset);
4.2516 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
4.2517 + (*_blossom_data)[vb].offset) {
4.2518 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
4.2519 + (*_blossom_data)[vb].offset);
4.2520 + }
4.2521 + }
4.2522 + }
4.2523 + }
4.2524 + }
4.2525 + }
4.2526 + (*_blossom_data)[blossom].offset = 0;
4.2527 + }
4.2528 +
4.2529 + void alternatePath(int even, int tree) {
4.2530 + int odd;
4.2531 +
4.2532 + evenToMatched(even, tree);
4.2533 + (*_blossom_data)[even].status = MATCHED;
4.2534 +
4.2535 + while ((*_blossom_data)[even].pred != INVALID) {
4.2536 + odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
4.2537 + (*_blossom_data)[odd].status = MATCHED;
4.2538 + oddToMatched(odd);
4.2539 + (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
4.2540 +
4.2541 + even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
4.2542 + (*_blossom_data)[even].status = MATCHED;
4.2543 + evenToMatched(even, tree);
4.2544 + (*_blossom_data)[even].next =
4.2545 + _graph.oppositeArc((*_blossom_data)[odd].pred);
4.2546 + }
4.2547 +
4.2548 + }
4.2549 +
4.2550 + void destroyTree(int tree) {
4.2551 + for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
4.2552 + if ((*_blossom_data)[b].status == EVEN) {
4.2553 + (*_blossom_data)[b].status = MATCHED;
4.2554 + evenToMatched(b, tree);
4.2555 + } else if ((*_blossom_data)[b].status == ODD) {
4.2556 + (*_blossom_data)[b].status = MATCHED;
4.2557 + oddToMatched(b);
4.2558 + }
4.2559 + }
4.2560 + _tree_set->eraseClass(tree);
4.2561 + }
4.2562 +
4.2563 + void augmentOnEdge(const Edge& edge) {
4.2564 +
4.2565 + int left = _blossom_set->find(_graph.u(edge));
4.2566 + int right = _blossom_set->find(_graph.v(edge));
4.2567 +
4.2568 + int left_tree = _tree_set->find(left);
4.2569 + alternatePath(left, left_tree);
4.2570 + destroyTree(left_tree);
4.2571 +
4.2572 + int right_tree = _tree_set->find(right);
4.2573 + alternatePath(right, right_tree);
4.2574 + destroyTree(right_tree);
4.2575 +
4.2576 + (*_blossom_data)[left].next = _graph.direct(edge, true);
4.2577 + (*_blossom_data)[right].next = _graph.direct(edge, false);
4.2578 + }
4.2579 +
4.2580 + void extendOnArc(const Arc& arc) {
4.2581 + int base = _blossom_set->find(_graph.target(arc));
4.2582 + int tree = _tree_set->find(base);
4.2583 +
4.2584 + int odd = _blossom_set->find(_graph.source(arc));
4.2585 + _tree_set->insert(odd, tree);
4.2586 + (*_blossom_data)[odd].status = ODD;
4.2587 + matchedToOdd(odd);
4.2588 + (*_blossom_data)[odd].pred = arc;
4.2589 +
4.2590 + int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
4.2591 + (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
4.2592 + _tree_set->insert(even, tree);
4.2593 + (*_blossom_data)[even].status = EVEN;
4.2594 + matchedToEven(even, tree);
4.2595 + }
4.2596 +
4.2597 + void shrinkOnEdge(const Edge& edge, int tree) {
4.2598 + int nca = -1;
4.2599 + std::vector<int> left_path, right_path;
4.2600 +
4.2601 + {
4.2602 + std::set<int> left_set, right_set;
4.2603 + int left = _blossom_set->find(_graph.u(edge));
4.2604 + left_path.push_back(left);
4.2605 + left_set.insert(left);
4.2606 +
4.2607 + int right = _blossom_set->find(_graph.v(edge));
4.2608 + right_path.push_back(right);
4.2609 + right_set.insert(right);
4.2610 +
4.2611 + while (true) {
4.2612 +
4.2613 + if ((*_blossom_data)[left].pred == INVALID) break;
4.2614 +
4.2615 + left =
4.2616 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
4.2617 + left_path.push_back(left);
4.2618 + left =
4.2619 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
4.2620 + left_path.push_back(left);
4.2621 +
4.2622 + left_set.insert(left);
4.2623 +
4.2624 + if (right_set.find(left) != right_set.end()) {
4.2625 + nca = left;
4.2626 + break;
4.2627 + }
4.2628 +
4.2629 + if ((*_blossom_data)[right].pred == INVALID) break;
4.2630 +
4.2631 + right =
4.2632 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
4.2633 + right_path.push_back(right);
4.2634 + right =
4.2635 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
4.2636 + right_path.push_back(right);
4.2637 +
4.2638 + right_set.insert(right);
4.2639 +
4.2640 + if (left_set.find(right) != left_set.end()) {
4.2641 + nca = right;
4.2642 + break;
4.2643 + }
4.2644 +
4.2645 + }
4.2646 +
4.2647 + if (nca == -1) {
4.2648 + if ((*_blossom_data)[left].pred == INVALID) {
4.2649 + nca = right;
4.2650 + while (left_set.find(nca) == left_set.end()) {
4.2651 + nca =
4.2652 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.2653 + right_path.push_back(nca);
4.2654 + nca =
4.2655 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.2656 + right_path.push_back(nca);
4.2657 + }
4.2658 + } else {
4.2659 + nca = left;
4.2660 + while (right_set.find(nca) == right_set.end()) {
4.2661 + nca =
4.2662 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.2663 + left_path.push_back(nca);
4.2664 + nca =
4.2665 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
4.2666 + left_path.push_back(nca);
4.2667 + }
4.2668 + }
4.2669 + }
4.2670 + }
4.2671 +
4.2672 + std::vector<int> subblossoms;
4.2673 + Arc prev;
4.2674 +
4.2675 + prev = _graph.direct(edge, true);
4.2676 + for (int i = 0; left_path[i] != nca; i += 2) {
4.2677 + subblossoms.push_back(left_path[i]);
4.2678 + (*_blossom_data)[left_path[i]].next = prev;
4.2679 + _tree_set->erase(left_path[i]);
4.2680 +
4.2681 + subblossoms.push_back(left_path[i + 1]);
4.2682 + (*_blossom_data)[left_path[i + 1]].status = EVEN;
4.2683 + oddToEven(left_path[i + 1], tree);
4.2684 + _tree_set->erase(left_path[i + 1]);
4.2685 + prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
4.2686 + }
4.2687 +
4.2688 + int k = 0;
4.2689 + while (right_path[k] != nca) ++k;
4.2690 +
4.2691 + subblossoms.push_back(nca);
4.2692 + (*_blossom_data)[nca].next = prev;
4.2693 +
4.2694 + for (int i = k - 2; i >= 0; i -= 2) {
4.2695 + subblossoms.push_back(right_path[i + 1]);
4.2696 + (*_blossom_data)[right_path[i + 1]].status = EVEN;
4.2697 + oddToEven(right_path[i + 1], tree);
4.2698 + _tree_set->erase(right_path[i + 1]);
4.2699 +
4.2700 + (*_blossom_data)[right_path[i + 1]].next =
4.2701 + (*_blossom_data)[right_path[i + 1]].pred;
4.2702 +
4.2703 + subblossoms.push_back(right_path[i]);
4.2704 + _tree_set->erase(right_path[i]);
4.2705 + }
4.2706 +
4.2707 + int surface =
4.2708 + _blossom_set->join(subblossoms.begin(), subblossoms.end());
4.2709 +
4.2710 + for (int i = 0; i < int(subblossoms.size()); ++i) {
4.2711 + if (!_blossom_set->trivial(subblossoms[i])) {
4.2712 + (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
4.2713 + }
4.2714 + (*_blossom_data)[subblossoms[i]].status = MATCHED;
4.2715 + }
4.2716 +
4.2717 + (*_blossom_data)[surface].pot = -2 * _delta_sum;
4.2718 + (*_blossom_data)[surface].offset = 0;
4.2719 + (*_blossom_data)[surface].status = EVEN;
4.2720 + (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
4.2721 + (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
4.2722 +
4.2723 + _tree_set->insert(surface, tree);
4.2724 + _tree_set->erase(nca);
4.2725 + }
4.2726 +
4.2727 + void splitBlossom(int blossom) {
4.2728 + Arc next = (*_blossom_data)[blossom].next;
4.2729 + Arc pred = (*_blossom_data)[blossom].pred;
4.2730 +
4.2731 + int tree = _tree_set->find(blossom);
4.2732 +
4.2733 + (*_blossom_data)[blossom].status = MATCHED;
4.2734 + oddToMatched(blossom);
4.2735 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
4.2736 + _delta2->erase(blossom);
4.2737 + }
4.2738 +
4.2739 + std::vector<int> subblossoms;
4.2740 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
4.2741 +
4.2742 + Value offset = (*_blossom_data)[blossom].offset;
4.2743 + int b = _blossom_set->find(_graph.source(pred));
4.2744 + int d = _blossom_set->find(_graph.source(next));
4.2745 +
4.2746 + int ib = -1, id = -1;
4.2747 + for (int i = 0; i < int(subblossoms.size()); ++i) {
4.2748 + if (subblossoms[i] == b) ib = i;
4.2749 + if (subblossoms[i] == d) id = i;
4.2750 +
4.2751 + (*_blossom_data)[subblossoms[i]].offset = offset;
4.2752 + if (!_blossom_set->trivial(subblossoms[i])) {
4.2753 + (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
4.2754 + }
4.2755 + if (_blossom_set->classPrio(subblossoms[i]) !=
4.2756 + std::numeric_limits<Value>::max()) {
4.2757 + _delta2->push(subblossoms[i],
4.2758 + _blossom_set->classPrio(subblossoms[i]) -
4.2759 + (*_blossom_data)[subblossoms[i]].offset);
4.2760 + }
4.2761 + }
4.2762 +
4.2763 + if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
4.2764 + for (int i = (id + 1) % subblossoms.size();
4.2765 + i != ib; i = (i + 2) % subblossoms.size()) {
4.2766 + int sb = subblossoms[i];
4.2767 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.2768 + (*_blossom_data)[sb].next =
4.2769 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.2770 + }
4.2771 +
4.2772 + for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
4.2773 + int sb = subblossoms[i];
4.2774 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.2775 + int ub = subblossoms[(i + 2) % subblossoms.size()];
4.2776 +
4.2777 + (*_blossom_data)[sb].status = ODD;
4.2778 + matchedToOdd(sb);
4.2779 + _tree_set->insert(sb, tree);
4.2780 + (*_blossom_data)[sb].pred = pred;
4.2781 + (*_blossom_data)[sb].next =
4.2782 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.2783 +
4.2784 + pred = (*_blossom_data)[ub].next;
4.2785 +
4.2786 + (*_blossom_data)[tb].status = EVEN;
4.2787 + matchedToEven(tb, tree);
4.2788 + _tree_set->insert(tb, tree);
4.2789 + (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
4.2790 + }
4.2791 +
4.2792 + (*_blossom_data)[subblossoms[id]].status = ODD;
4.2793 + matchedToOdd(subblossoms[id]);
4.2794 + _tree_set->insert(subblossoms[id], tree);
4.2795 + (*_blossom_data)[subblossoms[id]].next = next;
4.2796 + (*_blossom_data)[subblossoms[id]].pred = pred;
4.2797 +
4.2798 + } else {
4.2799 +
4.2800 + for (int i = (ib + 1) % subblossoms.size();
4.2801 + i != id; i = (i + 2) % subblossoms.size()) {
4.2802 + int sb = subblossoms[i];
4.2803 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.2804 + (*_blossom_data)[sb].next =
4.2805 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.2806 + }
4.2807 +
4.2808 + for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
4.2809 + int sb = subblossoms[i];
4.2810 + int tb = subblossoms[(i + 1) % subblossoms.size()];
4.2811 + int ub = subblossoms[(i + 2) % subblossoms.size()];
4.2812 +
4.2813 + (*_blossom_data)[sb].status = ODD;
4.2814 + matchedToOdd(sb);
4.2815 + _tree_set->insert(sb, tree);
4.2816 + (*_blossom_data)[sb].next = next;
4.2817 + (*_blossom_data)[sb].pred =
4.2818 + _graph.oppositeArc((*_blossom_data)[tb].next);
4.2819 +
4.2820 + (*_blossom_data)[tb].status = EVEN;
4.2821 + matchedToEven(tb, tree);
4.2822 + _tree_set->insert(tb, tree);
4.2823 + (*_blossom_data)[tb].pred =
4.2824 + (*_blossom_data)[tb].next =
4.2825 + _graph.oppositeArc((*_blossom_data)[ub].next);
4.2826 + next = (*_blossom_data)[ub].next;
4.2827 + }
4.2828 +
4.2829 + (*_blossom_data)[subblossoms[ib]].status = ODD;
4.2830 + matchedToOdd(subblossoms[ib]);
4.2831 + _tree_set->insert(subblossoms[ib], tree);
4.2832 + (*_blossom_data)[subblossoms[ib]].next = next;
4.2833 + (*_blossom_data)[subblossoms[ib]].pred = pred;
4.2834 + }
4.2835 + _tree_set->erase(blossom);
4.2836 + }
4.2837 +
4.2838 + void extractBlossom(int blossom, const Node& base, const Arc& matching) {
4.2839 + if (_blossom_set->trivial(blossom)) {
4.2840 + int bi = (*_node_index)[base];
4.2841 + Value pot = (*_node_data)[bi].pot;
4.2842 +
4.2843 + (*_matching)[base] = matching;
4.2844 + _blossom_node_list.push_back(base);
4.2845 + (*_node_potential)[base] = pot;
4.2846 + } else {
4.2847 +
4.2848 + Value pot = (*_blossom_data)[blossom].pot;
4.2849 + int bn = _blossom_node_list.size();
4.2850 +
4.2851 + std::vector<int> subblossoms;
4.2852 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
4.2853 + int b = _blossom_set->find(base);
4.2854 + int ib = -1;
4.2855 + for (int i = 0; i < int(subblossoms.size()); ++i) {
4.2856 + if (subblossoms[i] == b) { ib = i; break; }
4.2857 + }
4.2858 +
4.2859 + for (int i = 1; i < int(subblossoms.size()); i += 2) {
4.2860 + int sb = subblossoms[(ib + i) % subblossoms.size()];
4.2861 + int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
4.2862 +
4.2863 + Arc m = (*_blossom_data)[tb].next;
4.2864 + extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
4.2865 + extractBlossom(tb, _graph.source(m), m);
4.2866 + }
4.2867 + extractBlossom(subblossoms[ib], base, matching);
4.2868 +
4.2869 + int en = _blossom_node_list.size();
4.2870 +
4.2871 + _blossom_potential.push_back(BlossomVariable(bn, en, pot));
4.2872 + }
4.2873 + }
4.2874 +
4.2875 + void extractMatching() {
4.2876 + std::vector<int> blossoms;
4.2877 + for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
4.2878 + blossoms.push_back(c);
4.2879 + }
4.2880 +
4.2881 + for (int i = 0; i < int(blossoms.size()); ++i) {
4.2882 +
4.2883 + Value offset = (*_blossom_data)[blossoms[i]].offset;
4.2884 + (*_blossom_data)[blossoms[i]].pot += 2 * offset;
4.2885 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
4.2886 + n != INVALID; ++n) {
4.2887 + (*_node_data)[(*_node_index)[n]].pot -= offset;
4.2888 + }
4.2889 +
4.2890 + Arc matching = (*_blossom_data)[blossoms[i]].next;
4.2891 + Node base = _graph.source(matching);
4.2892 + extractBlossom(blossoms[i], base, matching);
4.2893 + }
4.2894 + }
4.2895 +
4.2896 + public:
4.2897 +
4.2898 + /// \brief Constructor
4.2899 + ///
4.2900 + /// Constructor.
4.2901 + MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
4.2902 + : _graph(graph), _weight(weight), _matching(0),
4.2903 + _node_potential(0), _blossom_potential(), _blossom_node_list(),
4.2904 + _node_num(0), _blossom_num(0),
4.2905 +
4.2906 + _blossom_index(0), _blossom_set(0), _blossom_data(0),
4.2907 + _node_index(0), _node_heap_index(0), _node_data(0),
4.2908 + _tree_set_index(0), _tree_set(0),
4.2909 +
4.2910 + _delta2_index(0), _delta2(0),
4.2911 + _delta3_index(0), _delta3(0),
4.2912 + _delta4_index(0), _delta4(0),
4.2913 +
4.2914 + _delta_sum() {}
4.2915 +
4.2916 + ~MaxWeightedPerfectMatching() {
4.2917 + destroyStructures();
4.2918 + }
4.2919 +
4.2920 + /// \name Execution Control
4.2921 + /// The simplest way to execute the algorithm is to use the
4.2922 + /// \ref run() member function.
4.2923 +
4.2924 + ///@{
4.2925 +
4.2926 + /// \brief Initialize the algorithm
4.2927 + ///
4.2928 + /// This function initializes the algorithm.
4.2929 + void init() {
4.2930 + createStructures();
4.2931 +
4.2932 + for (ArcIt e(_graph); e != INVALID; ++e) {
4.2933 + (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
4.2934 + }
4.2935 + for (EdgeIt e(_graph); e != INVALID; ++e) {
4.2936 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
4.2937 + }
4.2938 + for (int i = 0; i < _blossom_num; ++i) {
4.2939 + (*_delta2_index)[i] = _delta2->PRE_HEAP;
4.2940 + (*_delta4_index)[i] = _delta4->PRE_HEAP;
4.2941 + }
4.2942 +
4.2943 + int index = 0;
4.2944 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.2945 + Value max = - std::numeric_limits<Value>::max();
4.2946 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
4.2947 + if (_graph.target(e) == n) continue;
4.2948 + if ((dualScale * _weight[e]) / 2 > max) {
4.2949 + max = (dualScale * _weight[e]) / 2;
4.2950 + }
4.2951 + }
4.2952 + (*_node_index)[n] = index;
4.2953 + (*_node_data)[index].pot = max;
4.2954 + int blossom =
4.2955 + _blossom_set->insert(n, std::numeric_limits<Value>::max());
4.2956 +
4.2957 + _tree_set->insert(blossom);
4.2958 +
4.2959 + (*_blossom_data)[blossom].status = EVEN;
4.2960 + (*_blossom_data)[blossom].pred = INVALID;
4.2961 + (*_blossom_data)[blossom].next = INVALID;
4.2962 + (*_blossom_data)[blossom].pot = 0;
4.2963 + (*_blossom_data)[blossom].offset = 0;
4.2964 + ++index;
4.2965 + }
4.2966 + for (EdgeIt e(_graph); e != INVALID; ++e) {
4.2967 + int si = (*_node_index)[_graph.u(e)];
4.2968 + int ti = (*_node_index)[_graph.v(e)];
4.2969 + if (_graph.u(e) != _graph.v(e)) {
4.2970 + _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
4.2971 + dualScale * _weight[e]) / 2);
4.2972 + }
4.2973 + }
4.2974 + }
4.2975 +
4.2976 + /// \brief Start the algorithm
4.2977 + ///
4.2978 + /// This function starts the algorithm.
4.2979 + ///
4.2980 + /// \pre \ref init() must be called before using this function.
4.2981 + bool start() {
4.2982 + enum OpType {
4.2983 + D2, D3, D4
4.2984 + };
4.2985 +
4.2986 + int unmatched = _node_num;
4.2987 + while (unmatched > 0) {
4.2988 + Value d2 = !_delta2->empty() ?
4.2989 + _delta2->prio() : std::numeric_limits<Value>::max();
4.2990 +
4.2991 + Value d3 = !_delta3->empty() ?
4.2992 + _delta3->prio() : std::numeric_limits<Value>::max();
4.2993 +
4.2994 + Value d4 = !_delta4->empty() ?
4.2995 + _delta4->prio() : std::numeric_limits<Value>::max();
4.2996 +
4.2997 + _delta_sum = d2; OpType ot = D2;
4.2998 + if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
4.2999 + if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
4.3000 +
4.3001 + if (_delta_sum == std::numeric_limits<Value>::max()) {
4.3002 + return false;
4.3003 + }
4.3004 +
4.3005 + switch (ot) {
4.3006 + case D2:
4.3007 + {
4.3008 + int blossom = _delta2->top();
4.3009 + Node n = _blossom_set->classTop(blossom);
4.3010 + Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
4.3011 + extendOnArc(e);
4.3012 + }
4.3013 + break;
4.3014 + case D3:
4.3015 + {
4.3016 + Edge e = _delta3->top();
4.3017 +
4.3018 + int left_blossom = _blossom_set->find(_graph.u(e));
4.3019 + int right_blossom = _blossom_set->find(_graph.v(e));
4.3020 +
4.3021 + if (left_blossom == right_blossom) {
4.3022 + _delta3->pop();
4.3023 + } else {
4.3024 + int left_tree = _tree_set->find(left_blossom);
4.3025 + int right_tree = _tree_set->find(right_blossom);
4.3026 +
4.3027 + if (left_tree == right_tree) {
4.3028 + shrinkOnEdge(e, left_tree);
4.3029 + } else {
4.3030 + augmentOnEdge(e);
4.3031 + unmatched -= 2;
4.3032 + }
4.3033 + }
4.3034 + } break;
4.3035 + case D4:
4.3036 + splitBlossom(_delta4->top());
4.3037 + break;
4.3038 + }
4.3039 + }
4.3040 + extractMatching();
4.3041 + return true;
4.3042 + }
4.3043 +
4.3044 + /// \brief Run the algorithm.
4.3045 + ///
4.3046 + /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
4.3047 + ///
4.3048 + /// \note mwpm.run() is just a shortcut of the following code.
4.3049 + /// \code
4.3050 + /// mwpm.init();
4.3051 + /// mwpm.start();
4.3052 + /// \endcode
4.3053 + bool run() {
4.3054 + init();
4.3055 + return start();
4.3056 + }
4.3057 +
4.3058 + /// @}
4.3059 +
4.3060 + /// \name Primal Solution
4.3061 + /// Functions to get the primal solution, i.e. the maximum weighted
4.3062 + /// perfect matching.\n
4.3063 + /// Either \ref run() or \ref start() function should be called before
4.3064 + /// using them.
4.3065 +
4.3066 + /// @{
4.3067 +
4.3068 + /// \brief Return the weight of the matching.
4.3069 + ///
4.3070 + /// This function returns the weight of the found matching.
4.3071 + ///
4.3072 + /// \pre Either run() or start() must be called before using this function.
4.3073 + Value matchingWeight() const {
4.3074 + Value sum = 0;
4.3075 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.3076 + if ((*_matching)[n] != INVALID) {
4.3077 + sum += _weight[(*_matching)[n]];
4.3078 + }
4.3079 + }
4.3080 + return sum /= 2;
4.3081 + }
4.3082 +
4.3083 + /// \brief Return \c true if the given edge is in the matching.
4.3084 + ///
4.3085 + /// This function returns \c true if the given edge is in the found
4.3086 + /// matching.
4.3087 + ///
4.3088 + /// \pre Either run() or start() must be called before using this function.
4.3089 + bool matching(const Edge& edge) const {
4.3090 + return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
4.3091 + }
4.3092 +
4.3093 + /// \brief Return the matching arc (or edge) incident to the given node.
4.3094 + ///
4.3095 + /// This function returns the matching arc (or edge) incident to the
4.3096 + /// given node in the found matching or \c INVALID if the node is
4.3097 + /// not covered by the matching.
4.3098 + ///
4.3099 + /// \pre Either run() or start() must be called before using this function.
4.3100 + Arc matching(const Node& node) const {
4.3101 + return (*_matching)[node];
4.3102 + }
4.3103 +
4.3104 + /// \brief Return a const reference to the matching map.
4.3105 + ///
4.3106 + /// This function returns a const reference to a node map that stores
4.3107 + /// the matching arc (or edge) incident to each node.
4.3108 + const MatchingMap& matchingMap() const {
4.3109 + return *_matching;
4.3110 + }
4.3111 +
4.3112 + /// \brief Return the mate of the given node.
4.3113 + ///
4.3114 + /// This function returns the mate of the given node in the found
4.3115 + /// matching or \c INVALID if the node is not covered by the matching.
4.3116 + ///
4.3117 + /// \pre Either run() or start() must be called before using this function.
4.3118 + Node mate(const Node& node) const {
4.3119 + return _graph.target((*_matching)[node]);
4.3120 + }
4.3121 +
4.3122 + /// @}
4.3123 +
4.3124 + /// \name Dual Solution
4.3125 + /// Functions to get the dual solution.\n
4.3126 + /// Either \ref run() or \ref start() function should be called before
4.3127 + /// using them.
4.3128 +
4.3129 + /// @{
4.3130 +
4.3131 + /// \brief Return the value of the dual solution.
4.3132 + ///
4.3133 + /// This function returns the value of the dual solution.
4.3134 + /// It should be equal to the primal value scaled by \ref dualScale
4.3135 + /// "dual scale".
4.3136 + ///
4.3137 + /// \pre Either run() or start() must be called before using this function.
4.3138 + Value dualValue() const {
4.3139 + Value sum = 0;
4.3140 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.3141 + sum += nodeValue(n);
4.3142 + }
4.3143 + for (int i = 0; i < blossomNum(); ++i) {
4.3144 + sum += blossomValue(i) * (blossomSize(i) / 2);
4.3145 + }
4.3146 + return sum;
4.3147 + }
4.3148 +
4.3149 + /// \brief Return the dual value (potential) of the given node.
4.3150 + ///
4.3151 + /// This function returns the dual value (potential) of the given node.
4.3152 + ///
4.3153 + /// \pre Either run() or start() must be called before using this function.
4.3154 + Value nodeValue(const Node& n) const {
4.3155 + return (*_node_potential)[n];
4.3156 + }
4.3157 +
4.3158 + /// \brief Return the number of the blossoms in the basis.
4.3159 + ///
4.3160 + /// This function returns the number of the blossoms in the basis.
4.3161 + ///
4.3162 + /// \pre Either run() or start() must be called before using this function.
4.3163 + /// \see BlossomIt
4.3164 + int blossomNum() const {
4.3165 + return _blossom_potential.size();
4.3166 + }
4.3167 +
4.3168 + /// \brief Return the number of the nodes in the given blossom.
4.3169 + ///
4.3170 + /// This function returns the number of the nodes in the given blossom.
4.3171 + ///
4.3172 + /// \pre Either run() or start() must be called before using this function.
4.3173 + /// \see BlossomIt
4.3174 + int blossomSize(int k) const {
4.3175 + return _blossom_potential[k].end - _blossom_potential[k].begin;
4.3176 + }
4.3177 +
4.3178 + /// \brief Return the dual value (ptential) of the given blossom.
4.3179 + ///
4.3180 + /// This function returns the dual value (ptential) of the given blossom.
4.3181 + ///
4.3182 + /// \pre Either run() or start() must be called before using this function.
4.3183 + Value blossomValue(int k) const {
4.3184 + return _blossom_potential[k].value;
4.3185 + }
4.3186 +
4.3187 + /// \brief Iterator for obtaining the nodes of a blossom.
4.3188 + ///
4.3189 + /// This class provides an iterator for obtaining the nodes of the
4.3190 + /// given blossom. It lists a subset of the nodes.
4.3191 + /// Before using this iterator, you must allocate a
4.3192 + /// MaxWeightedPerfectMatching class and execute it.
4.3193 + class BlossomIt {
4.3194 + public:
4.3195 +
4.3196 + /// \brief Constructor.
4.3197 + ///
4.3198 + /// Constructor to get the nodes of the given variable.
4.3199 + ///
4.3200 + /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
4.3201 + /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
4.3202 + /// must be called before initializing this iterator.
4.3203 + BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
4.3204 + : _algorithm(&algorithm)
4.3205 + {
4.3206 + _index = _algorithm->_blossom_potential[variable].begin;
4.3207 + _last = _algorithm->_blossom_potential[variable].end;
4.3208 + }
4.3209 +
4.3210 + /// \brief Conversion to \c Node.
4.3211 + ///
4.3212 + /// Conversion to \c Node.
4.3213 + operator Node() const {
4.3214 + return _algorithm->_blossom_node_list[_index];
4.3215 + }
4.3216 +
4.3217 + /// \brief Increment operator.
4.3218 + ///
4.3219 + /// Increment operator.
4.3220 + BlossomIt& operator++() {
4.3221 + ++_index;
4.3222 + return *this;
4.3223 + }
4.3224 +
4.3225 + /// \brief Validity checking
4.3226 + ///
4.3227 + /// This function checks whether the iterator is invalid.
4.3228 + bool operator==(Invalid) const { return _index == _last; }
4.3229 +
4.3230 + /// \brief Validity checking
4.3231 + ///
4.3232 + /// This function checks whether the iterator is valid.
4.3233 + bool operator!=(Invalid) const { return _index != _last; }
4.3234 +
4.3235 + private:
4.3236 + const MaxWeightedPerfectMatching* _algorithm;
4.3237 + int _last;
4.3238 + int _index;
4.3239 + };
4.3240 +
4.3241 + /// @}
4.3242 +
4.3243 + };
4.3244 +
4.3245 +} //END OF NAMESPACE LEMON
4.3246 +
4.3247 +#endif //LEMON_MAX_MATCHING_H
5.1 --- a/lemon/max_matching.h Tue Apr 21 10:34:49 2009 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,3107 +0,0 @@
5.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
5.5 - *
5.6 - * This file is a part of LEMON, a generic C++ optimization library.
5.7 - *
5.8 - * Copyright (C) 2003-2009
5.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
5.11 - *
5.12 - * Permission to use, modify and distribute this software is granted
5.13 - * provided that this copyright notice appears in all copies. For
5.14 - * precise terms see the accompanying LICENSE file.
5.15 - *
5.16 - * This software is provided "AS IS" with no warranty of any kind,
5.17 - * express or implied, and with no claim as to its suitability for any
5.18 - * purpose.
5.19 - *
5.20 - */
5.21 -
5.22 -#ifndef LEMON_MAX_MATCHING_H
5.23 -#define LEMON_MAX_MATCHING_H
5.24 -
5.25 -#include <vector>
5.26 -#include <queue>
5.27 -#include <set>
5.28 -#include <limits>
5.29 -
5.30 -#include <lemon/core.h>
5.31 -#include <lemon/unionfind.h>
5.32 -#include <lemon/bin_heap.h>
5.33 -#include <lemon/maps.h>
5.34 -
5.35 -///\ingroup matching
5.36 -///\file
5.37 -///\brief Maximum matching algorithms in general graphs.
5.38 -
5.39 -namespace lemon {
5.40 -
5.41 - /// \ingroup matching
5.42 - ///
5.43 - /// \brief Edmonds' alternating forest maximum matching algorithm.
5.44 - ///
5.45 - /// This class implements Edmonds' alternating forest matching
5.46 - /// algorithm. The algorithm can be started from an arbitrary initial
5.47 - /// matching (the default is the empty one)
5.48 - ///
5.49 - /// The dual solution of the problem is a map of the nodes to
5.50 - /// MaxMatching::Status, having values \c EVEN/D, \c ODD/A and \c
5.51 - /// MATCHED/C showing the Gallai-Edmonds decomposition of the
5.52 - /// graph. The nodes in \c EVEN/D induce a graph with
5.53 - /// factor-critical components, the nodes in \c ODD/A form the
5.54 - /// barrier, and the nodes in \c MATCHED/C induce a graph having a
5.55 - /// perfect matching. The number of the factor-critical components
5.56 - /// minus the number of barrier nodes is a lower bound on the
5.57 - /// unmatched nodes, and the matching is optimal if and only if this bound is
5.58 - /// tight. This decomposition can be attained by calling \c
5.59 - /// decomposition() after running the algorithm.
5.60 - ///
5.61 - /// \param GR The graph type the algorithm runs on.
5.62 - template <typename GR>
5.63 - class MaxMatching {
5.64 - public:
5.65 -
5.66 - typedef GR Graph;
5.67 - typedef typename Graph::template NodeMap<typename Graph::Arc>
5.68 - MatchingMap;
5.69 -
5.70 - ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
5.71 - ///
5.72 - ///Indicates the Gallai-Edmonds decomposition of the graph. The
5.73 - ///nodes with Status \c EVEN/D induce a graph with factor-critical
5.74 - ///components, the nodes in \c ODD/A form the canonical barrier,
5.75 - ///and the nodes in \c MATCHED/C induce a graph having a perfect
5.76 - ///matching.
5.77 - enum Status {
5.78 - EVEN = 1, D = 1, MATCHED = 0, C = 0, ODD = -1, A = -1, UNMATCHED = -2
5.79 - };
5.80 -
5.81 - typedef typename Graph::template NodeMap<Status> StatusMap;
5.82 -
5.83 - private:
5.84 -
5.85 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
5.86 -
5.87 - typedef UnionFindEnum<IntNodeMap> BlossomSet;
5.88 - typedef ExtendFindEnum<IntNodeMap> TreeSet;
5.89 - typedef RangeMap<Node> NodeIntMap;
5.90 - typedef MatchingMap EarMap;
5.91 - typedef std::vector<Node> NodeQueue;
5.92 -
5.93 - const Graph& _graph;
5.94 - MatchingMap* _matching;
5.95 - StatusMap* _status;
5.96 -
5.97 - EarMap* _ear;
5.98 -
5.99 - IntNodeMap* _blossom_set_index;
5.100 - BlossomSet* _blossom_set;
5.101 - NodeIntMap* _blossom_rep;
5.102 -
5.103 - IntNodeMap* _tree_set_index;
5.104 - TreeSet* _tree_set;
5.105 -
5.106 - NodeQueue _node_queue;
5.107 - int _process, _postpone, _last;
5.108 -
5.109 - int _node_num;
5.110 -
5.111 - private:
5.112 -
5.113 - void createStructures() {
5.114 - _node_num = countNodes(_graph);
5.115 - if (!_matching) {
5.116 - _matching = new MatchingMap(_graph);
5.117 - }
5.118 - if (!_status) {
5.119 - _status = new StatusMap(_graph);
5.120 - }
5.121 - if (!_ear) {
5.122 - _ear = new EarMap(_graph);
5.123 - }
5.124 - if (!_blossom_set) {
5.125 - _blossom_set_index = new IntNodeMap(_graph);
5.126 - _blossom_set = new BlossomSet(*_blossom_set_index);
5.127 - }
5.128 - if (!_blossom_rep) {
5.129 - _blossom_rep = new NodeIntMap(_node_num);
5.130 - }
5.131 - if (!_tree_set) {
5.132 - _tree_set_index = new IntNodeMap(_graph);
5.133 - _tree_set = new TreeSet(*_tree_set_index);
5.134 - }
5.135 - _node_queue.resize(_node_num);
5.136 - }
5.137 -
5.138 - void destroyStructures() {
5.139 - if (_matching) {
5.140 - delete _matching;
5.141 - }
5.142 - if (_status) {
5.143 - delete _status;
5.144 - }
5.145 - if (_ear) {
5.146 - delete _ear;
5.147 - }
5.148 - if (_blossom_set) {
5.149 - delete _blossom_set;
5.150 - delete _blossom_set_index;
5.151 - }
5.152 - if (_blossom_rep) {
5.153 - delete _blossom_rep;
5.154 - }
5.155 - if (_tree_set) {
5.156 - delete _tree_set_index;
5.157 - delete _tree_set;
5.158 - }
5.159 - }
5.160 -
5.161 - void processDense(const Node& n) {
5.162 - _process = _postpone = _last = 0;
5.163 - _node_queue[_last++] = n;
5.164 -
5.165 - while (_process != _last) {
5.166 - Node u = _node_queue[_process++];
5.167 - for (OutArcIt a(_graph, u); a != INVALID; ++a) {
5.168 - Node v = _graph.target(a);
5.169 - if ((*_status)[v] == MATCHED) {
5.170 - extendOnArc(a);
5.171 - } else if ((*_status)[v] == UNMATCHED) {
5.172 - augmentOnArc(a);
5.173 - return;
5.174 - }
5.175 - }
5.176 - }
5.177 -
5.178 - while (_postpone != _last) {
5.179 - Node u = _node_queue[_postpone++];
5.180 -
5.181 - for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
5.182 - Node v = _graph.target(a);
5.183 -
5.184 - if ((*_status)[v] == EVEN) {
5.185 - if (_blossom_set->find(u) != _blossom_set->find(v)) {
5.186 - shrinkOnEdge(a);
5.187 - }
5.188 - }
5.189 -
5.190 - while (_process != _last) {
5.191 - Node w = _node_queue[_process++];
5.192 - for (OutArcIt b(_graph, w); b != INVALID; ++b) {
5.193 - Node x = _graph.target(b);
5.194 - if ((*_status)[x] == MATCHED) {
5.195 - extendOnArc(b);
5.196 - } else if ((*_status)[x] == UNMATCHED) {
5.197 - augmentOnArc(b);
5.198 - return;
5.199 - }
5.200 - }
5.201 - }
5.202 - }
5.203 - }
5.204 - }
5.205 -
5.206 - void processSparse(const Node& n) {
5.207 - _process = _last = 0;
5.208 - _node_queue[_last++] = n;
5.209 - while (_process != _last) {
5.210 - Node u = _node_queue[_process++];
5.211 - for (OutArcIt a(_graph, u); a != INVALID; ++a) {
5.212 - Node v = _graph.target(a);
5.213 -
5.214 - if ((*_status)[v] == EVEN) {
5.215 - if (_blossom_set->find(u) != _blossom_set->find(v)) {
5.216 - shrinkOnEdge(a);
5.217 - }
5.218 - } else if ((*_status)[v] == MATCHED) {
5.219 - extendOnArc(a);
5.220 - } else if ((*_status)[v] == UNMATCHED) {
5.221 - augmentOnArc(a);
5.222 - return;
5.223 - }
5.224 - }
5.225 - }
5.226 - }
5.227 -
5.228 - void shrinkOnEdge(const Edge& e) {
5.229 - Node nca = INVALID;
5.230 -
5.231 - {
5.232 - std::set<Node> left_set, right_set;
5.233 -
5.234 - Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
5.235 - left_set.insert(left);
5.236 -
5.237 - Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
5.238 - right_set.insert(right);
5.239 -
5.240 - while (true) {
5.241 - if ((*_matching)[left] == INVALID) break;
5.242 - left = _graph.target((*_matching)[left]);
5.243 - left = (*_blossom_rep)[_blossom_set->
5.244 - find(_graph.target((*_ear)[left]))];
5.245 - if (right_set.find(left) != right_set.end()) {
5.246 - nca = left;
5.247 - break;
5.248 - }
5.249 - left_set.insert(left);
5.250 -
5.251 - if ((*_matching)[right] == INVALID) break;
5.252 - right = _graph.target((*_matching)[right]);
5.253 - right = (*_blossom_rep)[_blossom_set->
5.254 - find(_graph.target((*_ear)[right]))];
5.255 - if (left_set.find(right) != left_set.end()) {
5.256 - nca = right;
5.257 - break;
5.258 - }
5.259 - right_set.insert(right);
5.260 - }
5.261 -
5.262 - if (nca == INVALID) {
5.263 - if ((*_matching)[left] == INVALID) {
5.264 - nca = right;
5.265 - while (left_set.find(nca) == left_set.end()) {
5.266 - nca = _graph.target((*_matching)[nca]);
5.267 - nca =(*_blossom_rep)[_blossom_set->
5.268 - find(_graph.target((*_ear)[nca]))];
5.269 - }
5.270 - } else {
5.271 - nca = left;
5.272 - while (right_set.find(nca) == right_set.end()) {
5.273 - nca = _graph.target((*_matching)[nca]);
5.274 - nca = (*_blossom_rep)[_blossom_set->
5.275 - find(_graph.target((*_ear)[nca]))];
5.276 - }
5.277 - }
5.278 - }
5.279 - }
5.280 -
5.281 - {
5.282 -
5.283 - Node node = _graph.u(e);
5.284 - Arc arc = _graph.direct(e, true);
5.285 - Node base = (*_blossom_rep)[_blossom_set->find(node)];
5.286 -
5.287 - while (base != nca) {
5.288 - (*_ear)[node] = arc;
5.289 -
5.290 - Node n = node;
5.291 - while (n != base) {
5.292 - n = _graph.target((*_matching)[n]);
5.293 - Arc a = (*_ear)[n];
5.294 - n = _graph.target(a);
5.295 - (*_ear)[n] = _graph.oppositeArc(a);
5.296 - }
5.297 - node = _graph.target((*_matching)[base]);
5.298 - _tree_set->erase(base);
5.299 - _tree_set->erase(node);
5.300 - _blossom_set->insert(node, _blossom_set->find(base));
5.301 - (*_status)[node] = EVEN;
5.302 - _node_queue[_last++] = node;
5.303 - arc = _graph.oppositeArc((*_ear)[node]);
5.304 - node = _graph.target((*_ear)[node]);
5.305 - base = (*_blossom_rep)[_blossom_set->find(node)];
5.306 - _blossom_set->join(_graph.target(arc), base);
5.307 - }
5.308 - }
5.309 -
5.310 - (*_blossom_rep)[_blossom_set->find(nca)] = nca;
5.311 -
5.312 - {
5.313 -
5.314 - Node node = _graph.v(e);
5.315 - Arc arc = _graph.direct(e, false);
5.316 - Node base = (*_blossom_rep)[_blossom_set->find(node)];
5.317 -
5.318 - while (base != nca) {
5.319 - (*_ear)[node] = arc;
5.320 -
5.321 - Node n = node;
5.322 - while (n != base) {
5.323 - n = _graph.target((*_matching)[n]);
5.324 - Arc a = (*_ear)[n];
5.325 - n = _graph.target(a);
5.326 - (*_ear)[n] = _graph.oppositeArc(a);
5.327 - }
5.328 - node = _graph.target((*_matching)[base]);
5.329 - _tree_set->erase(base);
5.330 - _tree_set->erase(node);
5.331 - _blossom_set->insert(node, _blossom_set->find(base));
5.332 - (*_status)[node] = EVEN;
5.333 - _node_queue[_last++] = node;
5.334 - arc = _graph.oppositeArc((*_ear)[node]);
5.335 - node = _graph.target((*_ear)[node]);
5.336 - base = (*_blossom_rep)[_blossom_set->find(node)];
5.337 - _blossom_set->join(_graph.target(arc), base);
5.338 - }
5.339 - }
5.340 -
5.341 - (*_blossom_rep)[_blossom_set->find(nca)] = nca;
5.342 - }
5.343 -
5.344 -
5.345 -
5.346 - void extendOnArc(const Arc& a) {
5.347 - Node base = _graph.source(a);
5.348 - Node odd = _graph.target(a);
5.349 -
5.350 - (*_ear)[odd] = _graph.oppositeArc(a);
5.351 - Node even = _graph.target((*_matching)[odd]);
5.352 - (*_blossom_rep)[_blossom_set->insert(even)] = even;
5.353 - (*_status)[odd] = ODD;
5.354 - (*_status)[even] = EVEN;
5.355 - int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
5.356 - _tree_set->insert(odd, tree);
5.357 - _tree_set->insert(even, tree);
5.358 - _node_queue[_last++] = even;
5.359 -
5.360 - }
5.361 -
5.362 - void augmentOnArc(const Arc& a) {
5.363 - Node even = _graph.source(a);
5.364 - Node odd = _graph.target(a);
5.365 -
5.366 - int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
5.367 -
5.368 - (*_matching)[odd] = _graph.oppositeArc(a);
5.369 - (*_status)[odd] = MATCHED;
5.370 -
5.371 - Arc arc = (*_matching)[even];
5.372 - (*_matching)[even] = a;
5.373 -
5.374 - while (arc != INVALID) {
5.375 - odd = _graph.target(arc);
5.376 - arc = (*_ear)[odd];
5.377 - even = _graph.target(arc);
5.378 - (*_matching)[odd] = arc;
5.379 - arc = (*_matching)[even];
5.380 - (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
5.381 - }
5.382 -
5.383 - for (typename TreeSet::ItemIt it(*_tree_set, tree);
5.384 - it != INVALID; ++it) {
5.385 - if ((*_status)[it] == ODD) {
5.386 - (*_status)[it] = MATCHED;
5.387 - } else {
5.388 - int blossom = _blossom_set->find(it);
5.389 - for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
5.390 - jt != INVALID; ++jt) {
5.391 - (*_status)[jt] = MATCHED;
5.392 - }
5.393 - _blossom_set->eraseClass(blossom);
5.394 - }
5.395 - }
5.396 - _tree_set->eraseClass(tree);
5.397 -
5.398 - }
5.399 -
5.400 - public:
5.401 -
5.402 - /// \brief Constructor
5.403 - ///
5.404 - /// Constructor.
5.405 - MaxMatching(const Graph& graph)
5.406 - : _graph(graph), _matching(0), _status(0), _ear(0),
5.407 - _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
5.408 - _tree_set_index(0), _tree_set(0) {}
5.409 -
5.410 - ~MaxMatching() {
5.411 - destroyStructures();
5.412 - }
5.413 -
5.414 - /// \name Execution control
5.415 - /// The simplest way to execute the algorithm is to use the
5.416 - /// \c run() member function.
5.417 - /// \n
5.418 -
5.419 - /// If you need better control on the execution, you must call
5.420 - /// \ref init(), \ref greedyInit() or \ref matchingInit()
5.421 - /// functions first, then you can start the algorithm with the \ref
5.422 - /// startSparse() or startDense() functions.
5.423 -
5.424 - ///@{
5.425 -
5.426 - /// \brief Sets the actual matching to the empty matching.
5.427 - ///
5.428 - /// Sets the actual matching to the empty matching.
5.429 - ///
5.430 - void init() {
5.431 - createStructures();
5.432 - for(NodeIt n(_graph); n != INVALID; ++n) {
5.433 - (*_matching)[n] = INVALID;
5.434 - (*_status)[n] = UNMATCHED;
5.435 - }
5.436 - }
5.437 -
5.438 - ///\brief Finds an initial matching in a greedy way
5.439 - ///
5.440 - ///It finds an initial matching in a greedy way.
5.441 - void greedyInit() {
5.442 - createStructures();
5.443 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.444 - (*_matching)[n] = INVALID;
5.445 - (*_status)[n] = UNMATCHED;
5.446 - }
5.447 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.448 - if ((*_matching)[n] == INVALID) {
5.449 - for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
5.450 - Node v = _graph.target(a);
5.451 - if ((*_matching)[v] == INVALID && v != n) {
5.452 - (*_matching)[n] = a;
5.453 - (*_status)[n] = MATCHED;
5.454 - (*_matching)[v] = _graph.oppositeArc(a);
5.455 - (*_status)[v] = MATCHED;
5.456 - break;
5.457 - }
5.458 - }
5.459 - }
5.460 - }
5.461 - }
5.462 -
5.463 -
5.464 - /// \brief Initialize the matching from a map containing.
5.465 - ///
5.466 - /// Initialize the matching from a \c bool valued \c Edge map. This
5.467 - /// map must have the property that there are no two incident edges
5.468 - /// with true value, ie. it contains a matching.
5.469 - /// \return \c true if the map contains a matching.
5.470 - template <typename MatchingMap>
5.471 - bool matchingInit(const MatchingMap& matching) {
5.472 - createStructures();
5.473 -
5.474 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.475 - (*_matching)[n] = INVALID;
5.476 - (*_status)[n] = UNMATCHED;
5.477 - }
5.478 - for(EdgeIt e(_graph); e!=INVALID; ++e) {
5.479 - if (matching[e]) {
5.480 -
5.481 - Node u = _graph.u(e);
5.482 - if ((*_matching)[u] != INVALID) return false;
5.483 - (*_matching)[u] = _graph.direct(e, true);
5.484 - (*_status)[u] = MATCHED;
5.485 -
5.486 - Node v = _graph.v(e);
5.487 - if ((*_matching)[v] != INVALID) return false;
5.488 - (*_matching)[v] = _graph.direct(e, false);
5.489 - (*_status)[v] = MATCHED;
5.490 - }
5.491 - }
5.492 - return true;
5.493 - }
5.494 -
5.495 - /// \brief Starts Edmonds' algorithm
5.496 - ///
5.497 - /// If runs the original Edmonds' algorithm.
5.498 - void startSparse() {
5.499 - for(NodeIt n(_graph); n != INVALID; ++n) {
5.500 - if ((*_status)[n] == UNMATCHED) {
5.501 - (*_blossom_rep)[_blossom_set->insert(n)] = n;
5.502 - _tree_set->insert(n);
5.503 - (*_status)[n] = EVEN;
5.504 - processSparse(n);
5.505 - }
5.506 - }
5.507 - }
5.508 -
5.509 - /// \brief Starts Edmonds' algorithm.
5.510 - ///
5.511 - /// It runs Edmonds' algorithm with a heuristic of postponing
5.512 - /// shrinks, therefore resulting in a faster algorithm for dense graphs.
5.513 - void startDense() {
5.514 - for(NodeIt n(_graph); n != INVALID; ++n) {
5.515 - if ((*_status)[n] == UNMATCHED) {
5.516 - (*_blossom_rep)[_blossom_set->insert(n)] = n;
5.517 - _tree_set->insert(n);
5.518 - (*_status)[n] = EVEN;
5.519 - processDense(n);
5.520 - }
5.521 - }
5.522 - }
5.523 -
5.524 -
5.525 - /// \brief Runs Edmonds' algorithm
5.526 - ///
5.527 - /// Runs Edmonds' algorithm for sparse graphs (<tt>m<2*n</tt>)
5.528 - /// or Edmonds' algorithm with a heuristic of
5.529 - /// postponing shrinks for dense graphs.
5.530 - void run() {
5.531 - if (countEdges(_graph) < 2 * countNodes(_graph)) {
5.532 - greedyInit();
5.533 - startSparse();
5.534 - } else {
5.535 - init();
5.536 - startDense();
5.537 - }
5.538 - }
5.539 -
5.540 - /// @}
5.541 -
5.542 - /// \name Primal solution
5.543 - /// Functions to get the primal solution, ie. the matching.
5.544 -
5.545 - /// @{
5.546 -
5.547 - ///\brief Returns the size of the current matching.
5.548 - ///
5.549 - ///Returns the size of the current matching. After \ref
5.550 - ///run() it returns the size of the maximum matching in the graph.
5.551 - int matchingSize() const {
5.552 - int size = 0;
5.553 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.554 - if ((*_matching)[n] != INVALID) {
5.555 - ++size;
5.556 - }
5.557 - }
5.558 - return size / 2;
5.559 - }
5.560 -
5.561 - /// \brief Returns true when the edge is in the matching.
5.562 - ///
5.563 - /// Returns true when the edge is in the matching.
5.564 - bool matching(const Edge& edge) const {
5.565 - return edge == (*_matching)[_graph.u(edge)];
5.566 - }
5.567 -
5.568 - /// \brief Returns the matching edge incident to the given node.
5.569 - ///
5.570 - /// Returns the matching edge of a \c node in the actual matching or
5.571 - /// INVALID if the \c node is not covered by the actual matching.
5.572 - Arc matching(const Node& n) const {
5.573 - return (*_matching)[n];
5.574 - }
5.575 -
5.576 - ///\brief Returns the mate of a node in the actual matching.
5.577 - ///
5.578 - ///Returns the mate of a \c node in the actual matching or
5.579 - ///INVALID if the \c node is not covered by the actual matching.
5.580 - Node mate(const Node& n) const {
5.581 - return (*_matching)[n] != INVALID ?
5.582 - _graph.target((*_matching)[n]) : INVALID;
5.583 - }
5.584 -
5.585 - /// @}
5.586 -
5.587 - /// \name Dual solution
5.588 - /// Functions to get the dual solution, ie. the decomposition.
5.589 -
5.590 - /// @{
5.591 -
5.592 - /// \brief Returns the class of the node in the Edmonds-Gallai
5.593 - /// decomposition.
5.594 - ///
5.595 - /// Returns the class of the node in the Edmonds-Gallai
5.596 - /// decomposition.
5.597 - Status decomposition(const Node& n) const {
5.598 - return (*_status)[n];
5.599 - }
5.600 -
5.601 - /// \brief Returns true when the node is in the barrier.
5.602 - ///
5.603 - /// Returns true when the node is in the barrier.
5.604 - bool barrier(const Node& n) const {
5.605 - return (*_status)[n] == ODD;
5.606 - }
5.607 -
5.608 - /// @}
5.609 -
5.610 - };
5.611 -
5.612 - /// \ingroup matching
5.613 - ///
5.614 - /// \brief Weighted matching in general graphs
5.615 - ///
5.616 - /// This class provides an efficient implementation of Edmond's
5.617 - /// maximum weighted matching algorithm. The implementation is based
5.618 - /// on extensive use of priority queues and provides
5.619 - /// \f$O(nm\log n)\f$ time complexity.
5.620 - ///
5.621 - /// The maximum weighted matching problem is to find undirected
5.622 - /// edges in the graph with maximum overall weight and no two of
5.623 - /// them shares their ends. The problem can be formulated with the
5.624 - /// following linear program.
5.625 - /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
5.626 - /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
5.627 - \quad \forall B\in\mathcal{O}\f] */
5.628 - /// \f[x_e \ge 0\quad \forall e\in E\f]
5.629 - /// \f[\max \sum_{e\in E}x_ew_e\f]
5.630 - /// where \f$\delta(X)\f$ is the set of edges incident to a node in
5.631 - /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
5.632 - /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
5.633 - /// subsets of the nodes.
5.634 - ///
5.635 - /// The algorithm calculates an optimal matching and a proof of the
5.636 - /// optimality. The solution of the dual problem can be used to check
5.637 - /// the result of the algorithm. The dual linear problem is the
5.638 - /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
5.639 - z_B \ge w_{uv} \quad \forall uv\in E\f] */
5.640 - /// \f[y_u \ge 0 \quad \forall u \in V\f]
5.641 - /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
5.642 - /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
5.643 - \frac{\vert B \vert - 1}{2}z_B\f] */
5.644 - ///
5.645 - /// The algorithm can be executed with \c run() or the \c init() and
5.646 - /// then the \c start() member functions. After it the matching can
5.647 - /// be asked with \c matching() or mate() functions. The dual
5.648 - /// solution can be get with \c nodeValue(), \c blossomNum() and \c
5.649 - /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
5.650 - /// "BlossomIt" nested class, which is able to iterate on the nodes
5.651 - /// of a blossom. If the value type is integral then the dual
5.652 - /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
5.653 - template <typename GR,
5.654 - typename WM = typename GR::template EdgeMap<int> >
5.655 - class MaxWeightedMatching {
5.656 - public:
5.657 -
5.658 - ///\e
5.659 - typedef GR Graph;
5.660 - ///\e
5.661 - typedef WM WeightMap;
5.662 - ///\e
5.663 - typedef typename WeightMap::Value Value;
5.664 -
5.665 - /// \brief Scaling factor for dual solution
5.666 - ///
5.667 - /// Scaling factor for dual solution, it is equal to 4 or 1
5.668 - /// according to the value type.
5.669 - static const int dualScale =
5.670 - std::numeric_limits<Value>::is_integer ? 4 : 1;
5.671 -
5.672 - typedef typename Graph::template NodeMap<typename Graph::Arc>
5.673 - MatchingMap;
5.674 -
5.675 - private:
5.676 -
5.677 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
5.678 -
5.679 - typedef typename Graph::template NodeMap<Value> NodePotential;
5.680 - typedef std::vector<Node> BlossomNodeList;
5.681 -
5.682 - struct BlossomVariable {
5.683 - int begin, end;
5.684 - Value value;
5.685 -
5.686 - BlossomVariable(int _begin, int _end, Value _value)
5.687 - : begin(_begin), end(_end), value(_value) {}
5.688 -
5.689 - };
5.690 -
5.691 - typedef std::vector<BlossomVariable> BlossomPotential;
5.692 -
5.693 - const Graph& _graph;
5.694 - const WeightMap& _weight;
5.695 -
5.696 - MatchingMap* _matching;
5.697 -
5.698 - NodePotential* _node_potential;
5.699 -
5.700 - BlossomPotential _blossom_potential;
5.701 - BlossomNodeList _blossom_node_list;
5.702 -
5.703 - int _node_num;
5.704 - int _blossom_num;
5.705 -
5.706 - typedef RangeMap<int> IntIntMap;
5.707 -
5.708 - enum Status {
5.709 - EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
5.710 - };
5.711 -
5.712 - typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
5.713 - struct BlossomData {
5.714 - int tree;
5.715 - Status status;
5.716 - Arc pred, next;
5.717 - Value pot, offset;
5.718 - Node base;
5.719 - };
5.720 -
5.721 - IntNodeMap *_blossom_index;
5.722 - BlossomSet *_blossom_set;
5.723 - RangeMap<BlossomData>* _blossom_data;
5.724 -
5.725 - IntNodeMap *_node_index;
5.726 - IntArcMap *_node_heap_index;
5.727 -
5.728 - struct NodeData {
5.729 -
5.730 - NodeData(IntArcMap& node_heap_index)
5.731 - : heap(node_heap_index) {}
5.732 -
5.733 - int blossom;
5.734 - Value pot;
5.735 - BinHeap<Value, IntArcMap> heap;
5.736 - std::map<int, Arc> heap_index;
5.737 -
5.738 - int tree;
5.739 - };
5.740 -
5.741 - RangeMap<NodeData>* _node_data;
5.742 -
5.743 - typedef ExtendFindEnum<IntIntMap> TreeSet;
5.744 -
5.745 - IntIntMap *_tree_set_index;
5.746 - TreeSet *_tree_set;
5.747 -
5.748 - IntNodeMap *_delta1_index;
5.749 - BinHeap<Value, IntNodeMap> *_delta1;
5.750 -
5.751 - IntIntMap *_delta2_index;
5.752 - BinHeap<Value, IntIntMap> *_delta2;
5.753 -
5.754 - IntEdgeMap *_delta3_index;
5.755 - BinHeap<Value, IntEdgeMap> *_delta3;
5.756 -
5.757 - IntIntMap *_delta4_index;
5.758 - BinHeap<Value, IntIntMap> *_delta4;
5.759 -
5.760 - Value _delta_sum;
5.761 -
5.762 - void createStructures() {
5.763 - _node_num = countNodes(_graph);
5.764 - _blossom_num = _node_num * 3 / 2;
5.765 -
5.766 - if (!_matching) {
5.767 - _matching = new MatchingMap(_graph);
5.768 - }
5.769 - if (!_node_potential) {
5.770 - _node_potential = new NodePotential(_graph);
5.771 - }
5.772 - if (!_blossom_set) {
5.773 - _blossom_index = new IntNodeMap(_graph);
5.774 - _blossom_set = new BlossomSet(*_blossom_index);
5.775 - _blossom_data = new RangeMap<BlossomData>(_blossom_num);
5.776 - }
5.777 -
5.778 - if (!_node_index) {
5.779 - _node_index = new IntNodeMap(_graph);
5.780 - _node_heap_index = new IntArcMap(_graph);
5.781 - _node_data = new RangeMap<NodeData>(_node_num,
5.782 - NodeData(*_node_heap_index));
5.783 - }
5.784 -
5.785 - if (!_tree_set) {
5.786 - _tree_set_index = new IntIntMap(_blossom_num);
5.787 - _tree_set = new TreeSet(*_tree_set_index);
5.788 - }
5.789 - if (!_delta1) {
5.790 - _delta1_index = new IntNodeMap(_graph);
5.791 - _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
5.792 - }
5.793 - if (!_delta2) {
5.794 - _delta2_index = new IntIntMap(_blossom_num);
5.795 - _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
5.796 - }
5.797 - if (!_delta3) {
5.798 - _delta3_index = new IntEdgeMap(_graph);
5.799 - _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
5.800 - }
5.801 - if (!_delta4) {
5.802 - _delta4_index = new IntIntMap(_blossom_num);
5.803 - _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
5.804 - }
5.805 - }
5.806 -
5.807 - void destroyStructures() {
5.808 - _node_num = countNodes(_graph);
5.809 - _blossom_num = _node_num * 3 / 2;
5.810 -
5.811 - if (_matching) {
5.812 - delete _matching;
5.813 - }
5.814 - if (_node_potential) {
5.815 - delete _node_potential;
5.816 - }
5.817 - if (_blossom_set) {
5.818 - delete _blossom_index;
5.819 - delete _blossom_set;
5.820 - delete _blossom_data;
5.821 - }
5.822 -
5.823 - if (_node_index) {
5.824 - delete _node_index;
5.825 - delete _node_heap_index;
5.826 - delete _node_data;
5.827 - }
5.828 -
5.829 - if (_tree_set) {
5.830 - delete _tree_set_index;
5.831 - delete _tree_set;
5.832 - }
5.833 - if (_delta1) {
5.834 - delete _delta1_index;
5.835 - delete _delta1;
5.836 - }
5.837 - if (_delta2) {
5.838 - delete _delta2_index;
5.839 - delete _delta2;
5.840 - }
5.841 - if (_delta3) {
5.842 - delete _delta3_index;
5.843 - delete _delta3;
5.844 - }
5.845 - if (_delta4) {
5.846 - delete _delta4_index;
5.847 - delete _delta4;
5.848 - }
5.849 - }
5.850 -
5.851 - void matchedToEven(int blossom, int tree) {
5.852 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
5.853 - _delta2->erase(blossom);
5.854 - }
5.855 -
5.856 - if (!_blossom_set->trivial(blossom)) {
5.857 - (*_blossom_data)[blossom].pot -=
5.858 - 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
5.859 - }
5.860 -
5.861 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.862 - n != INVALID; ++n) {
5.863 -
5.864 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
5.865 - int ni = (*_node_index)[n];
5.866 -
5.867 - (*_node_data)[ni].heap.clear();
5.868 - (*_node_data)[ni].heap_index.clear();
5.869 -
5.870 - (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
5.871 -
5.872 - _delta1->push(n, (*_node_data)[ni].pot);
5.873 -
5.874 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
5.875 - Node v = _graph.source(e);
5.876 - int vb = _blossom_set->find(v);
5.877 - int vi = (*_node_index)[v];
5.878 -
5.879 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.880 - dualScale * _weight[e];
5.881 -
5.882 - if ((*_blossom_data)[vb].status == EVEN) {
5.883 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
5.884 - _delta3->push(e, rw / 2);
5.885 - }
5.886 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
5.887 - if (_delta3->state(e) != _delta3->IN_HEAP) {
5.888 - _delta3->push(e, rw);
5.889 - }
5.890 - } else {
5.891 - typename std::map<int, Arc>::iterator it =
5.892 - (*_node_data)[vi].heap_index.find(tree);
5.893 -
5.894 - if (it != (*_node_data)[vi].heap_index.end()) {
5.895 - if ((*_node_data)[vi].heap[it->second] > rw) {
5.896 - (*_node_data)[vi].heap.replace(it->second, e);
5.897 - (*_node_data)[vi].heap.decrease(e, rw);
5.898 - it->second = e;
5.899 - }
5.900 - } else {
5.901 - (*_node_data)[vi].heap.push(e, rw);
5.902 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
5.903 - }
5.904 -
5.905 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
5.906 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
5.907 -
5.908 - if ((*_blossom_data)[vb].status == MATCHED) {
5.909 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
5.910 - _delta2->push(vb, _blossom_set->classPrio(vb) -
5.911 - (*_blossom_data)[vb].offset);
5.912 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
5.913 - (*_blossom_data)[vb].offset){
5.914 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
5.915 - (*_blossom_data)[vb].offset);
5.916 - }
5.917 - }
5.918 - }
5.919 - }
5.920 - }
5.921 - }
5.922 - (*_blossom_data)[blossom].offset = 0;
5.923 - }
5.924 -
5.925 - void matchedToOdd(int blossom) {
5.926 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
5.927 - _delta2->erase(blossom);
5.928 - }
5.929 - (*_blossom_data)[blossom].offset += _delta_sum;
5.930 - if (!_blossom_set->trivial(blossom)) {
5.931 - _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
5.932 - (*_blossom_data)[blossom].offset);
5.933 - }
5.934 - }
5.935 -
5.936 - void evenToMatched(int blossom, int tree) {
5.937 - if (!_blossom_set->trivial(blossom)) {
5.938 - (*_blossom_data)[blossom].pot += 2 * _delta_sum;
5.939 - }
5.940 -
5.941 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.942 - n != INVALID; ++n) {
5.943 - int ni = (*_node_index)[n];
5.944 - (*_node_data)[ni].pot -= _delta_sum;
5.945 -
5.946 - _delta1->erase(n);
5.947 -
5.948 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
5.949 - Node v = _graph.source(e);
5.950 - int vb = _blossom_set->find(v);
5.951 - int vi = (*_node_index)[v];
5.952 -
5.953 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.954 - dualScale * _weight[e];
5.955 -
5.956 - if (vb == blossom) {
5.957 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.958 - _delta3->erase(e);
5.959 - }
5.960 - } else if ((*_blossom_data)[vb].status == EVEN) {
5.961 -
5.962 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.963 - _delta3->erase(e);
5.964 - }
5.965 -
5.966 - int vt = _tree_set->find(vb);
5.967 -
5.968 - if (vt != tree) {
5.969 -
5.970 - Arc r = _graph.oppositeArc(e);
5.971 -
5.972 - typename std::map<int, Arc>::iterator it =
5.973 - (*_node_data)[ni].heap_index.find(vt);
5.974 -
5.975 - if (it != (*_node_data)[ni].heap_index.end()) {
5.976 - if ((*_node_data)[ni].heap[it->second] > rw) {
5.977 - (*_node_data)[ni].heap.replace(it->second, r);
5.978 - (*_node_data)[ni].heap.decrease(r, rw);
5.979 - it->second = r;
5.980 - }
5.981 - } else {
5.982 - (*_node_data)[ni].heap.push(r, rw);
5.983 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
5.984 - }
5.985 -
5.986 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
5.987 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
5.988 -
5.989 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
5.990 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
5.991 - (*_blossom_data)[blossom].offset);
5.992 - } else if ((*_delta2)[blossom] >
5.993 - _blossom_set->classPrio(blossom) -
5.994 - (*_blossom_data)[blossom].offset){
5.995 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
5.996 - (*_blossom_data)[blossom].offset);
5.997 - }
5.998 - }
5.999 - }
5.1000 -
5.1001 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
5.1002 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.1003 - _delta3->erase(e);
5.1004 - }
5.1005 - } else {
5.1006 -
5.1007 - typename std::map<int, Arc>::iterator it =
5.1008 - (*_node_data)[vi].heap_index.find(tree);
5.1009 -
5.1010 - if (it != (*_node_data)[vi].heap_index.end()) {
5.1011 - (*_node_data)[vi].heap.erase(it->second);
5.1012 - (*_node_data)[vi].heap_index.erase(it);
5.1013 - if ((*_node_data)[vi].heap.empty()) {
5.1014 - _blossom_set->increase(v, std::numeric_limits<Value>::max());
5.1015 - } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
5.1016 - _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
5.1017 - }
5.1018 -
5.1019 - if ((*_blossom_data)[vb].status == MATCHED) {
5.1020 - if (_blossom_set->classPrio(vb) ==
5.1021 - std::numeric_limits<Value>::max()) {
5.1022 - _delta2->erase(vb);
5.1023 - } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
5.1024 - (*_blossom_data)[vb].offset) {
5.1025 - _delta2->increase(vb, _blossom_set->classPrio(vb) -
5.1026 - (*_blossom_data)[vb].offset);
5.1027 - }
5.1028 - }
5.1029 - }
5.1030 - }
5.1031 - }
5.1032 - }
5.1033 - }
5.1034 -
5.1035 - void oddToMatched(int blossom) {
5.1036 - (*_blossom_data)[blossom].offset -= _delta_sum;
5.1037 -
5.1038 - if (_blossom_set->classPrio(blossom) !=
5.1039 - std::numeric_limits<Value>::max()) {
5.1040 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
5.1041 - (*_blossom_data)[blossom].offset);
5.1042 - }
5.1043 -
5.1044 - if (!_blossom_set->trivial(blossom)) {
5.1045 - _delta4->erase(blossom);
5.1046 - }
5.1047 - }
5.1048 -
5.1049 - void oddToEven(int blossom, int tree) {
5.1050 - if (!_blossom_set->trivial(blossom)) {
5.1051 - _delta4->erase(blossom);
5.1052 - (*_blossom_data)[blossom].pot -=
5.1053 - 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
5.1054 - }
5.1055 -
5.1056 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.1057 - n != INVALID; ++n) {
5.1058 - int ni = (*_node_index)[n];
5.1059 -
5.1060 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
5.1061 -
5.1062 - (*_node_data)[ni].heap.clear();
5.1063 - (*_node_data)[ni].heap_index.clear();
5.1064 - (*_node_data)[ni].pot +=
5.1065 - 2 * _delta_sum - (*_blossom_data)[blossom].offset;
5.1066 -
5.1067 - _delta1->push(n, (*_node_data)[ni].pot);
5.1068 -
5.1069 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
5.1070 - Node v = _graph.source(e);
5.1071 - int vb = _blossom_set->find(v);
5.1072 - int vi = (*_node_index)[v];
5.1073 -
5.1074 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.1075 - dualScale * _weight[e];
5.1076 -
5.1077 - if ((*_blossom_data)[vb].status == EVEN) {
5.1078 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
5.1079 - _delta3->push(e, rw / 2);
5.1080 - }
5.1081 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
5.1082 - if (_delta3->state(e) != _delta3->IN_HEAP) {
5.1083 - _delta3->push(e, rw);
5.1084 - }
5.1085 - } else {
5.1086 -
5.1087 - typename std::map<int, Arc>::iterator it =
5.1088 - (*_node_data)[vi].heap_index.find(tree);
5.1089 -
5.1090 - if (it != (*_node_data)[vi].heap_index.end()) {
5.1091 - if ((*_node_data)[vi].heap[it->second] > rw) {
5.1092 - (*_node_data)[vi].heap.replace(it->second, e);
5.1093 - (*_node_data)[vi].heap.decrease(e, rw);
5.1094 - it->second = e;
5.1095 - }
5.1096 - } else {
5.1097 - (*_node_data)[vi].heap.push(e, rw);
5.1098 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
5.1099 - }
5.1100 -
5.1101 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
5.1102 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
5.1103 -
5.1104 - if ((*_blossom_data)[vb].status == MATCHED) {
5.1105 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
5.1106 - _delta2->push(vb, _blossom_set->classPrio(vb) -
5.1107 - (*_blossom_data)[vb].offset);
5.1108 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
5.1109 - (*_blossom_data)[vb].offset) {
5.1110 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
5.1111 - (*_blossom_data)[vb].offset);
5.1112 - }
5.1113 - }
5.1114 - }
5.1115 - }
5.1116 - }
5.1117 - }
5.1118 - (*_blossom_data)[blossom].offset = 0;
5.1119 - }
5.1120 -
5.1121 -
5.1122 - void matchedToUnmatched(int blossom) {
5.1123 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
5.1124 - _delta2->erase(blossom);
5.1125 - }
5.1126 -
5.1127 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.1128 - n != INVALID; ++n) {
5.1129 - int ni = (*_node_index)[n];
5.1130 -
5.1131 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
5.1132 -
5.1133 - (*_node_data)[ni].heap.clear();
5.1134 - (*_node_data)[ni].heap_index.clear();
5.1135 -
5.1136 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
5.1137 - Node v = _graph.target(e);
5.1138 - int vb = _blossom_set->find(v);
5.1139 - int vi = (*_node_index)[v];
5.1140 -
5.1141 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.1142 - dualScale * _weight[e];
5.1143 -
5.1144 - if ((*_blossom_data)[vb].status == EVEN) {
5.1145 - if (_delta3->state(e) != _delta3->IN_HEAP) {
5.1146 - _delta3->push(e, rw);
5.1147 - }
5.1148 - }
5.1149 - }
5.1150 - }
5.1151 - }
5.1152 -
5.1153 - void unmatchedToMatched(int blossom) {
5.1154 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.1155 - n != INVALID; ++n) {
5.1156 - int ni = (*_node_index)[n];
5.1157 -
5.1158 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
5.1159 - Node v = _graph.source(e);
5.1160 - int vb = _blossom_set->find(v);
5.1161 - int vi = (*_node_index)[v];
5.1162 -
5.1163 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.1164 - dualScale * _weight[e];
5.1165 -
5.1166 - if (vb == blossom) {
5.1167 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.1168 - _delta3->erase(e);
5.1169 - }
5.1170 - } else if ((*_blossom_data)[vb].status == EVEN) {
5.1171 -
5.1172 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.1173 - _delta3->erase(e);
5.1174 - }
5.1175 -
5.1176 - int vt = _tree_set->find(vb);
5.1177 -
5.1178 - Arc r = _graph.oppositeArc(e);
5.1179 -
5.1180 - typename std::map<int, Arc>::iterator it =
5.1181 - (*_node_data)[ni].heap_index.find(vt);
5.1182 -
5.1183 - if (it != (*_node_data)[ni].heap_index.end()) {
5.1184 - if ((*_node_data)[ni].heap[it->second] > rw) {
5.1185 - (*_node_data)[ni].heap.replace(it->second, r);
5.1186 - (*_node_data)[ni].heap.decrease(r, rw);
5.1187 - it->second = r;
5.1188 - }
5.1189 - } else {
5.1190 - (*_node_data)[ni].heap.push(r, rw);
5.1191 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
5.1192 - }
5.1193 -
5.1194 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
5.1195 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
5.1196 -
5.1197 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
5.1198 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
5.1199 - (*_blossom_data)[blossom].offset);
5.1200 - } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
5.1201 - (*_blossom_data)[blossom].offset){
5.1202 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
5.1203 - (*_blossom_data)[blossom].offset);
5.1204 - }
5.1205 - }
5.1206 -
5.1207 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
5.1208 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.1209 - _delta3->erase(e);
5.1210 - }
5.1211 - }
5.1212 - }
5.1213 - }
5.1214 - }
5.1215 -
5.1216 - void alternatePath(int even, int tree) {
5.1217 - int odd;
5.1218 -
5.1219 - evenToMatched(even, tree);
5.1220 - (*_blossom_data)[even].status = MATCHED;
5.1221 -
5.1222 - while ((*_blossom_data)[even].pred != INVALID) {
5.1223 - odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
5.1224 - (*_blossom_data)[odd].status = MATCHED;
5.1225 - oddToMatched(odd);
5.1226 - (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
5.1227 -
5.1228 - even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
5.1229 - (*_blossom_data)[even].status = MATCHED;
5.1230 - evenToMatched(even, tree);
5.1231 - (*_blossom_data)[even].next =
5.1232 - _graph.oppositeArc((*_blossom_data)[odd].pred);
5.1233 - }
5.1234 -
5.1235 - }
5.1236 -
5.1237 - void destroyTree(int tree) {
5.1238 - for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
5.1239 - if ((*_blossom_data)[b].status == EVEN) {
5.1240 - (*_blossom_data)[b].status = MATCHED;
5.1241 - evenToMatched(b, tree);
5.1242 - } else if ((*_blossom_data)[b].status == ODD) {
5.1243 - (*_blossom_data)[b].status = MATCHED;
5.1244 - oddToMatched(b);
5.1245 - }
5.1246 - }
5.1247 - _tree_set->eraseClass(tree);
5.1248 - }
5.1249 -
5.1250 -
5.1251 - void unmatchNode(const Node& node) {
5.1252 - int blossom = _blossom_set->find(node);
5.1253 - int tree = _tree_set->find(blossom);
5.1254 -
5.1255 - alternatePath(blossom, tree);
5.1256 - destroyTree(tree);
5.1257 -
5.1258 - (*_blossom_data)[blossom].status = UNMATCHED;
5.1259 - (*_blossom_data)[blossom].base = node;
5.1260 - matchedToUnmatched(blossom);
5.1261 - }
5.1262 -
5.1263 -
5.1264 - void augmentOnEdge(const Edge& edge) {
5.1265 -
5.1266 - int left = _blossom_set->find(_graph.u(edge));
5.1267 - int right = _blossom_set->find(_graph.v(edge));
5.1268 -
5.1269 - if ((*_blossom_data)[left].status == EVEN) {
5.1270 - int left_tree = _tree_set->find(left);
5.1271 - alternatePath(left, left_tree);
5.1272 - destroyTree(left_tree);
5.1273 - } else {
5.1274 - (*_blossom_data)[left].status = MATCHED;
5.1275 - unmatchedToMatched(left);
5.1276 - }
5.1277 -
5.1278 - if ((*_blossom_data)[right].status == EVEN) {
5.1279 - int right_tree = _tree_set->find(right);
5.1280 - alternatePath(right, right_tree);
5.1281 - destroyTree(right_tree);
5.1282 - } else {
5.1283 - (*_blossom_data)[right].status = MATCHED;
5.1284 - unmatchedToMatched(right);
5.1285 - }
5.1286 -
5.1287 - (*_blossom_data)[left].next = _graph.direct(edge, true);
5.1288 - (*_blossom_data)[right].next = _graph.direct(edge, false);
5.1289 - }
5.1290 -
5.1291 - void extendOnArc(const Arc& arc) {
5.1292 - int base = _blossom_set->find(_graph.target(arc));
5.1293 - int tree = _tree_set->find(base);
5.1294 -
5.1295 - int odd = _blossom_set->find(_graph.source(arc));
5.1296 - _tree_set->insert(odd, tree);
5.1297 - (*_blossom_data)[odd].status = ODD;
5.1298 - matchedToOdd(odd);
5.1299 - (*_blossom_data)[odd].pred = arc;
5.1300 -
5.1301 - int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
5.1302 - (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
5.1303 - _tree_set->insert(even, tree);
5.1304 - (*_blossom_data)[even].status = EVEN;
5.1305 - matchedToEven(even, tree);
5.1306 - }
5.1307 -
5.1308 - void shrinkOnEdge(const Edge& edge, int tree) {
5.1309 - int nca = -1;
5.1310 - std::vector<int> left_path, right_path;
5.1311 -
5.1312 - {
5.1313 - std::set<int> left_set, right_set;
5.1314 - int left = _blossom_set->find(_graph.u(edge));
5.1315 - left_path.push_back(left);
5.1316 - left_set.insert(left);
5.1317 -
5.1318 - int right = _blossom_set->find(_graph.v(edge));
5.1319 - right_path.push_back(right);
5.1320 - right_set.insert(right);
5.1321 -
5.1322 - while (true) {
5.1323 -
5.1324 - if ((*_blossom_data)[left].pred == INVALID) break;
5.1325 -
5.1326 - left =
5.1327 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
5.1328 - left_path.push_back(left);
5.1329 - left =
5.1330 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
5.1331 - left_path.push_back(left);
5.1332 -
5.1333 - left_set.insert(left);
5.1334 -
5.1335 - if (right_set.find(left) != right_set.end()) {
5.1336 - nca = left;
5.1337 - break;
5.1338 - }
5.1339 -
5.1340 - if ((*_blossom_data)[right].pred == INVALID) break;
5.1341 -
5.1342 - right =
5.1343 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
5.1344 - right_path.push_back(right);
5.1345 - right =
5.1346 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
5.1347 - right_path.push_back(right);
5.1348 -
5.1349 - right_set.insert(right);
5.1350 -
5.1351 - if (left_set.find(right) != left_set.end()) {
5.1352 - nca = right;
5.1353 - break;
5.1354 - }
5.1355 -
5.1356 - }
5.1357 -
5.1358 - if (nca == -1) {
5.1359 - if ((*_blossom_data)[left].pred == INVALID) {
5.1360 - nca = right;
5.1361 - while (left_set.find(nca) == left_set.end()) {
5.1362 - nca =
5.1363 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.1364 - right_path.push_back(nca);
5.1365 - nca =
5.1366 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.1367 - right_path.push_back(nca);
5.1368 - }
5.1369 - } else {
5.1370 - nca = left;
5.1371 - while (right_set.find(nca) == right_set.end()) {
5.1372 - nca =
5.1373 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.1374 - left_path.push_back(nca);
5.1375 - nca =
5.1376 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.1377 - left_path.push_back(nca);
5.1378 - }
5.1379 - }
5.1380 - }
5.1381 - }
5.1382 -
5.1383 - std::vector<int> subblossoms;
5.1384 - Arc prev;
5.1385 -
5.1386 - prev = _graph.direct(edge, true);
5.1387 - for (int i = 0; left_path[i] != nca; i += 2) {
5.1388 - subblossoms.push_back(left_path[i]);
5.1389 - (*_blossom_data)[left_path[i]].next = prev;
5.1390 - _tree_set->erase(left_path[i]);
5.1391 -
5.1392 - subblossoms.push_back(left_path[i + 1]);
5.1393 - (*_blossom_data)[left_path[i + 1]].status = EVEN;
5.1394 - oddToEven(left_path[i + 1], tree);
5.1395 - _tree_set->erase(left_path[i + 1]);
5.1396 - prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
5.1397 - }
5.1398 -
5.1399 - int k = 0;
5.1400 - while (right_path[k] != nca) ++k;
5.1401 -
5.1402 - subblossoms.push_back(nca);
5.1403 - (*_blossom_data)[nca].next = prev;
5.1404 -
5.1405 - for (int i = k - 2; i >= 0; i -= 2) {
5.1406 - subblossoms.push_back(right_path[i + 1]);
5.1407 - (*_blossom_data)[right_path[i + 1]].status = EVEN;
5.1408 - oddToEven(right_path[i + 1], tree);
5.1409 - _tree_set->erase(right_path[i + 1]);
5.1410 -
5.1411 - (*_blossom_data)[right_path[i + 1]].next =
5.1412 - (*_blossom_data)[right_path[i + 1]].pred;
5.1413 -
5.1414 - subblossoms.push_back(right_path[i]);
5.1415 - _tree_set->erase(right_path[i]);
5.1416 - }
5.1417 -
5.1418 - int surface =
5.1419 - _blossom_set->join(subblossoms.begin(), subblossoms.end());
5.1420 -
5.1421 - for (int i = 0; i < int(subblossoms.size()); ++i) {
5.1422 - if (!_blossom_set->trivial(subblossoms[i])) {
5.1423 - (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
5.1424 - }
5.1425 - (*_blossom_data)[subblossoms[i]].status = MATCHED;
5.1426 - }
5.1427 -
5.1428 - (*_blossom_data)[surface].pot = -2 * _delta_sum;
5.1429 - (*_blossom_data)[surface].offset = 0;
5.1430 - (*_blossom_data)[surface].status = EVEN;
5.1431 - (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
5.1432 - (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
5.1433 -
5.1434 - _tree_set->insert(surface, tree);
5.1435 - _tree_set->erase(nca);
5.1436 - }
5.1437 -
5.1438 - void splitBlossom(int blossom) {
5.1439 - Arc next = (*_blossom_data)[blossom].next;
5.1440 - Arc pred = (*_blossom_data)[blossom].pred;
5.1441 -
5.1442 - int tree = _tree_set->find(blossom);
5.1443 -
5.1444 - (*_blossom_data)[blossom].status = MATCHED;
5.1445 - oddToMatched(blossom);
5.1446 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
5.1447 - _delta2->erase(blossom);
5.1448 - }
5.1449 -
5.1450 - std::vector<int> subblossoms;
5.1451 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
5.1452 -
5.1453 - Value offset = (*_blossom_data)[blossom].offset;
5.1454 - int b = _blossom_set->find(_graph.source(pred));
5.1455 - int d = _blossom_set->find(_graph.source(next));
5.1456 -
5.1457 - int ib = -1, id = -1;
5.1458 - for (int i = 0; i < int(subblossoms.size()); ++i) {
5.1459 - if (subblossoms[i] == b) ib = i;
5.1460 - if (subblossoms[i] == d) id = i;
5.1461 -
5.1462 - (*_blossom_data)[subblossoms[i]].offset = offset;
5.1463 - if (!_blossom_set->trivial(subblossoms[i])) {
5.1464 - (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
5.1465 - }
5.1466 - if (_blossom_set->classPrio(subblossoms[i]) !=
5.1467 - std::numeric_limits<Value>::max()) {
5.1468 - _delta2->push(subblossoms[i],
5.1469 - _blossom_set->classPrio(subblossoms[i]) -
5.1470 - (*_blossom_data)[subblossoms[i]].offset);
5.1471 - }
5.1472 - }
5.1473 -
5.1474 - if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
5.1475 - for (int i = (id + 1) % subblossoms.size();
5.1476 - i != ib; i = (i + 2) % subblossoms.size()) {
5.1477 - int sb = subblossoms[i];
5.1478 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.1479 - (*_blossom_data)[sb].next =
5.1480 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.1481 - }
5.1482 -
5.1483 - for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
5.1484 - int sb = subblossoms[i];
5.1485 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.1486 - int ub = subblossoms[(i + 2) % subblossoms.size()];
5.1487 -
5.1488 - (*_blossom_data)[sb].status = ODD;
5.1489 - matchedToOdd(sb);
5.1490 - _tree_set->insert(sb, tree);
5.1491 - (*_blossom_data)[sb].pred = pred;
5.1492 - (*_blossom_data)[sb].next =
5.1493 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.1494 -
5.1495 - pred = (*_blossom_data)[ub].next;
5.1496 -
5.1497 - (*_blossom_data)[tb].status = EVEN;
5.1498 - matchedToEven(tb, tree);
5.1499 - _tree_set->insert(tb, tree);
5.1500 - (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
5.1501 - }
5.1502 -
5.1503 - (*_blossom_data)[subblossoms[id]].status = ODD;
5.1504 - matchedToOdd(subblossoms[id]);
5.1505 - _tree_set->insert(subblossoms[id], tree);
5.1506 - (*_blossom_data)[subblossoms[id]].next = next;
5.1507 - (*_blossom_data)[subblossoms[id]].pred = pred;
5.1508 -
5.1509 - } else {
5.1510 -
5.1511 - for (int i = (ib + 1) % subblossoms.size();
5.1512 - i != id; i = (i + 2) % subblossoms.size()) {
5.1513 - int sb = subblossoms[i];
5.1514 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.1515 - (*_blossom_data)[sb].next =
5.1516 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.1517 - }
5.1518 -
5.1519 - for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
5.1520 - int sb = subblossoms[i];
5.1521 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.1522 - int ub = subblossoms[(i + 2) % subblossoms.size()];
5.1523 -
5.1524 - (*_blossom_data)[sb].status = ODD;
5.1525 - matchedToOdd(sb);
5.1526 - _tree_set->insert(sb, tree);
5.1527 - (*_blossom_data)[sb].next = next;
5.1528 - (*_blossom_data)[sb].pred =
5.1529 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.1530 -
5.1531 - (*_blossom_data)[tb].status = EVEN;
5.1532 - matchedToEven(tb, tree);
5.1533 - _tree_set->insert(tb, tree);
5.1534 - (*_blossom_data)[tb].pred =
5.1535 - (*_blossom_data)[tb].next =
5.1536 - _graph.oppositeArc((*_blossom_data)[ub].next);
5.1537 - next = (*_blossom_data)[ub].next;
5.1538 - }
5.1539 -
5.1540 - (*_blossom_data)[subblossoms[ib]].status = ODD;
5.1541 - matchedToOdd(subblossoms[ib]);
5.1542 - _tree_set->insert(subblossoms[ib], tree);
5.1543 - (*_blossom_data)[subblossoms[ib]].next = next;
5.1544 - (*_blossom_data)[subblossoms[ib]].pred = pred;
5.1545 - }
5.1546 - _tree_set->erase(blossom);
5.1547 - }
5.1548 -
5.1549 - void extractBlossom(int blossom, const Node& base, const Arc& matching) {
5.1550 - if (_blossom_set->trivial(blossom)) {
5.1551 - int bi = (*_node_index)[base];
5.1552 - Value pot = (*_node_data)[bi].pot;
5.1553 -
5.1554 - (*_matching)[base] = matching;
5.1555 - _blossom_node_list.push_back(base);
5.1556 - (*_node_potential)[base] = pot;
5.1557 - } else {
5.1558 -
5.1559 - Value pot = (*_blossom_data)[blossom].pot;
5.1560 - int bn = _blossom_node_list.size();
5.1561 -
5.1562 - std::vector<int> subblossoms;
5.1563 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
5.1564 - int b = _blossom_set->find(base);
5.1565 - int ib = -1;
5.1566 - for (int i = 0; i < int(subblossoms.size()); ++i) {
5.1567 - if (subblossoms[i] == b) { ib = i; break; }
5.1568 - }
5.1569 -
5.1570 - for (int i = 1; i < int(subblossoms.size()); i += 2) {
5.1571 - int sb = subblossoms[(ib + i) % subblossoms.size()];
5.1572 - int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
5.1573 -
5.1574 - Arc m = (*_blossom_data)[tb].next;
5.1575 - extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
5.1576 - extractBlossom(tb, _graph.source(m), m);
5.1577 - }
5.1578 - extractBlossom(subblossoms[ib], base, matching);
5.1579 -
5.1580 - int en = _blossom_node_list.size();
5.1581 -
5.1582 - _blossom_potential.push_back(BlossomVariable(bn, en, pot));
5.1583 - }
5.1584 - }
5.1585 -
5.1586 - void extractMatching() {
5.1587 - std::vector<int> blossoms;
5.1588 - for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
5.1589 - blossoms.push_back(c);
5.1590 - }
5.1591 -
5.1592 - for (int i = 0; i < int(blossoms.size()); ++i) {
5.1593 - if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
5.1594 -
5.1595 - Value offset = (*_blossom_data)[blossoms[i]].offset;
5.1596 - (*_blossom_data)[blossoms[i]].pot += 2 * offset;
5.1597 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
5.1598 - n != INVALID; ++n) {
5.1599 - (*_node_data)[(*_node_index)[n]].pot -= offset;
5.1600 - }
5.1601 -
5.1602 - Arc matching = (*_blossom_data)[blossoms[i]].next;
5.1603 - Node base = _graph.source(matching);
5.1604 - extractBlossom(blossoms[i], base, matching);
5.1605 - } else {
5.1606 - Node base = (*_blossom_data)[blossoms[i]].base;
5.1607 - extractBlossom(blossoms[i], base, INVALID);
5.1608 - }
5.1609 - }
5.1610 - }
5.1611 -
5.1612 - public:
5.1613 -
5.1614 - /// \brief Constructor
5.1615 - ///
5.1616 - /// Constructor.
5.1617 - MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
5.1618 - : _graph(graph), _weight(weight), _matching(0),
5.1619 - _node_potential(0), _blossom_potential(), _blossom_node_list(),
5.1620 - _node_num(0), _blossom_num(0),
5.1621 -
5.1622 - _blossom_index(0), _blossom_set(0), _blossom_data(0),
5.1623 - _node_index(0), _node_heap_index(0), _node_data(0),
5.1624 - _tree_set_index(0), _tree_set(0),
5.1625 -
5.1626 - _delta1_index(0), _delta1(0),
5.1627 - _delta2_index(0), _delta2(0),
5.1628 - _delta3_index(0), _delta3(0),
5.1629 - _delta4_index(0), _delta4(0),
5.1630 -
5.1631 - _delta_sum() {}
5.1632 -
5.1633 - ~MaxWeightedMatching() {
5.1634 - destroyStructures();
5.1635 - }
5.1636 -
5.1637 - /// \name Execution control
5.1638 - /// The simplest way to execute the algorithm is to use the
5.1639 - /// \c run() member function.
5.1640 -
5.1641 - ///@{
5.1642 -
5.1643 - /// \brief Initialize the algorithm
5.1644 - ///
5.1645 - /// Initialize the algorithm
5.1646 - void init() {
5.1647 - createStructures();
5.1648 -
5.1649 - for (ArcIt e(_graph); e != INVALID; ++e) {
5.1650 - (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
5.1651 - }
5.1652 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.1653 - (*_delta1_index)[n] = _delta1->PRE_HEAP;
5.1654 - }
5.1655 - for (EdgeIt e(_graph); e != INVALID; ++e) {
5.1656 - (*_delta3_index)[e] = _delta3->PRE_HEAP;
5.1657 - }
5.1658 - for (int i = 0; i < _blossom_num; ++i) {
5.1659 - (*_delta2_index)[i] = _delta2->PRE_HEAP;
5.1660 - (*_delta4_index)[i] = _delta4->PRE_HEAP;
5.1661 - }
5.1662 -
5.1663 - int index = 0;
5.1664 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.1665 - Value max = 0;
5.1666 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
5.1667 - if (_graph.target(e) == n) continue;
5.1668 - if ((dualScale * _weight[e]) / 2 > max) {
5.1669 - max = (dualScale * _weight[e]) / 2;
5.1670 - }
5.1671 - }
5.1672 - (*_node_index)[n] = index;
5.1673 - (*_node_data)[index].pot = max;
5.1674 - _delta1->push(n, max);
5.1675 - int blossom =
5.1676 - _blossom_set->insert(n, std::numeric_limits<Value>::max());
5.1677 -
5.1678 - _tree_set->insert(blossom);
5.1679 -
5.1680 - (*_blossom_data)[blossom].status = EVEN;
5.1681 - (*_blossom_data)[blossom].pred = INVALID;
5.1682 - (*_blossom_data)[blossom].next = INVALID;
5.1683 - (*_blossom_data)[blossom].pot = 0;
5.1684 - (*_blossom_data)[blossom].offset = 0;
5.1685 - ++index;
5.1686 - }
5.1687 - for (EdgeIt e(_graph); e != INVALID; ++e) {
5.1688 - int si = (*_node_index)[_graph.u(e)];
5.1689 - int ti = (*_node_index)[_graph.v(e)];
5.1690 - if (_graph.u(e) != _graph.v(e)) {
5.1691 - _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
5.1692 - dualScale * _weight[e]) / 2);
5.1693 - }
5.1694 - }
5.1695 - }
5.1696 -
5.1697 - /// \brief Starts the algorithm
5.1698 - ///
5.1699 - /// Starts the algorithm
5.1700 - void start() {
5.1701 - enum OpType {
5.1702 - D1, D2, D3, D4
5.1703 - };
5.1704 -
5.1705 - int unmatched = _node_num;
5.1706 - while (unmatched > 0) {
5.1707 - Value d1 = !_delta1->empty() ?
5.1708 - _delta1->prio() : std::numeric_limits<Value>::max();
5.1709 -
5.1710 - Value d2 = !_delta2->empty() ?
5.1711 - _delta2->prio() : std::numeric_limits<Value>::max();
5.1712 -
5.1713 - Value d3 = !_delta3->empty() ?
5.1714 - _delta3->prio() : std::numeric_limits<Value>::max();
5.1715 -
5.1716 - Value d4 = !_delta4->empty() ?
5.1717 - _delta4->prio() : std::numeric_limits<Value>::max();
5.1718 -
5.1719 - _delta_sum = d1; OpType ot = D1;
5.1720 - if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
5.1721 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
5.1722 - if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
5.1723 -
5.1724 -
5.1725 - switch (ot) {
5.1726 - case D1:
5.1727 - {
5.1728 - Node n = _delta1->top();
5.1729 - unmatchNode(n);
5.1730 - --unmatched;
5.1731 - }
5.1732 - break;
5.1733 - case D2:
5.1734 - {
5.1735 - int blossom = _delta2->top();
5.1736 - Node n = _blossom_set->classTop(blossom);
5.1737 - Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
5.1738 - extendOnArc(e);
5.1739 - }
5.1740 - break;
5.1741 - case D3:
5.1742 - {
5.1743 - Edge e = _delta3->top();
5.1744 -
5.1745 - int left_blossom = _blossom_set->find(_graph.u(e));
5.1746 - int right_blossom = _blossom_set->find(_graph.v(e));
5.1747 -
5.1748 - if (left_blossom == right_blossom) {
5.1749 - _delta3->pop();
5.1750 - } else {
5.1751 - int left_tree;
5.1752 - if ((*_blossom_data)[left_blossom].status == EVEN) {
5.1753 - left_tree = _tree_set->find(left_blossom);
5.1754 - } else {
5.1755 - left_tree = -1;
5.1756 - ++unmatched;
5.1757 - }
5.1758 - int right_tree;
5.1759 - if ((*_blossom_data)[right_blossom].status == EVEN) {
5.1760 - right_tree = _tree_set->find(right_blossom);
5.1761 - } else {
5.1762 - right_tree = -1;
5.1763 - ++unmatched;
5.1764 - }
5.1765 -
5.1766 - if (left_tree == right_tree) {
5.1767 - shrinkOnEdge(e, left_tree);
5.1768 - } else {
5.1769 - augmentOnEdge(e);
5.1770 - unmatched -= 2;
5.1771 - }
5.1772 - }
5.1773 - } break;
5.1774 - case D4:
5.1775 - splitBlossom(_delta4->top());
5.1776 - break;
5.1777 - }
5.1778 - }
5.1779 - extractMatching();
5.1780 - }
5.1781 -
5.1782 - /// \brief Runs %MaxWeightedMatching algorithm.
5.1783 - ///
5.1784 - /// This method runs the %MaxWeightedMatching algorithm.
5.1785 - ///
5.1786 - /// \note mwm.run() is just a shortcut of the following code.
5.1787 - /// \code
5.1788 - /// mwm.init();
5.1789 - /// mwm.start();
5.1790 - /// \endcode
5.1791 - void run() {
5.1792 - init();
5.1793 - start();
5.1794 - }
5.1795 -
5.1796 - /// @}
5.1797 -
5.1798 - /// \name Primal solution
5.1799 - /// Functions to get the primal solution, ie. the matching.
5.1800 -
5.1801 - /// @{
5.1802 -
5.1803 - /// \brief Returns the weight of the matching.
5.1804 - ///
5.1805 - /// Returns the weight of the matching.
5.1806 - Value matchingValue() const {
5.1807 - Value sum = 0;
5.1808 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.1809 - if ((*_matching)[n] != INVALID) {
5.1810 - sum += _weight[(*_matching)[n]];
5.1811 - }
5.1812 - }
5.1813 - return sum /= 2;
5.1814 - }
5.1815 -
5.1816 - /// \brief Returns the cardinality of the matching.
5.1817 - ///
5.1818 - /// Returns the cardinality of the matching.
5.1819 - int matchingSize() const {
5.1820 - int num = 0;
5.1821 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.1822 - if ((*_matching)[n] != INVALID) {
5.1823 - ++num;
5.1824 - }
5.1825 - }
5.1826 - return num /= 2;
5.1827 - }
5.1828 -
5.1829 - /// \brief Returns true when the edge is in the matching.
5.1830 - ///
5.1831 - /// Returns true when the edge is in the matching.
5.1832 - bool matching(const Edge& edge) const {
5.1833 - return edge == (*_matching)[_graph.u(edge)];
5.1834 - }
5.1835 -
5.1836 - /// \brief Returns the incident matching arc.
5.1837 - ///
5.1838 - /// Returns the incident matching arc from given node. If the
5.1839 - /// node is not matched then it gives back \c INVALID.
5.1840 - Arc matching(const Node& node) const {
5.1841 - return (*_matching)[node];
5.1842 - }
5.1843 -
5.1844 - /// \brief Returns the mate of the node.
5.1845 - ///
5.1846 - /// Returns the adjancent node in a mathcing arc. If the node is
5.1847 - /// not matched then it gives back \c INVALID.
5.1848 - Node mate(const Node& node) const {
5.1849 - return (*_matching)[node] != INVALID ?
5.1850 - _graph.target((*_matching)[node]) : INVALID;
5.1851 - }
5.1852 -
5.1853 - /// @}
5.1854 -
5.1855 - /// \name Dual solution
5.1856 - /// Functions to get the dual solution.
5.1857 -
5.1858 - /// @{
5.1859 -
5.1860 - /// \brief Returns the value of the dual solution.
5.1861 - ///
5.1862 - /// Returns the value of the dual solution. It should be equal to
5.1863 - /// the primal value scaled by \ref dualScale "dual scale".
5.1864 - Value dualValue() const {
5.1865 - Value sum = 0;
5.1866 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.1867 - sum += nodeValue(n);
5.1868 - }
5.1869 - for (int i = 0; i < blossomNum(); ++i) {
5.1870 - sum += blossomValue(i) * (blossomSize(i) / 2);
5.1871 - }
5.1872 - return sum;
5.1873 - }
5.1874 -
5.1875 - /// \brief Returns the value of the node.
5.1876 - ///
5.1877 - /// Returns the the value of the node.
5.1878 - Value nodeValue(const Node& n) const {
5.1879 - return (*_node_potential)[n];
5.1880 - }
5.1881 -
5.1882 - /// \brief Returns the number of the blossoms in the basis.
5.1883 - ///
5.1884 - /// Returns the number of the blossoms in the basis.
5.1885 - /// \see BlossomIt
5.1886 - int blossomNum() const {
5.1887 - return _blossom_potential.size();
5.1888 - }
5.1889 -
5.1890 -
5.1891 - /// \brief Returns the number of the nodes in the blossom.
5.1892 - ///
5.1893 - /// Returns the number of the nodes in the blossom.
5.1894 - int blossomSize(int k) const {
5.1895 - return _blossom_potential[k].end - _blossom_potential[k].begin;
5.1896 - }
5.1897 -
5.1898 - /// \brief Returns the value of the blossom.
5.1899 - ///
5.1900 - /// Returns the the value of the blossom.
5.1901 - /// \see BlossomIt
5.1902 - Value blossomValue(int k) const {
5.1903 - return _blossom_potential[k].value;
5.1904 - }
5.1905 -
5.1906 - /// \brief Iterator for obtaining the nodes of the blossom.
5.1907 - ///
5.1908 - /// Iterator for obtaining the nodes of the blossom. This class
5.1909 - /// provides a common lemon style iterator for listing a
5.1910 - /// subset of the nodes.
5.1911 - class BlossomIt {
5.1912 - public:
5.1913 -
5.1914 - /// \brief Constructor.
5.1915 - ///
5.1916 - /// Constructor to get the nodes of the variable.
5.1917 - BlossomIt(const MaxWeightedMatching& algorithm, int variable)
5.1918 - : _algorithm(&algorithm)
5.1919 - {
5.1920 - _index = _algorithm->_blossom_potential[variable].begin;
5.1921 - _last = _algorithm->_blossom_potential[variable].end;
5.1922 - }
5.1923 -
5.1924 - /// \brief Conversion to node.
5.1925 - ///
5.1926 - /// Conversion to node.
5.1927 - operator Node() const {
5.1928 - return _algorithm->_blossom_node_list[_index];
5.1929 - }
5.1930 -
5.1931 - /// \brief Increment operator.
5.1932 - ///
5.1933 - /// Increment operator.
5.1934 - BlossomIt& operator++() {
5.1935 - ++_index;
5.1936 - return *this;
5.1937 - }
5.1938 -
5.1939 - /// \brief Validity checking
5.1940 - ///
5.1941 - /// Checks whether the iterator is invalid.
5.1942 - bool operator==(Invalid) const { return _index == _last; }
5.1943 -
5.1944 - /// \brief Validity checking
5.1945 - ///
5.1946 - /// Checks whether the iterator is valid.
5.1947 - bool operator!=(Invalid) const { return _index != _last; }
5.1948 -
5.1949 - private:
5.1950 - const MaxWeightedMatching* _algorithm;
5.1951 - int _last;
5.1952 - int _index;
5.1953 - };
5.1954 -
5.1955 - /// @}
5.1956 -
5.1957 - };
5.1958 -
5.1959 - /// \ingroup matching
5.1960 - ///
5.1961 - /// \brief Weighted perfect matching in general graphs
5.1962 - ///
5.1963 - /// This class provides an efficient implementation of Edmond's
5.1964 - /// maximum weighted perfect matching algorithm. The implementation
5.1965 - /// is based on extensive use of priority queues and provides
5.1966 - /// \f$O(nm\log n)\f$ time complexity.
5.1967 - ///
5.1968 - /// The maximum weighted matching problem is to find undirected
5.1969 - /// edges in the graph with maximum overall weight and no two of
5.1970 - /// them shares their ends and covers all nodes. The problem can be
5.1971 - /// formulated with the following linear program.
5.1972 - /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
5.1973 - /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
5.1974 - \quad \forall B\in\mathcal{O}\f] */
5.1975 - /// \f[x_e \ge 0\quad \forall e\in E\f]
5.1976 - /// \f[\max \sum_{e\in E}x_ew_e\f]
5.1977 - /// where \f$\delta(X)\f$ is the set of edges incident to a node in
5.1978 - /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
5.1979 - /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
5.1980 - /// subsets of the nodes.
5.1981 - ///
5.1982 - /// The algorithm calculates an optimal matching and a proof of the
5.1983 - /// optimality. The solution of the dual problem can be used to check
5.1984 - /// the result of the algorithm. The dual linear problem is the
5.1985 - /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
5.1986 - w_{uv} \quad \forall uv\in E\f] */
5.1987 - /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
5.1988 - /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
5.1989 - \frac{\vert B \vert - 1}{2}z_B\f] */
5.1990 - ///
5.1991 - /// The algorithm can be executed with \c run() or the \c init() and
5.1992 - /// then the \c start() member functions. After it the matching can
5.1993 - /// be asked with \c matching() or mate() functions. The dual
5.1994 - /// solution can be get with \c nodeValue(), \c blossomNum() and \c
5.1995 - /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
5.1996 - /// "BlossomIt" nested class which is able to iterate on the nodes
5.1997 - /// of a blossom. If the value type is integral then the dual
5.1998 - /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
5.1999 - template <typename GR,
5.2000 - typename WM = typename GR::template EdgeMap<int> >
5.2001 - class MaxWeightedPerfectMatching {
5.2002 - public:
5.2003 -
5.2004 - typedef GR Graph;
5.2005 - typedef WM WeightMap;
5.2006 - typedef typename WeightMap::Value Value;
5.2007 -
5.2008 - /// \brief Scaling factor for dual solution
5.2009 - ///
5.2010 - /// Scaling factor for dual solution, it is equal to 4 or 1
5.2011 - /// according to the value type.
5.2012 - static const int dualScale =
5.2013 - std::numeric_limits<Value>::is_integer ? 4 : 1;
5.2014 -
5.2015 - typedef typename Graph::template NodeMap<typename Graph::Arc>
5.2016 - MatchingMap;
5.2017 -
5.2018 - private:
5.2019 -
5.2020 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
5.2021 -
5.2022 - typedef typename Graph::template NodeMap<Value> NodePotential;
5.2023 - typedef std::vector<Node> BlossomNodeList;
5.2024 -
5.2025 - struct BlossomVariable {
5.2026 - int begin, end;
5.2027 - Value value;
5.2028 -
5.2029 - BlossomVariable(int _begin, int _end, Value _value)
5.2030 - : begin(_begin), end(_end), value(_value) {}
5.2031 -
5.2032 - };
5.2033 -
5.2034 - typedef std::vector<BlossomVariable> BlossomPotential;
5.2035 -
5.2036 - const Graph& _graph;
5.2037 - const WeightMap& _weight;
5.2038 -
5.2039 - MatchingMap* _matching;
5.2040 -
5.2041 - NodePotential* _node_potential;
5.2042 -
5.2043 - BlossomPotential _blossom_potential;
5.2044 - BlossomNodeList _blossom_node_list;
5.2045 -
5.2046 - int _node_num;
5.2047 - int _blossom_num;
5.2048 -
5.2049 - typedef RangeMap<int> IntIntMap;
5.2050 -
5.2051 - enum Status {
5.2052 - EVEN = -1, MATCHED = 0, ODD = 1
5.2053 - };
5.2054 -
5.2055 - typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
5.2056 - struct BlossomData {
5.2057 - int tree;
5.2058 - Status status;
5.2059 - Arc pred, next;
5.2060 - Value pot, offset;
5.2061 - };
5.2062 -
5.2063 - IntNodeMap *_blossom_index;
5.2064 - BlossomSet *_blossom_set;
5.2065 - RangeMap<BlossomData>* _blossom_data;
5.2066 -
5.2067 - IntNodeMap *_node_index;
5.2068 - IntArcMap *_node_heap_index;
5.2069 -
5.2070 - struct NodeData {
5.2071 -
5.2072 - NodeData(IntArcMap& node_heap_index)
5.2073 - : heap(node_heap_index) {}
5.2074 -
5.2075 - int blossom;
5.2076 - Value pot;
5.2077 - BinHeap<Value, IntArcMap> heap;
5.2078 - std::map<int, Arc> heap_index;
5.2079 -
5.2080 - int tree;
5.2081 - };
5.2082 -
5.2083 - RangeMap<NodeData>* _node_data;
5.2084 -
5.2085 - typedef ExtendFindEnum<IntIntMap> TreeSet;
5.2086 -
5.2087 - IntIntMap *_tree_set_index;
5.2088 - TreeSet *_tree_set;
5.2089 -
5.2090 - IntIntMap *_delta2_index;
5.2091 - BinHeap<Value, IntIntMap> *_delta2;
5.2092 -
5.2093 - IntEdgeMap *_delta3_index;
5.2094 - BinHeap<Value, IntEdgeMap> *_delta3;
5.2095 -
5.2096 - IntIntMap *_delta4_index;
5.2097 - BinHeap<Value, IntIntMap> *_delta4;
5.2098 -
5.2099 - Value _delta_sum;
5.2100 -
5.2101 - void createStructures() {
5.2102 - _node_num = countNodes(_graph);
5.2103 - _blossom_num = _node_num * 3 / 2;
5.2104 -
5.2105 - if (!_matching) {
5.2106 - _matching = new MatchingMap(_graph);
5.2107 - }
5.2108 - if (!_node_potential) {
5.2109 - _node_potential = new NodePotential(_graph);
5.2110 - }
5.2111 - if (!_blossom_set) {
5.2112 - _blossom_index = new IntNodeMap(_graph);
5.2113 - _blossom_set = new BlossomSet(*_blossom_index);
5.2114 - _blossom_data = new RangeMap<BlossomData>(_blossom_num);
5.2115 - }
5.2116 -
5.2117 - if (!_node_index) {
5.2118 - _node_index = new IntNodeMap(_graph);
5.2119 - _node_heap_index = new IntArcMap(_graph);
5.2120 - _node_data = new RangeMap<NodeData>(_node_num,
5.2121 - NodeData(*_node_heap_index));
5.2122 - }
5.2123 -
5.2124 - if (!_tree_set) {
5.2125 - _tree_set_index = new IntIntMap(_blossom_num);
5.2126 - _tree_set = new TreeSet(*_tree_set_index);
5.2127 - }
5.2128 - if (!_delta2) {
5.2129 - _delta2_index = new IntIntMap(_blossom_num);
5.2130 - _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
5.2131 - }
5.2132 - if (!_delta3) {
5.2133 - _delta3_index = new IntEdgeMap(_graph);
5.2134 - _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
5.2135 - }
5.2136 - if (!_delta4) {
5.2137 - _delta4_index = new IntIntMap(_blossom_num);
5.2138 - _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
5.2139 - }
5.2140 - }
5.2141 -
5.2142 - void destroyStructures() {
5.2143 - _node_num = countNodes(_graph);
5.2144 - _blossom_num = _node_num * 3 / 2;
5.2145 -
5.2146 - if (_matching) {
5.2147 - delete _matching;
5.2148 - }
5.2149 - if (_node_potential) {
5.2150 - delete _node_potential;
5.2151 - }
5.2152 - if (_blossom_set) {
5.2153 - delete _blossom_index;
5.2154 - delete _blossom_set;
5.2155 - delete _blossom_data;
5.2156 - }
5.2157 -
5.2158 - if (_node_index) {
5.2159 - delete _node_index;
5.2160 - delete _node_heap_index;
5.2161 - delete _node_data;
5.2162 - }
5.2163 -
5.2164 - if (_tree_set) {
5.2165 - delete _tree_set_index;
5.2166 - delete _tree_set;
5.2167 - }
5.2168 - if (_delta2) {
5.2169 - delete _delta2_index;
5.2170 - delete _delta2;
5.2171 - }
5.2172 - if (_delta3) {
5.2173 - delete _delta3_index;
5.2174 - delete _delta3;
5.2175 - }
5.2176 - if (_delta4) {
5.2177 - delete _delta4_index;
5.2178 - delete _delta4;
5.2179 - }
5.2180 - }
5.2181 -
5.2182 - void matchedToEven(int blossom, int tree) {
5.2183 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
5.2184 - _delta2->erase(blossom);
5.2185 - }
5.2186 -
5.2187 - if (!_blossom_set->trivial(blossom)) {
5.2188 - (*_blossom_data)[blossom].pot -=
5.2189 - 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
5.2190 - }
5.2191 -
5.2192 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.2193 - n != INVALID; ++n) {
5.2194 -
5.2195 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
5.2196 - int ni = (*_node_index)[n];
5.2197 -
5.2198 - (*_node_data)[ni].heap.clear();
5.2199 - (*_node_data)[ni].heap_index.clear();
5.2200 -
5.2201 - (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
5.2202 -
5.2203 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
5.2204 - Node v = _graph.source(e);
5.2205 - int vb = _blossom_set->find(v);
5.2206 - int vi = (*_node_index)[v];
5.2207 -
5.2208 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.2209 - dualScale * _weight[e];
5.2210 -
5.2211 - if ((*_blossom_data)[vb].status == EVEN) {
5.2212 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
5.2213 - _delta3->push(e, rw / 2);
5.2214 - }
5.2215 - } else {
5.2216 - typename std::map<int, Arc>::iterator it =
5.2217 - (*_node_data)[vi].heap_index.find(tree);
5.2218 -
5.2219 - if (it != (*_node_data)[vi].heap_index.end()) {
5.2220 - if ((*_node_data)[vi].heap[it->second] > rw) {
5.2221 - (*_node_data)[vi].heap.replace(it->second, e);
5.2222 - (*_node_data)[vi].heap.decrease(e, rw);
5.2223 - it->second = e;
5.2224 - }
5.2225 - } else {
5.2226 - (*_node_data)[vi].heap.push(e, rw);
5.2227 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
5.2228 - }
5.2229 -
5.2230 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
5.2231 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
5.2232 -
5.2233 - if ((*_blossom_data)[vb].status == MATCHED) {
5.2234 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
5.2235 - _delta2->push(vb, _blossom_set->classPrio(vb) -
5.2236 - (*_blossom_data)[vb].offset);
5.2237 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
5.2238 - (*_blossom_data)[vb].offset){
5.2239 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
5.2240 - (*_blossom_data)[vb].offset);
5.2241 - }
5.2242 - }
5.2243 - }
5.2244 - }
5.2245 - }
5.2246 - }
5.2247 - (*_blossom_data)[blossom].offset = 0;
5.2248 - }
5.2249 -
5.2250 - void matchedToOdd(int blossom) {
5.2251 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
5.2252 - _delta2->erase(blossom);
5.2253 - }
5.2254 - (*_blossom_data)[blossom].offset += _delta_sum;
5.2255 - if (!_blossom_set->trivial(blossom)) {
5.2256 - _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
5.2257 - (*_blossom_data)[blossom].offset);
5.2258 - }
5.2259 - }
5.2260 -
5.2261 - void evenToMatched(int blossom, int tree) {
5.2262 - if (!_blossom_set->trivial(blossom)) {
5.2263 - (*_blossom_data)[blossom].pot += 2 * _delta_sum;
5.2264 - }
5.2265 -
5.2266 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.2267 - n != INVALID; ++n) {
5.2268 - int ni = (*_node_index)[n];
5.2269 - (*_node_data)[ni].pot -= _delta_sum;
5.2270 -
5.2271 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
5.2272 - Node v = _graph.source(e);
5.2273 - int vb = _blossom_set->find(v);
5.2274 - int vi = (*_node_index)[v];
5.2275 -
5.2276 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.2277 - dualScale * _weight[e];
5.2278 -
5.2279 - if (vb == blossom) {
5.2280 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.2281 - _delta3->erase(e);
5.2282 - }
5.2283 - } else if ((*_blossom_data)[vb].status == EVEN) {
5.2284 -
5.2285 - if (_delta3->state(e) == _delta3->IN_HEAP) {
5.2286 - _delta3->erase(e);
5.2287 - }
5.2288 -
5.2289 - int vt = _tree_set->find(vb);
5.2290 -
5.2291 - if (vt != tree) {
5.2292 -
5.2293 - Arc r = _graph.oppositeArc(e);
5.2294 -
5.2295 - typename std::map<int, Arc>::iterator it =
5.2296 - (*_node_data)[ni].heap_index.find(vt);
5.2297 -
5.2298 - if (it != (*_node_data)[ni].heap_index.end()) {
5.2299 - if ((*_node_data)[ni].heap[it->second] > rw) {
5.2300 - (*_node_data)[ni].heap.replace(it->second, r);
5.2301 - (*_node_data)[ni].heap.decrease(r, rw);
5.2302 - it->second = r;
5.2303 - }
5.2304 - } else {
5.2305 - (*_node_data)[ni].heap.push(r, rw);
5.2306 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
5.2307 - }
5.2308 -
5.2309 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
5.2310 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
5.2311 -
5.2312 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
5.2313 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
5.2314 - (*_blossom_data)[blossom].offset);
5.2315 - } else if ((*_delta2)[blossom] >
5.2316 - _blossom_set->classPrio(blossom) -
5.2317 - (*_blossom_data)[blossom].offset){
5.2318 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
5.2319 - (*_blossom_data)[blossom].offset);
5.2320 - }
5.2321 - }
5.2322 - }
5.2323 - } else {
5.2324 -
5.2325 - typename std::map<int, Arc>::iterator it =
5.2326 - (*_node_data)[vi].heap_index.find(tree);
5.2327 -
5.2328 - if (it != (*_node_data)[vi].heap_index.end()) {
5.2329 - (*_node_data)[vi].heap.erase(it->second);
5.2330 - (*_node_data)[vi].heap_index.erase(it);
5.2331 - if ((*_node_data)[vi].heap.empty()) {
5.2332 - _blossom_set->increase(v, std::numeric_limits<Value>::max());
5.2333 - } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
5.2334 - _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
5.2335 - }
5.2336 -
5.2337 - if ((*_blossom_data)[vb].status == MATCHED) {
5.2338 - if (_blossom_set->classPrio(vb) ==
5.2339 - std::numeric_limits<Value>::max()) {
5.2340 - _delta2->erase(vb);
5.2341 - } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
5.2342 - (*_blossom_data)[vb].offset) {
5.2343 - _delta2->increase(vb, _blossom_set->classPrio(vb) -
5.2344 - (*_blossom_data)[vb].offset);
5.2345 - }
5.2346 - }
5.2347 - }
5.2348 - }
5.2349 - }
5.2350 - }
5.2351 - }
5.2352 -
5.2353 - void oddToMatched(int blossom) {
5.2354 - (*_blossom_data)[blossom].offset -= _delta_sum;
5.2355 -
5.2356 - if (_blossom_set->classPrio(blossom) !=
5.2357 - std::numeric_limits<Value>::max()) {
5.2358 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
5.2359 - (*_blossom_data)[blossom].offset);
5.2360 - }
5.2361 -
5.2362 - if (!_blossom_set->trivial(blossom)) {
5.2363 - _delta4->erase(blossom);
5.2364 - }
5.2365 - }
5.2366 -
5.2367 - void oddToEven(int blossom, int tree) {
5.2368 - if (!_blossom_set->trivial(blossom)) {
5.2369 - _delta4->erase(blossom);
5.2370 - (*_blossom_data)[blossom].pot -=
5.2371 - 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
5.2372 - }
5.2373 -
5.2374 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
5.2375 - n != INVALID; ++n) {
5.2376 - int ni = (*_node_index)[n];
5.2377 -
5.2378 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
5.2379 -
5.2380 - (*_node_data)[ni].heap.clear();
5.2381 - (*_node_data)[ni].heap_index.clear();
5.2382 - (*_node_data)[ni].pot +=
5.2383 - 2 * _delta_sum - (*_blossom_data)[blossom].offset;
5.2384 -
5.2385 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
5.2386 - Node v = _graph.source(e);
5.2387 - int vb = _blossom_set->find(v);
5.2388 - int vi = (*_node_index)[v];
5.2389 -
5.2390 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
5.2391 - dualScale * _weight[e];
5.2392 -
5.2393 - if ((*_blossom_data)[vb].status == EVEN) {
5.2394 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
5.2395 - _delta3->push(e, rw / 2);
5.2396 - }
5.2397 - } else {
5.2398 -
5.2399 - typename std::map<int, Arc>::iterator it =
5.2400 - (*_node_data)[vi].heap_index.find(tree);
5.2401 -
5.2402 - if (it != (*_node_data)[vi].heap_index.end()) {
5.2403 - if ((*_node_data)[vi].heap[it->second] > rw) {
5.2404 - (*_node_data)[vi].heap.replace(it->second, e);
5.2405 - (*_node_data)[vi].heap.decrease(e, rw);
5.2406 - it->second = e;
5.2407 - }
5.2408 - } else {
5.2409 - (*_node_data)[vi].heap.push(e, rw);
5.2410 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
5.2411 - }
5.2412 -
5.2413 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
5.2414 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
5.2415 -
5.2416 - if ((*_blossom_data)[vb].status == MATCHED) {
5.2417 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
5.2418 - _delta2->push(vb, _blossom_set->classPrio(vb) -
5.2419 - (*_blossom_data)[vb].offset);
5.2420 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
5.2421 - (*_blossom_data)[vb].offset) {
5.2422 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
5.2423 - (*_blossom_data)[vb].offset);
5.2424 - }
5.2425 - }
5.2426 - }
5.2427 - }
5.2428 - }
5.2429 - }
5.2430 - (*_blossom_data)[blossom].offset = 0;
5.2431 - }
5.2432 -
5.2433 - void alternatePath(int even, int tree) {
5.2434 - int odd;
5.2435 -
5.2436 - evenToMatched(even, tree);
5.2437 - (*_blossom_data)[even].status = MATCHED;
5.2438 -
5.2439 - while ((*_blossom_data)[even].pred != INVALID) {
5.2440 - odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
5.2441 - (*_blossom_data)[odd].status = MATCHED;
5.2442 - oddToMatched(odd);
5.2443 - (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
5.2444 -
5.2445 - even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
5.2446 - (*_blossom_data)[even].status = MATCHED;
5.2447 - evenToMatched(even, tree);
5.2448 - (*_blossom_data)[even].next =
5.2449 - _graph.oppositeArc((*_blossom_data)[odd].pred);
5.2450 - }
5.2451 -
5.2452 - }
5.2453 -
5.2454 - void destroyTree(int tree) {
5.2455 - for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
5.2456 - if ((*_blossom_data)[b].status == EVEN) {
5.2457 - (*_blossom_data)[b].status = MATCHED;
5.2458 - evenToMatched(b, tree);
5.2459 - } else if ((*_blossom_data)[b].status == ODD) {
5.2460 - (*_blossom_data)[b].status = MATCHED;
5.2461 - oddToMatched(b);
5.2462 - }
5.2463 - }
5.2464 - _tree_set->eraseClass(tree);
5.2465 - }
5.2466 -
5.2467 - void augmentOnEdge(const Edge& edge) {
5.2468 -
5.2469 - int left = _blossom_set->find(_graph.u(edge));
5.2470 - int right = _blossom_set->find(_graph.v(edge));
5.2471 -
5.2472 - int left_tree = _tree_set->find(left);
5.2473 - alternatePath(left, left_tree);
5.2474 - destroyTree(left_tree);
5.2475 -
5.2476 - int right_tree = _tree_set->find(right);
5.2477 - alternatePath(right, right_tree);
5.2478 - destroyTree(right_tree);
5.2479 -
5.2480 - (*_blossom_data)[left].next = _graph.direct(edge, true);
5.2481 - (*_blossom_data)[right].next = _graph.direct(edge, false);
5.2482 - }
5.2483 -
5.2484 - void extendOnArc(const Arc& arc) {
5.2485 - int base = _blossom_set->find(_graph.target(arc));
5.2486 - int tree = _tree_set->find(base);
5.2487 -
5.2488 - int odd = _blossom_set->find(_graph.source(arc));
5.2489 - _tree_set->insert(odd, tree);
5.2490 - (*_blossom_data)[odd].status = ODD;
5.2491 - matchedToOdd(odd);
5.2492 - (*_blossom_data)[odd].pred = arc;
5.2493 -
5.2494 - int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
5.2495 - (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
5.2496 - _tree_set->insert(even, tree);
5.2497 - (*_blossom_data)[even].status = EVEN;
5.2498 - matchedToEven(even, tree);
5.2499 - }
5.2500 -
5.2501 - void shrinkOnEdge(const Edge& edge, int tree) {
5.2502 - int nca = -1;
5.2503 - std::vector<int> left_path, right_path;
5.2504 -
5.2505 - {
5.2506 - std::set<int> left_set, right_set;
5.2507 - int left = _blossom_set->find(_graph.u(edge));
5.2508 - left_path.push_back(left);
5.2509 - left_set.insert(left);
5.2510 -
5.2511 - int right = _blossom_set->find(_graph.v(edge));
5.2512 - right_path.push_back(right);
5.2513 - right_set.insert(right);
5.2514 -
5.2515 - while (true) {
5.2516 -
5.2517 - if ((*_blossom_data)[left].pred == INVALID) break;
5.2518 -
5.2519 - left =
5.2520 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
5.2521 - left_path.push_back(left);
5.2522 - left =
5.2523 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
5.2524 - left_path.push_back(left);
5.2525 -
5.2526 - left_set.insert(left);
5.2527 -
5.2528 - if (right_set.find(left) != right_set.end()) {
5.2529 - nca = left;
5.2530 - break;
5.2531 - }
5.2532 -
5.2533 - if ((*_blossom_data)[right].pred == INVALID) break;
5.2534 -
5.2535 - right =
5.2536 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
5.2537 - right_path.push_back(right);
5.2538 - right =
5.2539 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
5.2540 - right_path.push_back(right);
5.2541 -
5.2542 - right_set.insert(right);
5.2543 -
5.2544 - if (left_set.find(right) != left_set.end()) {
5.2545 - nca = right;
5.2546 - break;
5.2547 - }
5.2548 -
5.2549 - }
5.2550 -
5.2551 - if (nca == -1) {
5.2552 - if ((*_blossom_data)[left].pred == INVALID) {
5.2553 - nca = right;
5.2554 - while (left_set.find(nca) == left_set.end()) {
5.2555 - nca =
5.2556 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.2557 - right_path.push_back(nca);
5.2558 - nca =
5.2559 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.2560 - right_path.push_back(nca);
5.2561 - }
5.2562 - } else {
5.2563 - nca = left;
5.2564 - while (right_set.find(nca) == right_set.end()) {
5.2565 - nca =
5.2566 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.2567 - left_path.push_back(nca);
5.2568 - nca =
5.2569 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
5.2570 - left_path.push_back(nca);
5.2571 - }
5.2572 - }
5.2573 - }
5.2574 - }
5.2575 -
5.2576 - std::vector<int> subblossoms;
5.2577 - Arc prev;
5.2578 -
5.2579 - prev = _graph.direct(edge, true);
5.2580 - for (int i = 0; left_path[i] != nca; i += 2) {
5.2581 - subblossoms.push_back(left_path[i]);
5.2582 - (*_blossom_data)[left_path[i]].next = prev;
5.2583 - _tree_set->erase(left_path[i]);
5.2584 -
5.2585 - subblossoms.push_back(left_path[i + 1]);
5.2586 - (*_blossom_data)[left_path[i + 1]].status = EVEN;
5.2587 - oddToEven(left_path[i + 1], tree);
5.2588 - _tree_set->erase(left_path[i + 1]);
5.2589 - prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
5.2590 - }
5.2591 -
5.2592 - int k = 0;
5.2593 - while (right_path[k] != nca) ++k;
5.2594 -
5.2595 - subblossoms.push_back(nca);
5.2596 - (*_blossom_data)[nca].next = prev;
5.2597 -
5.2598 - for (int i = k - 2; i >= 0; i -= 2) {
5.2599 - subblossoms.push_back(right_path[i + 1]);
5.2600 - (*_blossom_data)[right_path[i + 1]].status = EVEN;
5.2601 - oddToEven(right_path[i + 1], tree);
5.2602 - _tree_set->erase(right_path[i + 1]);
5.2603 -
5.2604 - (*_blossom_data)[right_path[i + 1]].next =
5.2605 - (*_blossom_data)[right_path[i + 1]].pred;
5.2606 -
5.2607 - subblossoms.push_back(right_path[i]);
5.2608 - _tree_set->erase(right_path[i]);
5.2609 - }
5.2610 -
5.2611 - int surface =
5.2612 - _blossom_set->join(subblossoms.begin(), subblossoms.end());
5.2613 -
5.2614 - for (int i = 0; i < int(subblossoms.size()); ++i) {
5.2615 - if (!_blossom_set->trivial(subblossoms[i])) {
5.2616 - (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
5.2617 - }
5.2618 - (*_blossom_data)[subblossoms[i]].status = MATCHED;
5.2619 - }
5.2620 -
5.2621 - (*_blossom_data)[surface].pot = -2 * _delta_sum;
5.2622 - (*_blossom_data)[surface].offset = 0;
5.2623 - (*_blossom_data)[surface].status = EVEN;
5.2624 - (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
5.2625 - (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
5.2626 -
5.2627 - _tree_set->insert(surface, tree);
5.2628 - _tree_set->erase(nca);
5.2629 - }
5.2630 -
5.2631 - void splitBlossom(int blossom) {
5.2632 - Arc next = (*_blossom_data)[blossom].next;
5.2633 - Arc pred = (*_blossom_data)[blossom].pred;
5.2634 -
5.2635 - int tree = _tree_set->find(blossom);
5.2636 -
5.2637 - (*_blossom_data)[blossom].status = MATCHED;
5.2638 - oddToMatched(blossom);
5.2639 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
5.2640 - _delta2->erase(blossom);
5.2641 - }
5.2642 -
5.2643 - std::vector<int> subblossoms;
5.2644 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
5.2645 -
5.2646 - Value offset = (*_blossom_data)[blossom].offset;
5.2647 - int b = _blossom_set->find(_graph.source(pred));
5.2648 - int d = _blossom_set->find(_graph.source(next));
5.2649 -
5.2650 - int ib = -1, id = -1;
5.2651 - for (int i = 0; i < int(subblossoms.size()); ++i) {
5.2652 - if (subblossoms[i] == b) ib = i;
5.2653 - if (subblossoms[i] == d) id = i;
5.2654 -
5.2655 - (*_blossom_data)[subblossoms[i]].offset = offset;
5.2656 - if (!_blossom_set->trivial(subblossoms[i])) {
5.2657 - (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
5.2658 - }
5.2659 - if (_blossom_set->classPrio(subblossoms[i]) !=
5.2660 - std::numeric_limits<Value>::max()) {
5.2661 - _delta2->push(subblossoms[i],
5.2662 - _blossom_set->classPrio(subblossoms[i]) -
5.2663 - (*_blossom_data)[subblossoms[i]].offset);
5.2664 - }
5.2665 - }
5.2666 -
5.2667 - if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
5.2668 - for (int i = (id + 1) % subblossoms.size();
5.2669 - i != ib; i = (i + 2) % subblossoms.size()) {
5.2670 - int sb = subblossoms[i];
5.2671 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.2672 - (*_blossom_data)[sb].next =
5.2673 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.2674 - }
5.2675 -
5.2676 - for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
5.2677 - int sb = subblossoms[i];
5.2678 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.2679 - int ub = subblossoms[(i + 2) % subblossoms.size()];
5.2680 -
5.2681 - (*_blossom_data)[sb].status = ODD;
5.2682 - matchedToOdd(sb);
5.2683 - _tree_set->insert(sb, tree);
5.2684 - (*_blossom_data)[sb].pred = pred;
5.2685 - (*_blossom_data)[sb].next =
5.2686 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.2687 -
5.2688 - pred = (*_blossom_data)[ub].next;
5.2689 -
5.2690 - (*_blossom_data)[tb].status = EVEN;
5.2691 - matchedToEven(tb, tree);
5.2692 - _tree_set->insert(tb, tree);
5.2693 - (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
5.2694 - }
5.2695 -
5.2696 - (*_blossom_data)[subblossoms[id]].status = ODD;
5.2697 - matchedToOdd(subblossoms[id]);
5.2698 - _tree_set->insert(subblossoms[id], tree);
5.2699 - (*_blossom_data)[subblossoms[id]].next = next;
5.2700 - (*_blossom_data)[subblossoms[id]].pred = pred;
5.2701 -
5.2702 - } else {
5.2703 -
5.2704 - for (int i = (ib + 1) % subblossoms.size();
5.2705 - i != id; i = (i + 2) % subblossoms.size()) {
5.2706 - int sb = subblossoms[i];
5.2707 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.2708 - (*_blossom_data)[sb].next =
5.2709 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.2710 - }
5.2711 -
5.2712 - for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
5.2713 - int sb = subblossoms[i];
5.2714 - int tb = subblossoms[(i + 1) % subblossoms.size()];
5.2715 - int ub = subblossoms[(i + 2) % subblossoms.size()];
5.2716 -
5.2717 - (*_blossom_data)[sb].status = ODD;
5.2718 - matchedToOdd(sb);
5.2719 - _tree_set->insert(sb, tree);
5.2720 - (*_blossom_data)[sb].next = next;
5.2721 - (*_blossom_data)[sb].pred =
5.2722 - _graph.oppositeArc((*_blossom_data)[tb].next);
5.2723 -
5.2724 - (*_blossom_data)[tb].status = EVEN;
5.2725 - matchedToEven(tb, tree);
5.2726 - _tree_set->insert(tb, tree);
5.2727 - (*_blossom_data)[tb].pred =
5.2728 - (*_blossom_data)[tb].next =
5.2729 - _graph.oppositeArc((*_blossom_data)[ub].next);
5.2730 - next = (*_blossom_data)[ub].next;
5.2731 - }
5.2732 -
5.2733 - (*_blossom_data)[subblossoms[ib]].status = ODD;
5.2734 - matchedToOdd(subblossoms[ib]);
5.2735 - _tree_set->insert(subblossoms[ib], tree);
5.2736 - (*_blossom_data)[subblossoms[ib]].next = next;
5.2737 - (*_blossom_data)[subblossoms[ib]].pred = pred;
5.2738 - }
5.2739 - _tree_set->erase(blossom);
5.2740 - }
5.2741 -
5.2742 - void extractBlossom(int blossom, const Node& base, const Arc& matching) {
5.2743 - if (_blossom_set->trivial(blossom)) {
5.2744 - int bi = (*_node_index)[base];
5.2745 - Value pot = (*_node_data)[bi].pot;
5.2746 -
5.2747 - (*_matching)[base] = matching;
5.2748 - _blossom_node_list.push_back(base);
5.2749 - (*_node_potential)[base] = pot;
5.2750 - } else {
5.2751 -
5.2752 - Value pot = (*_blossom_data)[blossom].pot;
5.2753 - int bn = _blossom_node_list.size();
5.2754 -
5.2755 - std::vector<int> subblossoms;
5.2756 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
5.2757 - int b = _blossom_set->find(base);
5.2758 - int ib = -1;
5.2759 - for (int i = 0; i < int(subblossoms.size()); ++i) {
5.2760 - if (subblossoms[i] == b) { ib = i; break; }
5.2761 - }
5.2762 -
5.2763 - for (int i = 1; i < int(subblossoms.size()); i += 2) {
5.2764 - int sb = subblossoms[(ib + i) % subblossoms.size()];
5.2765 - int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
5.2766 -
5.2767 - Arc m = (*_blossom_data)[tb].next;
5.2768 - extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
5.2769 - extractBlossom(tb, _graph.source(m), m);
5.2770 - }
5.2771 - extractBlossom(subblossoms[ib], base, matching);
5.2772 -
5.2773 - int en = _blossom_node_list.size();
5.2774 -
5.2775 - _blossom_potential.push_back(BlossomVariable(bn, en, pot));
5.2776 - }
5.2777 - }
5.2778 -
5.2779 - void extractMatching() {
5.2780 - std::vector<int> blossoms;
5.2781 - for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
5.2782 - blossoms.push_back(c);
5.2783 - }
5.2784 -
5.2785 - for (int i = 0; i < int(blossoms.size()); ++i) {
5.2786 -
5.2787 - Value offset = (*_blossom_data)[blossoms[i]].offset;
5.2788 - (*_blossom_data)[blossoms[i]].pot += 2 * offset;
5.2789 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
5.2790 - n != INVALID; ++n) {
5.2791 - (*_node_data)[(*_node_index)[n]].pot -= offset;
5.2792 - }
5.2793 -
5.2794 - Arc matching = (*_blossom_data)[blossoms[i]].next;
5.2795 - Node base = _graph.source(matching);
5.2796 - extractBlossom(blossoms[i], base, matching);
5.2797 - }
5.2798 - }
5.2799 -
5.2800 - public:
5.2801 -
5.2802 - /// \brief Constructor
5.2803 - ///
5.2804 - /// Constructor.
5.2805 - MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
5.2806 - : _graph(graph), _weight(weight), _matching(0),
5.2807 - _node_potential(0), _blossom_potential(), _blossom_node_list(),
5.2808 - _node_num(0), _blossom_num(0),
5.2809 -
5.2810 - _blossom_index(0), _blossom_set(0), _blossom_data(0),
5.2811 - _node_index(0), _node_heap_index(0), _node_data(0),
5.2812 - _tree_set_index(0), _tree_set(0),
5.2813 -
5.2814 - _delta2_index(0), _delta2(0),
5.2815 - _delta3_index(0), _delta3(0),
5.2816 - _delta4_index(0), _delta4(0),
5.2817 -
5.2818 - _delta_sum() {}
5.2819 -
5.2820 - ~MaxWeightedPerfectMatching() {
5.2821 - destroyStructures();
5.2822 - }
5.2823 -
5.2824 - /// \name Execution control
5.2825 - /// The simplest way to execute the algorithm is to use the
5.2826 - /// \c run() member function.
5.2827 -
5.2828 - ///@{
5.2829 -
5.2830 - /// \brief Initialize the algorithm
5.2831 - ///
5.2832 - /// Initialize the algorithm
5.2833 - void init() {
5.2834 - createStructures();
5.2835 -
5.2836 - for (ArcIt e(_graph); e != INVALID; ++e) {
5.2837 - (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
5.2838 - }
5.2839 - for (EdgeIt e(_graph); e != INVALID; ++e) {
5.2840 - (*_delta3_index)[e] = _delta3->PRE_HEAP;
5.2841 - }
5.2842 - for (int i = 0; i < _blossom_num; ++i) {
5.2843 - (*_delta2_index)[i] = _delta2->PRE_HEAP;
5.2844 - (*_delta4_index)[i] = _delta4->PRE_HEAP;
5.2845 - }
5.2846 -
5.2847 - int index = 0;
5.2848 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.2849 - Value max = - std::numeric_limits<Value>::max();
5.2850 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
5.2851 - if (_graph.target(e) == n) continue;
5.2852 - if ((dualScale * _weight[e]) / 2 > max) {
5.2853 - max = (dualScale * _weight[e]) / 2;
5.2854 - }
5.2855 - }
5.2856 - (*_node_index)[n] = index;
5.2857 - (*_node_data)[index].pot = max;
5.2858 - int blossom =
5.2859 - _blossom_set->insert(n, std::numeric_limits<Value>::max());
5.2860 -
5.2861 - _tree_set->insert(blossom);
5.2862 -
5.2863 - (*_blossom_data)[blossom].status = EVEN;
5.2864 - (*_blossom_data)[blossom].pred = INVALID;
5.2865 - (*_blossom_data)[blossom].next = INVALID;
5.2866 - (*_blossom_data)[blossom].pot = 0;
5.2867 - (*_blossom_data)[blossom].offset = 0;
5.2868 - ++index;
5.2869 - }
5.2870 - for (EdgeIt e(_graph); e != INVALID; ++e) {
5.2871 - int si = (*_node_index)[_graph.u(e)];
5.2872 - int ti = (*_node_index)[_graph.v(e)];
5.2873 - if (_graph.u(e) != _graph.v(e)) {
5.2874 - _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
5.2875 - dualScale * _weight[e]) / 2);
5.2876 - }
5.2877 - }
5.2878 - }
5.2879 -
5.2880 - /// \brief Starts the algorithm
5.2881 - ///
5.2882 - /// Starts the algorithm
5.2883 - bool start() {
5.2884 - enum OpType {
5.2885 - D2, D3, D4
5.2886 - };
5.2887 -
5.2888 - int unmatched = _node_num;
5.2889 - while (unmatched > 0) {
5.2890 - Value d2 = !_delta2->empty() ?
5.2891 - _delta2->prio() : std::numeric_limits<Value>::max();
5.2892 -
5.2893 - Value d3 = !_delta3->empty() ?
5.2894 - _delta3->prio() : std::numeric_limits<Value>::max();
5.2895 -
5.2896 - Value d4 = !_delta4->empty() ?
5.2897 - _delta4->prio() : std::numeric_limits<Value>::max();
5.2898 -
5.2899 - _delta_sum = d2; OpType ot = D2;
5.2900 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
5.2901 - if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
5.2902 -
5.2903 - if (_delta_sum == std::numeric_limits<Value>::max()) {
5.2904 - return false;
5.2905 - }
5.2906 -
5.2907 - switch (ot) {
5.2908 - case D2:
5.2909 - {
5.2910 - int blossom = _delta2->top();
5.2911 - Node n = _blossom_set->classTop(blossom);
5.2912 - Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
5.2913 - extendOnArc(e);
5.2914 - }
5.2915 - break;
5.2916 - case D3:
5.2917 - {
5.2918 - Edge e = _delta3->top();
5.2919 -
5.2920 - int left_blossom = _blossom_set->find(_graph.u(e));
5.2921 - int right_blossom = _blossom_set->find(_graph.v(e));
5.2922 -
5.2923 - if (left_blossom == right_blossom) {
5.2924 - _delta3->pop();
5.2925 - } else {
5.2926 - int left_tree = _tree_set->find(left_blossom);
5.2927 - int right_tree = _tree_set->find(right_blossom);
5.2928 -
5.2929 - if (left_tree == right_tree) {
5.2930 - shrinkOnEdge(e, left_tree);
5.2931 - } else {
5.2932 - augmentOnEdge(e);
5.2933 - unmatched -= 2;
5.2934 - }
5.2935 - }
5.2936 - } break;
5.2937 - case D4:
5.2938 - splitBlossom(_delta4->top());
5.2939 - break;
5.2940 - }
5.2941 - }
5.2942 - extractMatching();
5.2943 - return true;
5.2944 - }
5.2945 -
5.2946 - /// \brief Runs %MaxWeightedPerfectMatching algorithm.
5.2947 - ///
5.2948 - /// This method runs the %MaxWeightedPerfectMatching algorithm.
5.2949 - ///
5.2950 - /// \note mwm.run() is just a shortcut of the following code.
5.2951 - /// \code
5.2952 - /// mwm.init();
5.2953 - /// mwm.start();
5.2954 - /// \endcode
5.2955 - bool run() {
5.2956 - init();
5.2957 - return start();
5.2958 - }
5.2959 -
5.2960 - /// @}
5.2961 -
5.2962 - /// \name Primal solution
5.2963 - /// Functions to get the primal solution, ie. the matching.
5.2964 -
5.2965 - /// @{
5.2966 -
5.2967 - /// \brief Returns the matching value.
5.2968 - ///
5.2969 - /// Returns the matching value.
5.2970 - Value matchingValue() const {
5.2971 - Value sum = 0;
5.2972 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.2973 - if ((*_matching)[n] != INVALID) {
5.2974 - sum += _weight[(*_matching)[n]];
5.2975 - }
5.2976 - }
5.2977 - return sum /= 2;
5.2978 - }
5.2979 -
5.2980 - /// \brief Returns true when the edge is in the matching.
5.2981 - ///
5.2982 - /// Returns true when the edge is in the matching.
5.2983 - bool matching(const Edge& edge) const {
5.2984 - return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
5.2985 - }
5.2986 -
5.2987 - /// \brief Returns the incident matching edge.
5.2988 - ///
5.2989 - /// Returns the incident matching arc from given edge.
5.2990 - Arc matching(const Node& node) const {
5.2991 - return (*_matching)[node];
5.2992 - }
5.2993 -
5.2994 - /// \brief Returns the mate of the node.
5.2995 - ///
5.2996 - /// Returns the adjancent node in a mathcing arc.
5.2997 - Node mate(const Node& node) const {
5.2998 - return _graph.target((*_matching)[node]);
5.2999 - }
5.3000 -
5.3001 - /// @}
5.3002 -
5.3003 - /// \name Dual solution
5.3004 - /// Functions to get the dual solution.
5.3005 -
5.3006 - /// @{
5.3007 -
5.3008 - /// \brief Returns the value of the dual solution.
5.3009 - ///
5.3010 - /// Returns the value of the dual solution. It should be equal to
5.3011 - /// the primal value scaled by \ref dualScale "dual scale".
5.3012 - Value dualValue() const {
5.3013 - Value sum = 0;
5.3014 - for (NodeIt n(_graph); n != INVALID; ++n) {
5.3015 - sum += nodeValue(n);
5.3016 - }
5.3017 - for (int i = 0; i < blossomNum(); ++i) {
5.3018 - sum += blossomValue(i) * (blossomSize(i) / 2);
5.3019 - }
5.3020 - return sum;
5.3021 - }
5.3022 -
5.3023 - /// \brief Returns the value of the node.
5.3024 - ///
5.3025 - /// Returns the the value of the node.
5.3026 - Value nodeValue(const Node& n) const {
5.3027 - return (*_node_potential)[n];
5.3028 - }
5.3029 -
5.3030 - /// \brief Returns the number of the blossoms in the basis.
5.3031 - ///
5.3032 - /// Returns the number of the blossoms in the basis.
5.3033 - /// \see BlossomIt
5.3034 - int blossomNum() const {
5.3035 - return _blossom_potential.size();
5.3036 - }
5.3037 -
5.3038 -
5.3039 - /// \brief Returns the number of the nodes in the blossom.
5.3040 - ///
5.3041 - /// Returns the number of the nodes in the blossom.
5.3042 - int blossomSize(int k) const {
5.3043 - return _blossom_potential[k].end - _blossom_potential[k].begin;
5.3044 - }
5.3045 -
5.3046 - /// \brief Returns the value of the blossom.
5.3047 - ///
5.3048 - /// Returns the the value of the blossom.
5.3049 - /// \see BlossomIt
5.3050 - Value blossomValue(int k) const {
5.3051 - return _blossom_potential[k].value;
5.3052 - }
5.3053 -
5.3054 - /// \brief Iterator for obtaining the nodes of the blossom.
5.3055 - ///
5.3056 - /// Iterator for obtaining the nodes of the blossom. This class
5.3057 - /// provides a common lemon style iterator for listing a
5.3058 - /// subset of the nodes.
5.3059 - class BlossomIt {
5.3060 - public:
5.3061 -
5.3062 - /// \brief Constructor.
5.3063 - ///
5.3064 - /// Constructor to get the nodes of the variable.
5.3065 - BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
5.3066 - : _algorithm(&algorithm)
5.3067 - {
5.3068 - _index = _algorithm->_blossom_potential[variable].begin;
5.3069 - _last = _algorithm->_blossom_potential[variable].end;
5.3070 - }
5.3071 -
5.3072 - /// \brief Conversion to node.
5.3073 - ///
5.3074 - /// Conversion to node.
5.3075 - operator Node() const {
5.3076 - return _algorithm->_blossom_node_list[_index];
5.3077 - }
5.3078 -
5.3079 - /// \brief Increment operator.
5.3080 - ///
5.3081 - /// Increment operator.
5.3082 - BlossomIt& operator++() {
5.3083 - ++_index;
5.3084 - return *this;
5.3085 - }
5.3086 -
5.3087 - /// \brief Validity checking
5.3088 - ///
5.3089 - /// Checks whether the iterator is invalid.
5.3090 - bool operator==(Invalid) const { return _index == _last; }
5.3091 -
5.3092 - /// \brief Validity checking
5.3093 - ///
5.3094 - /// Checks whether the iterator is valid.
5.3095 - bool operator!=(Invalid) const { return _index != _last; }
5.3096 -
5.3097 - private:
5.3098 - const MaxWeightedPerfectMatching* _algorithm;
5.3099 - int _last;
5.3100 - int _index;
5.3101 - };
5.3102 -
5.3103 - /// @}
5.3104 -
5.3105 - };
5.3106 -
5.3107 -
5.3108 -} //END OF NAMESPACE LEMON
5.3109 -
5.3110 -#endif //LEMON_MAX_MATCHING_H
6.1 --- a/test/CMakeLists.txt Tue Apr 21 10:34:49 2009 +0100
6.2 +++ b/test/CMakeLists.txt Tue Apr 21 13:08:19 2009 +0100
6.3 @@ -29,7 +29,7 @@
6.4 heap_test
6.5 kruskal_test
6.6 maps_test
6.7 - max_matching_test
6.8 + matching_test
6.9 min_cost_arborescence_test
6.10 path_test
6.11 preflow_test
7.1 --- a/test/Makefile.am Tue Apr 21 10:34:49 2009 +0100
7.2 +++ b/test/Makefile.am Tue Apr 21 13:08:19 2009 +0100
7.3 @@ -25,7 +25,7 @@
7.4 test/heap_test \
7.5 test/kruskal_test \
7.6 test/maps_test \
7.7 - test/max_matching_test \
7.8 + test/matching_test \
7.9 test/min_cost_arborescence_test \
7.10 test/path_test \
7.11 test/preflow_test \
7.12 @@ -70,7 +70,7 @@
7.13 test_lp_test_SOURCES = test/lp_test.cc
7.14 test_maps_test_SOURCES = test/maps_test.cc
7.15 test_mip_test_SOURCES = test/mip_test.cc
7.16 -test_max_matching_test_SOURCES = test/max_matching_test.cc
7.17 +test_matching_test_SOURCES = test/matching_test.cc
7.18 test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
7.19 test_path_test_SOURCES = test/path_test.cc
7.20 test_preflow_test_SOURCES = test/preflow_test.cc
8.1 --- a/test/euler_test.cc Tue Apr 21 10:34:49 2009 +0100
8.2 +++ b/test/euler_test.cc Tue Apr 21 13:08:19 2009 +0100
8.3 @@ -18,136 +18,206 @@
8.4
8.5 #include <lemon/euler.h>
8.6 #include <lemon/list_graph.h>
8.7 -#include <test/test_tools.h>
8.8 +#include <lemon/adaptors.h>
8.9 +#include "test_tools.h"
8.10
8.11 using namespace lemon;
8.12
8.13 template <typename Digraph>
8.14 -void checkDiEulerIt(const Digraph& g)
8.15 +void checkDiEulerIt(const Digraph& g,
8.16 + const typename Digraph::Node& start = INVALID)
8.17 {
8.18 typename Digraph::template ArcMap<int> visitationNumber(g, 0);
8.19
8.20 - DiEulerIt<Digraph> e(g);
8.21 + DiEulerIt<Digraph> e(g, start);
8.22 + if (e == INVALID) return;
8.23 typename Digraph::Node firstNode = g.source(e);
8.24 typename Digraph::Node lastNode = g.target(e);
8.25 + if (start != INVALID) {
8.26 + check(firstNode == start, "checkDiEulerIt: Wrong first node");
8.27 + }
8.28
8.29 - for (; e != INVALID; ++e)
8.30 - {
8.31 - if (e != INVALID)
8.32 - {
8.33 - lastNode = g.target(e);
8.34 - }
8.35 + for (; e != INVALID; ++e) {
8.36 + if (e != INVALID) lastNode = g.target(e);
8.37 ++visitationNumber[e];
8.38 }
8.39
8.40 check(firstNode == lastNode,
8.41 - "checkDiEulerIt: first and last node are not the same");
8.42 + "checkDiEulerIt: First and last nodes are not the same");
8.43
8.44 for (typename Digraph::ArcIt a(g); a != INVALID; ++a)
8.45 {
8.46 check(visitationNumber[a] == 1,
8.47 - "checkDiEulerIt: not visited or multiple times visited arc found");
8.48 + "checkDiEulerIt: Not visited or multiple times visited arc found");
8.49 }
8.50 }
8.51
8.52 template <typename Graph>
8.53 -void checkEulerIt(const Graph& g)
8.54 +void checkEulerIt(const Graph& g,
8.55 + const typename Graph::Node& start = INVALID)
8.56 {
8.57 typename Graph::template EdgeMap<int> visitationNumber(g, 0);
8.58
8.59 - EulerIt<Graph> e(g);
8.60 - typename Graph::Node firstNode = g.u(e);
8.61 - typename Graph::Node lastNode = g.v(e);
8.62 + EulerIt<Graph> e(g, start);
8.63 + if (e == INVALID) return;
8.64 + typename Graph::Node firstNode = g.source(typename Graph::Arc(e));
8.65 + typename Graph::Node lastNode = g.target(typename Graph::Arc(e));
8.66 + if (start != INVALID) {
8.67 + check(firstNode == start, "checkEulerIt: Wrong first node");
8.68 + }
8.69
8.70 - for (; e != INVALID; ++e)
8.71 - {
8.72 - if (e != INVALID)
8.73 - {
8.74 - lastNode = g.v(e);
8.75 - }
8.76 + for (; e != INVALID; ++e) {
8.77 + if (e != INVALID) lastNode = g.target(typename Graph::Arc(e));
8.78 ++visitationNumber[e];
8.79 }
8.80
8.81 check(firstNode == lastNode,
8.82 - "checkEulerIt: first and last node are not the same");
8.83 + "checkEulerIt: First and last nodes are not the same");
8.84
8.85 for (typename Graph::EdgeIt e(g); e != INVALID; ++e)
8.86 {
8.87 check(visitationNumber[e] == 1,
8.88 - "checkEulerIt: not visited or multiple times visited edge found");
8.89 + "checkEulerIt: Not visited or multiple times visited edge found");
8.90 }
8.91 }
8.92
8.93 int main()
8.94 {
8.95 typedef ListDigraph Digraph;
8.96 - typedef ListGraph Graph;
8.97 + typedef Undirector<Digraph> Graph;
8.98 +
8.99 + {
8.100 + Digraph d;
8.101 + Graph g(d);
8.102 +
8.103 + checkDiEulerIt(d);
8.104 + checkDiEulerIt(g);
8.105 + checkEulerIt(g);
8.106
8.107 - Digraph digraphWithEulerianCircuit;
8.108 + check(eulerian(d), "This graph is Eulerian");
8.109 + check(eulerian(g), "This graph is Eulerian");
8.110 + }
8.111 {
8.112 - Digraph& g = digraphWithEulerianCircuit;
8.113 + Digraph d;
8.114 + Graph g(d);
8.115 + Digraph::Node n = d.addNode();
8.116
8.117 - Digraph::Node n0 = g.addNode();
8.118 - Digraph::Node n1 = g.addNode();
8.119 - Digraph::Node n2 = g.addNode();
8.120 + checkDiEulerIt(d);
8.121 + checkDiEulerIt(g);
8.122 + checkEulerIt(g);
8.123
8.124 - g.addArc(n0, n1);
8.125 - g.addArc(n1, n0);
8.126 - g.addArc(n1, n2);
8.127 - g.addArc(n2, n1);
8.128 + check(eulerian(d), "This graph is Eulerian");
8.129 + check(eulerian(g), "This graph is Eulerian");
8.130 }
8.131 + {
8.132 + Digraph d;
8.133 + Graph g(d);
8.134 + Digraph::Node n = d.addNode();
8.135 + d.addArc(n, n);
8.136
8.137 - Digraph digraphWithoutEulerianCircuit;
8.138 + checkDiEulerIt(d);
8.139 + checkDiEulerIt(g);
8.140 + checkEulerIt(g);
8.141 +
8.142 + check(eulerian(d), "This graph is Eulerian");
8.143 + check(eulerian(g), "This graph is Eulerian");
8.144 + }
8.145 {
8.146 - Digraph& g = digraphWithoutEulerianCircuit;
8.147 + Digraph d;
8.148 + Graph g(d);
8.149 + Digraph::Node n1 = d.addNode();
8.150 + Digraph::Node n2 = d.addNode();
8.151 + Digraph::Node n3 = d.addNode();
8.152 +
8.153 + d.addArc(n1, n2);
8.154 + d.addArc(n2, n1);
8.155 + d.addArc(n2, n3);
8.156 + d.addArc(n3, n2);
8.157
8.158 - Digraph::Node n0 = g.addNode();
8.159 - Digraph::Node n1 = g.addNode();
8.160 - Digraph::Node n2 = g.addNode();
8.161 + checkDiEulerIt(d);
8.162 + checkDiEulerIt(d, n2);
8.163 + checkDiEulerIt(g);
8.164 + checkDiEulerIt(g, n2);
8.165 + checkEulerIt(g);
8.166 + checkEulerIt(g, n2);
8.167
8.168 - g.addArc(n0, n1);
8.169 - g.addArc(n1, n0);
8.170 - g.addArc(n1, n2);
8.171 + check(eulerian(d), "This graph is Eulerian");
8.172 + check(eulerian(g), "This graph is Eulerian");
8.173 }
8.174 + {
8.175 + Digraph d;
8.176 + Graph g(d);
8.177 + Digraph::Node n1 = d.addNode();
8.178 + Digraph::Node n2 = d.addNode();
8.179 + Digraph::Node n3 = d.addNode();
8.180 + Digraph::Node n4 = d.addNode();
8.181 + Digraph::Node n5 = d.addNode();
8.182 + Digraph::Node n6 = d.addNode();
8.183 +
8.184 + d.addArc(n1, n2);
8.185 + d.addArc(n2, n4);
8.186 + d.addArc(n1, n3);
8.187 + d.addArc(n3, n4);
8.188 + d.addArc(n4, n1);
8.189 + d.addArc(n3, n5);
8.190 + d.addArc(n5, n2);
8.191 + d.addArc(n4, n6);
8.192 + d.addArc(n2, n6);
8.193 + d.addArc(n6, n1);
8.194 + d.addArc(n6, n3);
8.195
8.196 - Graph graphWithEulerianCircuit;
8.197 + checkDiEulerIt(d);
8.198 + checkDiEulerIt(d, n1);
8.199 + checkDiEulerIt(d, n5);
8.200 +
8.201 + checkDiEulerIt(g);
8.202 + checkDiEulerIt(g, n1);
8.203 + checkDiEulerIt(g, n5);
8.204 + checkEulerIt(g);
8.205 + checkEulerIt(g, n1);
8.206 + checkEulerIt(g, n5);
8.207 +
8.208 + check(eulerian(d), "This graph is Eulerian");
8.209 + check(eulerian(g), "This graph is Eulerian");
8.210 + }
8.211 {
8.212 - Graph& g = graphWithEulerianCircuit;
8.213 + Digraph d;
8.214 + Graph g(d);
8.215 + Digraph::Node n0 = d.addNode();
8.216 + Digraph::Node n1 = d.addNode();
8.217 + Digraph::Node n2 = d.addNode();
8.218 + Digraph::Node n3 = d.addNode();
8.219 + Digraph::Node n4 = d.addNode();
8.220 + Digraph::Node n5 = d.addNode();
8.221 +
8.222 + d.addArc(n1, n2);
8.223 + d.addArc(n2, n3);
8.224 + d.addArc(n3, n1);
8.225
8.226 - Graph::Node n0 = g.addNode();
8.227 - Graph::Node n1 = g.addNode();
8.228 - Graph::Node n2 = g.addNode();
8.229 + checkDiEulerIt(d);
8.230 + checkDiEulerIt(d, n2);
8.231
8.232 - g.addEdge(n0, n1);
8.233 - g.addEdge(n1, n2);
8.234 - g.addEdge(n2, n0);
8.235 + checkDiEulerIt(g);
8.236 + checkDiEulerIt(g, n2);
8.237 + checkEulerIt(g);
8.238 + checkEulerIt(g, n2);
8.239 +
8.240 + check(!eulerian(d), "This graph is not Eulerian");
8.241 + check(!eulerian(g), "This graph is not Eulerian");
8.242 }
8.243 + {
8.244 + Digraph d;
8.245 + Graph g(d);
8.246 + Digraph::Node n1 = d.addNode();
8.247 + Digraph::Node n2 = d.addNode();
8.248 + Digraph::Node n3 = d.addNode();
8.249 +
8.250 + d.addArc(n1, n2);
8.251 + d.addArc(n2, n3);
8.252
8.253 - Graph graphWithoutEulerianCircuit;
8.254 - {
8.255 - Graph& g = graphWithoutEulerianCircuit;
8.256 -
8.257 - Graph::Node n0 = g.addNode();
8.258 - Graph::Node n1 = g.addNode();
8.259 - Graph::Node n2 = g.addNode();
8.260 -
8.261 - g.addEdge(n0, n1);
8.262 - g.addEdge(n1, n2);
8.263 + check(!eulerian(d), "This graph is not Eulerian");
8.264 + check(!eulerian(g), "This graph is not Eulerian");
8.265 }
8.266
8.267 - checkDiEulerIt(digraphWithEulerianCircuit);
8.268 -
8.269 - checkEulerIt(graphWithEulerianCircuit);
8.270 -
8.271 - check(eulerian(digraphWithEulerianCircuit),
8.272 - "this graph should have an Eulerian circuit");
8.273 - check(!eulerian(digraphWithoutEulerianCircuit),
8.274 - "this graph should not have an Eulerian circuit");
8.275 -
8.276 - check(eulerian(graphWithEulerianCircuit),
8.277 - "this graph should have an Eulerian circuit");
8.278 - check(!eulerian(graphWithoutEulerianCircuit),
8.279 - "this graph should have an Eulerian circuit");
8.280 -
8.281 return 0;
8.282 }
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/test/matching_test.cc Tue Apr 21 13:08:19 2009 +0100
9.3 @@ -0,0 +1,424 @@
9.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
9.5 + *
9.6 + * This file is a part of LEMON, a generic C++ optimization library.
9.7 + *
9.8 + * Copyright (C) 2003-2009
9.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
9.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
9.11 + *
9.12 + * Permission to use, modify and distribute this software is granted
9.13 + * provided that this copyright notice appears in all copies. For
9.14 + * precise terms see the accompanying LICENSE file.
9.15 + *
9.16 + * This software is provided "AS IS" with no warranty of any kind,
9.17 + * express or implied, and with no claim as to its suitability for any
9.18 + * purpose.
9.19 + *
9.20 + */
9.21 +
9.22 +#include <iostream>
9.23 +#include <sstream>
9.24 +#include <vector>
9.25 +#include <queue>
9.26 +#include <cstdlib>
9.27 +
9.28 +#include <lemon/matching.h>
9.29 +#include <lemon/smart_graph.h>
9.30 +#include <lemon/concepts/graph.h>
9.31 +#include <lemon/concepts/maps.h>
9.32 +#include <lemon/lgf_reader.h>
9.33 +#include <lemon/math.h>
9.34 +
9.35 +#include "test_tools.h"
9.36 +
9.37 +using namespace std;
9.38 +using namespace lemon;
9.39 +
9.40 +GRAPH_TYPEDEFS(SmartGraph);
9.41 +
9.42 +
9.43 +const int lgfn = 3;
9.44 +const std::string lgf[lgfn] = {
9.45 + "@nodes\n"
9.46 + "label\n"
9.47 + "0\n"
9.48 + "1\n"
9.49 + "2\n"
9.50 + "3\n"
9.51 + "4\n"
9.52 + "5\n"
9.53 + "6\n"
9.54 + "7\n"
9.55 + "@edges\n"
9.56 + " label weight\n"
9.57 + "7 4 0 984\n"
9.58 + "0 7 1 73\n"
9.59 + "7 1 2 204\n"
9.60 + "2 3 3 583\n"
9.61 + "2 7 4 565\n"
9.62 + "2 1 5 582\n"
9.63 + "0 4 6 551\n"
9.64 + "2 5 7 385\n"
9.65 + "1 5 8 561\n"
9.66 + "5 3 9 484\n"
9.67 + "7 5 10 904\n"
9.68 + "3 6 11 47\n"
9.69 + "7 6 12 888\n"
9.70 + "3 0 13 747\n"
9.71 + "6 1 14 310\n",
9.72 +
9.73 + "@nodes\n"
9.74 + "label\n"
9.75 + "0\n"
9.76 + "1\n"
9.77 + "2\n"
9.78 + "3\n"
9.79 + "4\n"
9.80 + "5\n"
9.81 + "6\n"
9.82 + "7\n"
9.83 + "@edges\n"
9.84 + " label weight\n"
9.85 + "2 5 0 710\n"
9.86 + "0 5 1 241\n"
9.87 + "2 4 2 856\n"
9.88 + "2 6 3 762\n"
9.89 + "4 1 4 747\n"
9.90 + "6 1 5 962\n"
9.91 + "4 7 6 723\n"
9.92 + "1 7 7 661\n"
9.93 + "2 3 8 376\n"
9.94 + "1 0 9 416\n"
9.95 + "6 7 10 391\n",
9.96 +
9.97 + "@nodes\n"
9.98 + "label\n"
9.99 + "0\n"
9.100 + "1\n"
9.101 + "2\n"
9.102 + "3\n"
9.103 + "4\n"
9.104 + "5\n"
9.105 + "6\n"
9.106 + "7\n"
9.107 + "@edges\n"
9.108 + " label weight\n"
9.109 + "6 2 0 553\n"
9.110 + "0 7 1 653\n"
9.111 + "6 3 2 22\n"
9.112 + "4 7 3 846\n"
9.113 + "7 2 4 981\n"
9.114 + "7 6 5 250\n"
9.115 + "5 2 6 539\n",
9.116 +};
9.117 +
9.118 +void checkMaxMatchingCompile()
9.119 +{
9.120 + typedef concepts::Graph Graph;
9.121 + typedef Graph::Node Node;
9.122 + typedef Graph::Edge Edge;
9.123 + typedef Graph::EdgeMap<bool> MatMap;
9.124 +
9.125 + Graph g;
9.126 + Node n;
9.127 + Edge e;
9.128 + MatMap mat(g);
9.129 +
9.130 + MaxMatching<Graph> mat_test(g);
9.131 + const MaxMatching<Graph>&
9.132 + const_mat_test = mat_test;
9.133 +
9.134 + mat_test.init();
9.135 + mat_test.greedyInit();
9.136 + mat_test.matchingInit(mat);
9.137 + mat_test.startSparse();
9.138 + mat_test.startDense();
9.139 + mat_test.run();
9.140 +
9.141 + const_mat_test.matchingSize();
9.142 + const_mat_test.matching(e);
9.143 + const_mat_test.matching(n);
9.144 + const MaxMatching<Graph>::MatchingMap& mmap =
9.145 + const_mat_test.matchingMap();
9.146 + e = mmap[n];
9.147 + const_mat_test.mate(n);
9.148 +
9.149 + MaxMatching<Graph>::Status stat =
9.150 + const_mat_test.status(n);
9.151 + const MaxMatching<Graph>::StatusMap& smap =
9.152 + const_mat_test.statusMap();
9.153 + stat = smap[n];
9.154 + const_mat_test.barrier(n);
9.155 +}
9.156 +
9.157 +void checkMaxWeightedMatchingCompile()
9.158 +{
9.159 + typedef concepts::Graph Graph;
9.160 + typedef Graph::Node Node;
9.161 + typedef Graph::Edge Edge;
9.162 + typedef Graph::EdgeMap<int> WeightMap;
9.163 +
9.164 + Graph g;
9.165 + Node n;
9.166 + Edge e;
9.167 + WeightMap w(g);
9.168 +
9.169 + MaxWeightedMatching<Graph> mat_test(g, w);
9.170 + const MaxWeightedMatching<Graph>&
9.171 + const_mat_test = mat_test;
9.172 +
9.173 + mat_test.init();
9.174 + mat_test.start();
9.175 + mat_test.run();
9.176 +
9.177 + const_mat_test.matchingWeight();
9.178 + const_mat_test.matchingSize();
9.179 + const_mat_test.matching(e);
9.180 + const_mat_test.matching(n);
9.181 + const MaxWeightedMatching<Graph>::MatchingMap& mmap =
9.182 + const_mat_test.matchingMap();
9.183 + e = mmap[n];
9.184 + const_mat_test.mate(n);
9.185 +
9.186 + int k = 0;
9.187 + const_mat_test.dualValue();
9.188 + const_mat_test.nodeValue(n);
9.189 + const_mat_test.blossomNum();
9.190 + const_mat_test.blossomSize(k);
9.191 + const_mat_test.blossomValue(k);
9.192 +}
9.193 +
9.194 +void checkMaxWeightedPerfectMatchingCompile()
9.195 +{
9.196 + typedef concepts::Graph Graph;
9.197 + typedef Graph::Node Node;
9.198 + typedef Graph::Edge Edge;
9.199 + typedef Graph::EdgeMap<int> WeightMap;
9.200 +
9.201 + Graph g;
9.202 + Node n;
9.203 + Edge e;
9.204 + WeightMap w(g);
9.205 +
9.206 + MaxWeightedPerfectMatching<Graph> mat_test(g, w);
9.207 + const MaxWeightedPerfectMatching<Graph>&
9.208 + const_mat_test = mat_test;
9.209 +
9.210 + mat_test.init();
9.211 + mat_test.start();
9.212 + mat_test.run();
9.213 +
9.214 + const_mat_test.matchingWeight();
9.215 + const_mat_test.matching(e);
9.216 + const_mat_test.matching(n);
9.217 + const MaxWeightedPerfectMatching<Graph>::MatchingMap& mmap =
9.218 + const_mat_test.matchingMap();
9.219 + e = mmap[n];
9.220 + const_mat_test.mate(n);
9.221 +
9.222 + int k = 0;
9.223 + const_mat_test.dualValue();
9.224 + const_mat_test.nodeValue(n);
9.225 + const_mat_test.blossomNum();
9.226 + const_mat_test.blossomSize(k);
9.227 + const_mat_test.blossomValue(k);
9.228 +}
9.229 +
9.230 +void checkMatching(const SmartGraph& graph,
9.231 + const MaxMatching<SmartGraph>& mm) {
9.232 + int num = 0;
9.233 +
9.234 + IntNodeMap comp_index(graph);
9.235 + UnionFind<IntNodeMap> comp(comp_index);
9.236 +
9.237 + int barrier_num = 0;
9.238 +
9.239 + for (NodeIt n(graph); n != INVALID; ++n) {
9.240 + check(mm.status(n) == MaxMatching<SmartGraph>::EVEN ||
9.241 + mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
9.242 + if (mm.status(n) == MaxMatching<SmartGraph>::ODD) {
9.243 + ++barrier_num;
9.244 + } else {
9.245 + comp.insert(n);
9.246 + }
9.247 + }
9.248 +
9.249 + for (EdgeIt e(graph); e != INVALID; ++e) {
9.250 + if (mm.matching(e)) {
9.251 + check(e == mm.matching(graph.u(e)), "Wrong matching");
9.252 + check(e == mm.matching(graph.v(e)), "Wrong matching");
9.253 + ++num;
9.254 + }
9.255 + check(mm.status(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
9.256 + mm.status(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
9.257 + "Wrong Gallai-Edmonds decomposition");
9.258 +
9.259 + check(mm.status(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
9.260 + mm.status(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
9.261 + "Wrong Gallai-Edmonds decomposition");
9.262 +
9.263 + if (mm.status(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
9.264 + mm.status(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
9.265 + comp.join(graph.u(e), graph.v(e));
9.266 + }
9.267 + }
9.268 +
9.269 + std::set<int> comp_root;
9.270 + int odd_comp_num = 0;
9.271 + for (NodeIt n(graph); n != INVALID; ++n) {
9.272 + if (mm.status(n) != MaxMatching<SmartGraph>::ODD) {
9.273 + int root = comp.find(n);
9.274 + if (comp_root.find(root) == comp_root.end()) {
9.275 + comp_root.insert(root);
9.276 + if (comp.size(n) % 2 == 1) {
9.277 + ++odd_comp_num;
9.278 + }
9.279 + }
9.280 + }
9.281 + }
9.282 +
9.283 + check(mm.matchingSize() == num, "Wrong matching");
9.284 + check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
9.285 + "Wrong matching");
9.286 + return;
9.287 +}
9.288 +
9.289 +void checkWeightedMatching(const SmartGraph& graph,
9.290 + const SmartGraph::EdgeMap<int>& weight,
9.291 + const MaxWeightedMatching<SmartGraph>& mwm) {
9.292 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
9.293 + if (graph.u(e) == graph.v(e)) continue;
9.294 + int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
9.295 +
9.296 + for (int i = 0; i < mwm.blossomNum(); ++i) {
9.297 + bool s = false, t = false;
9.298 + for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
9.299 + n != INVALID; ++n) {
9.300 + if (graph.u(e) == n) s = true;
9.301 + if (graph.v(e) == n) t = true;
9.302 + }
9.303 + if (s == true && t == true) {
9.304 + rw += mwm.blossomValue(i);
9.305 + }
9.306 + }
9.307 + rw -= weight[e] * mwm.dualScale;
9.308 +
9.309 + check(rw >= 0, "Negative reduced weight");
9.310 + check(rw == 0 || !mwm.matching(e),
9.311 + "Non-zero reduced weight on matching edge");
9.312 + }
9.313 +
9.314 + int pv = 0;
9.315 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
9.316 + if (mwm.matching(n) != INVALID) {
9.317 + check(mwm.nodeValue(n) >= 0, "Invalid node value");
9.318 + pv += weight[mwm.matching(n)];
9.319 + SmartGraph::Node o = graph.target(mwm.matching(n));
9.320 + check(mwm.mate(n) == o, "Invalid matching");
9.321 + check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
9.322 + "Invalid matching");
9.323 + } else {
9.324 + check(mwm.mate(n) == INVALID, "Invalid matching");
9.325 + check(mwm.nodeValue(n) == 0, "Invalid matching");
9.326 + }
9.327 + }
9.328 +
9.329 + int dv = 0;
9.330 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
9.331 + dv += mwm.nodeValue(n);
9.332 + }
9.333 +
9.334 + for (int i = 0; i < mwm.blossomNum(); ++i) {
9.335 + check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
9.336 + check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
9.337 + dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
9.338 + }
9.339 +
9.340 + check(pv * mwm.dualScale == dv * 2, "Wrong duality");
9.341 +
9.342 + return;
9.343 +}
9.344 +
9.345 +void checkWeightedPerfectMatching(const SmartGraph& graph,
9.346 + const SmartGraph::EdgeMap<int>& weight,
9.347 + const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
9.348 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
9.349 + if (graph.u(e) == graph.v(e)) continue;
9.350 + int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
9.351 +
9.352 + for (int i = 0; i < mwpm.blossomNum(); ++i) {
9.353 + bool s = false, t = false;
9.354 + for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
9.355 + n != INVALID; ++n) {
9.356 + if (graph.u(e) == n) s = true;
9.357 + if (graph.v(e) == n) t = true;
9.358 + }
9.359 + if (s == true && t == true) {
9.360 + rw += mwpm.blossomValue(i);
9.361 + }
9.362 + }
9.363 + rw -= weight[e] * mwpm.dualScale;
9.364 +
9.365 + check(rw >= 0, "Negative reduced weight");
9.366 + check(rw == 0 || !mwpm.matching(e),
9.367 + "Non-zero reduced weight on matching edge");
9.368 + }
9.369 +
9.370 + int pv = 0;
9.371 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
9.372 + check(mwpm.matching(n) != INVALID, "Non perfect");
9.373 + pv += weight[mwpm.matching(n)];
9.374 + SmartGraph::Node o = graph.target(mwpm.matching(n));
9.375 + check(mwpm.mate(n) == o, "Invalid matching");
9.376 + check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
9.377 + "Invalid matching");
9.378 + }
9.379 +
9.380 + int dv = 0;
9.381 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
9.382 + dv += mwpm.nodeValue(n);
9.383 + }
9.384 +
9.385 + for (int i = 0; i < mwpm.blossomNum(); ++i) {
9.386 + check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
9.387 + check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
9.388 + dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
9.389 + }
9.390 +
9.391 + check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
9.392 +
9.393 + return;
9.394 +}
9.395 +
9.396 +
9.397 +int main() {
9.398 +
9.399 + for (int i = 0; i < lgfn; ++i) {
9.400 + SmartGraph graph;
9.401 + SmartGraph::EdgeMap<int> weight(graph);
9.402 +
9.403 + istringstream lgfs(lgf[i]);
9.404 + graphReader(graph, lgfs).
9.405 + edgeMap("weight", weight).run();
9.406 +
9.407 + MaxMatching<SmartGraph> mm(graph);
9.408 + mm.run();
9.409 + checkMatching(graph, mm);
9.410 +
9.411 + MaxWeightedMatching<SmartGraph> mwm(graph, weight);
9.412 + mwm.run();
9.413 + checkWeightedMatching(graph, weight, mwm);
9.414 +
9.415 + MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
9.416 + bool perfect = mwpm.run();
9.417 +
9.418 + check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
9.419 + "Perfect matching found");
9.420 +
9.421 + if (perfect) {
9.422 + checkWeightedPerfectMatching(graph, weight, mwpm);
9.423 + }
9.424 + }
9.425 +
9.426 + return 0;
9.427 +}
10.1 --- a/test/max_matching_test.cc Tue Apr 21 10:34:49 2009 +0100
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,310 +0,0 @@
10.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
10.5 - *
10.6 - * This file is a part of LEMON, a generic C++ optimization library.
10.7 - *
10.8 - * Copyright (C) 2003-2009
10.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
10.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
10.11 - *
10.12 - * Permission to use, modify and distribute this software is granted
10.13 - * provided that this copyright notice appears in all copies. For
10.14 - * precise terms see the accompanying LICENSE file.
10.15 - *
10.16 - * This software is provided "AS IS" with no warranty of any kind,
10.17 - * express or implied, and with no claim as to its suitability for any
10.18 - * purpose.
10.19 - *
10.20 - */
10.21 -
10.22 -#include <iostream>
10.23 -#include <sstream>
10.24 -#include <vector>
10.25 -#include <queue>
10.26 -#include <lemon/math.h>
10.27 -#include <cstdlib>
10.28 -
10.29 -#include <lemon/max_matching.h>
10.30 -#include <lemon/smart_graph.h>
10.31 -#include <lemon/lgf_reader.h>
10.32 -
10.33 -#include "test_tools.h"
10.34 -
10.35 -using namespace std;
10.36 -using namespace lemon;
10.37 -
10.38 -GRAPH_TYPEDEFS(SmartGraph);
10.39 -
10.40 -
10.41 -const int lgfn = 3;
10.42 -const std::string lgf[lgfn] = {
10.43 - "@nodes\n"
10.44 - "label\n"
10.45 - "0\n"
10.46 - "1\n"
10.47 - "2\n"
10.48 - "3\n"
10.49 - "4\n"
10.50 - "5\n"
10.51 - "6\n"
10.52 - "7\n"
10.53 - "@edges\n"
10.54 - " label weight\n"
10.55 - "7 4 0 984\n"
10.56 - "0 7 1 73\n"
10.57 - "7 1 2 204\n"
10.58 - "2 3 3 583\n"
10.59 - "2 7 4 565\n"
10.60 - "2 1 5 582\n"
10.61 - "0 4 6 551\n"
10.62 - "2 5 7 385\n"
10.63 - "1 5 8 561\n"
10.64 - "5 3 9 484\n"
10.65 - "7 5 10 904\n"
10.66 - "3 6 11 47\n"
10.67 - "7 6 12 888\n"
10.68 - "3 0 13 747\n"
10.69 - "6 1 14 310\n",
10.70 -
10.71 - "@nodes\n"
10.72 - "label\n"
10.73 - "0\n"
10.74 - "1\n"
10.75 - "2\n"
10.76 - "3\n"
10.77 - "4\n"
10.78 - "5\n"
10.79 - "6\n"
10.80 - "7\n"
10.81 - "@edges\n"
10.82 - " label weight\n"
10.83 - "2 5 0 710\n"
10.84 - "0 5 1 241\n"
10.85 - "2 4 2 856\n"
10.86 - "2 6 3 762\n"
10.87 - "4 1 4 747\n"
10.88 - "6 1 5 962\n"
10.89 - "4 7 6 723\n"
10.90 - "1 7 7 661\n"
10.91 - "2 3 8 376\n"
10.92 - "1 0 9 416\n"
10.93 - "6 7 10 391\n",
10.94 -
10.95 - "@nodes\n"
10.96 - "label\n"
10.97 - "0\n"
10.98 - "1\n"
10.99 - "2\n"
10.100 - "3\n"
10.101 - "4\n"
10.102 - "5\n"
10.103 - "6\n"
10.104 - "7\n"
10.105 - "@edges\n"
10.106 - " label weight\n"
10.107 - "6 2 0 553\n"
10.108 - "0 7 1 653\n"
10.109 - "6 3 2 22\n"
10.110 - "4 7 3 846\n"
10.111 - "7 2 4 981\n"
10.112 - "7 6 5 250\n"
10.113 - "5 2 6 539\n",
10.114 -};
10.115 -
10.116 -void checkMatching(const SmartGraph& graph,
10.117 - const MaxMatching<SmartGraph>& mm) {
10.118 - int num = 0;
10.119 -
10.120 - IntNodeMap comp_index(graph);
10.121 - UnionFind<IntNodeMap> comp(comp_index);
10.122 -
10.123 - int barrier_num = 0;
10.124 -
10.125 - for (NodeIt n(graph); n != INVALID; ++n) {
10.126 - check(mm.decomposition(n) == MaxMatching<SmartGraph>::EVEN ||
10.127 - mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
10.128 - if (mm.decomposition(n) == MaxMatching<SmartGraph>::ODD) {
10.129 - ++barrier_num;
10.130 - } else {
10.131 - comp.insert(n);
10.132 - }
10.133 - }
10.134 -
10.135 - for (EdgeIt e(graph); e != INVALID; ++e) {
10.136 - if (mm.matching(e)) {
10.137 - check(e == mm.matching(graph.u(e)), "Wrong matching");
10.138 - check(e == mm.matching(graph.v(e)), "Wrong matching");
10.139 - ++num;
10.140 - }
10.141 - check(mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
10.142 - mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
10.143 - "Wrong Gallai-Edmonds decomposition");
10.144 -
10.145 - check(mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
10.146 - mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
10.147 - "Wrong Gallai-Edmonds decomposition");
10.148 -
10.149 - if (mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
10.150 - mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
10.151 - comp.join(graph.u(e), graph.v(e));
10.152 - }
10.153 - }
10.154 -
10.155 - std::set<int> comp_root;
10.156 - int odd_comp_num = 0;
10.157 - for (NodeIt n(graph); n != INVALID; ++n) {
10.158 - if (mm.decomposition(n) != MaxMatching<SmartGraph>::ODD) {
10.159 - int root = comp.find(n);
10.160 - if (comp_root.find(root) == comp_root.end()) {
10.161 - comp_root.insert(root);
10.162 - if (comp.size(n) % 2 == 1) {
10.163 - ++odd_comp_num;
10.164 - }
10.165 - }
10.166 - }
10.167 - }
10.168 -
10.169 - check(mm.matchingSize() == num, "Wrong matching");
10.170 - check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
10.171 - "Wrong matching");
10.172 - return;
10.173 -}
10.174 -
10.175 -void checkWeightedMatching(const SmartGraph& graph,
10.176 - const SmartGraph::EdgeMap<int>& weight,
10.177 - const MaxWeightedMatching<SmartGraph>& mwm) {
10.178 - for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
10.179 - if (graph.u(e) == graph.v(e)) continue;
10.180 - int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
10.181 -
10.182 - for (int i = 0; i < mwm.blossomNum(); ++i) {
10.183 - bool s = false, t = false;
10.184 - for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
10.185 - n != INVALID; ++n) {
10.186 - if (graph.u(e) == n) s = true;
10.187 - if (graph.v(e) == n) t = true;
10.188 - }
10.189 - if (s == true && t == true) {
10.190 - rw += mwm.blossomValue(i);
10.191 - }
10.192 - }
10.193 - rw -= weight[e] * mwm.dualScale;
10.194 -
10.195 - check(rw >= 0, "Negative reduced weight");
10.196 - check(rw == 0 || !mwm.matching(e),
10.197 - "Non-zero reduced weight on matching edge");
10.198 - }
10.199 -
10.200 - int pv = 0;
10.201 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
10.202 - if (mwm.matching(n) != INVALID) {
10.203 - check(mwm.nodeValue(n) >= 0, "Invalid node value");
10.204 - pv += weight[mwm.matching(n)];
10.205 - SmartGraph::Node o = graph.target(mwm.matching(n));
10.206 - check(mwm.mate(n) == o, "Invalid matching");
10.207 - check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
10.208 - "Invalid matching");
10.209 - } else {
10.210 - check(mwm.mate(n) == INVALID, "Invalid matching");
10.211 - check(mwm.nodeValue(n) == 0, "Invalid matching");
10.212 - }
10.213 - }
10.214 -
10.215 - int dv = 0;
10.216 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
10.217 - dv += mwm.nodeValue(n);
10.218 - }
10.219 -
10.220 - for (int i = 0; i < mwm.blossomNum(); ++i) {
10.221 - check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
10.222 - check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
10.223 - dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
10.224 - }
10.225 -
10.226 - check(pv * mwm.dualScale == dv * 2, "Wrong duality");
10.227 -
10.228 - return;
10.229 -}
10.230 -
10.231 -void checkWeightedPerfectMatching(const SmartGraph& graph,
10.232 - const SmartGraph::EdgeMap<int>& weight,
10.233 - const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
10.234 - for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
10.235 - if (graph.u(e) == graph.v(e)) continue;
10.236 - int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
10.237 -
10.238 - for (int i = 0; i < mwpm.blossomNum(); ++i) {
10.239 - bool s = false, t = false;
10.240 - for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
10.241 - n != INVALID; ++n) {
10.242 - if (graph.u(e) == n) s = true;
10.243 - if (graph.v(e) == n) t = true;
10.244 - }
10.245 - if (s == true && t == true) {
10.246 - rw += mwpm.blossomValue(i);
10.247 - }
10.248 - }
10.249 - rw -= weight[e] * mwpm.dualScale;
10.250 -
10.251 - check(rw >= 0, "Negative reduced weight");
10.252 - check(rw == 0 || !mwpm.matching(e),
10.253 - "Non-zero reduced weight on matching edge");
10.254 - }
10.255 -
10.256 - int pv = 0;
10.257 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
10.258 - check(mwpm.matching(n) != INVALID, "Non perfect");
10.259 - pv += weight[mwpm.matching(n)];
10.260 - SmartGraph::Node o = graph.target(mwpm.matching(n));
10.261 - check(mwpm.mate(n) == o, "Invalid matching");
10.262 - check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
10.263 - "Invalid matching");
10.264 - }
10.265 -
10.266 - int dv = 0;
10.267 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
10.268 - dv += mwpm.nodeValue(n);
10.269 - }
10.270 -
10.271 - for (int i = 0; i < mwpm.blossomNum(); ++i) {
10.272 - check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
10.273 - check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
10.274 - dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
10.275 - }
10.276 -
10.277 - check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
10.278 -
10.279 - return;
10.280 -}
10.281 -
10.282 -
10.283 -int main() {
10.284 -
10.285 - for (int i = 0; i < lgfn; ++i) {
10.286 - SmartGraph graph;
10.287 - SmartGraph::EdgeMap<int> weight(graph);
10.288 -
10.289 - istringstream lgfs(lgf[i]);
10.290 - graphReader(graph, lgfs).
10.291 - edgeMap("weight", weight).run();
10.292 -
10.293 - MaxMatching<SmartGraph> mm(graph);
10.294 - mm.run();
10.295 - checkMatching(graph, mm);
10.296 -
10.297 - MaxWeightedMatching<SmartGraph> mwm(graph, weight);
10.298 - mwm.run();
10.299 - checkWeightedMatching(graph, weight, mwm);
10.300 -
10.301 - MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
10.302 - bool perfect = mwpm.run();
10.303 -
10.304 - check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
10.305 - "Perfect matching found");
10.306 -
10.307 - if (perfect) {
10.308 - checkWeightedPerfectMatching(graph, weight, mwpm);
10.309 - }
10.310 - }
10.311 -
10.312 - return 0;
10.313 -}
11.1 --- a/tools/dimacs-solver.cc Tue Apr 21 10:34:49 2009 +0100
11.2 +++ b/tools/dimacs-solver.cc Tue Apr 21 13:08:19 2009 +0100
11.3 @@ -42,7 +42,7 @@
11.4
11.5 #include <lemon/dijkstra.h>
11.6 #include <lemon/preflow.h>
11.7 -#include <lemon/max_matching.h>
11.8 +#include <lemon/matching.h>
11.9
11.10 using namespace lemon;
11.11 typedef SmartDigraph Digraph;