1.1 --- a/lemon/Makefile.am Fri Apr 17 09:54:14 2009 +0200
1.2 +++ b/lemon/Makefile.am Fri Apr 17 09:58:50 2009 +0200
1.3 @@ -89,8 +89,8 @@
1.4 lemon/lp_skeleton.h \
1.5 lemon/list_graph.h \
1.6 lemon/maps.h \
1.7 + lemon/matching.h \
1.8 lemon/math.h \
1.9 - lemon/max_matching.h \
1.10 lemon/min_cost_arborescence.h \
1.11 lemon/nauty_reader.h \
1.12 lemon/path.h \
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/lemon/matching.h Fri Apr 17 09:58:50 2009 +0200
2.3 @@ -0,0 +1,3244 @@
2.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
2.5 + *
2.6 + * This file is a part of LEMON, a generic C++ optimization library.
2.7 + *
2.8 + * Copyright (C) 2003-2009
2.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
2.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
2.11 + *
2.12 + * Permission to use, modify and distribute this software is granted
2.13 + * provided that this copyright notice appears in all copies. For
2.14 + * precise terms see the accompanying LICENSE file.
2.15 + *
2.16 + * This software is provided "AS IS" with no warranty of any kind,
2.17 + * express or implied, and with no claim as to its suitability for any
2.18 + * purpose.
2.19 + *
2.20 + */
2.21 +
2.22 +#ifndef LEMON_MAX_MATCHING_H
2.23 +#define LEMON_MAX_MATCHING_H
2.24 +
2.25 +#include <vector>
2.26 +#include <queue>
2.27 +#include <set>
2.28 +#include <limits>
2.29 +
2.30 +#include <lemon/core.h>
2.31 +#include <lemon/unionfind.h>
2.32 +#include <lemon/bin_heap.h>
2.33 +#include <lemon/maps.h>
2.34 +
2.35 +///\ingroup matching
2.36 +///\file
2.37 +///\brief Maximum matching algorithms in general graphs.
2.38 +
2.39 +namespace lemon {
2.40 +
2.41 + /// \ingroup matching
2.42 + ///
2.43 + /// \brief Maximum cardinality matching in general graphs
2.44 + ///
2.45 + /// This class implements Edmonds' alternating forest matching algorithm
2.46 + /// for finding a maximum cardinality matching in a general undirected graph.
2.47 + /// It can be started from an arbitrary initial matching
2.48 + /// (the default is the empty one).
2.49 + ///
2.50 + /// The dual solution of the problem is a map of the nodes to
2.51 + /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
2.52 + /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
2.53 + /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
2.54 + /// with factor-critical components, the nodes in \c ODD/A form the
2.55 + /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
2.56 + /// a perfect matching. The number of the factor-critical components
2.57 + /// minus the number of barrier nodes is a lower bound on the
2.58 + /// unmatched nodes, and the matching is optimal if and only if this bound is
2.59 + /// tight. This decomposition can be obtained using \ref status() or
2.60 + /// \ref statusMap() after running the algorithm.
2.61 + ///
2.62 + /// \tparam GR The undirected graph type the algorithm runs on.
2.63 + template <typename GR>
2.64 + class MaxMatching {
2.65 + public:
2.66 +
2.67 + /// The graph type of the algorithm
2.68 + typedef GR Graph;
2.69 + /// The type of the matching map
2.70 + typedef typename Graph::template NodeMap<typename Graph::Arc>
2.71 + MatchingMap;
2.72 +
2.73 + ///\brief Status constants for Gallai-Edmonds decomposition.
2.74 + ///
2.75 + ///These constants are used for indicating the Gallai-Edmonds
2.76 + ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
2.77 + ///induce a subgraph with factor-critical components, the nodes with
2.78 + ///status \c ODD (or \c A) form the canonical barrier, and the nodes
2.79 + ///with status \c MATCHED (or \c C) induce a subgraph having a
2.80 + ///perfect matching.
2.81 + enum Status {
2.82 + EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.)
2.83 + D = 1,
2.84 + MATCHED = 0, ///< = 0. (\c C is an alias for \c MATCHED.)
2.85 + C = 0,
2.86 + ODD = -1, ///< = -1. (\c A is an alias for \c ODD.)
2.87 + A = -1,
2.88 + UNMATCHED = -2 ///< = -2.
2.89 + };
2.90 +
2.91 + /// The type of the status map
2.92 + typedef typename Graph::template NodeMap<Status> StatusMap;
2.93 +
2.94 + private:
2.95 +
2.96 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
2.97 +
2.98 + typedef UnionFindEnum<IntNodeMap> BlossomSet;
2.99 + typedef ExtendFindEnum<IntNodeMap> TreeSet;
2.100 + typedef RangeMap<Node> NodeIntMap;
2.101 + typedef MatchingMap EarMap;
2.102 + typedef std::vector<Node> NodeQueue;
2.103 +
2.104 + const Graph& _graph;
2.105 + MatchingMap* _matching;
2.106 + StatusMap* _status;
2.107 +
2.108 + EarMap* _ear;
2.109 +
2.110 + IntNodeMap* _blossom_set_index;
2.111 + BlossomSet* _blossom_set;
2.112 + NodeIntMap* _blossom_rep;
2.113 +
2.114 + IntNodeMap* _tree_set_index;
2.115 + TreeSet* _tree_set;
2.116 +
2.117 + NodeQueue _node_queue;
2.118 + int _process, _postpone, _last;
2.119 +
2.120 + int _node_num;
2.121 +
2.122 + private:
2.123 +
2.124 + void createStructures() {
2.125 + _node_num = countNodes(_graph);
2.126 + if (!_matching) {
2.127 + _matching = new MatchingMap(_graph);
2.128 + }
2.129 + if (!_status) {
2.130 + _status = new StatusMap(_graph);
2.131 + }
2.132 + if (!_ear) {
2.133 + _ear = new EarMap(_graph);
2.134 + }
2.135 + if (!_blossom_set) {
2.136 + _blossom_set_index = new IntNodeMap(_graph);
2.137 + _blossom_set = new BlossomSet(*_blossom_set_index);
2.138 + }
2.139 + if (!_blossom_rep) {
2.140 + _blossom_rep = new NodeIntMap(_node_num);
2.141 + }
2.142 + if (!_tree_set) {
2.143 + _tree_set_index = new IntNodeMap(_graph);
2.144 + _tree_set = new TreeSet(*_tree_set_index);
2.145 + }
2.146 + _node_queue.resize(_node_num);
2.147 + }
2.148 +
2.149 + void destroyStructures() {
2.150 + if (_matching) {
2.151 + delete _matching;
2.152 + }
2.153 + if (_status) {
2.154 + delete _status;
2.155 + }
2.156 + if (_ear) {
2.157 + delete _ear;
2.158 + }
2.159 + if (_blossom_set) {
2.160 + delete _blossom_set;
2.161 + delete _blossom_set_index;
2.162 + }
2.163 + if (_blossom_rep) {
2.164 + delete _blossom_rep;
2.165 + }
2.166 + if (_tree_set) {
2.167 + delete _tree_set_index;
2.168 + delete _tree_set;
2.169 + }
2.170 + }
2.171 +
2.172 + void processDense(const Node& n) {
2.173 + _process = _postpone = _last = 0;
2.174 + _node_queue[_last++] = n;
2.175 +
2.176 + while (_process != _last) {
2.177 + Node u = _node_queue[_process++];
2.178 + for (OutArcIt a(_graph, u); a != INVALID; ++a) {
2.179 + Node v = _graph.target(a);
2.180 + if ((*_status)[v] == MATCHED) {
2.181 + extendOnArc(a);
2.182 + } else if ((*_status)[v] == UNMATCHED) {
2.183 + augmentOnArc(a);
2.184 + return;
2.185 + }
2.186 + }
2.187 + }
2.188 +
2.189 + while (_postpone != _last) {
2.190 + Node u = _node_queue[_postpone++];
2.191 +
2.192 + for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
2.193 + Node v = _graph.target(a);
2.194 +
2.195 + if ((*_status)[v] == EVEN) {
2.196 + if (_blossom_set->find(u) != _blossom_set->find(v)) {
2.197 + shrinkOnEdge(a);
2.198 + }
2.199 + }
2.200 +
2.201 + while (_process != _last) {
2.202 + Node w = _node_queue[_process++];
2.203 + for (OutArcIt b(_graph, w); b != INVALID; ++b) {
2.204 + Node x = _graph.target(b);
2.205 + if ((*_status)[x] == MATCHED) {
2.206 + extendOnArc(b);
2.207 + } else if ((*_status)[x] == UNMATCHED) {
2.208 + augmentOnArc(b);
2.209 + return;
2.210 + }
2.211 + }
2.212 + }
2.213 + }
2.214 + }
2.215 + }
2.216 +
2.217 + void processSparse(const Node& n) {
2.218 + _process = _last = 0;
2.219 + _node_queue[_last++] = n;
2.220 + while (_process != _last) {
2.221 + Node u = _node_queue[_process++];
2.222 + for (OutArcIt a(_graph, u); a != INVALID; ++a) {
2.223 + Node v = _graph.target(a);
2.224 +
2.225 + if ((*_status)[v] == EVEN) {
2.226 + if (_blossom_set->find(u) != _blossom_set->find(v)) {
2.227 + shrinkOnEdge(a);
2.228 + }
2.229 + } else if ((*_status)[v] == MATCHED) {
2.230 + extendOnArc(a);
2.231 + } else if ((*_status)[v] == UNMATCHED) {
2.232 + augmentOnArc(a);
2.233 + return;
2.234 + }
2.235 + }
2.236 + }
2.237 + }
2.238 +
2.239 + void shrinkOnEdge(const Edge& e) {
2.240 + Node nca = INVALID;
2.241 +
2.242 + {
2.243 + std::set<Node> left_set, right_set;
2.244 +
2.245 + Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
2.246 + left_set.insert(left);
2.247 +
2.248 + Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
2.249 + right_set.insert(right);
2.250 +
2.251 + while (true) {
2.252 + if ((*_matching)[left] == INVALID) break;
2.253 + left = _graph.target((*_matching)[left]);
2.254 + left = (*_blossom_rep)[_blossom_set->
2.255 + find(_graph.target((*_ear)[left]))];
2.256 + if (right_set.find(left) != right_set.end()) {
2.257 + nca = left;
2.258 + break;
2.259 + }
2.260 + left_set.insert(left);
2.261 +
2.262 + if ((*_matching)[right] == INVALID) break;
2.263 + right = _graph.target((*_matching)[right]);
2.264 + right = (*_blossom_rep)[_blossom_set->
2.265 + find(_graph.target((*_ear)[right]))];
2.266 + if (left_set.find(right) != left_set.end()) {
2.267 + nca = right;
2.268 + break;
2.269 + }
2.270 + right_set.insert(right);
2.271 + }
2.272 +
2.273 + if (nca == INVALID) {
2.274 + if ((*_matching)[left] == INVALID) {
2.275 + nca = right;
2.276 + while (left_set.find(nca) == left_set.end()) {
2.277 + nca = _graph.target((*_matching)[nca]);
2.278 + nca =(*_blossom_rep)[_blossom_set->
2.279 + find(_graph.target((*_ear)[nca]))];
2.280 + }
2.281 + } else {
2.282 + nca = left;
2.283 + while (right_set.find(nca) == right_set.end()) {
2.284 + nca = _graph.target((*_matching)[nca]);
2.285 + nca = (*_blossom_rep)[_blossom_set->
2.286 + find(_graph.target((*_ear)[nca]))];
2.287 + }
2.288 + }
2.289 + }
2.290 + }
2.291 +
2.292 + {
2.293 +
2.294 + Node node = _graph.u(e);
2.295 + Arc arc = _graph.direct(e, true);
2.296 + Node base = (*_blossom_rep)[_blossom_set->find(node)];
2.297 +
2.298 + while (base != nca) {
2.299 + (*_ear)[node] = arc;
2.300 +
2.301 + Node n = node;
2.302 + while (n != base) {
2.303 + n = _graph.target((*_matching)[n]);
2.304 + Arc a = (*_ear)[n];
2.305 + n = _graph.target(a);
2.306 + (*_ear)[n] = _graph.oppositeArc(a);
2.307 + }
2.308 + node = _graph.target((*_matching)[base]);
2.309 + _tree_set->erase(base);
2.310 + _tree_set->erase(node);
2.311 + _blossom_set->insert(node, _blossom_set->find(base));
2.312 + (*_status)[node] = EVEN;
2.313 + _node_queue[_last++] = node;
2.314 + arc = _graph.oppositeArc((*_ear)[node]);
2.315 + node = _graph.target((*_ear)[node]);
2.316 + base = (*_blossom_rep)[_blossom_set->find(node)];
2.317 + _blossom_set->join(_graph.target(arc), base);
2.318 + }
2.319 + }
2.320 +
2.321 + (*_blossom_rep)[_blossom_set->find(nca)] = nca;
2.322 +
2.323 + {
2.324 +
2.325 + Node node = _graph.v(e);
2.326 + Arc arc = _graph.direct(e, false);
2.327 + Node base = (*_blossom_rep)[_blossom_set->find(node)];
2.328 +
2.329 + while (base != nca) {
2.330 + (*_ear)[node] = arc;
2.331 +
2.332 + Node n = node;
2.333 + while (n != base) {
2.334 + n = _graph.target((*_matching)[n]);
2.335 + Arc a = (*_ear)[n];
2.336 + n = _graph.target(a);
2.337 + (*_ear)[n] = _graph.oppositeArc(a);
2.338 + }
2.339 + node = _graph.target((*_matching)[base]);
2.340 + _tree_set->erase(base);
2.341 + _tree_set->erase(node);
2.342 + _blossom_set->insert(node, _blossom_set->find(base));
2.343 + (*_status)[node] = EVEN;
2.344 + _node_queue[_last++] = node;
2.345 + arc = _graph.oppositeArc((*_ear)[node]);
2.346 + node = _graph.target((*_ear)[node]);
2.347 + base = (*_blossom_rep)[_blossom_set->find(node)];
2.348 + _blossom_set->join(_graph.target(arc), base);
2.349 + }
2.350 + }
2.351 +
2.352 + (*_blossom_rep)[_blossom_set->find(nca)] = nca;
2.353 + }
2.354 +
2.355 + void extendOnArc(const Arc& a) {
2.356 + Node base = _graph.source(a);
2.357 + Node odd = _graph.target(a);
2.358 +
2.359 + (*_ear)[odd] = _graph.oppositeArc(a);
2.360 + Node even = _graph.target((*_matching)[odd]);
2.361 + (*_blossom_rep)[_blossom_set->insert(even)] = even;
2.362 + (*_status)[odd] = ODD;
2.363 + (*_status)[even] = EVEN;
2.364 + int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
2.365 + _tree_set->insert(odd, tree);
2.366 + _tree_set->insert(even, tree);
2.367 + _node_queue[_last++] = even;
2.368 +
2.369 + }
2.370 +
2.371 + void augmentOnArc(const Arc& a) {
2.372 + Node even = _graph.source(a);
2.373 + Node odd = _graph.target(a);
2.374 +
2.375 + int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
2.376 +
2.377 + (*_matching)[odd] = _graph.oppositeArc(a);
2.378 + (*_status)[odd] = MATCHED;
2.379 +
2.380 + Arc arc = (*_matching)[even];
2.381 + (*_matching)[even] = a;
2.382 +
2.383 + while (arc != INVALID) {
2.384 + odd = _graph.target(arc);
2.385 + arc = (*_ear)[odd];
2.386 + even = _graph.target(arc);
2.387 + (*_matching)[odd] = arc;
2.388 + arc = (*_matching)[even];
2.389 + (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
2.390 + }
2.391 +
2.392 + for (typename TreeSet::ItemIt it(*_tree_set, tree);
2.393 + it != INVALID; ++it) {
2.394 + if ((*_status)[it] == ODD) {
2.395 + (*_status)[it] = MATCHED;
2.396 + } else {
2.397 + int blossom = _blossom_set->find(it);
2.398 + for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
2.399 + jt != INVALID; ++jt) {
2.400 + (*_status)[jt] = MATCHED;
2.401 + }
2.402 + _blossom_set->eraseClass(blossom);
2.403 + }
2.404 + }
2.405 + _tree_set->eraseClass(tree);
2.406 +
2.407 + }
2.408 +
2.409 + public:
2.410 +
2.411 + /// \brief Constructor
2.412 + ///
2.413 + /// Constructor.
2.414 + MaxMatching(const Graph& graph)
2.415 + : _graph(graph), _matching(0), _status(0), _ear(0),
2.416 + _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
2.417 + _tree_set_index(0), _tree_set(0) {}
2.418 +
2.419 + ~MaxMatching() {
2.420 + destroyStructures();
2.421 + }
2.422 +
2.423 + /// \name Execution Control
2.424 + /// The simplest way to execute the algorithm is to use the
2.425 + /// \c run() member function.\n
2.426 + /// If you need better control on the execution, you have to call
2.427 + /// one of the functions \ref init(), \ref greedyInit() or
2.428 + /// \ref matchingInit() first, then you can start the algorithm with
2.429 + /// \ref startSparse() or \ref startDense().
2.430 +
2.431 + ///@{
2.432 +
2.433 + /// \brief Set the initial matching to the empty matching.
2.434 + ///
2.435 + /// This function sets the initial matching to the empty matching.
2.436 + void init() {
2.437 + createStructures();
2.438 + for(NodeIt n(_graph); n != INVALID; ++n) {
2.439 + (*_matching)[n] = INVALID;
2.440 + (*_status)[n] = UNMATCHED;
2.441 + }
2.442 + }
2.443 +
2.444 + /// \brief Find an initial matching in a greedy way.
2.445 + ///
2.446 + /// This function finds an initial matching in a greedy way.
2.447 + void greedyInit() {
2.448 + createStructures();
2.449 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.450 + (*_matching)[n] = INVALID;
2.451 + (*_status)[n] = UNMATCHED;
2.452 + }
2.453 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.454 + if ((*_matching)[n] == INVALID) {
2.455 + for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
2.456 + Node v = _graph.target(a);
2.457 + if ((*_matching)[v] == INVALID && v != n) {
2.458 + (*_matching)[n] = a;
2.459 + (*_status)[n] = MATCHED;
2.460 + (*_matching)[v] = _graph.oppositeArc(a);
2.461 + (*_status)[v] = MATCHED;
2.462 + break;
2.463 + }
2.464 + }
2.465 + }
2.466 + }
2.467 + }
2.468 +
2.469 +
2.470 + /// \brief Initialize the matching from a map.
2.471 + ///
2.472 + /// This function initializes the matching from a \c bool valued edge
2.473 + /// map. This map should have the property that there are no two incident
2.474 + /// edges with \c true value, i.e. it really contains a matching.
2.475 + /// \return \c true if the map contains a matching.
2.476 + template <typename MatchingMap>
2.477 + bool matchingInit(const MatchingMap& matching) {
2.478 + createStructures();
2.479 +
2.480 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.481 + (*_matching)[n] = INVALID;
2.482 + (*_status)[n] = UNMATCHED;
2.483 + }
2.484 + for(EdgeIt e(_graph); e!=INVALID; ++e) {
2.485 + if (matching[e]) {
2.486 +
2.487 + Node u = _graph.u(e);
2.488 + if ((*_matching)[u] != INVALID) return false;
2.489 + (*_matching)[u] = _graph.direct(e, true);
2.490 + (*_status)[u] = MATCHED;
2.491 +
2.492 + Node v = _graph.v(e);
2.493 + if ((*_matching)[v] != INVALID) return false;
2.494 + (*_matching)[v] = _graph.direct(e, false);
2.495 + (*_status)[v] = MATCHED;
2.496 + }
2.497 + }
2.498 + return true;
2.499 + }
2.500 +
2.501 + /// \brief Start Edmonds' algorithm
2.502 + ///
2.503 + /// This function runs the original Edmonds' algorithm.
2.504 + ///
2.505 + /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
2.506 + /// called before using this function.
2.507 + void startSparse() {
2.508 + for(NodeIt n(_graph); n != INVALID; ++n) {
2.509 + if ((*_status)[n] == UNMATCHED) {
2.510 + (*_blossom_rep)[_blossom_set->insert(n)] = n;
2.511 + _tree_set->insert(n);
2.512 + (*_status)[n] = EVEN;
2.513 + processSparse(n);
2.514 + }
2.515 + }
2.516 + }
2.517 +
2.518 + /// \brief Start Edmonds' algorithm with a heuristic improvement
2.519 + /// for dense graphs
2.520 + ///
2.521 + /// This function runs Edmonds' algorithm with a heuristic of postponing
2.522 + /// shrinks, therefore resulting in a faster algorithm for dense graphs.
2.523 + ///
2.524 + /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
2.525 + /// called before using this function.
2.526 + void startDense() {
2.527 + for(NodeIt n(_graph); n != INVALID; ++n) {
2.528 + if ((*_status)[n] == UNMATCHED) {
2.529 + (*_blossom_rep)[_blossom_set->insert(n)] = n;
2.530 + _tree_set->insert(n);
2.531 + (*_status)[n] = EVEN;
2.532 + processDense(n);
2.533 + }
2.534 + }
2.535 + }
2.536 +
2.537 +
2.538 + /// \brief Run Edmonds' algorithm
2.539 + ///
2.540 + /// This function runs Edmonds' algorithm. An additional heuristic of
2.541 + /// postponing shrinks is used for relatively dense graphs
2.542 + /// (for which <tt>m>=2*n</tt> holds).
2.543 + void run() {
2.544 + if (countEdges(_graph) < 2 * countNodes(_graph)) {
2.545 + greedyInit();
2.546 + startSparse();
2.547 + } else {
2.548 + init();
2.549 + startDense();
2.550 + }
2.551 + }
2.552 +
2.553 + /// @}
2.554 +
2.555 + /// \name Primal Solution
2.556 + /// Functions to get the primal solution, i.e. the maximum matching.
2.557 +
2.558 + /// @{
2.559 +
2.560 + /// \brief Return the size (cardinality) of the matching.
2.561 + ///
2.562 + /// This function returns the size (cardinality) of the current matching.
2.563 + /// After run() it returns the size of the maximum matching in the graph.
2.564 + int matchingSize() const {
2.565 + int size = 0;
2.566 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.567 + if ((*_matching)[n] != INVALID) {
2.568 + ++size;
2.569 + }
2.570 + }
2.571 + return size / 2;
2.572 + }
2.573 +
2.574 + /// \brief Return \c true if the given edge is in the matching.
2.575 + ///
2.576 + /// This function returns \c true if the given edge is in the current
2.577 + /// matching.
2.578 + bool matching(const Edge& edge) const {
2.579 + return edge == (*_matching)[_graph.u(edge)];
2.580 + }
2.581 +
2.582 + /// \brief Return the matching arc (or edge) incident to the given node.
2.583 + ///
2.584 + /// This function returns the matching arc (or edge) incident to the
2.585 + /// given node in the current matching or \c INVALID if the node is
2.586 + /// not covered by the matching.
2.587 + Arc matching(const Node& n) const {
2.588 + return (*_matching)[n];
2.589 + }
2.590 +
2.591 + /// \brief Return a const reference to the matching map.
2.592 + ///
2.593 + /// This function returns a const reference to a node map that stores
2.594 + /// the matching arc (or edge) incident to each node.
2.595 + const MatchingMap& matchingMap() const {
2.596 + return *_matching;
2.597 + }
2.598 +
2.599 + /// \brief Return the mate of the given node.
2.600 + ///
2.601 + /// This function returns the mate of the given node in the current
2.602 + /// matching or \c INVALID if the node is not covered by the matching.
2.603 + Node mate(const Node& n) const {
2.604 + return (*_matching)[n] != INVALID ?
2.605 + _graph.target((*_matching)[n]) : INVALID;
2.606 + }
2.607 +
2.608 + /// @}
2.609 +
2.610 + /// \name Dual Solution
2.611 + /// Functions to get the dual solution, i.e. the Gallai-Edmonds
2.612 + /// decomposition.
2.613 +
2.614 + /// @{
2.615 +
2.616 + /// \brief Return the status of the given node in the Edmonds-Gallai
2.617 + /// decomposition.
2.618 + ///
2.619 + /// This function returns the \ref Status "status" of the given node
2.620 + /// in the Edmonds-Gallai decomposition.
2.621 + Status status(const Node& n) const {
2.622 + return (*_status)[n];
2.623 + }
2.624 +
2.625 + /// \brief Return a const reference to the status map, which stores
2.626 + /// the Edmonds-Gallai decomposition.
2.627 + ///
2.628 + /// This function returns a const reference to a node map that stores the
2.629 + /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
2.630 + const StatusMap& statusMap() const {
2.631 + return *_status;
2.632 + }
2.633 +
2.634 + /// \brief Return \c true if the given node is in the barrier.
2.635 + ///
2.636 + /// This function returns \c true if the given node is in the barrier.
2.637 + bool barrier(const Node& n) const {
2.638 + return (*_status)[n] == ODD;
2.639 + }
2.640 +
2.641 + /// @}
2.642 +
2.643 + };
2.644 +
2.645 + /// \ingroup matching
2.646 + ///
2.647 + /// \brief Weighted matching in general graphs
2.648 + ///
2.649 + /// This class provides an efficient implementation of Edmond's
2.650 + /// maximum weighted matching algorithm. The implementation is based
2.651 + /// on extensive use of priority queues and provides
2.652 + /// \f$O(nm\log n)\f$ time complexity.
2.653 + ///
2.654 + /// The maximum weighted matching problem is to find a subset of the
2.655 + /// edges in an undirected graph with maximum overall weight for which
2.656 + /// each node has at most one incident edge.
2.657 + /// It can be formulated with the following linear program.
2.658 + /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
2.659 + /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2.660 + \quad \forall B\in\mathcal{O}\f] */
2.661 + /// \f[x_e \ge 0\quad \forall e\in E\f]
2.662 + /// \f[\max \sum_{e\in E}x_ew_e\f]
2.663 + /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2.664 + /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2.665 + /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2.666 + /// subsets of the nodes.
2.667 + ///
2.668 + /// The algorithm calculates an optimal matching and a proof of the
2.669 + /// optimality. The solution of the dual problem can be used to check
2.670 + /// the result of the algorithm. The dual linear problem is the
2.671 + /// following.
2.672 + /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
2.673 + z_B \ge w_{uv} \quad \forall uv\in E\f] */
2.674 + /// \f[y_u \ge 0 \quad \forall u \in V\f]
2.675 + /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2.676 + /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2.677 + \frac{\vert B \vert - 1}{2}z_B\f] */
2.678 + ///
2.679 + /// The algorithm can be executed with the run() function.
2.680 + /// After it the matching (the primal solution) and the dual solution
2.681 + /// can be obtained using the query functions and the
2.682 + /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
2.683 + /// which is able to iterate on the nodes of a blossom.
2.684 + /// If the value type is integer, then the dual solution is multiplied
2.685 + /// by \ref MaxWeightedMatching::dualScale "4".
2.686 + ///
2.687 + /// \tparam GR The undirected graph type the algorithm runs on.
2.688 + /// \tparam WM The type edge weight map. The default type is
2.689 + /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2.690 +#ifdef DOXYGEN
2.691 + template <typename GR, typename WM>
2.692 +#else
2.693 + template <typename GR,
2.694 + typename WM = typename GR::template EdgeMap<int> >
2.695 +#endif
2.696 + class MaxWeightedMatching {
2.697 + public:
2.698 +
2.699 + /// The graph type of the algorithm
2.700 + typedef GR Graph;
2.701 + /// The type of the edge weight map
2.702 + typedef WM WeightMap;
2.703 + /// The value type of the edge weights
2.704 + typedef typename WeightMap::Value Value;
2.705 +
2.706 + /// The type of the matching map
2.707 + typedef typename Graph::template NodeMap<typename Graph::Arc>
2.708 + MatchingMap;
2.709 +
2.710 + /// \brief Scaling factor for dual solution
2.711 + ///
2.712 + /// Scaling factor for dual solution. It is equal to 4 or 1
2.713 + /// according to the value type.
2.714 + static const int dualScale =
2.715 + std::numeric_limits<Value>::is_integer ? 4 : 1;
2.716 +
2.717 + private:
2.718 +
2.719 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
2.720 +
2.721 + typedef typename Graph::template NodeMap<Value> NodePotential;
2.722 + typedef std::vector<Node> BlossomNodeList;
2.723 +
2.724 + struct BlossomVariable {
2.725 + int begin, end;
2.726 + Value value;
2.727 +
2.728 + BlossomVariable(int _begin, int _end, Value _value)
2.729 + : begin(_begin), end(_end), value(_value) {}
2.730 +
2.731 + };
2.732 +
2.733 + typedef std::vector<BlossomVariable> BlossomPotential;
2.734 +
2.735 + const Graph& _graph;
2.736 + const WeightMap& _weight;
2.737 +
2.738 + MatchingMap* _matching;
2.739 +
2.740 + NodePotential* _node_potential;
2.741 +
2.742 + BlossomPotential _blossom_potential;
2.743 + BlossomNodeList _blossom_node_list;
2.744 +
2.745 + int _node_num;
2.746 + int _blossom_num;
2.747 +
2.748 + typedef RangeMap<int> IntIntMap;
2.749 +
2.750 + enum Status {
2.751 + EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
2.752 + };
2.753 +
2.754 + typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2.755 + struct BlossomData {
2.756 + int tree;
2.757 + Status status;
2.758 + Arc pred, next;
2.759 + Value pot, offset;
2.760 + Node base;
2.761 + };
2.762 +
2.763 + IntNodeMap *_blossom_index;
2.764 + BlossomSet *_blossom_set;
2.765 + RangeMap<BlossomData>* _blossom_data;
2.766 +
2.767 + IntNodeMap *_node_index;
2.768 + IntArcMap *_node_heap_index;
2.769 +
2.770 + struct NodeData {
2.771 +
2.772 + NodeData(IntArcMap& node_heap_index)
2.773 + : heap(node_heap_index) {}
2.774 +
2.775 + int blossom;
2.776 + Value pot;
2.777 + BinHeap<Value, IntArcMap> heap;
2.778 + std::map<int, Arc> heap_index;
2.779 +
2.780 + int tree;
2.781 + };
2.782 +
2.783 + RangeMap<NodeData>* _node_data;
2.784 +
2.785 + typedef ExtendFindEnum<IntIntMap> TreeSet;
2.786 +
2.787 + IntIntMap *_tree_set_index;
2.788 + TreeSet *_tree_set;
2.789 +
2.790 + IntNodeMap *_delta1_index;
2.791 + BinHeap<Value, IntNodeMap> *_delta1;
2.792 +
2.793 + IntIntMap *_delta2_index;
2.794 + BinHeap<Value, IntIntMap> *_delta2;
2.795 +
2.796 + IntEdgeMap *_delta3_index;
2.797 + BinHeap<Value, IntEdgeMap> *_delta3;
2.798 +
2.799 + IntIntMap *_delta4_index;
2.800 + BinHeap<Value, IntIntMap> *_delta4;
2.801 +
2.802 + Value _delta_sum;
2.803 +
2.804 + void createStructures() {
2.805 + _node_num = countNodes(_graph);
2.806 + _blossom_num = _node_num * 3 / 2;
2.807 +
2.808 + if (!_matching) {
2.809 + _matching = new MatchingMap(_graph);
2.810 + }
2.811 + if (!_node_potential) {
2.812 + _node_potential = new NodePotential(_graph);
2.813 + }
2.814 + if (!_blossom_set) {
2.815 + _blossom_index = new IntNodeMap(_graph);
2.816 + _blossom_set = new BlossomSet(*_blossom_index);
2.817 + _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2.818 + }
2.819 +
2.820 + if (!_node_index) {
2.821 + _node_index = new IntNodeMap(_graph);
2.822 + _node_heap_index = new IntArcMap(_graph);
2.823 + _node_data = new RangeMap<NodeData>(_node_num,
2.824 + NodeData(*_node_heap_index));
2.825 + }
2.826 +
2.827 + if (!_tree_set) {
2.828 + _tree_set_index = new IntIntMap(_blossom_num);
2.829 + _tree_set = new TreeSet(*_tree_set_index);
2.830 + }
2.831 + if (!_delta1) {
2.832 + _delta1_index = new IntNodeMap(_graph);
2.833 + _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
2.834 + }
2.835 + if (!_delta2) {
2.836 + _delta2_index = new IntIntMap(_blossom_num);
2.837 + _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2.838 + }
2.839 + if (!_delta3) {
2.840 + _delta3_index = new IntEdgeMap(_graph);
2.841 + _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2.842 + }
2.843 + if (!_delta4) {
2.844 + _delta4_index = new IntIntMap(_blossom_num);
2.845 + _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2.846 + }
2.847 + }
2.848 +
2.849 + void destroyStructures() {
2.850 + _node_num = countNodes(_graph);
2.851 + _blossom_num = _node_num * 3 / 2;
2.852 +
2.853 + if (_matching) {
2.854 + delete _matching;
2.855 + }
2.856 + if (_node_potential) {
2.857 + delete _node_potential;
2.858 + }
2.859 + if (_blossom_set) {
2.860 + delete _blossom_index;
2.861 + delete _blossom_set;
2.862 + delete _blossom_data;
2.863 + }
2.864 +
2.865 + if (_node_index) {
2.866 + delete _node_index;
2.867 + delete _node_heap_index;
2.868 + delete _node_data;
2.869 + }
2.870 +
2.871 + if (_tree_set) {
2.872 + delete _tree_set_index;
2.873 + delete _tree_set;
2.874 + }
2.875 + if (_delta1) {
2.876 + delete _delta1_index;
2.877 + delete _delta1;
2.878 + }
2.879 + if (_delta2) {
2.880 + delete _delta2_index;
2.881 + delete _delta2;
2.882 + }
2.883 + if (_delta3) {
2.884 + delete _delta3_index;
2.885 + delete _delta3;
2.886 + }
2.887 + if (_delta4) {
2.888 + delete _delta4_index;
2.889 + delete _delta4;
2.890 + }
2.891 + }
2.892 +
2.893 + void matchedToEven(int blossom, int tree) {
2.894 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2.895 + _delta2->erase(blossom);
2.896 + }
2.897 +
2.898 + if (!_blossom_set->trivial(blossom)) {
2.899 + (*_blossom_data)[blossom].pot -=
2.900 + 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2.901 + }
2.902 +
2.903 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.904 + n != INVALID; ++n) {
2.905 +
2.906 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
2.907 + int ni = (*_node_index)[n];
2.908 +
2.909 + (*_node_data)[ni].heap.clear();
2.910 + (*_node_data)[ni].heap_index.clear();
2.911 +
2.912 + (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2.913 +
2.914 + _delta1->push(n, (*_node_data)[ni].pot);
2.915 +
2.916 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
2.917 + Node v = _graph.source(e);
2.918 + int vb = _blossom_set->find(v);
2.919 + int vi = (*_node_index)[v];
2.920 +
2.921 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.922 + dualScale * _weight[e];
2.923 +
2.924 + if ((*_blossom_data)[vb].status == EVEN) {
2.925 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2.926 + _delta3->push(e, rw / 2);
2.927 + }
2.928 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
2.929 + if (_delta3->state(e) != _delta3->IN_HEAP) {
2.930 + _delta3->push(e, rw);
2.931 + }
2.932 + } else {
2.933 + typename std::map<int, Arc>::iterator it =
2.934 + (*_node_data)[vi].heap_index.find(tree);
2.935 +
2.936 + if (it != (*_node_data)[vi].heap_index.end()) {
2.937 + if ((*_node_data)[vi].heap[it->second] > rw) {
2.938 + (*_node_data)[vi].heap.replace(it->second, e);
2.939 + (*_node_data)[vi].heap.decrease(e, rw);
2.940 + it->second = e;
2.941 + }
2.942 + } else {
2.943 + (*_node_data)[vi].heap.push(e, rw);
2.944 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2.945 + }
2.946 +
2.947 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2.948 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2.949 +
2.950 + if ((*_blossom_data)[vb].status == MATCHED) {
2.951 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
2.952 + _delta2->push(vb, _blossom_set->classPrio(vb) -
2.953 + (*_blossom_data)[vb].offset);
2.954 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2.955 + (*_blossom_data)[vb].offset){
2.956 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2.957 + (*_blossom_data)[vb].offset);
2.958 + }
2.959 + }
2.960 + }
2.961 + }
2.962 + }
2.963 + }
2.964 + (*_blossom_data)[blossom].offset = 0;
2.965 + }
2.966 +
2.967 + void matchedToOdd(int blossom) {
2.968 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2.969 + _delta2->erase(blossom);
2.970 + }
2.971 + (*_blossom_data)[blossom].offset += _delta_sum;
2.972 + if (!_blossom_set->trivial(blossom)) {
2.973 + _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2.974 + (*_blossom_data)[blossom].offset);
2.975 + }
2.976 + }
2.977 +
2.978 + void evenToMatched(int blossom, int tree) {
2.979 + if (!_blossom_set->trivial(blossom)) {
2.980 + (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2.981 + }
2.982 +
2.983 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.984 + n != INVALID; ++n) {
2.985 + int ni = (*_node_index)[n];
2.986 + (*_node_data)[ni].pot -= _delta_sum;
2.987 +
2.988 + _delta1->erase(n);
2.989 +
2.990 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
2.991 + Node v = _graph.source(e);
2.992 + int vb = _blossom_set->find(v);
2.993 + int vi = (*_node_index)[v];
2.994 +
2.995 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.996 + dualScale * _weight[e];
2.997 +
2.998 + if (vb == blossom) {
2.999 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.1000 + _delta3->erase(e);
2.1001 + }
2.1002 + } else if ((*_blossom_data)[vb].status == EVEN) {
2.1003 +
2.1004 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.1005 + _delta3->erase(e);
2.1006 + }
2.1007 +
2.1008 + int vt = _tree_set->find(vb);
2.1009 +
2.1010 + if (vt != tree) {
2.1011 +
2.1012 + Arc r = _graph.oppositeArc(e);
2.1013 +
2.1014 + typename std::map<int, Arc>::iterator it =
2.1015 + (*_node_data)[ni].heap_index.find(vt);
2.1016 +
2.1017 + if (it != (*_node_data)[ni].heap_index.end()) {
2.1018 + if ((*_node_data)[ni].heap[it->second] > rw) {
2.1019 + (*_node_data)[ni].heap.replace(it->second, r);
2.1020 + (*_node_data)[ni].heap.decrease(r, rw);
2.1021 + it->second = r;
2.1022 + }
2.1023 + } else {
2.1024 + (*_node_data)[ni].heap.push(r, rw);
2.1025 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2.1026 + }
2.1027 +
2.1028 + if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2.1029 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2.1030 +
2.1031 + if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2.1032 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2.1033 + (*_blossom_data)[blossom].offset);
2.1034 + } else if ((*_delta2)[blossom] >
2.1035 + _blossom_set->classPrio(blossom) -
2.1036 + (*_blossom_data)[blossom].offset){
2.1037 + _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2.1038 + (*_blossom_data)[blossom].offset);
2.1039 + }
2.1040 + }
2.1041 + }
2.1042 +
2.1043 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
2.1044 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.1045 + _delta3->erase(e);
2.1046 + }
2.1047 + } else {
2.1048 +
2.1049 + typename std::map<int, Arc>::iterator it =
2.1050 + (*_node_data)[vi].heap_index.find(tree);
2.1051 +
2.1052 + if (it != (*_node_data)[vi].heap_index.end()) {
2.1053 + (*_node_data)[vi].heap.erase(it->second);
2.1054 + (*_node_data)[vi].heap_index.erase(it);
2.1055 + if ((*_node_data)[vi].heap.empty()) {
2.1056 + _blossom_set->increase(v, std::numeric_limits<Value>::max());
2.1057 + } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2.1058 + _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2.1059 + }
2.1060 +
2.1061 + if ((*_blossom_data)[vb].status == MATCHED) {
2.1062 + if (_blossom_set->classPrio(vb) ==
2.1063 + std::numeric_limits<Value>::max()) {
2.1064 + _delta2->erase(vb);
2.1065 + } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2.1066 + (*_blossom_data)[vb].offset) {
2.1067 + _delta2->increase(vb, _blossom_set->classPrio(vb) -
2.1068 + (*_blossom_data)[vb].offset);
2.1069 + }
2.1070 + }
2.1071 + }
2.1072 + }
2.1073 + }
2.1074 + }
2.1075 + }
2.1076 +
2.1077 + void oddToMatched(int blossom) {
2.1078 + (*_blossom_data)[blossom].offset -= _delta_sum;
2.1079 +
2.1080 + if (_blossom_set->classPrio(blossom) !=
2.1081 + std::numeric_limits<Value>::max()) {
2.1082 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2.1083 + (*_blossom_data)[blossom].offset);
2.1084 + }
2.1085 +
2.1086 + if (!_blossom_set->trivial(blossom)) {
2.1087 + _delta4->erase(blossom);
2.1088 + }
2.1089 + }
2.1090 +
2.1091 + void oddToEven(int blossom, int tree) {
2.1092 + if (!_blossom_set->trivial(blossom)) {
2.1093 + _delta4->erase(blossom);
2.1094 + (*_blossom_data)[blossom].pot -=
2.1095 + 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2.1096 + }
2.1097 +
2.1098 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.1099 + n != INVALID; ++n) {
2.1100 + int ni = (*_node_index)[n];
2.1101 +
2.1102 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
2.1103 +
2.1104 + (*_node_data)[ni].heap.clear();
2.1105 + (*_node_data)[ni].heap_index.clear();
2.1106 + (*_node_data)[ni].pot +=
2.1107 + 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2.1108 +
2.1109 + _delta1->push(n, (*_node_data)[ni].pot);
2.1110 +
2.1111 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
2.1112 + Node v = _graph.source(e);
2.1113 + int vb = _blossom_set->find(v);
2.1114 + int vi = (*_node_index)[v];
2.1115 +
2.1116 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.1117 + dualScale * _weight[e];
2.1118 +
2.1119 + if ((*_blossom_data)[vb].status == EVEN) {
2.1120 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2.1121 + _delta3->push(e, rw / 2);
2.1122 + }
2.1123 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
2.1124 + if (_delta3->state(e) != _delta3->IN_HEAP) {
2.1125 + _delta3->push(e, rw);
2.1126 + }
2.1127 + } else {
2.1128 +
2.1129 + typename std::map<int, Arc>::iterator it =
2.1130 + (*_node_data)[vi].heap_index.find(tree);
2.1131 +
2.1132 + if (it != (*_node_data)[vi].heap_index.end()) {
2.1133 + if ((*_node_data)[vi].heap[it->second] > rw) {
2.1134 + (*_node_data)[vi].heap.replace(it->second, e);
2.1135 + (*_node_data)[vi].heap.decrease(e, rw);
2.1136 + it->second = e;
2.1137 + }
2.1138 + } else {
2.1139 + (*_node_data)[vi].heap.push(e, rw);
2.1140 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2.1141 + }
2.1142 +
2.1143 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2.1144 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2.1145 +
2.1146 + if ((*_blossom_data)[vb].status == MATCHED) {
2.1147 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
2.1148 + _delta2->push(vb, _blossom_set->classPrio(vb) -
2.1149 + (*_blossom_data)[vb].offset);
2.1150 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2.1151 + (*_blossom_data)[vb].offset) {
2.1152 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2.1153 + (*_blossom_data)[vb].offset);
2.1154 + }
2.1155 + }
2.1156 + }
2.1157 + }
2.1158 + }
2.1159 + }
2.1160 + (*_blossom_data)[blossom].offset = 0;
2.1161 + }
2.1162 +
2.1163 +
2.1164 + void matchedToUnmatched(int blossom) {
2.1165 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2.1166 + _delta2->erase(blossom);
2.1167 + }
2.1168 +
2.1169 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.1170 + n != INVALID; ++n) {
2.1171 + int ni = (*_node_index)[n];
2.1172 +
2.1173 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
2.1174 +
2.1175 + (*_node_data)[ni].heap.clear();
2.1176 + (*_node_data)[ni].heap_index.clear();
2.1177 +
2.1178 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2.1179 + Node v = _graph.target(e);
2.1180 + int vb = _blossom_set->find(v);
2.1181 + int vi = (*_node_index)[v];
2.1182 +
2.1183 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.1184 + dualScale * _weight[e];
2.1185 +
2.1186 + if ((*_blossom_data)[vb].status == EVEN) {
2.1187 + if (_delta3->state(e) != _delta3->IN_HEAP) {
2.1188 + _delta3->push(e, rw);
2.1189 + }
2.1190 + }
2.1191 + }
2.1192 + }
2.1193 + }
2.1194 +
2.1195 + void unmatchedToMatched(int blossom) {
2.1196 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.1197 + n != INVALID; ++n) {
2.1198 + int ni = (*_node_index)[n];
2.1199 +
2.1200 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
2.1201 + Node v = _graph.source(e);
2.1202 + int vb = _blossom_set->find(v);
2.1203 + int vi = (*_node_index)[v];
2.1204 +
2.1205 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.1206 + dualScale * _weight[e];
2.1207 +
2.1208 + if (vb == blossom) {
2.1209 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.1210 + _delta3->erase(e);
2.1211 + }
2.1212 + } else if ((*_blossom_data)[vb].status == EVEN) {
2.1213 +
2.1214 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.1215 + _delta3->erase(e);
2.1216 + }
2.1217 +
2.1218 + int vt = _tree_set->find(vb);
2.1219 +
2.1220 + Arc r = _graph.oppositeArc(e);
2.1221 +
2.1222 + typename std::map<int, Arc>::iterator it =
2.1223 + (*_node_data)[ni].heap_index.find(vt);
2.1224 +
2.1225 + if (it != (*_node_data)[ni].heap_index.end()) {
2.1226 + if ((*_node_data)[ni].heap[it->second] > rw) {
2.1227 + (*_node_data)[ni].heap.replace(it->second, r);
2.1228 + (*_node_data)[ni].heap.decrease(r, rw);
2.1229 + it->second = r;
2.1230 + }
2.1231 + } else {
2.1232 + (*_node_data)[ni].heap.push(r, rw);
2.1233 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2.1234 + }
2.1235 +
2.1236 + if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2.1237 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2.1238 +
2.1239 + if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2.1240 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2.1241 + (*_blossom_data)[blossom].offset);
2.1242 + } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
2.1243 + (*_blossom_data)[blossom].offset){
2.1244 + _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2.1245 + (*_blossom_data)[blossom].offset);
2.1246 + }
2.1247 + }
2.1248 +
2.1249 + } else if ((*_blossom_data)[vb].status == UNMATCHED) {
2.1250 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.1251 + _delta3->erase(e);
2.1252 + }
2.1253 + }
2.1254 + }
2.1255 + }
2.1256 + }
2.1257 +
2.1258 + void alternatePath(int even, int tree) {
2.1259 + int odd;
2.1260 +
2.1261 + evenToMatched(even, tree);
2.1262 + (*_blossom_data)[even].status = MATCHED;
2.1263 +
2.1264 + while ((*_blossom_data)[even].pred != INVALID) {
2.1265 + odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2.1266 + (*_blossom_data)[odd].status = MATCHED;
2.1267 + oddToMatched(odd);
2.1268 + (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2.1269 +
2.1270 + even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2.1271 + (*_blossom_data)[even].status = MATCHED;
2.1272 + evenToMatched(even, tree);
2.1273 + (*_blossom_data)[even].next =
2.1274 + _graph.oppositeArc((*_blossom_data)[odd].pred);
2.1275 + }
2.1276 +
2.1277 + }
2.1278 +
2.1279 + void destroyTree(int tree) {
2.1280 + for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2.1281 + if ((*_blossom_data)[b].status == EVEN) {
2.1282 + (*_blossom_data)[b].status = MATCHED;
2.1283 + evenToMatched(b, tree);
2.1284 + } else if ((*_blossom_data)[b].status == ODD) {
2.1285 + (*_blossom_data)[b].status = MATCHED;
2.1286 + oddToMatched(b);
2.1287 + }
2.1288 + }
2.1289 + _tree_set->eraseClass(tree);
2.1290 + }
2.1291 +
2.1292 +
2.1293 + void unmatchNode(const Node& node) {
2.1294 + int blossom = _blossom_set->find(node);
2.1295 + int tree = _tree_set->find(blossom);
2.1296 +
2.1297 + alternatePath(blossom, tree);
2.1298 + destroyTree(tree);
2.1299 +
2.1300 + (*_blossom_data)[blossom].status = UNMATCHED;
2.1301 + (*_blossom_data)[blossom].base = node;
2.1302 + matchedToUnmatched(blossom);
2.1303 + }
2.1304 +
2.1305 +
2.1306 + void augmentOnEdge(const Edge& edge) {
2.1307 +
2.1308 + int left = _blossom_set->find(_graph.u(edge));
2.1309 + int right = _blossom_set->find(_graph.v(edge));
2.1310 +
2.1311 + if ((*_blossom_data)[left].status == EVEN) {
2.1312 + int left_tree = _tree_set->find(left);
2.1313 + alternatePath(left, left_tree);
2.1314 + destroyTree(left_tree);
2.1315 + } else {
2.1316 + (*_blossom_data)[left].status = MATCHED;
2.1317 + unmatchedToMatched(left);
2.1318 + }
2.1319 +
2.1320 + if ((*_blossom_data)[right].status == EVEN) {
2.1321 + int right_tree = _tree_set->find(right);
2.1322 + alternatePath(right, right_tree);
2.1323 + destroyTree(right_tree);
2.1324 + } else {
2.1325 + (*_blossom_data)[right].status = MATCHED;
2.1326 + unmatchedToMatched(right);
2.1327 + }
2.1328 +
2.1329 + (*_blossom_data)[left].next = _graph.direct(edge, true);
2.1330 + (*_blossom_data)[right].next = _graph.direct(edge, false);
2.1331 + }
2.1332 +
2.1333 + void extendOnArc(const Arc& arc) {
2.1334 + int base = _blossom_set->find(_graph.target(arc));
2.1335 + int tree = _tree_set->find(base);
2.1336 +
2.1337 + int odd = _blossom_set->find(_graph.source(arc));
2.1338 + _tree_set->insert(odd, tree);
2.1339 + (*_blossom_data)[odd].status = ODD;
2.1340 + matchedToOdd(odd);
2.1341 + (*_blossom_data)[odd].pred = arc;
2.1342 +
2.1343 + int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2.1344 + (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2.1345 + _tree_set->insert(even, tree);
2.1346 + (*_blossom_data)[even].status = EVEN;
2.1347 + matchedToEven(even, tree);
2.1348 + }
2.1349 +
2.1350 + void shrinkOnEdge(const Edge& edge, int tree) {
2.1351 + int nca = -1;
2.1352 + std::vector<int> left_path, right_path;
2.1353 +
2.1354 + {
2.1355 + std::set<int> left_set, right_set;
2.1356 + int left = _blossom_set->find(_graph.u(edge));
2.1357 + left_path.push_back(left);
2.1358 + left_set.insert(left);
2.1359 +
2.1360 + int right = _blossom_set->find(_graph.v(edge));
2.1361 + right_path.push_back(right);
2.1362 + right_set.insert(right);
2.1363 +
2.1364 + while (true) {
2.1365 +
2.1366 + if ((*_blossom_data)[left].pred == INVALID) break;
2.1367 +
2.1368 + left =
2.1369 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2.1370 + left_path.push_back(left);
2.1371 + left =
2.1372 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2.1373 + left_path.push_back(left);
2.1374 +
2.1375 + left_set.insert(left);
2.1376 +
2.1377 + if (right_set.find(left) != right_set.end()) {
2.1378 + nca = left;
2.1379 + break;
2.1380 + }
2.1381 +
2.1382 + if ((*_blossom_data)[right].pred == INVALID) break;
2.1383 +
2.1384 + right =
2.1385 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2.1386 + right_path.push_back(right);
2.1387 + right =
2.1388 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2.1389 + right_path.push_back(right);
2.1390 +
2.1391 + right_set.insert(right);
2.1392 +
2.1393 + if (left_set.find(right) != left_set.end()) {
2.1394 + nca = right;
2.1395 + break;
2.1396 + }
2.1397 +
2.1398 + }
2.1399 +
2.1400 + if (nca == -1) {
2.1401 + if ((*_blossom_data)[left].pred == INVALID) {
2.1402 + nca = right;
2.1403 + while (left_set.find(nca) == left_set.end()) {
2.1404 + nca =
2.1405 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.1406 + right_path.push_back(nca);
2.1407 + nca =
2.1408 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.1409 + right_path.push_back(nca);
2.1410 + }
2.1411 + } else {
2.1412 + nca = left;
2.1413 + while (right_set.find(nca) == right_set.end()) {
2.1414 + nca =
2.1415 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.1416 + left_path.push_back(nca);
2.1417 + nca =
2.1418 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.1419 + left_path.push_back(nca);
2.1420 + }
2.1421 + }
2.1422 + }
2.1423 + }
2.1424 +
2.1425 + std::vector<int> subblossoms;
2.1426 + Arc prev;
2.1427 +
2.1428 + prev = _graph.direct(edge, true);
2.1429 + for (int i = 0; left_path[i] != nca; i += 2) {
2.1430 + subblossoms.push_back(left_path[i]);
2.1431 + (*_blossom_data)[left_path[i]].next = prev;
2.1432 + _tree_set->erase(left_path[i]);
2.1433 +
2.1434 + subblossoms.push_back(left_path[i + 1]);
2.1435 + (*_blossom_data)[left_path[i + 1]].status = EVEN;
2.1436 + oddToEven(left_path[i + 1], tree);
2.1437 + _tree_set->erase(left_path[i + 1]);
2.1438 + prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2.1439 + }
2.1440 +
2.1441 + int k = 0;
2.1442 + while (right_path[k] != nca) ++k;
2.1443 +
2.1444 + subblossoms.push_back(nca);
2.1445 + (*_blossom_data)[nca].next = prev;
2.1446 +
2.1447 + for (int i = k - 2; i >= 0; i -= 2) {
2.1448 + subblossoms.push_back(right_path[i + 1]);
2.1449 + (*_blossom_data)[right_path[i + 1]].status = EVEN;
2.1450 + oddToEven(right_path[i + 1], tree);
2.1451 + _tree_set->erase(right_path[i + 1]);
2.1452 +
2.1453 + (*_blossom_data)[right_path[i + 1]].next =
2.1454 + (*_blossom_data)[right_path[i + 1]].pred;
2.1455 +
2.1456 + subblossoms.push_back(right_path[i]);
2.1457 + _tree_set->erase(right_path[i]);
2.1458 + }
2.1459 +
2.1460 + int surface =
2.1461 + _blossom_set->join(subblossoms.begin(), subblossoms.end());
2.1462 +
2.1463 + for (int i = 0; i < int(subblossoms.size()); ++i) {
2.1464 + if (!_blossom_set->trivial(subblossoms[i])) {
2.1465 + (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2.1466 + }
2.1467 + (*_blossom_data)[subblossoms[i]].status = MATCHED;
2.1468 + }
2.1469 +
2.1470 + (*_blossom_data)[surface].pot = -2 * _delta_sum;
2.1471 + (*_blossom_data)[surface].offset = 0;
2.1472 + (*_blossom_data)[surface].status = EVEN;
2.1473 + (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2.1474 + (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2.1475 +
2.1476 + _tree_set->insert(surface, tree);
2.1477 + _tree_set->erase(nca);
2.1478 + }
2.1479 +
2.1480 + void splitBlossom(int blossom) {
2.1481 + Arc next = (*_blossom_data)[blossom].next;
2.1482 + Arc pred = (*_blossom_data)[blossom].pred;
2.1483 +
2.1484 + int tree = _tree_set->find(blossom);
2.1485 +
2.1486 + (*_blossom_data)[blossom].status = MATCHED;
2.1487 + oddToMatched(blossom);
2.1488 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2.1489 + _delta2->erase(blossom);
2.1490 + }
2.1491 +
2.1492 + std::vector<int> subblossoms;
2.1493 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
2.1494 +
2.1495 + Value offset = (*_blossom_data)[blossom].offset;
2.1496 + int b = _blossom_set->find(_graph.source(pred));
2.1497 + int d = _blossom_set->find(_graph.source(next));
2.1498 +
2.1499 + int ib = -1, id = -1;
2.1500 + for (int i = 0; i < int(subblossoms.size()); ++i) {
2.1501 + if (subblossoms[i] == b) ib = i;
2.1502 + if (subblossoms[i] == d) id = i;
2.1503 +
2.1504 + (*_blossom_data)[subblossoms[i]].offset = offset;
2.1505 + if (!_blossom_set->trivial(subblossoms[i])) {
2.1506 + (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2.1507 + }
2.1508 + if (_blossom_set->classPrio(subblossoms[i]) !=
2.1509 + std::numeric_limits<Value>::max()) {
2.1510 + _delta2->push(subblossoms[i],
2.1511 + _blossom_set->classPrio(subblossoms[i]) -
2.1512 + (*_blossom_data)[subblossoms[i]].offset);
2.1513 + }
2.1514 + }
2.1515 +
2.1516 + if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2.1517 + for (int i = (id + 1) % subblossoms.size();
2.1518 + i != ib; i = (i + 2) % subblossoms.size()) {
2.1519 + int sb = subblossoms[i];
2.1520 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.1521 + (*_blossom_data)[sb].next =
2.1522 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.1523 + }
2.1524 +
2.1525 + for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2.1526 + int sb = subblossoms[i];
2.1527 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.1528 + int ub = subblossoms[(i + 2) % subblossoms.size()];
2.1529 +
2.1530 + (*_blossom_data)[sb].status = ODD;
2.1531 + matchedToOdd(sb);
2.1532 + _tree_set->insert(sb, tree);
2.1533 + (*_blossom_data)[sb].pred = pred;
2.1534 + (*_blossom_data)[sb].next =
2.1535 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.1536 +
2.1537 + pred = (*_blossom_data)[ub].next;
2.1538 +
2.1539 + (*_blossom_data)[tb].status = EVEN;
2.1540 + matchedToEven(tb, tree);
2.1541 + _tree_set->insert(tb, tree);
2.1542 + (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2.1543 + }
2.1544 +
2.1545 + (*_blossom_data)[subblossoms[id]].status = ODD;
2.1546 + matchedToOdd(subblossoms[id]);
2.1547 + _tree_set->insert(subblossoms[id], tree);
2.1548 + (*_blossom_data)[subblossoms[id]].next = next;
2.1549 + (*_blossom_data)[subblossoms[id]].pred = pred;
2.1550 +
2.1551 + } else {
2.1552 +
2.1553 + for (int i = (ib + 1) % subblossoms.size();
2.1554 + i != id; i = (i + 2) % subblossoms.size()) {
2.1555 + int sb = subblossoms[i];
2.1556 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.1557 + (*_blossom_data)[sb].next =
2.1558 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.1559 + }
2.1560 +
2.1561 + for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2.1562 + int sb = subblossoms[i];
2.1563 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.1564 + int ub = subblossoms[(i + 2) % subblossoms.size()];
2.1565 +
2.1566 + (*_blossom_data)[sb].status = ODD;
2.1567 + matchedToOdd(sb);
2.1568 + _tree_set->insert(sb, tree);
2.1569 + (*_blossom_data)[sb].next = next;
2.1570 + (*_blossom_data)[sb].pred =
2.1571 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.1572 +
2.1573 + (*_blossom_data)[tb].status = EVEN;
2.1574 + matchedToEven(tb, tree);
2.1575 + _tree_set->insert(tb, tree);
2.1576 + (*_blossom_data)[tb].pred =
2.1577 + (*_blossom_data)[tb].next =
2.1578 + _graph.oppositeArc((*_blossom_data)[ub].next);
2.1579 + next = (*_blossom_data)[ub].next;
2.1580 + }
2.1581 +
2.1582 + (*_blossom_data)[subblossoms[ib]].status = ODD;
2.1583 + matchedToOdd(subblossoms[ib]);
2.1584 + _tree_set->insert(subblossoms[ib], tree);
2.1585 + (*_blossom_data)[subblossoms[ib]].next = next;
2.1586 + (*_blossom_data)[subblossoms[ib]].pred = pred;
2.1587 + }
2.1588 + _tree_set->erase(blossom);
2.1589 + }
2.1590 +
2.1591 + void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2.1592 + if (_blossom_set->trivial(blossom)) {
2.1593 + int bi = (*_node_index)[base];
2.1594 + Value pot = (*_node_data)[bi].pot;
2.1595 +
2.1596 + (*_matching)[base] = matching;
2.1597 + _blossom_node_list.push_back(base);
2.1598 + (*_node_potential)[base] = pot;
2.1599 + } else {
2.1600 +
2.1601 + Value pot = (*_blossom_data)[blossom].pot;
2.1602 + int bn = _blossom_node_list.size();
2.1603 +
2.1604 + std::vector<int> subblossoms;
2.1605 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
2.1606 + int b = _blossom_set->find(base);
2.1607 + int ib = -1;
2.1608 + for (int i = 0; i < int(subblossoms.size()); ++i) {
2.1609 + if (subblossoms[i] == b) { ib = i; break; }
2.1610 + }
2.1611 +
2.1612 + for (int i = 1; i < int(subblossoms.size()); i += 2) {
2.1613 + int sb = subblossoms[(ib + i) % subblossoms.size()];
2.1614 + int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2.1615 +
2.1616 + Arc m = (*_blossom_data)[tb].next;
2.1617 + extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2.1618 + extractBlossom(tb, _graph.source(m), m);
2.1619 + }
2.1620 + extractBlossom(subblossoms[ib], base, matching);
2.1621 +
2.1622 + int en = _blossom_node_list.size();
2.1623 +
2.1624 + _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2.1625 + }
2.1626 + }
2.1627 +
2.1628 + void extractMatching() {
2.1629 + std::vector<int> blossoms;
2.1630 + for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2.1631 + blossoms.push_back(c);
2.1632 + }
2.1633 +
2.1634 + for (int i = 0; i < int(blossoms.size()); ++i) {
2.1635 + if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
2.1636 +
2.1637 + Value offset = (*_blossom_data)[blossoms[i]].offset;
2.1638 + (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2.1639 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2.1640 + n != INVALID; ++n) {
2.1641 + (*_node_data)[(*_node_index)[n]].pot -= offset;
2.1642 + }
2.1643 +
2.1644 + Arc matching = (*_blossom_data)[blossoms[i]].next;
2.1645 + Node base = _graph.source(matching);
2.1646 + extractBlossom(blossoms[i], base, matching);
2.1647 + } else {
2.1648 + Node base = (*_blossom_data)[blossoms[i]].base;
2.1649 + extractBlossom(blossoms[i], base, INVALID);
2.1650 + }
2.1651 + }
2.1652 + }
2.1653 +
2.1654 + public:
2.1655 +
2.1656 + /// \brief Constructor
2.1657 + ///
2.1658 + /// Constructor.
2.1659 + MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
2.1660 + : _graph(graph), _weight(weight), _matching(0),
2.1661 + _node_potential(0), _blossom_potential(), _blossom_node_list(),
2.1662 + _node_num(0), _blossom_num(0),
2.1663 +
2.1664 + _blossom_index(0), _blossom_set(0), _blossom_data(0),
2.1665 + _node_index(0), _node_heap_index(0), _node_data(0),
2.1666 + _tree_set_index(0), _tree_set(0),
2.1667 +
2.1668 + _delta1_index(0), _delta1(0),
2.1669 + _delta2_index(0), _delta2(0),
2.1670 + _delta3_index(0), _delta3(0),
2.1671 + _delta4_index(0), _delta4(0),
2.1672 +
2.1673 + _delta_sum() {}
2.1674 +
2.1675 + ~MaxWeightedMatching() {
2.1676 + destroyStructures();
2.1677 + }
2.1678 +
2.1679 + /// \name Execution Control
2.1680 + /// The simplest way to execute the algorithm is to use the
2.1681 + /// \ref run() member function.
2.1682 +
2.1683 + ///@{
2.1684 +
2.1685 + /// \brief Initialize the algorithm
2.1686 + ///
2.1687 + /// This function initializes the algorithm.
2.1688 + void init() {
2.1689 + createStructures();
2.1690 +
2.1691 + for (ArcIt e(_graph); e != INVALID; ++e) {
2.1692 + (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2.1693 + }
2.1694 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.1695 + (*_delta1_index)[n] = _delta1->PRE_HEAP;
2.1696 + }
2.1697 + for (EdgeIt e(_graph); e != INVALID; ++e) {
2.1698 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
2.1699 + }
2.1700 + for (int i = 0; i < _blossom_num; ++i) {
2.1701 + (*_delta2_index)[i] = _delta2->PRE_HEAP;
2.1702 + (*_delta4_index)[i] = _delta4->PRE_HEAP;
2.1703 + }
2.1704 +
2.1705 + int index = 0;
2.1706 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.1707 + Value max = 0;
2.1708 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2.1709 + if (_graph.target(e) == n) continue;
2.1710 + if ((dualScale * _weight[e]) / 2 > max) {
2.1711 + max = (dualScale * _weight[e]) / 2;
2.1712 + }
2.1713 + }
2.1714 + (*_node_index)[n] = index;
2.1715 + (*_node_data)[index].pot = max;
2.1716 + _delta1->push(n, max);
2.1717 + int blossom =
2.1718 + _blossom_set->insert(n, std::numeric_limits<Value>::max());
2.1719 +
2.1720 + _tree_set->insert(blossom);
2.1721 +
2.1722 + (*_blossom_data)[blossom].status = EVEN;
2.1723 + (*_blossom_data)[blossom].pred = INVALID;
2.1724 + (*_blossom_data)[blossom].next = INVALID;
2.1725 + (*_blossom_data)[blossom].pot = 0;
2.1726 + (*_blossom_data)[blossom].offset = 0;
2.1727 + ++index;
2.1728 + }
2.1729 + for (EdgeIt e(_graph); e != INVALID; ++e) {
2.1730 + int si = (*_node_index)[_graph.u(e)];
2.1731 + int ti = (*_node_index)[_graph.v(e)];
2.1732 + if (_graph.u(e) != _graph.v(e)) {
2.1733 + _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2.1734 + dualScale * _weight[e]) / 2);
2.1735 + }
2.1736 + }
2.1737 + }
2.1738 +
2.1739 + /// \brief Start the algorithm
2.1740 + ///
2.1741 + /// This function starts the algorithm.
2.1742 + ///
2.1743 + /// \pre \ref init() must be called before using this function.
2.1744 + void start() {
2.1745 + enum OpType {
2.1746 + D1, D2, D3, D4
2.1747 + };
2.1748 +
2.1749 + int unmatched = _node_num;
2.1750 + while (unmatched > 0) {
2.1751 + Value d1 = !_delta1->empty() ?
2.1752 + _delta1->prio() : std::numeric_limits<Value>::max();
2.1753 +
2.1754 + Value d2 = !_delta2->empty() ?
2.1755 + _delta2->prio() : std::numeric_limits<Value>::max();
2.1756 +
2.1757 + Value d3 = !_delta3->empty() ?
2.1758 + _delta3->prio() : std::numeric_limits<Value>::max();
2.1759 +
2.1760 + Value d4 = !_delta4->empty() ?
2.1761 + _delta4->prio() : std::numeric_limits<Value>::max();
2.1762 +
2.1763 + _delta_sum = d1; OpType ot = D1;
2.1764 + if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
2.1765 + if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
2.1766 + if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2.1767 +
2.1768 +
2.1769 + switch (ot) {
2.1770 + case D1:
2.1771 + {
2.1772 + Node n = _delta1->top();
2.1773 + unmatchNode(n);
2.1774 + --unmatched;
2.1775 + }
2.1776 + break;
2.1777 + case D2:
2.1778 + {
2.1779 + int blossom = _delta2->top();
2.1780 + Node n = _blossom_set->classTop(blossom);
2.1781 + Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
2.1782 + extendOnArc(e);
2.1783 + }
2.1784 + break;
2.1785 + case D3:
2.1786 + {
2.1787 + Edge e = _delta3->top();
2.1788 +
2.1789 + int left_blossom = _blossom_set->find(_graph.u(e));
2.1790 + int right_blossom = _blossom_set->find(_graph.v(e));
2.1791 +
2.1792 + if (left_blossom == right_blossom) {
2.1793 + _delta3->pop();
2.1794 + } else {
2.1795 + int left_tree;
2.1796 + if ((*_blossom_data)[left_blossom].status == EVEN) {
2.1797 + left_tree = _tree_set->find(left_blossom);
2.1798 + } else {
2.1799 + left_tree = -1;
2.1800 + ++unmatched;
2.1801 + }
2.1802 + int right_tree;
2.1803 + if ((*_blossom_data)[right_blossom].status == EVEN) {
2.1804 + right_tree = _tree_set->find(right_blossom);
2.1805 + } else {
2.1806 + right_tree = -1;
2.1807 + ++unmatched;
2.1808 + }
2.1809 +
2.1810 + if (left_tree == right_tree) {
2.1811 + shrinkOnEdge(e, left_tree);
2.1812 + } else {
2.1813 + augmentOnEdge(e);
2.1814 + unmatched -= 2;
2.1815 + }
2.1816 + }
2.1817 + } break;
2.1818 + case D4:
2.1819 + splitBlossom(_delta4->top());
2.1820 + break;
2.1821 + }
2.1822 + }
2.1823 + extractMatching();
2.1824 + }
2.1825 +
2.1826 + /// \brief Run the algorithm.
2.1827 + ///
2.1828 + /// This method runs the \c %MaxWeightedMatching algorithm.
2.1829 + ///
2.1830 + /// \note mwm.run() is just a shortcut of the following code.
2.1831 + /// \code
2.1832 + /// mwm.init();
2.1833 + /// mwm.start();
2.1834 + /// \endcode
2.1835 + void run() {
2.1836 + init();
2.1837 + start();
2.1838 + }
2.1839 +
2.1840 + /// @}
2.1841 +
2.1842 + /// \name Primal Solution
2.1843 + /// Functions to get the primal solution, i.e. the maximum weighted
2.1844 + /// matching.\n
2.1845 + /// Either \ref run() or \ref start() function should be called before
2.1846 + /// using them.
2.1847 +
2.1848 + /// @{
2.1849 +
2.1850 + /// \brief Return the weight of the matching.
2.1851 + ///
2.1852 + /// This function returns the weight of the found matching.
2.1853 + ///
2.1854 + /// \pre Either run() or start() must be called before using this function.
2.1855 + Value matchingWeight() const {
2.1856 + Value sum = 0;
2.1857 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.1858 + if ((*_matching)[n] != INVALID) {
2.1859 + sum += _weight[(*_matching)[n]];
2.1860 + }
2.1861 + }
2.1862 + return sum /= 2;
2.1863 + }
2.1864 +
2.1865 + /// \brief Return the size (cardinality) of the matching.
2.1866 + ///
2.1867 + /// This function returns the size (cardinality) of the found matching.
2.1868 + ///
2.1869 + /// \pre Either run() or start() must be called before using this function.
2.1870 + int matchingSize() const {
2.1871 + int num = 0;
2.1872 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.1873 + if ((*_matching)[n] != INVALID) {
2.1874 + ++num;
2.1875 + }
2.1876 + }
2.1877 + return num /= 2;
2.1878 + }
2.1879 +
2.1880 + /// \brief Return \c true if the given edge is in the matching.
2.1881 + ///
2.1882 + /// This function returns \c true if the given edge is in the found
2.1883 + /// matching.
2.1884 + ///
2.1885 + /// \pre Either run() or start() must be called before using this function.
2.1886 + bool matching(const Edge& edge) const {
2.1887 + return edge == (*_matching)[_graph.u(edge)];
2.1888 + }
2.1889 +
2.1890 + /// \brief Return the matching arc (or edge) incident to the given node.
2.1891 + ///
2.1892 + /// This function returns the matching arc (or edge) incident to the
2.1893 + /// given node in the found matching or \c INVALID if the node is
2.1894 + /// not covered by the matching.
2.1895 + ///
2.1896 + /// \pre Either run() or start() must be called before using this function.
2.1897 + Arc matching(const Node& node) const {
2.1898 + return (*_matching)[node];
2.1899 + }
2.1900 +
2.1901 + /// \brief Return a const reference to the matching map.
2.1902 + ///
2.1903 + /// This function returns a const reference to a node map that stores
2.1904 + /// the matching arc (or edge) incident to each node.
2.1905 + const MatchingMap& matchingMap() const {
2.1906 + return *_matching;
2.1907 + }
2.1908 +
2.1909 + /// \brief Return the mate of the given node.
2.1910 + ///
2.1911 + /// This function returns the mate of the given node in the found
2.1912 + /// matching or \c INVALID if the node is not covered by the matching.
2.1913 + ///
2.1914 + /// \pre Either run() or start() must be called before using this function.
2.1915 + Node mate(const Node& node) const {
2.1916 + return (*_matching)[node] != INVALID ?
2.1917 + _graph.target((*_matching)[node]) : INVALID;
2.1918 + }
2.1919 +
2.1920 + /// @}
2.1921 +
2.1922 + /// \name Dual Solution
2.1923 + /// Functions to get the dual solution.\n
2.1924 + /// Either \ref run() or \ref start() function should be called before
2.1925 + /// using them.
2.1926 +
2.1927 + /// @{
2.1928 +
2.1929 + /// \brief Return the value of the dual solution.
2.1930 + ///
2.1931 + /// This function returns the value of the dual solution.
2.1932 + /// It should be equal to the primal value scaled by \ref dualScale
2.1933 + /// "dual scale".
2.1934 + ///
2.1935 + /// \pre Either run() or start() must be called before using this function.
2.1936 + Value dualValue() const {
2.1937 + Value sum = 0;
2.1938 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.1939 + sum += nodeValue(n);
2.1940 + }
2.1941 + for (int i = 0; i < blossomNum(); ++i) {
2.1942 + sum += blossomValue(i) * (blossomSize(i) / 2);
2.1943 + }
2.1944 + return sum;
2.1945 + }
2.1946 +
2.1947 + /// \brief Return the dual value (potential) of the given node.
2.1948 + ///
2.1949 + /// This function returns the dual value (potential) of the given node.
2.1950 + ///
2.1951 + /// \pre Either run() or start() must be called before using this function.
2.1952 + Value nodeValue(const Node& n) const {
2.1953 + return (*_node_potential)[n];
2.1954 + }
2.1955 +
2.1956 + /// \brief Return the number of the blossoms in the basis.
2.1957 + ///
2.1958 + /// This function returns the number of the blossoms in the basis.
2.1959 + ///
2.1960 + /// \pre Either run() or start() must be called before using this function.
2.1961 + /// \see BlossomIt
2.1962 + int blossomNum() const {
2.1963 + return _blossom_potential.size();
2.1964 + }
2.1965 +
2.1966 + /// \brief Return the number of the nodes in the given blossom.
2.1967 + ///
2.1968 + /// This function returns the number of the nodes in the given blossom.
2.1969 + ///
2.1970 + /// \pre Either run() or start() must be called before using this function.
2.1971 + /// \see BlossomIt
2.1972 + int blossomSize(int k) const {
2.1973 + return _blossom_potential[k].end - _blossom_potential[k].begin;
2.1974 + }
2.1975 +
2.1976 + /// \brief Return the dual value (ptential) of the given blossom.
2.1977 + ///
2.1978 + /// This function returns the dual value (ptential) of the given blossom.
2.1979 + ///
2.1980 + /// \pre Either run() or start() must be called before using this function.
2.1981 + Value blossomValue(int k) const {
2.1982 + return _blossom_potential[k].value;
2.1983 + }
2.1984 +
2.1985 + /// \brief Iterator for obtaining the nodes of a blossom.
2.1986 + ///
2.1987 + /// This class provides an iterator for obtaining the nodes of the
2.1988 + /// given blossom. It lists a subset of the nodes.
2.1989 + /// Before using this iterator, you must allocate a
2.1990 + /// MaxWeightedMatching class and execute it.
2.1991 + class BlossomIt {
2.1992 + public:
2.1993 +
2.1994 + /// \brief Constructor.
2.1995 + ///
2.1996 + /// Constructor to get the nodes of the given variable.
2.1997 + ///
2.1998 + /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
2.1999 + /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
2.2000 + /// called before initializing this iterator.
2.2001 + BlossomIt(const MaxWeightedMatching& algorithm, int variable)
2.2002 + : _algorithm(&algorithm)
2.2003 + {
2.2004 + _index = _algorithm->_blossom_potential[variable].begin;
2.2005 + _last = _algorithm->_blossom_potential[variable].end;
2.2006 + }
2.2007 +
2.2008 + /// \brief Conversion to \c Node.
2.2009 + ///
2.2010 + /// Conversion to \c Node.
2.2011 + operator Node() const {
2.2012 + return _algorithm->_blossom_node_list[_index];
2.2013 + }
2.2014 +
2.2015 + /// \brief Increment operator.
2.2016 + ///
2.2017 + /// Increment operator.
2.2018 + BlossomIt& operator++() {
2.2019 + ++_index;
2.2020 + return *this;
2.2021 + }
2.2022 +
2.2023 + /// \brief Validity checking
2.2024 + ///
2.2025 + /// Checks whether the iterator is invalid.
2.2026 + bool operator==(Invalid) const { return _index == _last; }
2.2027 +
2.2028 + /// \brief Validity checking
2.2029 + ///
2.2030 + /// Checks whether the iterator is valid.
2.2031 + bool operator!=(Invalid) const { return _index != _last; }
2.2032 +
2.2033 + private:
2.2034 + const MaxWeightedMatching* _algorithm;
2.2035 + int _last;
2.2036 + int _index;
2.2037 + };
2.2038 +
2.2039 + /// @}
2.2040 +
2.2041 + };
2.2042 +
2.2043 + /// \ingroup matching
2.2044 + ///
2.2045 + /// \brief Weighted perfect matching in general graphs
2.2046 + ///
2.2047 + /// This class provides an efficient implementation of Edmond's
2.2048 + /// maximum weighted perfect matching algorithm. The implementation
2.2049 + /// is based on extensive use of priority queues and provides
2.2050 + /// \f$O(nm\log n)\f$ time complexity.
2.2051 + ///
2.2052 + /// The maximum weighted perfect matching problem is to find a subset of
2.2053 + /// the edges in an undirected graph with maximum overall weight for which
2.2054 + /// each node has exactly one incident edge.
2.2055 + /// It can be formulated with the following linear program.
2.2056 + /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2.2057 + /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2.2058 + \quad \forall B\in\mathcal{O}\f] */
2.2059 + /// \f[x_e \ge 0\quad \forall e\in E\f]
2.2060 + /// \f[\max \sum_{e\in E}x_ew_e\f]
2.2061 + /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2.2062 + /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2.2063 + /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2.2064 + /// subsets of the nodes.
2.2065 + ///
2.2066 + /// The algorithm calculates an optimal matching and a proof of the
2.2067 + /// optimality. The solution of the dual problem can be used to check
2.2068 + /// the result of the algorithm. The dual linear problem is the
2.2069 + /// following.
2.2070 + /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2.2071 + w_{uv} \quad \forall uv\in E\f] */
2.2072 + /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2.2073 + /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2.2074 + \frac{\vert B \vert - 1}{2}z_B\f] */
2.2075 + ///
2.2076 + /// The algorithm can be executed with the run() function.
2.2077 + /// After it the matching (the primal solution) and the dual solution
2.2078 + /// can be obtained using the query functions and the
2.2079 + /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2.2080 + /// which is able to iterate on the nodes of a blossom.
2.2081 + /// If the value type is integer, then the dual solution is multiplied
2.2082 + /// by \ref MaxWeightedMatching::dualScale "4".
2.2083 + ///
2.2084 + /// \tparam GR The undirected graph type the algorithm runs on.
2.2085 + /// \tparam WM The type edge weight map. The default type is
2.2086 + /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2.2087 +#ifdef DOXYGEN
2.2088 + template <typename GR, typename WM>
2.2089 +#else
2.2090 + template <typename GR,
2.2091 + typename WM = typename GR::template EdgeMap<int> >
2.2092 +#endif
2.2093 + class MaxWeightedPerfectMatching {
2.2094 + public:
2.2095 +
2.2096 + /// The graph type of the algorithm
2.2097 + typedef GR Graph;
2.2098 + /// The type of the edge weight map
2.2099 + typedef WM WeightMap;
2.2100 + /// The value type of the edge weights
2.2101 + typedef typename WeightMap::Value Value;
2.2102 +
2.2103 + /// \brief Scaling factor for dual solution
2.2104 + ///
2.2105 + /// Scaling factor for dual solution, it is equal to 4 or 1
2.2106 + /// according to the value type.
2.2107 + static const int dualScale =
2.2108 + std::numeric_limits<Value>::is_integer ? 4 : 1;
2.2109 +
2.2110 + /// The type of the matching map
2.2111 + typedef typename Graph::template NodeMap<typename Graph::Arc>
2.2112 + MatchingMap;
2.2113 +
2.2114 + private:
2.2115 +
2.2116 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
2.2117 +
2.2118 + typedef typename Graph::template NodeMap<Value> NodePotential;
2.2119 + typedef std::vector<Node> BlossomNodeList;
2.2120 +
2.2121 + struct BlossomVariable {
2.2122 + int begin, end;
2.2123 + Value value;
2.2124 +
2.2125 + BlossomVariable(int _begin, int _end, Value _value)
2.2126 + : begin(_begin), end(_end), value(_value) {}
2.2127 +
2.2128 + };
2.2129 +
2.2130 + typedef std::vector<BlossomVariable> BlossomPotential;
2.2131 +
2.2132 + const Graph& _graph;
2.2133 + const WeightMap& _weight;
2.2134 +
2.2135 + MatchingMap* _matching;
2.2136 +
2.2137 + NodePotential* _node_potential;
2.2138 +
2.2139 + BlossomPotential _blossom_potential;
2.2140 + BlossomNodeList _blossom_node_list;
2.2141 +
2.2142 + int _node_num;
2.2143 + int _blossom_num;
2.2144 +
2.2145 + typedef RangeMap<int> IntIntMap;
2.2146 +
2.2147 + enum Status {
2.2148 + EVEN = -1, MATCHED = 0, ODD = 1
2.2149 + };
2.2150 +
2.2151 + typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2.2152 + struct BlossomData {
2.2153 + int tree;
2.2154 + Status status;
2.2155 + Arc pred, next;
2.2156 + Value pot, offset;
2.2157 + };
2.2158 +
2.2159 + IntNodeMap *_blossom_index;
2.2160 + BlossomSet *_blossom_set;
2.2161 + RangeMap<BlossomData>* _blossom_data;
2.2162 +
2.2163 + IntNodeMap *_node_index;
2.2164 + IntArcMap *_node_heap_index;
2.2165 +
2.2166 + struct NodeData {
2.2167 +
2.2168 + NodeData(IntArcMap& node_heap_index)
2.2169 + : heap(node_heap_index) {}
2.2170 +
2.2171 + int blossom;
2.2172 + Value pot;
2.2173 + BinHeap<Value, IntArcMap> heap;
2.2174 + std::map<int, Arc> heap_index;
2.2175 +
2.2176 + int tree;
2.2177 + };
2.2178 +
2.2179 + RangeMap<NodeData>* _node_data;
2.2180 +
2.2181 + typedef ExtendFindEnum<IntIntMap> TreeSet;
2.2182 +
2.2183 + IntIntMap *_tree_set_index;
2.2184 + TreeSet *_tree_set;
2.2185 +
2.2186 + IntIntMap *_delta2_index;
2.2187 + BinHeap<Value, IntIntMap> *_delta2;
2.2188 +
2.2189 + IntEdgeMap *_delta3_index;
2.2190 + BinHeap<Value, IntEdgeMap> *_delta3;
2.2191 +
2.2192 + IntIntMap *_delta4_index;
2.2193 + BinHeap<Value, IntIntMap> *_delta4;
2.2194 +
2.2195 + Value _delta_sum;
2.2196 +
2.2197 + void createStructures() {
2.2198 + _node_num = countNodes(_graph);
2.2199 + _blossom_num = _node_num * 3 / 2;
2.2200 +
2.2201 + if (!_matching) {
2.2202 + _matching = new MatchingMap(_graph);
2.2203 + }
2.2204 + if (!_node_potential) {
2.2205 + _node_potential = new NodePotential(_graph);
2.2206 + }
2.2207 + if (!_blossom_set) {
2.2208 + _blossom_index = new IntNodeMap(_graph);
2.2209 + _blossom_set = new BlossomSet(*_blossom_index);
2.2210 + _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2.2211 + }
2.2212 +
2.2213 + if (!_node_index) {
2.2214 + _node_index = new IntNodeMap(_graph);
2.2215 + _node_heap_index = new IntArcMap(_graph);
2.2216 + _node_data = new RangeMap<NodeData>(_node_num,
2.2217 + NodeData(*_node_heap_index));
2.2218 + }
2.2219 +
2.2220 + if (!_tree_set) {
2.2221 + _tree_set_index = new IntIntMap(_blossom_num);
2.2222 + _tree_set = new TreeSet(*_tree_set_index);
2.2223 + }
2.2224 + if (!_delta2) {
2.2225 + _delta2_index = new IntIntMap(_blossom_num);
2.2226 + _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2.2227 + }
2.2228 + if (!_delta3) {
2.2229 + _delta3_index = new IntEdgeMap(_graph);
2.2230 + _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2.2231 + }
2.2232 + if (!_delta4) {
2.2233 + _delta4_index = new IntIntMap(_blossom_num);
2.2234 + _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2.2235 + }
2.2236 + }
2.2237 +
2.2238 + void destroyStructures() {
2.2239 + _node_num = countNodes(_graph);
2.2240 + _blossom_num = _node_num * 3 / 2;
2.2241 +
2.2242 + if (_matching) {
2.2243 + delete _matching;
2.2244 + }
2.2245 + if (_node_potential) {
2.2246 + delete _node_potential;
2.2247 + }
2.2248 + if (_blossom_set) {
2.2249 + delete _blossom_index;
2.2250 + delete _blossom_set;
2.2251 + delete _blossom_data;
2.2252 + }
2.2253 +
2.2254 + if (_node_index) {
2.2255 + delete _node_index;
2.2256 + delete _node_heap_index;
2.2257 + delete _node_data;
2.2258 + }
2.2259 +
2.2260 + if (_tree_set) {
2.2261 + delete _tree_set_index;
2.2262 + delete _tree_set;
2.2263 + }
2.2264 + if (_delta2) {
2.2265 + delete _delta2_index;
2.2266 + delete _delta2;
2.2267 + }
2.2268 + if (_delta3) {
2.2269 + delete _delta3_index;
2.2270 + delete _delta3;
2.2271 + }
2.2272 + if (_delta4) {
2.2273 + delete _delta4_index;
2.2274 + delete _delta4;
2.2275 + }
2.2276 + }
2.2277 +
2.2278 + void matchedToEven(int blossom, int tree) {
2.2279 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2.2280 + _delta2->erase(blossom);
2.2281 + }
2.2282 +
2.2283 + if (!_blossom_set->trivial(blossom)) {
2.2284 + (*_blossom_data)[blossom].pot -=
2.2285 + 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2.2286 + }
2.2287 +
2.2288 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.2289 + n != INVALID; ++n) {
2.2290 +
2.2291 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
2.2292 + int ni = (*_node_index)[n];
2.2293 +
2.2294 + (*_node_data)[ni].heap.clear();
2.2295 + (*_node_data)[ni].heap_index.clear();
2.2296 +
2.2297 + (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2.2298 +
2.2299 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
2.2300 + Node v = _graph.source(e);
2.2301 + int vb = _blossom_set->find(v);
2.2302 + int vi = (*_node_index)[v];
2.2303 +
2.2304 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.2305 + dualScale * _weight[e];
2.2306 +
2.2307 + if ((*_blossom_data)[vb].status == EVEN) {
2.2308 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2.2309 + _delta3->push(e, rw / 2);
2.2310 + }
2.2311 + } else {
2.2312 + typename std::map<int, Arc>::iterator it =
2.2313 + (*_node_data)[vi].heap_index.find(tree);
2.2314 +
2.2315 + if (it != (*_node_data)[vi].heap_index.end()) {
2.2316 + if ((*_node_data)[vi].heap[it->second] > rw) {
2.2317 + (*_node_data)[vi].heap.replace(it->second, e);
2.2318 + (*_node_data)[vi].heap.decrease(e, rw);
2.2319 + it->second = e;
2.2320 + }
2.2321 + } else {
2.2322 + (*_node_data)[vi].heap.push(e, rw);
2.2323 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2.2324 + }
2.2325 +
2.2326 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2.2327 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2.2328 +
2.2329 + if ((*_blossom_data)[vb].status == MATCHED) {
2.2330 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
2.2331 + _delta2->push(vb, _blossom_set->classPrio(vb) -
2.2332 + (*_blossom_data)[vb].offset);
2.2333 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2.2334 + (*_blossom_data)[vb].offset){
2.2335 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2.2336 + (*_blossom_data)[vb].offset);
2.2337 + }
2.2338 + }
2.2339 + }
2.2340 + }
2.2341 + }
2.2342 + }
2.2343 + (*_blossom_data)[blossom].offset = 0;
2.2344 + }
2.2345 +
2.2346 + void matchedToOdd(int blossom) {
2.2347 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2.2348 + _delta2->erase(blossom);
2.2349 + }
2.2350 + (*_blossom_data)[blossom].offset += _delta_sum;
2.2351 + if (!_blossom_set->trivial(blossom)) {
2.2352 + _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2.2353 + (*_blossom_data)[blossom].offset);
2.2354 + }
2.2355 + }
2.2356 +
2.2357 + void evenToMatched(int blossom, int tree) {
2.2358 + if (!_blossom_set->trivial(blossom)) {
2.2359 + (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2.2360 + }
2.2361 +
2.2362 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.2363 + n != INVALID; ++n) {
2.2364 + int ni = (*_node_index)[n];
2.2365 + (*_node_data)[ni].pot -= _delta_sum;
2.2366 +
2.2367 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
2.2368 + Node v = _graph.source(e);
2.2369 + int vb = _blossom_set->find(v);
2.2370 + int vi = (*_node_index)[v];
2.2371 +
2.2372 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.2373 + dualScale * _weight[e];
2.2374 +
2.2375 + if (vb == blossom) {
2.2376 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.2377 + _delta3->erase(e);
2.2378 + }
2.2379 + } else if ((*_blossom_data)[vb].status == EVEN) {
2.2380 +
2.2381 + if (_delta3->state(e) == _delta3->IN_HEAP) {
2.2382 + _delta3->erase(e);
2.2383 + }
2.2384 +
2.2385 + int vt = _tree_set->find(vb);
2.2386 +
2.2387 + if (vt != tree) {
2.2388 +
2.2389 + Arc r = _graph.oppositeArc(e);
2.2390 +
2.2391 + typename std::map<int, Arc>::iterator it =
2.2392 + (*_node_data)[ni].heap_index.find(vt);
2.2393 +
2.2394 + if (it != (*_node_data)[ni].heap_index.end()) {
2.2395 + if ((*_node_data)[ni].heap[it->second] > rw) {
2.2396 + (*_node_data)[ni].heap.replace(it->second, r);
2.2397 + (*_node_data)[ni].heap.decrease(r, rw);
2.2398 + it->second = r;
2.2399 + }
2.2400 + } else {
2.2401 + (*_node_data)[ni].heap.push(r, rw);
2.2402 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2.2403 + }
2.2404 +
2.2405 + if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2.2406 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2.2407 +
2.2408 + if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2.2409 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2.2410 + (*_blossom_data)[blossom].offset);
2.2411 + } else if ((*_delta2)[blossom] >
2.2412 + _blossom_set->classPrio(blossom) -
2.2413 + (*_blossom_data)[blossom].offset){
2.2414 + _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2.2415 + (*_blossom_data)[blossom].offset);
2.2416 + }
2.2417 + }
2.2418 + }
2.2419 + } else {
2.2420 +
2.2421 + typename std::map<int, Arc>::iterator it =
2.2422 + (*_node_data)[vi].heap_index.find(tree);
2.2423 +
2.2424 + if (it != (*_node_data)[vi].heap_index.end()) {
2.2425 + (*_node_data)[vi].heap.erase(it->second);
2.2426 + (*_node_data)[vi].heap_index.erase(it);
2.2427 + if ((*_node_data)[vi].heap.empty()) {
2.2428 + _blossom_set->increase(v, std::numeric_limits<Value>::max());
2.2429 + } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2.2430 + _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2.2431 + }
2.2432 +
2.2433 + if ((*_blossom_data)[vb].status == MATCHED) {
2.2434 + if (_blossom_set->classPrio(vb) ==
2.2435 + std::numeric_limits<Value>::max()) {
2.2436 + _delta2->erase(vb);
2.2437 + } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2.2438 + (*_blossom_data)[vb].offset) {
2.2439 + _delta2->increase(vb, _blossom_set->classPrio(vb) -
2.2440 + (*_blossom_data)[vb].offset);
2.2441 + }
2.2442 + }
2.2443 + }
2.2444 + }
2.2445 + }
2.2446 + }
2.2447 + }
2.2448 +
2.2449 + void oddToMatched(int blossom) {
2.2450 + (*_blossom_data)[blossom].offset -= _delta_sum;
2.2451 +
2.2452 + if (_blossom_set->classPrio(blossom) !=
2.2453 + std::numeric_limits<Value>::max()) {
2.2454 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2.2455 + (*_blossom_data)[blossom].offset);
2.2456 + }
2.2457 +
2.2458 + if (!_blossom_set->trivial(blossom)) {
2.2459 + _delta4->erase(blossom);
2.2460 + }
2.2461 + }
2.2462 +
2.2463 + void oddToEven(int blossom, int tree) {
2.2464 + if (!_blossom_set->trivial(blossom)) {
2.2465 + _delta4->erase(blossom);
2.2466 + (*_blossom_data)[blossom].pot -=
2.2467 + 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2.2468 + }
2.2469 +
2.2470 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2.2471 + n != INVALID; ++n) {
2.2472 + int ni = (*_node_index)[n];
2.2473 +
2.2474 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
2.2475 +
2.2476 + (*_node_data)[ni].heap.clear();
2.2477 + (*_node_data)[ni].heap_index.clear();
2.2478 + (*_node_data)[ni].pot +=
2.2479 + 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2.2480 +
2.2481 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
2.2482 + Node v = _graph.source(e);
2.2483 + int vb = _blossom_set->find(v);
2.2484 + int vi = (*_node_index)[v];
2.2485 +
2.2486 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2.2487 + dualScale * _weight[e];
2.2488 +
2.2489 + if ((*_blossom_data)[vb].status == EVEN) {
2.2490 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2.2491 + _delta3->push(e, rw / 2);
2.2492 + }
2.2493 + } else {
2.2494 +
2.2495 + typename std::map<int, Arc>::iterator it =
2.2496 + (*_node_data)[vi].heap_index.find(tree);
2.2497 +
2.2498 + if (it != (*_node_data)[vi].heap_index.end()) {
2.2499 + if ((*_node_data)[vi].heap[it->second] > rw) {
2.2500 + (*_node_data)[vi].heap.replace(it->second, e);
2.2501 + (*_node_data)[vi].heap.decrease(e, rw);
2.2502 + it->second = e;
2.2503 + }
2.2504 + } else {
2.2505 + (*_node_data)[vi].heap.push(e, rw);
2.2506 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2.2507 + }
2.2508 +
2.2509 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2.2510 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2.2511 +
2.2512 + if ((*_blossom_data)[vb].status == MATCHED) {
2.2513 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
2.2514 + _delta2->push(vb, _blossom_set->classPrio(vb) -
2.2515 + (*_blossom_data)[vb].offset);
2.2516 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2.2517 + (*_blossom_data)[vb].offset) {
2.2518 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2.2519 + (*_blossom_data)[vb].offset);
2.2520 + }
2.2521 + }
2.2522 + }
2.2523 + }
2.2524 + }
2.2525 + }
2.2526 + (*_blossom_data)[blossom].offset = 0;
2.2527 + }
2.2528 +
2.2529 + void alternatePath(int even, int tree) {
2.2530 + int odd;
2.2531 +
2.2532 + evenToMatched(even, tree);
2.2533 + (*_blossom_data)[even].status = MATCHED;
2.2534 +
2.2535 + while ((*_blossom_data)[even].pred != INVALID) {
2.2536 + odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2.2537 + (*_blossom_data)[odd].status = MATCHED;
2.2538 + oddToMatched(odd);
2.2539 + (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2.2540 +
2.2541 + even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2.2542 + (*_blossom_data)[even].status = MATCHED;
2.2543 + evenToMatched(even, tree);
2.2544 + (*_blossom_data)[even].next =
2.2545 + _graph.oppositeArc((*_blossom_data)[odd].pred);
2.2546 + }
2.2547 +
2.2548 + }
2.2549 +
2.2550 + void destroyTree(int tree) {
2.2551 + for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2.2552 + if ((*_blossom_data)[b].status == EVEN) {
2.2553 + (*_blossom_data)[b].status = MATCHED;
2.2554 + evenToMatched(b, tree);
2.2555 + } else if ((*_blossom_data)[b].status == ODD) {
2.2556 + (*_blossom_data)[b].status = MATCHED;
2.2557 + oddToMatched(b);
2.2558 + }
2.2559 + }
2.2560 + _tree_set->eraseClass(tree);
2.2561 + }
2.2562 +
2.2563 + void augmentOnEdge(const Edge& edge) {
2.2564 +
2.2565 + int left = _blossom_set->find(_graph.u(edge));
2.2566 + int right = _blossom_set->find(_graph.v(edge));
2.2567 +
2.2568 + int left_tree = _tree_set->find(left);
2.2569 + alternatePath(left, left_tree);
2.2570 + destroyTree(left_tree);
2.2571 +
2.2572 + int right_tree = _tree_set->find(right);
2.2573 + alternatePath(right, right_tree);
2.2574 + destroyTree(right_tree);
2.2575 +
2.2576 + (*_blossom_data)[left].next = _graph.direct(edge, true);
2.2577 + (*_blossom_data)[right].next = _graph.direct(edge, false);
2.2578 + }
2.2579 +
2.2580 + void extendOnArc(const Arc& arc) {
2.2581 + int base = _blossom_set->find(_graph.target(arc));
2.2582 + int tree = _tree_set->find(base);
2.2583 +
2.2584 + int odd = _blossom_set->find(_graph.source(arc));
2.2585 + _tree_set->insert(odd, tree);
2.2586 + (*_blossom_data)[odd].status = ODD;
2.2587 + matchedToOdd(odd);
2.2588 + (*_blossom_data)[odd].pred = arc;
2.2589 +
2.2590 + int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2.2591 + (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2.2592 + _tree_set->insert(even, tree);
2.2593 + (*_blossom_data)[even].status = EVEN;
2.2594 + matchedToEven(even, tree);
2.2595 + }
2.2596 +
2.2597 + void shrinkOnEdge(const Edge& edge, int tree) {
2.2598 + int nca = -1;
2.2599 + std::vector<int> left_path, right_path;
2.2600 +
2.2601 + {
2.2602 + std::set<int> left_set, right_set;
2.2603 + int left = _blossom_set->find(_graph.u(edge));
2.2604 + left_path.push_back(left);
2.2605 + left_set.insert(left);
2.2606 +
2.2607 + int right = _blossom_set->find(_graph.v(edge));
2.2608 + right_path.push_back(right);
2.2609 + right_set.insert(right);
2.2610 +
2.2611 + while (true) {
2.2612 +
2.2613 + if ((*_blossom_data)[left].pred == INVALID) break;
2.2614 +
2.2615 + left =
2.2616 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2.2617 + left_path.push_back(left);
2.2618 + left =
2.2619 + _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2.2620 + left_path.push_back(left);
2.2621 +
2.2622 + left_set.insert(left);
2.2623 +
2.2624 + if (right_set.find(left) != right_set.end()) {
2.2625 + nca = left;
2.2626 + break;
2.2627 + }
2.2628 +
2.2629 + if ((*_blossom_data)[right].pred == INVALID) break;
2.2630 +
2.2631 + right =
2.2632 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2.2633 + right_path.push_back(right);
2.2634 + right =
2.2635 + _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2.2636 + right_path.push_back(right);
2.2637 +
2.2638 + right_set.insert(right);
2.2639 +
2.2640 + if (left_set.find(right) != left_set.end()) {
2.2641 + nca = right;
2.2642 + break;
2.2643 + }
2.2644 +
2.2645 + }
2.2646 +
2.2647 + if (nca == -1) {
2.2648 + if ((*_blossom_data)[left].pred == INVALID) {
2.2649 + nca = right;
2.2650 + while (left_set.find(nca) == left_set.end()) {
2.2651 + nca =
2.2652 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.2653 + right_path.push_back(nca);
2.2654 + nca =
2.2655 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.2656 + right_path.push_back(nca);
2.2657 + }
2.2658 + } else {
2.2659 + nca = left;
2.2660 + while (right_set.find(nca) == right_set.end()) {
2.2661 + nca =
2.2662 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.2663 + left_path.push_back(nca);
2.2664 + nca =
2.2665 + _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2.2666 + left_path.push_back(nca);
2.2667 + }
2.2668 + }
2.2669 + }
2.2670 + }
2.2671 +
2.2672 + std::vector<int> subblossoms;
2.2673 + Arc prev;
2.2674 +
2.2675 + prev = _graph.direct(edge, true);
2.2676 + for (int i = 0; left_path[i] != nca; i += 2) {
2.2677 + subblossoms.push_back(left_path[i]);
2.2678 + (*_blossom_data)[left_path[i]].next = prev;
2.2679 + _tree_set->erase(left_path[i]);
2.2680 +
2.2681 + subblossoms.push_back(left_path[i + 1]);
2.2682 + (*_blossom_data)[left_path[i + 1]].status = EVEN;
2.2683 + oddToEven(left_path[i + 1], tree);
2.2684 + _tree_set->erase(left_path[i + 1]);
2.2685 + prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2.2686 + }
2.2687 +
2.2688 + int k = 0;
2.2689 + while (right_path[k] != nca) ++k;
2.2690 +
2.2691 + subblossoms.push_back(nca);
2.2692 + (*_blossom_data)[nca].next = prev;
2.2693 +
2.2694 + for (int i = k - 2; i >= 0; i -= 2) {
2.2695 + subblossoms.push_back(right_path[i + 1]);
2.2696 + (*_blossom_data)[right_path[i + 1]].status = EVEN;
2.2697 + oddToEven(right_path[i + 1], tree);
2.2698 + _tree_set->erase(right_path[i + 1]);
2.2699 +
2.2700 + (*_blossom_data)[right_path[i + 1]].next =
2.2701 + (*_blossom_data)[right_path[i + 1]].pred;
2.2702 +
2.2703 + subblossoms.push_back(right_path[i]);
2.2704 + _tree_set->erase(right_path[i]);
2.2705 + }
2.2706 +
2.2707 + int surface =
2.2708 + _blossom_set->join(subblossoms.begin(), subblossoms.end());
2.2709 +
2.2710 + for (int i = 0; i < int(subblossoms.size()); ++i) {
2.2711 + if (!_blossom_set->trivial(subblossoms[i])) {
2.2712 + (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2.2713 + }
2.2714 + (*_blossom_data)[subblossoms[i]].status = MATCHED;
2.2715 + }
2.2716 +
2.2717 + (*_blossom_data)[surface].pot = -2 * _delta_sum;
2.2718 + (*_blossom_data)[surface].offset = 0;
2.2719 + (*_blossom_data)[surface].status = EVEN;
2.2720 + (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2.2721 + (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2.2722 +
2.2723 + _tree_set->insert(surface, tree);
2.2724 + _tree_set->erase(nca);
2.2725 + }
2.2726 +
2.2727 + void splitBlossom(int blossom) {
2.2728 + Arc next = (*_blossom_data)[blossom].next;
2.2729 + Arc pred = (*_blossom_data)[blossom].pred;
2.2730 +
2.2731 + int tree = _tree_set->find(blossom);
2.2732 +
2.2733 + (*_blossom_data)[blossom].status = MATCHED;
2.2734 + oddToMatched(blossom);
2.2735 + if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2.2736 + _delta2->erase(blossom);
2.2737 + }
2.2738 +
2.2739 + std::vector<int> subblossoms;
2.2740 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
2.2741 +
2.2742 + Value offset = (*_blossom_data)[blossom].offset;
2.2743 + int b = _blossom_set->find(_graph.source(pred));
2.2744 + int d = _blossom_set->find(_graph.source(next));
2.2745 +
2.2746 + int ib = -1, id = -1;
2.2747 + for (int i = 0; i < int(subblossoms.size()); ++i) {
2.2748 + if (subblossoms[i] == b) ib = i;
2.2749 + if (subblossoms[i] == d) id = i;
2.2750 +
2.2751 + (*_blossom_data)[subblossoms[i]].offset = offset;
2.2752 + if (!_blossom_set->trivial(subblossoms[i])) {
2.2753 + (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2.2754 + }
2.2755 + if (_blossom_set->classPrio(subblossoms[i]) !=
2.2756 + std::numeric_limits<Value>::max()) {
2.2757 + _delta2->push(subblossoms[i],
2.2758 + _blossom_set->classPrio(subblossoms[i]) -
2.2759 + (*_blossom_data)[subblossoms[i]].offset);
2.2760 + }
2.2761 + }
2.2762 +
2.2763 + if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2.2764 + for (int i = (id + 1) % subblossoms.size();
2.2765 + i != ib; i = (i + 2) % subblossoms.size()) {
2.2766 + int sb = subblossoms[i];
2.2767 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.2768 + (*_blossom_data)[sb].next =
2.2769 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.2770 + }
2.2771 +
2.2772 + for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2.2773 + int sb = subblossoms[i];
2.2774 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.2775 + int ub = subblossoms[(i + 2) % subblossoms.size()];
2.2776 +
2.2777 + (*_blossom_data)[sb].status = ODD;
2.2778 + matchedToOdd(sb);
2.2779 + _tree_set->insert(sb, tree);
2.2780 + (*_blossom_data)[sb].pred = pred;
2.2781 + (*_blossom_data)[sb].next =
2.2782 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.2783 +
2.2784 + pred = (*_blossom_data)[ub].next;
2.2785 +
2.2786 + (*_blossom_data)[tb].status = EVEN;
2.2787 + matchedToEven(tb, tree);
2.2788 + _tree_set->insert(tb, tree);
2.2789 + (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2.2790 + }
2.2791 +
2.2792 + (*_blossom_data)[subblossoms[id]].status = ODD;
2.2793 + matchedToOdd(subblossoms[id]);
2.2794 + _tree_set->insert(subblossoms[id], tree);
2.2795 + (*_blossom_data)[subblossoms[id]].next = next;
2.2796 + (*_blossom_data)[subblossoms[id]].pred = pred;
2.2797 +
2.2798 + } else {
2.2799 +
2.2800 + for (int i = (ib + 1) % subblossoms.size();
2.2801 + i != id; i = (i + 2) % subblossoms.size()) {
2.2802 + int sb = subblossoms[i];
2.2803 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.2804 + (*_blossom_data)[sb].next =
2.2805 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.2806 + }
2.2807 +
2.2808 + for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2.2809 + int sb = subblossoms[i];
2.2810 + int tb = subblossoms[(i + 1) % subblossoms.size()];
2.2811 + int ub = subblossoms[(i + 2) % subblossoms.size()];
2.2812 +
2.2813 + (*_blossom_data)[sb].status = ODD;
2.2814 + matchedToOdd(sb);
2.2815 + _tree_set->insert(sb, tree);
2.2816 + (*_blossom_data)[sb].next = next;
2.2817 + (*_blossom_data)[sb].pred =
2.2818 + _graph.oppositeArc((*_blossom_data)[tb].next);
2.2819 +
2.2820 + (*_blossom_data)[tb].status = EVEN;
2.2821 + matchedToEven(tb, tree);
2.2822 + _tree_set->insert(tb, tree);
2.2823 + (*_blossom_data)[tb].pred =
2.2824 + (*_blossom_data)[tb].next =
2.2825 + _graph.oppositeArc((*_blossom_data)[ub].next);
2.2826 + next = (*_blossom_data)[ub].next;
2.2827 + }
2.2828 +
2.2829 + (*_blossom_data)[subblossoms[ib]].status = ODD;
2.2830 + matchedToOdd(subblossoms[ib]);
2.2831 + _tree_set->insert(subblossoms[ib], tree);
2.2832 + (*_blossom_data)[subblossoms[ib]].next = next;
2.2833 + (*_blossom_data)[subblossoms[ib]].pred = pred;
2.2834 + }
2.2835 + _tree_set->erase(blossom);
2.2836 + }
2.2837 +
2.2838 + void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2.2839 + if (_blossom_set->trivial(blossom)) {
2.2840 + int bi = (*_node_index)[base];
2.2841 + Value pot = (*_node_data)[bi].pot;
2.2842 +
2.2843 + (*_matching)[base] = matching;
2.2844 + _blossom_node_list.push_back(base);
2.2845 + (*_node_potential)[base] = pot;
2.2846 + } else {
2.2847 +
2.2848 + Value pot = (*_blossom_data)[blossom].pot;
2.2849 + int bn = _blossom_node_list.size();
2.2850 +
2.2851 + std::vector<int> subblossoms;
2.2852 + _blossom_set->split(blossom, std::back_inserter(subblossoms));
2.2853 + int b = _blossom_set->find(base);
2.2854 + int ib = -1;
2.2855 + for (int i = 0; i < int(subblossoms.size()); ++i) {
2.2856 + if (subblossoms[i] == b) { ib = i; break; }
2.2857 + }
2.2858 +
2.2859 + for (int i = 1; i < int(subblossoms.size()); i += 2) {
2.2860 + int sb = subblossoms[(ib + i) % subblossoms.size()];
2.2861 + int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2.2862 +
2.2863 + Arc m = (*_blossom_data)[tb].next;
2.2864 + extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2.2865 + extractBlossom(tb, _graph.source(m), m);
2.2866 + }
2.2867 + extractBlossom(subblossoms[ib], base, matching);
2.2868 +
2.2869 + int en = _blossom_node_list.size();
2.2870 +
2.2871 + _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2.2872 + }
2.2873 + }
2.2874 +
2.2875 + void extractMatching() {
2.2876 + std::vector<int> blossoms;
2.2877 + for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2.2878 + blossoms.push_back(c);
2.2879 + }
2.2880 +
2.2881 + for (int i = 0; i < int(blossoms.size()); ++i) {
2.2882 +
2.2883 + Value offset = (*_blossom_data)[blossoms[i]].offset;
2.2884 + (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2.2885 + for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2.2886 + n != INVALID; ++n) {
2.2887 + (*_node_data)[(*_node_index)[n]].pot -= offset;
2.2888 + }
2.2889 +
2.2890 + Arc matching = (*_blossom_data)[blossoms[i]].next;
2.2891 + Node base = _graph.source(matching);
2.2892 + extractBlossom(blossoms[i], base, matching);
2.2893 + }
2.2894 + }
2.2895 +
2.2896 + public:
2.2897 +
2.2898 + /// \brief Constructor
2.2899 + ///
2.2900 + /// Constructor.
2.2901 + MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2.2902 + : _graph(graph), _weight(weight), _matching(0),
2.2903 + _node_potential(0), _blossom_potential(), _blossom_node_list(),
2.2904 + _node_num(0), _blossom_num(0),
2.2905 +
2.2906 + _blossom_index(0), _blossom_set(0), _blossom_data(0),
2.2907 + _node_index(0), _node_heap_index(0), _node_data(0),
2.2908 + _tree_set_index(0), _tree_set(0),
2.2909 +
2.2910 + _delta2_index(0), _delta2(0),
2.2911 + _delta3_index(0), _delta3(0),
2.2912 + _delta4_index(0), _delta4(0),
2.2913 +
2.2914 + _delta_sum() {}
2.2915 +
2.2916 + ~MaxWeightedPerfectMatching() {
2.2917 + destroyStructures();
2.2918 + }
2.2919 +
2.2920 + /// \name Execution Control
2.2921 + /// The simplest way to execute the algorithm is to use the
2.2922 + /// \ref run() member function.
2.2923 +
2.2924 + ///@{
2.2925 +
2.2926 + /// \brief Initialize the algorithm
2.2927 + ///
2.2928 + /// This function initializes the algorithm.
2.2929 + void init() {
2.2930 + createStructures();
2.2931 +
2.2932 + for (ArcIt e(_graph); e != INVALID; ++e) {
2.2933 + (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2.2934 + }
2.2935 + for (EdgeIt e(_graph); e != INVALID; ++e) {
2.2936 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
2.2937 + }
2.2938 + for (int i = 0; i < _blossom_num; ++i) {
2.2939 + (*_delta2_index)[i] = _delta2->PRE_HEAP;
2.2940 + (*_delta4_index)[i] = _delta4->PRE_HEAP;
2.2941 + }
2.2942 +
2.2943 + int index = 0;
2.2944 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.2945 + Value max = - std::numeric_limits<Value>::max();
2.2946 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2.2947 + if (_graph.target(e) == n) continue;
2.2948 + if ((dualScale * _weight[e]) / 2 > max) {
2.2949 + max = (dualScale * _weight[e]) / 2;
2.2950 + }
2.2951 + }
2.2952 + (*_node_index)[n] = index;
2.2953 + (*_node_data)[index].pot = max;
2.2954 + int blossom =
2.2955 + _blossom_set->insert(n, std::numeric_limits<Value>::max());
2.2956 +
2.2957 + _tree_set->insert(blossom);
2.2958 +
2.2959 + (*_blossom_data)[blossom].status = EVEN;
2.2960 + (*_blossom_data)[blossom].pred = INVALID;
2.2961 + (*_blossom_data)[blossom].next = INVALID;
2.2962 + (*_blossom_data)[blossom].pot = 0;
2.2963 + (*_blossom_data)[blossom].offset = 0;
2.2964 + ++index;
2.2965 + }
2.2966 + for (EdgeIt e(_graph); e != INVALID; ++e) {
2.2967 + int si = (*_node_index)[_graph.u(e)];
2.2968 + int ti = (*_node_index)[_graph.v(e)];
2.2969 + if (_graph.u(e) != _graph.v(e)) {
2.2970 + _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2.2971 + dualScale * _weight[e]) / 2);
2.2972 + }
2.2973 + }
2.2974 + }
2.2975 +
2.2976 + /// \brief Start the algorithm
2.2977 + ///
2.2978 + /// This function starts the algorithm.
2.2979 + ///
2.2980 + /// \pre \ref init() must be called before using this function.
2.2981 + bool start() {
2.2982 + enum OpType {
2.2983 + D2, D3, D4
2.2984 + };
2.2985 +
2.2986 + int unmatched = _node_num;
2.2987 + while (unmatched > 0) {
2.2988 + Value d2 = !_delta2->empty() ?
2.2989 + _delta2->prio() : std::numeric_limits<Value>::max();
2.2990 +
2.2991 + Value d3 = !_delta3->empty() ?
2.2992 + _delta3->prio() : std::numeric_limits<Value>::max();
2.2993 +
2.2994 + Value d4 = !_delta4->empty() ?
2.2995 + _delta4->prio() : std::numeric_limits<Value>::max();
2.2996 +
2.2997 + _delta_sum = d2; OpType ot = D2;
2.2998 + if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
2.2999 + if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2.3000 +
2.3001 + if (_delta_sum == std::numeric_limits<Value>::max()) {
2.3002 + return false;
2.3003 + }
2.3004 +
2.3005 + switch (ot) {
2.3006 + case D2:
2.3007 + {
2.3008 + int blossom = _delta2->top();
2.3009 + Node n = _blossom_set->classTop(blossom);
2.3010 + Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
2.3011 + extendOnArc(e);
2.3012 + }
2.3013 + break;
2.3014 + case D3:
2.3015 + {
2.3016 + Edge e = _delta3->top();
2.3017 +
2.3018 + int left_blossom = _blossom_set->find(_graph.u(e));
2.3019 + int right_blossom = _blossom_set->find(_graph.v(e));
2.3020 +
2.3021 + if (left_blossom == right_blossom) {
2.3022 + _delta3->pop();
2.3023 + } else {
2.3024 + int left_tree = _tree_set->find(left_blossom);
2.3025 + int right_tree = _tree_set->find(right_blossom);
2.3026 +
2.3027 + if (left_tree == right_tree) {
2.3028 + shrinkOnEdge(e, left_tree);
2.3029 + } else {
2.3030 + augmentOnEdge(e);
2.3031 + unmatched -= 2;
2.3032 + }
2.3033 + }
2.3034 + } break;
2.3035 + case D4:
2.3036 + splitBlossom(_delta4->top());
2.3037 + break;
2.3038 + }
2.3039 + }
2.3040 + extractMatching();
2.3041 + return true;
2.3042 + }
2.3043 +
2.3044 + /// \brief Run the algorithm.
2.3045 + ///
2.3046 + /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
2.3047 + ///
2.3048 + /// \note mwpm.run() is just a shortcut of the following code.
2.3049 + /// \code
2.3050 + /// mwpm.init();
2.3051 + /// mwpm.start();
2.3052 + /// \endcode
2.3053 + bool run() {
2.3054 + init();
2.3055 + return start();
2.3056 + }
2.3057 +
2.3058 + /// @}
2.3059 +
2.3060 + /// \name Primal Solution
2.3061 + /// Functions to get the primal solution, i.e. the maximum weighted
2.3062 + /// perfect matching.\n
2.3063 + /// Either \ref run() or \ref start() function should be called before
2.3064 + /// using them.
2.3065 +
2.3066 + /// @{
2.3067 +
2.3068 + /// \brief Return the weight of the matching.
2.3069 + ///
2.3070 + /// This function returns the weight of the found matching.
2.3071 + ///
2.3072 + /// \pre Either run() or start() must be called before using this function.
2.3073 + Value matchingWeight() const {
2.3074 + Value sum = 0;
2.3075 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.3076 + if ((*_matching)[n] != INVALID) {
2.3077 + sum += _weight[(*_matching)[n]];
2.3078 + }
2.3079 + }
2.3080 + return sum /= 2;
2.3081 + }
2.3082 +
2.3083 + /// \brief Return \c true if the given edge is in the matching.
2.3084 + ///
2.3085 + /// This function returns \c true if the given edge is in the found
2.3086 + /// matching.
2.3087 + ///
2.3088 + /// \pre Either run() or start() must be called before using this function.
2.3089 + bool matching(const Edge& edge) const {
2.3090 + return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
2.3091 + }
2.3092 +
2.3093 + /// \brief Return the matching arc (or edge) incident to the given node.
2.3094 + ///
2.3095 + /// This function returns the matching arc (or edge) incident to the
2.3096 + /// given node in the found matching or \c INVALID if the node is
2.3097 + /// not covered by the matching.
2.3098 + ///
2.3099 + /// \pre Either run() or start() must be called before using this function.
2.3100 + Arc matching(const Node& node) const {
2.3101 + return (*_matching)[node];
2.3102 + }
2.3103 +
2.3104 + /// \brief Return a const reference to the matching map.
2.3105 + ///
2.3106 + /// This function returns a const reference to a node map that stores
2.3107 + /// the matching arc (or edge) incident to each node.
2.3108 + const MatchingMap& matchingMap() const {
2.3109 + return *_matching;
2.3110 + }
2.3111 +
2.3112 + /// \brief Return the mate of the given node.
2.3113 + ///
2.3114 + /// This function returns the mate of the given node in the found
2.3115 + /// matching or \c INVALID if the node is not covered by the matching.
2.3116 + ///
2.3117 + /// \pre Either run() or start() must be called before using this function.
2.3118 + Node mate(const Node& node) const {
2.3119 + return _graph.target((*_matching)[node]);
2.3120 + }
2.3121 +
2.3122 + /// @}
2.3123 +
2.3124 + /// \name Dual Solution
2.3125 + /// Functions to get the dual solution.\n
2.3126 + /// Either \ref run() or \ref start() function should be called before
2.3127 + /// using them.
2.3128 +
2.3129 + /// @{
2.3130 +
2.3131 + /// \brief Return the value of the dual solution.
2.3132 + ///
2.3133 + /// This function returns the value of the dual solution.
2.3134 + /// It should be equal to the primal value scaled by \ref dualScale
2.3135 + /// "dual scale".
2.3136 + ///
2.3137 + /// \pre Either run() or start() must be called before using this function.
2.3138 + Value dualValue() const {
2.3139 + Value sum = 0;
2.3140 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.3141 + sum += nodeValue(n);
2.3142 + }
2.3143 + for (int i = 0; i < blossomNum(); ++i) {
2.3144 + sum += blossomValue(i) * (blossomSize(i) / 2);
2.3145 + }
2.3146 + return sum;
2.3147 + }
2.3148 +
2.3149 + /// \brief Return the dual value (potential) of the given node.
2.3150 + ///
2.3151 + /// This function returns the dual value (potential) of the given node.
2.3152 + ///
2.3153 + /// \pre Either run() or start() must be called before using this function.
2.3154 + Value nodeValue(const Node& n) const {
2.3155 + return (*_node_potential)[n];
2.3156 + }
2.3157 +
2.3158 + /// \brief Return the number of the blossoms in the basis.
2.3159 + ///
2.3160 + /// This function returns the number of the blossoms in the basis.
2.3161 + ///
2.3162 + /// \pre Either run() or start() must be called before using this function.
2.3163 + /// \see BlossomIt
2.3164 + int blossomNum() const {
2.3165 + return _blossom_potential.size();
2.3166 + }
2.3167 +
2.3168 + /// \brief Return the number of the nodes in the given blossom.
2.3169 + ///
2.3170 + /// This function returns the number of the nodes in the given blossom.
2.3171 + ///
2.3172 + /// \pre Either run() or start() must be called before using this function.
2.3173 + /// \see BlossomIt
2.3174 + int blossomSize(int k) const {
2.3175 + return _blossom_potential[k].end - _blossom_potential[k].begin;
2.3176 + }
2.3177 +
2.3178 + /// \brief Return the dual value (ptential) of the given blossom.
2.3179 + ///
2.3180 + /// This function returns the dual value (ptential) of the given blossom.
2.3181 + ///
2.3182 + /// \pre Either run() or start() must be called before using this function.
2.3183 + Value blossomValue(int k) const {
2.3184 + return _blossom_potential[k].value;
2.3185 + }
2.3186 +
2.3187 + /// \brief Iterator for obtaining the nodes of a blossom.
2.3188 + ///
2.3189 + /// This class provides an iterator for obtaining the nodes of the
2.3190 + /// given blossom. It lists a subset of the nodes.
2.3191 + /// Before using this iterator, you must allocate a
2.3192 + /// MaxWeightedPerfectMatching class and execute it.
2.3193 + class BlossomIt {
2.3194 + public:
2.3195 +
2.3196 + /// \brief Constructor.
2.3197 + ///
2.3198 + /// Constructor to get the nodes of the given variable.
2.3199 + ///
2.3200 + /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
2.3201 + /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
2.3202 + /// must be called before initializing this iterator.
2.3203 + BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
2.3204 + : _algorithm(&algorithm)
2.3205 + {
2.3206 + _index = _algorithm->_blossom_potential[variable].begin;
2.3207 + _last = _algorithm->_blossom_potential[variable].end;
2.3208 + }
2.3209 +
2.3210 + /// \brief Conversion to \c Node.
2.3211 + ///
2.3212 + /// Conversion to \c Node.
2.3213 + operator Node() const {
2.3214 + return _algorithm->_blossom_node_list[_index];
2.3215 + }
2.3216 +
2.3217 + /// \brief Increment operator.
2.3218 + ///
2.3219 + /// Increment operator.
2.3220 + BlossomIt& operator++() {
2.3221 + ++_index;
2.3222 + return *this;
2.3223 + }
2.3224 +
2.3225 + /// \brief Validity checking
2.3226 + ///
2.3227 + /// This function checks whether the iterator is invalid.
2.3228 + bool operator==(Invalid) const { return _index == _last; }
2.3229 +
2.3230 + /// \brief Validity checking
2.3231 + ///
2.3232 + /// This function checks whether the iterator is valid.
2.3233 + bool operator!=(Invalid) const { return _index != _last; }
2.3234 +
2.3235 + private:
2.3236 + const MaxWeightedPerfectMatching* _algorithm;
2.3237 + int _last;
2.3238 + int _index;
2.3239 + };
2.3240 +
2.3241 + /// @}
2.3242 +
2.3243 + };
2.3244 +
2.3245 +} //END OF NAMESPACE LEMON
2.3246 +
2.3247 +#endif //LEMON_MAX_MATCHING_H
3.1 --- a/lemon/max_matching.h Fri Apr 17 09:54:14 2009 +0200
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,3244 +0,0 @@
3.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
3.5 - *
3.6 - * This file is a part of LEMON, a generic C++ optimization library.
3.7 - *
3.8 - * Copyright (C) 2003-2009
3.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
3.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
3.11 - *
3.12 - * Permission to use, modify and distribute this software is granted
3.13 - * provided that this copyright notice appears in all copies. For
3.14 - * precise terms see the accompanying LICENSE file.
3.15 - *
3.16 - * This software is provided "AS IS" with no warranty of any kind,
3.17 - * express or implied, and with no claim as to its suitability for any
3.18 - * purpose.
3.19 - *
3.20 - */
3.21 -
3.22 -#ifndef LEMON_MAX_MATCHING_H
3.23 -#define LEMON_MAX_MATCHING_H
3.24 -
3.25 -#include <vector>
3.26 -#include <queue>
3.27 -#include <set>
3.28 -#include <limits>
3.29 -
3.30 -#include <lemon/core.h>
3.31 -#include <lemon/unionfind.h>
3.32 -#include <lemon/bin_heap.h>
3.33 -#include <lemon/maps.h>
3.34 -
3.35 -///\ingroup matching
3.36 -///\file
3.37 -///\brief Maximum matching algorithms in general graphs.
3.38 -
3.39 -namespace lemon {
3.40 -
3.41 - /// \ingroup matching
3.42 - ///
3.43 - /// \brief Maximum cardinality matching in general graphs
3.44 - ///
3.45 - /// This class implements Edmonds' alternating forest matching algorithm
3.46 - /// for finding a maximum cardinality matching in a general undirected graph.
3.47 - /// It can be started from an arbitrary initial matching
3.48 - /// (the default is the empty one).
3.49 - ///
3.50 - /// The dual solution of the problem is a map of the nodes to
3.51 - /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
3.52 - /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
3.53 - /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
3.54 - /// with factor-critical components, the nodes in \c ODD/A form the
3.55 - /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
3.56 - /// a perfect matching. The number of the factor-critical components
3.57 - /// minus the number of barrier nodes is a lower bound on the
3.58 - /// unmatched nodes, and the matching is optimal if and only if this bound is
3.59 - /// tight. This decomposition can be obtained using \ref status() or
3.60 - /// \ref statusMap() after running the algorithm.
3.61 - ///
3.62 - /// \tparam GR The undirected graph type the algorithm runs on.
3.63 - template <typename GR>
3.64 - class MaxMatching {
3.65 - public:
3.66 -
3.67 - /// The graph type of the algorithm
3.68 - typedef GR Graph;
3.69 - /// The type of the matching map
3.70 - typedef typename Graph::template NodeMap<typename Graph::Arc>
3.71 - MatchingMap;
3.72 -
3.73 - ///\brief Status constants for Gallai-Edmonds decomposition.
3.74 - ///
3.75 - ///These constants are used for indicating the Gallai-Edmonds
3.76 - ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
3.77 - ///induce a subgraph with factor-critical components, the nodes with
3.78 - ///status \c ODD (or \c A) form the canonical barrier, and the nodes
3.79 - ///with status \c MATCHED (or \c C) induce a subgraph having a
3.80 - ///perfect matching.
3.81 - enum Status {
3.82 - EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.)
3.83 - D = 1,
3.84 - MATCHED = 0, ///< = 0. (\c C is an alias for \c MATCHED.)
3.85 - C = 0,
3.86 - ODD = -1, ///< = -1. (\c A is an alias for \c ODD.)
3.87 - A = -1,
3.88 - UNMATCHED = -2 ///< = -2.
3.89 - };
3.90 -
3.91 - /// The type of the status map
3.92 - typedef typename Graph::template NodeMap<Status> StatusMap;
3.93 -
3.94 - private:
3.95 -
3.96 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
3.97 -
3.98 - typedef UnionFindEnum<IntNodeMap> BlossomSet;
3.99 - typedef ExtendFindEnum<IntNodeMap> TreeSet;
3.100 - typedef RangeMap<Node> NodeIntMap;
3.101 - typedef MatchingMap EarMap;
3.102 - typedef std::vector<Node> NodeQueue;
3.103 -
3.104 - const Graph& _graph;
3.105 - MatchingMap* _matching;
3.106 - StatusMap* _status;
3.107 -
3.108 - EarMap* _ear;
3.109 -
3.110 - IntNodeMap* _blossom_set_index;
3.111 - BlossomSet* _blossom_set;
3.112 - NodeIntMap* _blossom_rep;
3.113 -
3.114 - IntNodeMap* _tree_set_index;
3.115 - TreeSet* _tree_set;
3.116 -
3.117 - NodeQueue _node_queue;
3.118 - int _process, _postpone, _last;
3.119 -
3.120 - int _node_num;
3.121 -
3.122 - private:
3.123 -
3.124 - void createStructures() {
3.125 - _node_num = countNodes(_graph);
3.126 - if (!_matching) {
3.127 - _matching = new MatchingMap(_graph);
3.128 - }
3.129 - if (!_status) {
3.130 - _status = new StatusMap(_graph);
3.131 - }
3.132 - if (!_ear) {
3.133 - _ear = new EarMap(_graph);
3.134 - }
3.135 - if (!_blossom_set) {
3.136 - _blossom_set_index = new IntNodeMap(_graph);
3.137 - _blossom_set = new BlossomSet(*_blossom_set_index);
3.138 - }
3.139 - if (!_blossom_rep) {
3.140 - _blossom_rep = new NodeIntMap(_node_num);
3.141 - }
3.142 - if (!_tree_set) {
3.143 - _tree_set_index = new IntNodeMap(_graph);
3.144 - _tree_set = new TreeSet(*_tree_set_index);
3.145 - }
3.146 - _node_queue.resize(_node_num);
3.147 - }
3.148 -
3.149 - void destroyStructures() {
3.150 - if (_matching) {
3.151 - delete _matching;
3.152 - }
3.153 - if (_status) {
3.154 - delete _status;
3.155 - }
3.156 - if (_ear) {
3.157 - delete _ear;
3.158 - }
3.159 - if (_blossom_set) {
3.160 - delete _blossom_set;
3.161 - delete _blossom_set_index;
3.162 - }
3.163 - if (_blossom_rep) {
3.164 - delete _blossom_rep;
3.165 - }
3.166 - if (_tree_set) {
3.167 - delete _tree_set_index;
3.168 - delete _tree_set;
3.169 - }
3.170 - }
3.171 -
3.172 - void processDense(const Node& n) {
3.173 - _process = _postpone = _last = 0;
3.174 - _node_queue[_last++] = n;
3.175 -
3.176 - while (_process != _last) {
3.177 - Node u = _node_queue[_process++];
3.178 - for (OutArcIt a(_graph, u); a != INVALID; ++a) {
3.179 - Node v = _graph.target(a);
3.180 - if ((*_status)[v] == MATCHED) {
3.181 - extendOnArc(a);
3.182 - } else if ((*_status)[v] == UNMATCHED) {
3.183 - augmentOnArc(a);
3.184 - return;
3.185 - }
3.186 - }
3.187 - }
3.188 -
3.189 - while (_postpone != _last) {
3.190 - Node u = _node_queue[_postpone++];
3.191 -
3.192 - for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
3.193 - Node v = _graph.target(a);
3.194 -
3.195 - if ((*_status)[v] == EVEN) {
3.196 - if (_blossom_set->find(u) != _blossom_set->find(v)) {
3.197 - shrinkOnEdge(a);
3.198 - }
3.199 - }
3.200 -
3.201 - while (_process != _last) {
3.202 - Node w = _node_queue[_process++];
3.203 - for (OutArcIt b(_graph, w); b != INVALID; ++b) {
3.204 - Node x = _graph.target(b);
3.205 - if ((*_status)[x] == MATCHED) {
3.206 - extendOnArc(b);
3.207 - } else if ((*_status)[x] == UNMATCHED) {
3.208 - augmentOnArc(b);
3.209 - return;
3.210 - }
3.211 - }
3.212 - }
3.213 - }
3.214 - }
3.215 - }
3.216 -
3.217 - void processSparse(const Node& n) {
3.218 - _process = _last = 0;
3.219 - _node_queue[_last++] = n;
3.220 - while (_process != _last) {
3.221 - Node u = _node_queue[_process++];
3.222 - for (OutArcIt a(_graph, u); a != INVALID; ++a) {
3.223 - Node v = _graph.target(a);
3.224 -
3.225 - if ((*_status)[v] == EVEN) {
3.226 - if (_blossom_set->find(u) != _blossom_set->find(v)) {
3.227 - shrinkOnEdge(a);
3.228 - }
3.229 - } else if ((*_status)[v] == MATCHED) {
3.230 - extendOnArc(a);
3.231 - } else if ((*_status)[v] == UNMATCHED) {
3.232 - augmentOnArc(a);
3.233 - return;
3.234 - }
3.235 - }
3.236 - }
3.237 - }
3.238 -
3.239 - void shrinkOnEdge(const Edge& e) {
3.240 - Node nca = INVALID;
3.241 -
3.242 - {
3.243 - std::set<Node> left_set, right_set;
3.244 -
3.245 - Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
3.246 - left_set.insert(left);
3.247 -
3.248 - Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
3.249 - right_set.insert(right);
3.250 -
3.251 - while (true) {
3.252 - if ((*_matching)[left] == INVALID) break;
3.253 - left = _graph.target((*_matching)[left]);
3.254 - left = (*_blossom_rep)[_blossom_set->
3.255 - find(_graph.target((*_ear)[left]))];
3.256 - if (right_set.find(left) != right_set.end()) {
3.257 - nca = left;
3.258 - break;
3.259 - }
3.260 - left_set.insert(left);
3.261 -
3.262 - if ((*_matching)[right] == INVALID) break;
3.263 - right = _graph.target((*_matching)[right]);
3.264 - right = (*_blossom_rep)[_blossom_set->
3.265 - find(_graph.target((*_ear)[right]))];
3.266 - if (left_set.find(right) != left_set.end()) {
3.267 - nca = right;
3.268 - break;
3.269 - }
3.270 - right_set.insert(right);
3.271 - }
3.272 -
3.273 - if (nca == INVALID) {
3.274 - if ((*_matching)[left] == INVALID) {
3.275 - nca = right;
3.276 - while (left_set.find(nca) == left_set.end()) {
3.277 - nca = _graph.target((*_matching)[nca]);
3.278 - nca =(*_blossom_rep)[_blossom_set->
3.279 - find(_graph.target((*_ear)[nca]))];
3.280 - }
3.281 - } else {
3.282 - nca = left;
3.283 - while (right_set.find(nca) == right_set.end()) {
3.284 - nca = _graph.target((*_matching)[nca]);
3.285 - nca = (*_blossom_rep)[_blossom_set->
3.286 - find(_graph.target((*_ear)[nca]))];
3.287 - }
3.288 - }
3.289 - }
3.290 - }
3.291 -
3.292 - {
3.293 -
3.294 - Node node = _graph.u(e);
3.295 - Arc arc = _graph.direct(e, true);
3.296 - Node base = (*_blossom_rep)[_blossom_set->find(node)];
3.297 -
3.298 - while (base != nca) {
3.299 - (*_ear)[node] = arc;
3.300 -
3.301 - Node n = node;
3.302 - while (n != base) {
3.303 - n = _graph.target((*_matching)[n]);
3.304 - Arc a = (*_ear)[n];
3.305 - n = _graph.target(a);
3.306 - (*_ear)[n] = _graph.oppositeArc(a);
3.307 - }
3.308 - node = _graph.target((*_matching)[base]);
3.309 - _tree_set->erase(base);
3.310 - _tree_set->erase(node);
3.311 - _blossom_set->insert(node, _blossom_set->find(base));
3.312 - (*_status)[node] = EVEN;
3.313 - _node_queue[_last++] = node;
3.314 - arc = _graph.oppositeArc((*_ear)[node]);
3.315 - node = _graph.target((*_ear)[node]);
3.316 - base = (*_blossom_rep)[_blossom_set->find(node)];
3.317 - _blossom_set->join(_graph.target(arc), base);
3.318 - }
3.319 - }
3.320 -
3.321 - (*_blossom_rep)[_blossom_set->find(nca)] = nca;
3.322 -
3.323 - {
3.324 -
3.325 - Node node = _graph.v(e);
3.326 - Arc arc = _graph.direct(e, false);
3.327 - Node base = (*_blossom_rep)[_blossom_set->find(node)];
3.328 -
3.329 - while (base != nca) {
3.330 - (*_ear)[node] = arc;
3.331 -
3.332 - Node n = node;
3.333 - while (n != base) {
3.334 - n = _graph.target((*_matching)[n]);
3.335 - Arc a = (*_ear)[n];
3.336 - n = _graph.target(a);
3.337 - (*_ear)[n] = _graph.oppositeArc(a);
3.338 - }
3.339 - node = _graph.target((*_matching)[base]);
3.340 - _tree_set->erase(base);
3.341 - _tree_set->erase(node);
3.342 - _blossom_set->insert(node, _blossom_set->find(base));
3.343 - (*_status)[node] = EVEN;
3.344 - _node_queue[_last++] = node;
3.345 - arc = _graph.oppositeArc((*_ear)[node]);
3.346 - node = _graph.target((*_ear)[node]);
3.347 - base = (*_blossom_rep)[_blossom_set->find(node)];
3.348 - _blossom_set->join(_graph.target(arc), base);
3.349 - }
3.350 - }
3.351 -
3.352 - (*_blossom_rep)[_blossom_set->find(nca)] = nca;
3.353 - }
3.354 -
3.355 - void extendOnArc(const Arc& a) {
3.356 - Node base = _graph.source(a);
3.357 - Node odd = _graph.target(a);
3.358 -
3.359 - (*_ear)[odd] = _graph.oppositeArc(a);
3.360 - Node even = _graph.target((*_matching)[odd]);
3.361 - (*_blossom_rep)[_blossom_set->insert(even)] = even;
3.362 - (*_status)[odd] = ODD;
3.363 - (*_status)[even] = EVEN;
3.364 - int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
3.365 - _tree_set->insert(odd, tree);
3.366 - _tree_set->insert(even, tree);
3.367 - _node_queue[_last++] = even;
3.368 -
3.369 - }
3.370 -
3.371 - void augmentOnArc(const Arc& a) {
3.372 - Node even = _graph.source(a);
3.373 - Node odd = _graph.target(a);
3.374 -
3.375 - int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
3.376 -
3.377 - (*_matching)[odd] = _graph.oppositeArc(a);
3.378 - (*_status)[odd] = MATCHED;
3.379 -
3.380 - Arc arc = (*_matching)[even];
3.381 - (*_matching)[even] = a;
3.382 -
3.383 - while (arc != INVALID) {
3.384 - odd = _graph.target(arc);
3.385 - arc = (*_ear)[odd];
3.386 - even = _graph.target(arc);
3.387 - (*_matching)[odd] = arc;
3.388 - arc = (*_matching)[even];
3.389 - (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
3.390 - }
3.391 -
3.392 - for (typename TreeSet::ItemIt it(*_tree_set, tree);
3.393 - it != INVALID; ++it) {
3.394 - if ((*_status)[it] == ODD) {
3.395 - (*_status)[it] = MATCHED;
3.396 - } else {
3.397 - int blossom = _blossom_set->find(it);
3.398 - for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
3.399 - jt != INVALID; ++jt) {
3.400 - (*_status)[jt] = MATCHED;
3.401 - }
3.402 - _blossom_set->eraseClass(blossom);
3.403 - }
3.404 - }
3.405 - _tree_set->eraseClass(tree);
3.406 -
3.407 - }
3.408 -
3.409 - public:
3.410 -
3.411 - /// \brief Constructor
3.412 - ///
3.413 - /// Constructor.
3.414 - MaxMatching(const Graph& graph)
3.415 - : _graph(graph), _matching(0), _status(0), _ear(0),
3.416 - _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
3.417 - _tree_set_index(0), _tree_set(0) {}
3.418 -
3.419 - ~MaxMatching() {
3.420 - destroyStructures();
3.421 - }
3.422 -
3.423 - /// \name Execution Control
3.424 - /// The simplest way to execute the algorithm is to use the
3.425 - /// \c run() member function.\n
3.426 - /// If you need better control on the execution, you have to call
3.427 - /// one of the functions \ref init(), \ref greedyInit() or
3.428 - /// \ref matchingInit() first, then you can start the algorithm with
3.429 - /// \ref startSparse() or \ref startDense().
3.430 -
3.431 - ///@{
3.432 -
3.433 - /// \brief Set the initial matching to the empty matching.
3.434 - ///
3.435 - /// This function sets the initial matching to the empty matching.
3.436 - void init() {
3.437 - createStructures();
3.438 - for(NodeIt n(_graph); n != INVALID; ++n) {
3.439 - (*_matching)[n] = INVALID;
3.440 - (*_status)[n] = UNMATCHED;
3.441 - }
3.442 - }
3.443 -
3.444 - /// \brief Find an initial matching in a greedy way.
3.445 - ///
3.446 - /// This function finds an initial matching in a greedy way.
3.447 - void greedyInit() {
3.448 - createStructures();
3.449 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.450 - (*_matching)[n] = INVALID;
3.451 - (*_status)[n] = UNMATCHED;
3.452 - }
3.453 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.454 - if ((*_matching)[n] == INVALID) {
3.455 - for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
3.456 - Node v = _graph.target(a);
3.457 - if ((*_matching)[v] == INVALID && v != n) {
3.458 - (*_matching)[n] = a;
3.459 - (*_status)[n] = MATCHED;
3.460 - (*_matching)[v] = _graph.oppositeArc(a);
3.461 - (*_status)[v] = MATCHED;
3.462 - break;
3.463 - }
3.464 - }
3.465 - }
3.466 - }
3.467 - }
3.468 -
3.469 -
3.470 - /// \brief Initialize the matching from a map.
3.471 - ///
3.472 - /// This function initializes the matching from a \c bool valued edge
3.473 - /// map. This map should have the property that there are no two incident
3.474 - /// edges with \c true value, i.e. it really contains a matching.
3.475 - /// \return \c true if the map contains a matching.
3.476 - template <typename MatchingMap>
3.477 - bool matchingInit(const MatchingMap& matching) {
3.478 - createStructures();
3.479 -
3.480 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.481 - (*_matching)[n] = INVALID;
3.482 - (*_status)[n] = UNMATCHED;
3.483 - }
3.484 - for(EdgeIt e(_graph); e!=INVALID; ++e) {
3.485 - if (matching[e]) {
3.486 -
3.487 - Node u = _graph.u(e);
3.488 - if ((*_matching)[u] != INVALID) return false;
3.489 - (*_matching)[u] = _graph.direct(e, true);
3.490 - (*_status)[u] = MATCHED;
3.491 -
3.492 - Node v = _graph.v(e);
3.493 - if ((*_matching)[v] != INVALID) return false;
3.494 - (*_matching)[v] = _graph.direct(e, false);
3.495 - (*_status)[v] = MATCHED;
3.496 - }
3.497 - }
3.498 - return true;
3.499 - }
3.500 -
3.501 - /// \brief Start Edmonds' algorithm
3.502 - ///
3.503 - /// This function runs the original Edmonds' algorithm.
3.504 - ///
3.505 - /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
3.506 - /// called before using this function.
3.507 - void startSparse() {
3.508 - for(NodeIt n(_graph); n != INVALID; ++n) {
3.509 - if ((*_status)[n] == UNMATCHED) {
3.510 - (*_blossom_rep)[_blossom_set->insert(n)] = n;
3.511 - _tree_set->insert(n);
3.512 - (*_status)[n] = EVEN;
3.513 - processSparse(n);
3.514 - }
3.515 - }
3.516 - }
3.517 -
3.518 - /// \brief Start Edmonds' algorithm with a heuristic improvement
3.519 - /// for dense graphs
3.520 - ///
3.521 - /// This function runs Edmonds' algorithm with a heuristic of postponing
3.522 - /// shrinks, therefore resulting in a faster algorithm for dense graphs.
3.523 - ///
3.524 - /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
3.525 - /// called before using this function.
3.526 - void startDense() {
3.527 - for(NodeIt n(_graph); n != INVALID; ++n) {
3.528 - if ((*_status)[n] == UNMATCHED) {
3.529 - (*_blossom_rep)[_blossom_set->insert(n)] = n;
3.530 - _tree_set->insert(n);
3.531 - (*_status)[n] = EVEN;
3.532 - processDense(n);
3.533 - }
3.534 - }
3.535 - }
3.536 -
3.537 -
3.538 - /// \brief Run Edmonds' algorithm
3.539 - ///
3.540 - /// This function runs Edmonds' algorithm. An additional heuristic of
3.541 - /// postponing shrinks is used for relatively dense graphs
3.542 - /// (for which <tt>m>=2*n</tt> holds).
3.543 - void run() {
3.544 - if (countEdges(_graph) < 2 * countNodes(_graph)) {
3.545 - greedyInit();
3.546 - startSparse();
3.547 - } else {
3.548 - init();
3.549 - startDense();
3.550 - }
3.551 - }
3.552 -
3.553 - /// @}
3.554 -
3.555 - /// \name Primal Solution
3.556 - /// Functions to get the primal solution, i.e. the maximum matching.
3.557 -
3.558 - /// @{
3.559 -
3.560 - /// \brief Return the size (cardinality) of the matching.
3.561 - ///
3.562 - /// This function returns the size (cardinality) of the current matching.
3.563 - /// After run() it returns the size of the maximum matching in the graph.
3.564 - int matchingSize() const {
3.565 - int size = 0;
3.566 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.567 - if ((*_matching)[n] != INVALID) {
3.568 - ++size;
3.569 - }
3.570 - }
3.571 - return size / 2;
3.572 - }
3.573 -
3.574 - /// \brief Return \c true if the given edge is in the matching.
3.575 - ///
3.576 - /// This function returns \c true if the given edge is in the current
3.577 - /// matching.
3.578 - bool matching(const Edge& edge) const {
3.579 - return edge == (*_matching)[_graph.u(edge)];
3.580 - }
3.581 -
3.582 - /// \brief Return the matching arc (or edge) incident to the given node.
3.583 - ///
3.584 - /// This function returns the matching arc (or edge) incident to the
3.585 - /// given node in the current matching or \c INVALID if the node is
3.586 - /// not covered by the matching.
3.587 - Arc matching(const Node& n) const {
3.588 - return (*_matching)[n];
3.589 - }
3.590 -
3.591 - /// \brief Return a const reference to the matching map.
3.592 - ///
3.593 - /// This function returns a const reference to a node map that stores
3.594 - /// the matching arc (or edge) incident to each node.
3.595 - const MatchingMap& matchingMap() const {
3.596 - return *_matching;
3.597 - }
3.598 -
3.599 - /// \brief Return the mate of the given node.
3.600 - ///
3.601 - /// This function returns the mate of the given node in the current
3.602 - /// matching or \c INVALID if the node is not covered by the matching.
3.603 - Node mate(const Node& n) const {
3.604 - return (*_matching)[n] != INVALID ?
3.605 - _graph.target((*_matching)[n]) : INVALID;
3.606 - }
3.607 -
3.608 - /// @}
3.609 -
3.610 - /// \name Dual Solution
3.611 - /// Functions to get the dual solution, i.e. the Gallai-Edmonds
3.612 - /// decomposition.
3.613 -
3.614 - /// @{
3.615 -
3.616 - /// \brief Return the status of the given node in the Edmonds-Gallai
3.617 - /// decomposition.
3.618 - ///
3.619 - /// This function returns the \ref Status "status" of the given node
3.620 - /// in the Edmonds-Gallai decomposition.
3.621 - Status status(const Node& n) const {
3.622 - return (*_status)[n];
3.623 - }
3.624 -
3.625 - /// \brief Return a const reference to the status map, which stores
3.626 - /// the Edmonds-Gallai decomposition.
3.627 - ///
3.628 - /// This function returns a const reference to a node map that stores the
3.629 - /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
3.630 - const StatusMap& statusMap() const {
3.631 - return *_status;
3.632 - }
3.633 -
3.634 - /// \brief Return \c true if the given node is in the barrier.
3.635 - ///
3.636 - /// This function returns \c true if the given node is in the barrier.
3.637 - bool barrier(const Node& n) const {
3.638 - return (*_status)[n] == ODD;
3.639 - }
3.640 -
3.641 - /// @}
3.642 -
3.643 - };
3.644 -
3.645 - /// \ingroup matching
3.646 - ///
3.647 - /// \brief Weighted matching in general graphs
3.648 - ///
3.649 - /// This class provides an efficient implementation of Edmond's
3.650 - /// maximum weighted matching algorithm. The implementation is based
3.651 - /// on extensive use of priority queues and provides
3.652 - /// \f$O(nm\log n)\f$ time complexity.
3.653 - ///
3.654 - /// The maximum weighted matching problem is to find a subset of the
3.655 - /// edges in an undirected graph with maximum overall weight for which
3.656 - /// each node has at most one incident edge.
3.657 - /// It can be formulated with the following linear program.
3.658 - /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
3.659 - /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
3.660 - \quad \forall B\in\mathcal{O}\f] */
3.661 - /// \f[x_e \ge 0\quad \forall e\in E\f]
3.662 - /// \f[\max \sum_{e\in E}x_ew_e\f]
3.663 - /// where \f$\delta(X)\f$ is the set of edges incident to a node in
3.664 - /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
3.665 - /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
3.666 - /// subsets of the nodes.
3.667 - ///
3.668 - /// The algorithm calculates an optimal matching and a proof of the
3.669 - /// optimality. The solution of the dual problem can be used to check
3.670 - /// the result of the algorithm. The dual linear problem is the
3.671 - /// following.
3.672 - /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
3.673 - z_B \ge w_{uv} \quad \forall uv\in E\f] */
3.674 - /// \f[y_u \ge 0 \quad \forall u \in V\f]
3.675 - /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
3.676 - /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
3.677 - \frac{\vert B \vert - 1}{2}z_B\f] */
3.678 - ///
3.679 - /// The algorithm can be executed with the run() function.
3.680 - /// After it the matching (the primal solution) and the dual solution
3.681 - /// can be obtained using the query functions and the
3.682 - /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
3.683 - /// which is able to iterate on the nodes of a blossom.
3.684 - /// If the value type is integer, then the dual solution is multiplied
3.685 - /// by \ref MaxWeightedMatching::dualScale "4".
3.686 - ///
3.687 - /// \tparam GR The undirected graph type the algorithm runs on.
3.688 - /// \tparam WM The type edge weight map. The default type is
3.689 - /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
3.690 -#ifdef DOXYGEN
3.691 - template <typename GR, typename WM>
3.692 -#else
3.693 - template <typename GR,
3.694 - typename WM = typename GR::template EdgeMap<int> >
3.695 -#endif
3.696 - class MaxWeightedMatching {
3.697 - public:
3.698 -
3.699 - /// The graph type of the algorithm
3.700 - typedef GR Graph;
3.701 - /// The type of the edge weight map
3.702 - typedef WM WeightMap;
3.703 - /// The value type of the edge weights
3.704 - typedef typename WeightMap::Value Value;
3.705 -
3.706 - /// The type of the matching map
3.707 - typedef typename Graph::template NodeMap<typename Graph::Arc>
3.708 - MatchingMap;
3.709 -
3.710 - /// \brief Scaling factor for dual solution
3.711 - ///
3.712 - /// Scaling factor for dual solution. It is equal to 4 or 1
3.713 - /// according to the value type.
3.714 - static const int dualScale =
3.715 - std::numeric_limits<Value>::is_integer ? 4 : 1;
3.716 -
3.717 - private:
3.718 -
3.719 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
3.720 -
3.721 - typedef typename Graph::template NodeMap<Value> NodePotential;
3.722 - typedef std::vector<Node> BlossomNodeList;
3.723 -
3.724 - struct BlossomVariable {
3.725 - int begin, end;
3.726 - Value value;
3.727 -
3.728 - BlossomVariable(int _begin, int _end, Value _value)
3.729 - : begin(_begin), end(_end), value(_value) {}
3.730 -
3.731 - };
3.732 -
3.733 - typedef std::vector<BlossomVariable> BlossomPotential;
3.734 -
3.735 - const Graph& _graph;
3.736 - const WeightMap& _weight;
3.737 -
3.738 - MatchingMap* _matching;
3.739 -
3.740 - NodePotential* _node_potential;
3.741 -
3.742 - BlossomPotential _blossom_potential;
3.743 - BlossomNodeList _blossom_node_list;
3.744 -
3.745 - int _node_num;
3.746 - int _blossom_num;
3.747 -
3.748 - typedef RangeMap<int> IntIntMap;
3.749 -
3.750 - enum Status {
3.751 - EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
3.752 - };
3.753 -
3.754 - typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
3.755 - struct BlossomData {
3.756 - int tree;
3.757 - Status status;
3.758 - Arc pred, next;
3.759 - Value pot, offset;
3.760 - Node base;
3.761 - };
3.762 -
3.763 - IntNodeMap *_blossom_index;
3.764 - BlossomSet *_blossom_set;
3.765 - RangeMap<BlossomData>* _blossom_data;
3.766 -
3.767 - IntNodeMap *_node_index;
3.768 - IntArcMap *_node_heap_index;
3.769 -
3.770 - struct NodeData {
3.771 -
3.772 - NodeData(IntArcMap& node_heap_index)
3.773 - : heap(node_heap_index) {}
3.774 -
3.775 - int blossom;
3.776 - Value pot;
3.777 - BinHeap<Value, IntArcMap> heap;
3.778 - std::map<int, Arc> heap_index;
3.779 -
3.780 - int tree;
3.781 - };
3.782 -
3.783 - RangeMap<NodeData>* _node_data;
3.784 -
3.785 - typedef ExtendFindEnum<IntIntMap> TreeSet;
3.786 -
3.787 - IntIntMap *_tree_set_index;
3.788 - TreeSet *_tree_set;
3.789 -
3.790 - IntNodeMap *_delta1_index;
3.791 - BinHeap<Value, IntNodeMap> *_delta1;
3.792 -
3.793 - IntIntMap *_delta2_index;
3.794 - BinHeap<Value, IntIntMap> *_delta2;
3.795 -
3.796 - IntEdgeMap *_delta3_index;
3.797 - BinHeap<Value, IntEdgeMap> *_delta3;
3.798 -
3.799 - IntIntMap *_delta4_index;
3.800 - BinHeap<Value, IntIntMap> *_delta4;
3.801 -
3.802 - Value _delta_sum;
3.803 -
3.804 - void createStructures() {
3.805 - _node_num = countNodes(_graph);
3.806 - _blossom_num = _node_num * 3 / 2;
3.807 -
3.808 - if (!_matching) {
3.809 - _matching = new MatchingMap(_graph);
3.810 - }
3.811 - if (!_node_potential) {
3.812 - _node_potential = new NodePotential(_graph);
3.813 - }
3.814 - if (!_blossom_set) {
3.815 - _blossom_index = new IntNodeMap(_graph);
3.816 - _blossom_set = new BlossomSet(*_blossom_index);
3.817 - _blossom_data = new RangeMap<BlossomData>(_blossom_num);
3.818 - }
3.819 -
3.820 - if (!_node_index) {
3.821 - _node_index = new IntNodeMap(_graph);
3.822 - _node_heap_index = new IntArcMap(_graph);
3.823 - _node_data = new RangeMap<NodeData>(_node_num,
3.824 - NodeData(*_node_heap_index));
3.825 - }
3.826 -
3.827 - if (!_tree_set) {
3.828 - _tree_set_index = new IntIntMap(_blossom_num);
3.829 - _tree_set = new TreeSet(*_tree_set_index);
3.830 - }
3.831 - if (!_delta1) {
3.832 - _delta1_index = new IntNodeMap(_graph);
3.833 - _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
3.834 - }
3.835 - if (!_delta2) {
3.836 - _delta2_index = new IntIntMap(_blossom_num);
3.837 - _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
3.838 - }
3.839 - if (!_delta3) {
3.840 - _delta3_index = new IntEdgeMap(_graph);
3.841 - _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
3.842 - }
3.843 - if (!_delta4) {
3.844 - _delta4_index = new IntIntMap(_blossom_num);
3.845 - _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
3.846 - }
3.847 - }
3.848 -
3.849 - void destroyStructures() {
3.850 - _node_num = countNodes(_graph);
3.851 - _blossom_num = _node_num * 3 / 2;
3.852 -
3.853 - if (_matching) {
3.854 - delete _matching;
3.855 - }
3.856 - if (_node_potential) {
3.857 - delete _node_potential;
3.858 - }
3.859 - if (_blossom_set) {
3.860 - delete _blossom_index;
3.861 - delete _blossom_set;
3.862 - delete _blossom_data;
3.863 - }
3.864 -
3.865 - if (_node_index) {
3.866 - delete _node_index;
3.867 - delete _node_heap_index;
3.868 - delete _node_data;
3.869 - }
3.870 -
3.871 - if (_tree_set) {
3.872 - delete _tree_set_index;
3.873 - delete _tree_set;
3.874 - }
3.875 - if (_delta1) {
3.876 - delete _delta1_index;
3.877 - delete _delta1;
3.878 - }
3.879 - if (_delta2) {
3.880 - delete _delta2_index;
3.881 - delete _delta2;
3.882 - }
3.883 - if (_delta3) {
3.884 - delete _delta3_index;
3.885 - delete _delta3;
3.886 - }
3.887 - if (_delta4) {
3.888 - delete _delta4_index;
3.889 - delete _delta4;
3.890 - }
3.891 - }
3.892 -
3.893 - void matchedToEven(int blossom, int tree) {
3.894 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
3.895 - _delta2->erase(blossom);
3.896 - }
3.897 -
3.898 - if (!_blossom_set->trivial(blossom)) {
3.899 - (*_blossom_data)[blossom].pot -=
3.900 - 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
3.901 - }
3.902 -
3.903 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.904 - n != INVALID; ++n) {
3.905 -
3.906 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
3.907 - int ni = (*_node_index)[n];
3.908 -
3.909 - (*_node_data)[ni].heap.clear();
3.910 - (*_node_data)[ni].heap_index.clear();
3.911 -
3.912 - (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
3.913 -
3.914 - _delta1->push(n, (*_node_data)[ni].pot);
3.915 -
3.916 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
3.917 - Node v = _graph.source(e);
3.918 - int vb = _blossom_set->find(v);
3.919 - int vi = (*_node_index)[v];
3.920 -
3.921 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.922 - dualScale * _weight[e];
3.923 -
3.924 - if ((*_blossom_data)[vb].status == EVEN) {
3.925 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
3.926 - _delta3->push(e, rw / 2);
3.927 - }
3.928 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
3.929 - if (_delta3->state(e) != _delta3->IN_HEAP) {
3.930 - _delta3->push(e, rw);
3.931 - }
3.932 - } else {
3.933 - typename std::map<int, Arc>::iterator it =
3.934 - (*_node_data)[vi].heap_index.find(tree);
3.935 -
3.936 - if (it != (*_node_data)[vi].heap_index.end()) {
3.937 - if ((*_node_data)[vi].heap[it->second] > rw) {
3.938 - (*_node_data)[vi].heap.replace(it->second, e);
3.939 - (*_node_data)[vi].heap.decrease(e, rw);
3.940 - it->second = e;
3.941 - }
3.942 - } else {
3.943 - (*_node_data)[vi].heap.push(e, rw);
3.944 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
3.945 - }
3.946 -
3.947 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
3.948 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
3.949 -
3.950 - if ((*_blossom_data)[vb].status == MATCHED) {
3.951 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
3.952 - _delta2->push(vb, _blossom_set->classPrio(vb) -
3.953 - (*_blossom_data)[vb].offset);
3.954 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
3.955 - (*_blossom_data)[vb].offset){
3.956 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
3.957 - (*_blossom_data)[vb].offset);
3.958 - }
3.959 - }
3.960 - }
3.961 - }
3.962 - }
3.963 - }
3.964 - (*_blossom_data)[blossom].offset = 0;
3.965 - }
3.966 -
3.967 - void matchedToOdd(int blossom) {
3.968 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
3.969 - _delta2->erase(blossom);
3.970 - }
3.971 - (*_blossom_data)[blossom].offset += _delta_sum;
3.972 - if (!_blossom_set->trivial(blossom)) {
3.973 - _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
3.974 - (*_blossom_data)[blossom].offset);
3.975 - }
3.976 - }
3.977 -
3.978 - void evenToMatched(int blossom, int tree) {
3.979 - if (!_blossom_set->trivial(blossom)) {
3.980 - (*_blossom_data)[blossom].pot += 2 * _delta_sum;
3.981 - }
3.982 -
3.983 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.984 - n != INVALID; ++n) {
3.985 - int ni = (*_node_index)[n];
3.986 - (*_node_data)[ni].pot -= _delta_sum;
3.987 -
3.988 - _delta1->erase(n);
3.989 -
3.990 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
3.991 - Node v = _graph.source(e);
3.992 - int vb = _blossom_set->find(v);
3.993 - int vi = (*_node_index)[v];
3.994 -
3.995 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.996 - dualScale * _weight[e];
3.997 -
3.998 - if (vb == blossom) {
3.999 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.1000 - _delta3->erase(e);
3.1001 - }
3.1002 - } else if ((*_blossom_data)[vb].status == EVEN) {
3.1003 -
3.1004 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.1005 - _delta3->erase(e);
3.1006 - }
3.1007 -
3.1008 - int vt = _tree_set->find(vb);
3.1009 -
3.1010 - if (vt != tree) {
3.1011 -
3.1012 - Arc r = _graph.oppositeArc(e);
3.1013 -
3.1014 - typename std::map<int, Arc>::iterator it =
3.1015 - (*_node_data)[ni].heap_index.find(vt);
3.1016 -
3.1017 - if (it != (*_node_data)[ni].heap_index.end()) {
3.1018 - if ((*_node_data)[ni].heap[it->second] > rw) {
3.1019 - (*_node_data)[ni].heap.replace(it->second, r);
3.1020 - (*_node_data)[ni].heap.decrease(r, rw);
3.1021 - it->second = r;
3.1022 - }
3.1023 - } else {
3.1024 - (*_node_data)[ni].heap.push(r, rw);
3.1025 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
3.1026 - }
3.1027 -
3.1028 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
3.1029 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3.1030 -
3.1031 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
3.1032 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
3.1033 - (*_blossom_data)[blossom].offset);
3.1034 - } else if ((*_delta2)[blossom] >
3.1035 - _blossom_set->classPrio(blossom) -
3.1036 - (*_blossom_data)[blossom].offset){
3.1037 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
3.1038 - (*_blossom_data)[blossom].offset);
3.1039 - }
3.1040 - }
3.1041 - }
3.1042 -
3.1043 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
3.1044 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.1045 - _delta3->erase(e);
3.1046 - }
3.1047 - } else {
3.1048 -
3.1049 - typename std::map<int, Arc>::iterator it =
3.1050 - (*_node_data)[vi].heap_index.find(tree);
3.1051 -
3.1052 - if (it != (*_node_data)[vi].heap_index.end()) {
3.1053 - (*_node_data)[vi].heap.erase(it->second);
3.1054 - (*_node_data)[vi].heap_index.erase(it);
3.1055 - if ((*_node_data)[vi].heap.empty()) {
3.1056 - _blossom_set->increase(v, std::numeric_limits<Value>::max());
3.1057 - } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
3.1058 - _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
3.1059 - }
3.1060 -
3.1061 - if ((*_blossom_data)[vb].status == MATCHED) {
3.1062 - if (_blossom_set->classPrio(vb) ==
3.1063 - std::numeric_limits<Value>::max()) {
3.1064 - _delta2->erase(vb);
3.1065 - } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
3.1066 - (*_blossom_data)[vb].offset) {
3.1067 - _delta2->increase(vb, _blossom_set->classPrio(vb) -
3.1068 - (*_blossom_data)[vb].offset);
3.1069 - }
3.1070 - }
3.1071 - }
3.1072 - }
3.1073 - }
3.1074 - }
3.1075 - }
3.1076 -
3.1077 - void oddToMatched(int blossom) {
3.1078 - (*_blossom_data)[blossom].offset -= _delta_sum;
3.1079 -
3.1080 - if (_blossom_set->classPrio(blossom) !=
3.1081 - std::numeric_limits<Value>::max()) {
3.1082 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
3.1083 - (*_blossom_data)[blossom].offset);
3.1084 - }
3.1085 -
3.1086 - if (!_blossom_set->trivial(blossom)) {
3.1087 - _delta4->erase(blossom);
3.1088 - }
3.1089 - }
3.1090 -
3.1091 - void oddToEven(int blossom, int tree) {
3.1092 - if (!_blossom_set->trivial(blossom)) {
3.1093 - _delta4->erase(blossom);
3.1094 - (*_blossom_data)[blossom].pot -=
3.1095 - 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
3.1096 - }
3.1097 -
3.1098 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.1099 - n != INVALID; ++n) {
3.1100 - int ni = (*_node_index)[n];
3.1101 -
3.1102 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
3.1103 -
3.1104 - (*_node_data)[ni].heap.clear();
3.1105 - (*_node_data)[ni].heap_index.clear();
3.1106 - (*_node_data)[ni].pot +=
3.1107 - 2 * _delta_sum - (*_blossom_data)[blossom].offset;
3.1108 -
3.1109 - _delta1->push(n, (*_node_data)[ni].pot);
3.1110 -
3.1111 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
3.1112 - Node v = _graph.source(e);
3.1113 - int vb = _blossom_set->find(v);
3.1114 - int vi = (*_node_index)[v];
3.1115 -
3.1116 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.1117 - dualScale * _weight[e];
3.1118 -
3.1119 - if ((*_blossom_data)[vb].status == EVEN) {
3.1120 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
3.1121 - _delta3->push(e, rw / 2);
3.1122 - }
3.1123 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
3.1124 - if (_delta3->state(e) != _delta3->IN_HEAP) {
3.1125 - _delta3->push(e, rw);
3.1126 - }
3.1127 - } else {
3.1128 -
3.1129 - typename std::map<int, Arc>::iterator it =
3.1130 - (*_node_data)[vi].heap_index.find(tree);
3.1131 -
3.1132 - if (it != (*_node_data)[vi].heap_index.end()) {
3.1133 - if ((*_node_data)[vi].heap[it->second] > rw) {
3.1134 - (*_node_data)[vi].heap.replace(it->second, e);
3.1135 - (*_node_data)[vi].heap.decrease(e, rw);
3.1136 - it->second = e;
3.1137 - }
3.1138 - } else {
3.1139 - (*_node_data)[vi].heap.push(e, rw);
3.1140 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
3.1141 - }
3.1142 -
3.1143 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
3.1144 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
3.1145 -
3.1146 - if ((*_blossom_data)[vb].status == MATCHED) {
3.1147 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
3.1148 - _delta2->push(vb, _blossom_set->classPrio(vb) -
3.1149 - (*_blossom_data)[vb].offset);
3.1150 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
3.1151 - (*_blossom_data)[vb].offset) {
3.1152 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
3.1153 - (*_blossom_data)[vb].offset);
3.1154 - }
3.1155 - }
3.1156 - }
3.1157 - }
3.1158 - }
3.1159 - }
3.1160 - (*_blossom_data)[blossom].offset = 0;
3.1161 - }
3.1162 -
3.1163 -
3.1164 - void matchedToUnmatched(int blossom) {
3.1165 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
3.1166 - _delta2->erase(blossom);
3.1167 - }
3.1168 -
3.1169 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.1170 - n != INVALID; ++n) {
3.1171 - int ni = (*_node_index)[n];
3.1172 -
3.1173 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
3.1174 -
3.1175 - (*_node_data)[ni].heap.clear();
3.1176 - (*_node_data)[ni].heap_index.clear();
3.1177 -
3.1178 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3.1179 - Node v = _graph.target(e);
3.1180 - int vb = _blossom_set->find(v);
3.1181 - int vi = (*_node_index)[v];
3.1182 -
3.1183 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.1184 - dualScale * _weight[e];
3.1185 -
3.1186 - if ((*_blossom_data)[vb].status == EVEN) {
3.1187 - if (_delta3->state(e) != _delta3->IN_HEAP) {
3.1188 - _delta3->push(e, rw);
3.1189 - }
3.1190 - }
3.1191 - }
3.1192 - }
3.1193 - }
3.1194 -
3.1195 - void unmatchedToMatched(int blossom) {
3.1196 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.1197 - n != INVALID; ++n) {
3.1198 - int ni = (*_node_index)[n];
3.1199 -
3.1200 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
3.1201 - Node v = _graph.source(e);
3.1202 - int vb = _blossom_set->find(v);
3.1203 - int vi = (*_node_index)[v];
3.1204 -
3.1205 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.1206 - dualScale * _weight[e];
3.1207 -
3.1208 - if (vb == blossom) {
3.1209 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.1210 - _delta3->erase(e);
3.1211 - }
3.1212 - } else if ((*_blossom_data)[vb].status == EVEN) {
3.1213 -
3.1214 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.1215 - _delta3->erase(e);
3.1216 - }
3.1217 -
3.1218 - int vt = _tree_set->find(vb);
3.1219 -
3.1220 - Arc r = _graph.oppositeArc(e);
3.1221 -
3.1222 - typename std::map<int, Arc>::iterator it =
3.1223 - (*_node_data)[ni].heap_index.find(vt);
3.1224 -
3.1225 - if (it != (*_node_data)[ni].heap_index.end()) {
3.1226 - if ((*_node_data)[ni].heap[it->second] > rw) {
3.1227 - (*_node_data)[ni].heap.replace(it->second, r);
3.1228 - (*_node_data)[ni].heap.decrease(r, rw);
3.1229 - it->second = r;
3.1230 - }
3.1231 - } else {
3.1232 - (*_node_data)[ni].heap.push(r, rw);
3.1233 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
3.1234 - }
3.1235 -
3.1236 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
3.1237 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3.1238 -
3.1239 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
3.1240 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
3.1241 - (*_blossom_data)[blossom].offset);
3.1242 - } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
3.1243 - (*_blossom_data)[blossom].offset){
3.1244 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
3.1245 - (*_blossom_data)[blossom].offset);
3.1246 - }
3.1247 - }
3.1248 -
3.1249 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
3.1250 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.1251 - _delta3->erase(e);
3.1252 - }
3.1253 - }
3.1254 - }
3.1255 - }
3.1256 - }
3.1257 -
3.1258 - void alternatePath(int even, int tree) {
3.1259 - int odd;
3.1260 -
3.1261 - evenToMatched(even, tree);
3.1262 - (*_blossom_data)[even].status = MATCHED;
3.1263 -
3.1264 - while ((*_blossom_data)[even].pred != INVALID) {
3.1265 - odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
3.1266 - (*_blossom_data)[odd].status = MATCHED;
3.1267 - oddToMatched(odd);
3.1268 - (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
3.1269 -
3.1270 - even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
3.1271 - (*_blossom_data)[even].status = MATCHED;
3.1272 - evenToMatched(even, tree);
3.1273 - (*_blossom_data)[even].next =
3.1274 - _graph.oppositeArc((*_blossom_data)[odd].pred);
3.1275 - }
3.1276 -
3.1277 - }
3.1278 -
3.1279 - void destroyTree(int tree) {
3.1280 - for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
3.1281 - if ((*_blossom_data)[b].status == EVEN) {
3.1282 - (*_blossom_data)[b].status = MATCHED;
3.1283 - evenToMatched(b, tree);
3.1284 - } else if ((*_blossom_data)[b].status == ODD) {
3.1285 - (*_blossom_data)[b].status = MATCHED;
3.1286 - oddToMatched(b);
3.1287 - }
3.1288 - }
3.1289 - _tree_set->eraseClass(tree);
3.1290 - }
3.1291 -
3.1292 -
3.1293 - void unmatchNode(const Node& node) {
3.1294 - int blossom = _blossom_set->find(node);
3.1295 - int tree = _tree_set->find(blossom);
3.1296 -
3.1297 - alternatePath(blossom, tree);
3.1298 - destroyTree(tree);
3.1299 -
3.1300 - (*_blossom_data)[blossom].status = UNMATCHED;
3.1301 - (*_blossom_data)[blossom].base = node;
3.1302 - matchedToUnmatched(blossom);
3.1303 - }
3.1304 -
3.1305 -
3.1306 - void augmentOnEdge(const Edge& edge) {
3.1307 -
3.1308 - int left = _blossom_set->find(_graph.u(edge));
3.1309 - int right = _blossom_set->find(_graph.v(edge));
3.1310 -
3.1311 - if ((*_blossom_data)[left].status == EVEN) {
3.1312 - int left_tree = _tree_set->find(left);
3.1313 - alternatePath(left, left_tree);
3.1314 - destroyTree(left_tree);
3.1315 - } else {
3.1316 - (*_blossom_data)[left].status = MATCHED;
3.1317 - unmatchedToMatched(left);
3.1318 - }
3.1319 -
3.1320 - if ((*_blossom_data)[right].status == EVEN) {
3.1321 - int right_tree = _tree_set->find(right);
3.1322 - alternatePath(right, right_tree);
3.1323 - destroyTree(right_tree);
3.1324 - } else {
3.1325 - (*_blossom_data)[right].status = MATCHED;
3.1326 - unmatchedToMatched(right);
3.1327 - }
3.1328 -
3.1329 - (*_blossom_data)[left].next = _graph.direct(edge, true);
3.1330 - (*_blossom_data)[right].next = _graph.direct(edge, false);
3.1331 - }
3.1332 -
3.1333 - void extendOnArc(const Arc& arc) {
3.1334 - int base = _blossom_set->find(_graph.target(arc));
3.1335 - int tree = _tree_set->find(base);
3.1336 -
3.1337 - int odd = _blossom_set->find(_graph.source(arc));
3.1338 - _tree_set->insert(odd, tree);
3.1339 - (*_blossom_data)[odd].status = ODD;
3.1340 - matchedToOdd(odd);
3.1341 - (*_blossom_data)[odd].pred = arc;
3.1342 -
3.1343 - int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
3.1344 - (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
3.1345 - _tree_set->insert(even, tree);
3.1346 - (*_blossom_data)[even].status = EVEN;
3.1347 - matchedToEven(even, tree);
3.1348 - }
3.1349 -
3.1350 - void shrinkOnEdge(const Edge& edge, int tree) {
3.1351 - int nca = -1;
3.1352 - std::vector<int> left_path, right_path;
3.1353 -
3.1354 - {
3.1355 - std::set<int> left_set, right_set;
3.1356 - int left = _blossom_set->find(_graph.u(edge));
3.1357 - left_path.push_back(left);
3.1358 - left_set.insert(left);
3.1359 -
3.1360 - int right = _blossom_set->find(_graph.v(edge));
3.1361 - right_path.push_back(right);
3.1362 - right_set.insert(right);
3.1363 -
3.1364 - while (true) {
3.1365 -
3.1366 - if ((*_blossom_data)[left].pred == INVALID) break;
3.1367 -
3.1368 - left =
3.1369 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
3.1370 - left_path.push_back(left);
3.1371 - left =
3.1372 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
3.1373 - left_path.push_back(left);
3.1374 -
3.1375 - left_set.insert(left);
3.1376 -
3.1377 - if (right_set.find(left) != right_set.end()) {
3.1378 - nca = left;
3.1379 - break;
3.1380 - }
3.1381 -
3.1382 - if ((*_blossom_data)[right].pred == INVALID) break;
3.1383 -
3.1384 - right =
3.1385 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
3.1386 - right_path.push_back(right);
3.1387 - right =
3.1388 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
3.1389 - right_path.push_back(right);
3.1390 -
3.1391 - right_set.insert(right);
3.1392 -
3.1393 - if (left_set.find(right) != left_set.end()) {
3.1394 - nca = right;
3.1395 - break;
3.1396 - }
3.1397 -
3.1398 - }
3.1399 -
3.1400 - if (nca == -1) {
3.1401 - if ((*_blossom_data)[left].pred == INVALID) {
3.1402 - nca = right;
3.1403 - while (left_set.find(nca) == left_set.end()) {
3.1404 - nca =
3.1405 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.1406 - right_path.push_back(nca);
3.1407 - nca =
3.1408 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.1409 - right_path.push_back(nca);
3.1410 - }
3.1411 - } else {
3.1412 - nca = left;
3.1413 - while (right_set.find(nca) == right_set.end()) {
3.1414 - nca =
3.1415 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.1416 - left_path.push_back(nca);
3.1417 - nca =
3.1418 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.1419 - left_path.push_back(nca);
3.1420 - }
3.1421 - }
3.1422 - }
3.1423 - }
3.1424 -
3.1425 - std::vector<int> subblossoms;
3.1426 - Arc prev;
3.1427 -
3.1428 - prev = _graph.direct(edge, true);
3.1429 - for (int i = 0; left_path[i] != nca; i += 2) {
3.1430 - subblossoms.push_back(left_path[i]);
3.1431 - (*_blossom_data)[left_path[i]].next = prev;
3.1432 - _tree_set->erase(left_path[i]);
3.1433 -
3.1434 - subblossoms.push_back(left_path[i + 1]);
3.1435 - (*_blossom_data)[left_path[i + 1]].status = EVEN;
3.1436 - oddToEven(left_path[i + 1], tree);
3.1437 - _tree_set->erase(left_path[i + 1]);
3.1438 - prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
3.1439 - }
3.1440 -
3.1441 - int k = 0;
3.1442 - while (right_path[k] != nca) ++k;
3.1443 -
3.1444 - subblossoms.push_back(nca);
3.1445 - (*_blossom_data)[nca].next = prev;
3.1446 -
3.1447 - for (int i = k - 2; i >= 0; i -= 2) {
3.1448 - subblossoms.push_back(right_path[i + 1]);
3.1449 - (*_blossom_data)[right_path[i + 1]].status = EVEN;
3.1450 - oddToEven(right_path[i + 1], tree);
3.1451 - _tree_set->erase(right_path[i + 1]);
3.1452 -
3.1453 - (*_blossom_data)[right_path[i + 1]].next =
3.1454 - (*_blossom_data)[right_path[i + 1]].pred;
3.1455 -
3.1456 - subblossoms.push_back(right_path[i]);
3.1457 - _tree_set->erase(right_path[i]);
3.1458 - }
3.1459 -
3.1460 - int surface =
3.1461 - _blossom_set->join(subblossoms.begin(), subblossoms.end());
3.1462 -
3.1463 - for (int i = 0; i < int(subblossoms.size()); ++i) {
3.1464 - if (!_blossom_set->trivial(subblossoms[i])) {
3.1465 - (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
3.1466 - }
3.1467 - (*_blossom_data)[subblossoms[i]].status = MATCHED;
3.1468 - }
3.1469 -
3.1470 - (*_blossom_data)[surface].pot = -2 * _delta_sum;
3.1471 - (*_blossom_data)[surface].offset = 0;
3.1472 - (*_blossom_data)[surface].status = EVEN;
3.1473 - (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
3.1474 - (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
3.1475 -
3.1476 - _tree_set->insert(surface, tree);
3.1477 - _tree_set->erase(nca);
3.1478 - }
3.1479 -
3.1480 - void splitBlossom(int blossom) {
3.1481 - Arc next = (*_blossom_data)[blossom].next;
3.1482 - Arc pred = (*_blossom_data)[blossom].pred;
3.1483 -
3.1484 - int tree = _tree_set->find(blossom);
3.1485 -
3.1486 - (*_blossom_data)[blossom].status = MATCHED;
3.1487 - oddToMatched(blossom);
3.1488 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
3.1489 - _delta2->erase(blossom);
3.1490 - }
3.1491 -
3.1492 - std::vector<int> subblossoms;
3.1493 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
3.1494 -
3.1495 - Value offset = (*_blossom_data)[blossom].offset;
3.1496 - int b = _blossom_set->find(_graph.source(pred));
3.1497 - int d = _blossom_set->find(_graph.source(next));
3.1498 -
3.1499 - int ib = -1, id = -1;
3.1500 - for (int i = 0; i < int(subblossoms.size()); ++i) {
3.1501 - if (subblossoms[i] == b) ib = i;
3.1502 - if (subblossoms[i] == d) id = i;
3.1503 -
3.1504 - (*_blossom_data)[subblossoms[i]].offset = offset;
3.1505 - if (!_blossom_set->trivial(subblossoms[i])) {
3.1506 - (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
3.1507 - }
3.1508 - if (_blossom_set->classPrio(subblossoms[i]) !=
3.1509 - std::numeric_limits<Value>::max()) {
3.1510 - _delta2->push(subblossoms[i],
3.1511 - _blossom_set->classPrio(subblossoms[i]) -
3.1512 - (*_blossom_data)[subblossoms[i]].offset);
3.1513 - }
3.1514 - }
3.1515 -
3.1516 - if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
3.1517 - for (int i = (id + 1) % subblossoms.size();
3.1518 - i != ib; i = (i + 2) % subblossoms.size()) {
3.1519 - int sb = subblossoms[i];
3.1520 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.1521 - (*_blossom_data)[sb].next =
3.1522 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.1523 - }
3.1524 -
3.1525 - for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
3.1526 - int sb = subblossoms[i];
3.1527 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.1528 - int ub = subblossoms[(i + 2) % subblossoms.size()];
3.1529 -
3.1530 - (*_blossom_data)[sb].status = ODD;
3.1531 - matchedToOdd(sb);
3.1532 - _tree_set->insert(sb, tree);
3.1533 - (*_blossom_data)[sb].pred = pred;
3.1534 - (*_blossom_data)[sb].next =
3.1535 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.1536 -
3.1537 - pred = (*_blossom_data)[ub].next;
3.1538 -
3.1539 - (*_blossom_data)[tb].status = EVEN;
3.1540 - matchedToEven(tb, tree);
3.1541 - _tree_set->insert(tb, tree);
3.1542 - (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
3.1543 - }
3.1544 -
3.1545 - (*_blossom_data)[subblossoms[id]].status = ODD;
3.1546 - matchedToOdd(subblossoms[id]);
3.1547 - _tree_set->insert(subblossoms[id], tree);
3.1548 - (*_blossom_data)[subblossoms[id]].next = next;
3.1549 - (*_blossom_data)[subblossoms[id]].pred = pred;
3.1550 -
3.1551 - } else {
3.1552 -
3.1553 - for (int i = (ib + 1) % subblossoms.size();
3.1554 - i != id; i = (i + 2) % subblossoms.size()) {
3.1555 - int sb = subblossoms[i];
3.1556 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.1557 - (*_blossom_data)[sb].next =
3.1558 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.1559 - }
3.1560 -
3.1561 - for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
3.1562 - int sb = subblossoms[i];
3.1563 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.1564 - int ub = subblossoms[(i + 2) % subblossoms.size()];
3.1565 -
3.1566 - (*_blossom_data)[sb].status = ODD;
3.1567 - matchedToOdd(sb);
3.1568 - _tree_set->insert(sb, tree);
3.1569 - (*_blossom_data)[sb].next = next;
3.1570 - (*_blossom_data)[sb].pred =
3.1571 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.1572 -
3.1573 - (*_blossom_data)[tb].status = EVEN;
3.1574 - matchedToEven(tb, tree);
3.1575 - _tree_set->insert(tb, tree);
3.1576 - (*_blossom_data)[tb].pred =
3.1577 - (*_blossom_data)[tb].next =
3.1578 - _graph.oppositeArc((*_blossom_data)[ub].next);
3.1579 - next = (*_blossom_data)[ub].next;
3.1580 - }
3.1581 -
3.1582 - (*_blossom_data)[subblossoms[ib]].status = ODD;
3.1583 - matchedToOdd(subblossoms[ib]);
3.1584 - _tree_set->insert(subblossoms[ib], tree);
3.1585 - (*_blossom_data)[subblossoms[ib]].next = next;
3.1586 - (*_blossom_data)[subblossoms[ib]].pred = pred;
3.1587 - }
3.1588 - _tree_set->erase(blossom);
3.1589 - }
3.1590 -
3.1591 - void extractBlossom(int blossom, const Node& base, const Arc& matching) {
3.1592 - if (_blossom_set->trivial(blossom)) {
3.1593 - int bi = (*_node_index)[base];
3.1594 - Value pot = (*_node_data)[bi].pot;
3.1595 -
3.1596 - (*_matching)[base] = matching;
3.1597 - _blossom_node_list.push_back(base);
3.1598 - (*_node_potential)[base] = pot;
3.1599 - } else {
3.1600 -
3.1601 - Value pot = (*_blossom_data)[blossom].pot;
3.1602 - int bn = _blossom_node_list.size();
3.1603 -
3.1604 - std::vector<int> subblossoms;
3.1605 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
3.1606 - int b = _blossom_set->find(base);
3.1607 - int ib = -1;
3.1608 - for (int i = 0; i < int(subblossoms.size()); ++i) {
3.1609 - if (subblossoms[i] == b) { ib = i; break; }
3.1610 - }
3.1611 -
3.1612 - for (int i = 1; i < int(subblossoms.size()); i += 2) {
3.1613 - int sb = subblossoms[(ib + i) % subblossoms.size()];
3.1614 - int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
3.1615 -
3.1616 - Arc m = (*_blossom_data)[tb].next;
3.1617 - extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
3.1618 - extractBlossom(tb, _graph.source(m), m);
3.1619 - }
3.1620 - extractBlossom(subblossoms[ib], base, matching);
3.1621 -
3.1622 - int en = _blossom_node_list.size();
3.1623 -
3.1624 - _blossom_potential.push_back(BlossomVariable(bn, en, pot));
3.1625 - }
3.1626 - }
3.1627 -
3.1628 - void extractMatching() {
3.1629 - std::vector<int> blossoms;
3.1630 - for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
3.1631 - blossoms.push_back(c);
3.1632 - }
3.1633 -
3.1634 - for (int i = 0; i < int(blossoms.size()); ++i) {
3.1635 - if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
3.1636 -
3.1637 - Value offset = (*_blossom_data)[blossoms[i]].offset;
3.1638 - (*_blossom_data)[blossoms[i]].pot += 2 * offset;
3.1639 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
3.1640 - n != INVALID; ++n) {
3.1641 - (*_node_data)[(*_node_index)[n]].pot -= offset;
3.1642 - }
3.1643 -
3.1644 - Arc matching = (*_blossom_data)[blossoms[i]].next;
3.1645 - Node base = _graph.source(matching);
3.1646 - extractBlossom(blossoms[i], base, matching);
3.1647 - } else {
3.1648 - Node base = (*_blossom_data)[blossoms[i]].base;
3.1649 - extractBlossom(blossoms[i], base, INVALID);
3.1650 - }
3.1651 - }
3.1652 - }
3.1653 -
3.1654 - public:
3.1655 -
3.1656 - /// \brief Constructor
3.1657 - ///
3.1658 - /// Constructor.
3.1659 - MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
3.1660 - : _graph(graph), _weight(weight), _matching(0),
3.1661 - _node_potential(0), _blossom_potential(), _blossom_node_list(),
3.1662 - _node_num(0), _blossom_num(0),
3.1663 -
3.1664 - _blossom_index(0), _blossom_set(0), _blossom_data(0),
3.1665 - _node_index(0), _node_heap_index(0), _node_data(0),
3.1666 - _tree_set_index(0), _tree_set(0),
3.1667 -
3.1668 - _delta1_index(0), _delta1(0),
3.1669 - _delta2_index(0), _delta2(0),
3.1670 - _delta3_index(0), _delta3(0),
3.1671 - _delta4_index(0), _delta4(0),
3.1672 -
3.1673 - _delta_sum() {}
3.1674 -
3.1675 - ~MaxWeightedMatching() {
3.1676 - destroyStructures();
3.1677 - }
3.1678 -
3.1679 - /// \name Execution Control
3.1680 - /// The simplest way to execute the algorithm is to use the
3.1681 - /// \ref run() member function.
3.1682 -
3.1683 - ///@{
3.1684 -
3.1685 - /// \brief Initialize the algorithm
3.1686 - ///
3.1687 - /// This function initializes the algorithm.
3.1688 - void init() {
3.1689 - createStructures();
3.1690 -
3.1691 - for (ArcIt e(_graph); e != INVALID; ++e) {
3.1692 - (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3.1693 - }
3.1694 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.1695 - (*_delta1_index)[n] = _delta1->PRE_HEAP;
3.1696 - }
3.1697 - for (EdgeIt e(_graph); e != INVALID; ++e) {
3.1698 - (*_delta3_index)[e] = _delta3->PRE_HEAP;
3.1699 - }
3.1700 - for (int i = 0; i < _blossom_num; ++i) {
3.1701 - (*_delta2_index)[i] = _delta2->PRE_HEAP;
3.1702 - (*_delta4_index)[i] = _delta4->PRE_HEAP;
3.1703 - }
3.1704 -
3.1705 - int index = 0;
3.1706 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.1707 - Value max = 0;
3.1708 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3.1709 - if (_graph.target(e) == n) continue;
3.1710 - if ((dualScale * _weight[e]) / 2 > max) {
3.1711 - max = (dualScale * _weight[e]) / 2;
3.1712 - }
3.1713 - }
3.1714 - (*_node_index)[n] = index;
3.1715 - (*_node_data)[index].pot = max;
3.1716 - _delta1->push(n, max);
3.1717 - int blossom =
3.1718 - _blossom_set->insert(n, std::numeric_limits<Value>::max());
3.1719 -
3.1720 - _tree_set->insert(blossom);
3.1721 -
3.1722 - (*_blossom_data)[blossom].status = EVEN;
3.1723 - (*_blossom_data)[blossom].pred = INVALID;
3.1724 - (*_blossom_data)[blossom].next = INVALID;
3.1725 - (*_blossom_data)[blossom].pot = 0;
3.1726 - (*_blossom_data)[blossom].offset = 0;
3.1727 - ++index;
3.1728 - }
3.1729 - for (EdgeIt e(_graph); e != INVALID; ++e) {
3.1730 - int si = (*_node_index)[_graph.u(e)];
3.1731 - int ti = (*_node_index)[_graph.v(e)];
3.1732 - if (_graph.u(e) != _graph.v(e)) {
3.1733 - _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3.1734 - dualScale * _weight[e]) / 2);
3.1735 - }
3.1736 - }
3.1737 - }
3.1738 -
3.1739 - /// \brief Start the algorithm
3.1740 - ///
3.1741 - /// This function starts the algorithm.
3.1742 - ///
3.1743 - /// \pre \ref init() must be called before using this function.
3.1744 - void start() {
3.1745 - enum OpType {
3.1746 - D1, D2, D3, D4
3.1747 - };
3.1748 -
3.1749 - int unmatched = _node_num;
3.1750 - while (unmatched > 0) {
3.1751 - Value d1 = !_delta1->empty() ?
3.1752 - _delta1->prio() : std::numeric_limits<Value>::max();
3.1753 -
3.1754 - Value d2 = !_delta2->empty() ?
3.1755 - _delta2->prio() : std::numeric_limits<Value>::max();
3.1756 -
3.1757 - Value d3 = !_delta3->empty() ?
3.1758 - _delta3->prio() : std::numeric_limits<Value>::max();
3.1759 -
3.1760 - Value d4 = !_delta4->empty() ?
3.1761 - _delta4->prio() : std::numeric_limits<Value>::max();
3.1762 -
3.1763 - _delta_sum = d1; OpType ot = D1;
3.1764 - if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
3.1765 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
3.1766 - if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
3.1767 -
3.1768 -
3.1769 - switch (ot) {
3.1770 - case D1:
3.1771 - {
3.1772 - Node n = _delta1->top();
3.1773 - unmatchNode(n);
3.1774 - --unmatched;
3.1775 - }
3.1776 - break;
3.1777 - case D2:
3.1778 - {
3.1779 - int blossom = _delta2->top();
3.1780 - Node n = _blossom_set->classTop(blossom);
3.1781 - Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3.1782 - extendOnArc(e);
3.1783 - }
3.1784 - break;
3.1785 - case D3:
3.1786 - {
3.1787 - Edge e = _delta3->top();
3.1788 -
3.1789 - int left_blossom = _blossom_set->find(_graph.u(e));
3.1790 - int right_blossom = _blossom_set->find(_graph.v(e));
3.1791 -
3.1792 - if (left_blossom == right_blossom) {
3.1793 - _delta3->pop();
3.1794 - } else {
3.1795 - int left_tree;
3.1796 - if ((*_blossom_data)[left_blossom].status == EVEN) {
3.1797 - left_tree = _tree_set->find(left_blossom);
3.1798 - } else {
3.1799 - left_tree = -1;
3.1800 - ++unmatched;
3.1801 - }
3.1802 - int right_tree;
3.1803 - if ((*_blossom_data)[right_blossom].status == EVEN) {
3.1804 - right_tree = _tree_set->find(right_blossom);
3.1805 - } else {
3.1806 - right_tree = -1;
3.1807 - ++unmatched;
3.1808 - }
3.1809 -
3.1810 - if (left_tree == right_tree) {
3.1811 - shrinkOnEdge(e, left_tree);
3.1812 - } else {
3.1813 - augmentOnEdge(e);
3.1814 - unmatched -= 2;
3.1815 - }
3.1816 - }
3.1817 - } break;
3.1818 - case D4:
3.1819 - splitBlossom(_delta4->top());
3.1820 - break;
3.1821 - }
3.1822 - }
3.1823 - extractMatching();
3.1824 - }
3.1825 -
3.1826 - /// \brief Run the algorithm.
3.1827 - ///
3.1828 - /// This method runs the \c %MaxWeightedMatching algorithm.
3.1829 - ///
3.1830 - /// \note mwm.run() is just a shortcut of the following code.
3.1831 - /// \code
3.1832 - /// mwm.init();
3.1833 - /// mwm.start();
3.1834 - /// \endcode
3.1835 - void run() {
3.1836 - init();
3.1837 - start();
3.1838 - }
3.1839 -
3.1840 - /// @}
3.1841 -
3.1842 - /// \name Primal Solution
3.1843 - /// Functions to get the primal solution, i.e. the maximum weighted
3.1844 - /// matching.\n
3.1845 - /// Either \ref run() or \ref start() function should be called before
3.1846 - /// using them.
3.1847 -
3.1848 - /// @{
3.1849 -
3.1850 - /// \brief Return the weight of the matching.
3.1851 - ///
3.1852 - /// This function returns the weight of the found matching.
3.1853 - ///
3.1854 - /// \pre Either run() or start() must be called before using this function.
3.1855 - Value matchingWeight() const {
3.1856 - Value sum = 0;
3.1857 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.1858 - if ((*_matching)[n] != INVALID) {
3.1859 - sum += _weight[(*_matching)[n]];
3.1860 - }
3.1861 - }
3.1862 - return sum /= 2;
3.1863 - }
3.1864 -
3.1865 - /// \brief Return the size (cardinality) of the matching.
3.1866 - ///
3.1867 - /// This function returns the size (cardinality) of the found matching.
3.1868 - ///
3.1869 - /// \pre Either run() or start() must be called before using this function.
3.1870 - int matchingSize() const {
3.1871 - int num = 0;
3.1872 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.1873 - if ((*_matching)[n] != INVALID) {
3.1874 - ++num;
3.1875 - }
3.1876 - }
3.1877 - return num /= 2;
3.1878 - }
3.1879 -
3.1880 - /// \brief Return \c true if the given edge is in the matching.
3.1881 - ///
3.1882 - /// This function returns \c true if the given edge is in the found
3.1883 - /// matching.
3.1884 - ///
3.1885 - /// \pre Either run() or start() must be called before using this function.
3.1886 - bool matching(const Edge& edge) const {
3.1887 - return edge == (*_matching)[_graph.u(edge)];
3.1888 - }
3.1889 -
3.1890 - /// \brief Return the matching arc (or edge) incident to the given node.
3.1891 - ///
3.1892 - /// This function returns the matching arc (or edge) incident to the
3.1893 - /// given node in the found matching or \c INVALID if the node is
3.1894 - /// not covered by the matching.
3.1895 - ///
3.1896 - /// \pre Either run() or start() must be called before using this function.
3.1897 - Arc matching(const Node& node) const {
3.1898 - return (*_matching)[node];
3.1899 - }
3.1900 -
3.1901 - /// \brief Return a const reference to the matching map.
3.1902 - ///
3.1903 - /// This function returns a const reference to a node map that stores
3.1904 - /// the matching arc (or edge) incident to each node.
3.1905 - const MatchingMap& matchingMap() const {
3.1906 - return *_matching;
3.1907 - }
3.1908 -
3.1909 - /// \brief Return the mate of the given node.
3.1910 - ///
3.1911 - /// This function returns the mate of the given node in the found
3.1912 - /// matching or \c INVALID if the node is not covered by the matching.
3.1913 - ///
3.1914 - /// \pre Either run() or start() must be called before using this function.
3.1915 - Node mate(const Node& node) const {
3.1916 - return (*_matching)[node] != INVALID ?
3.1917 - _graph.target((*_matching)[node]) : INVALID;
3.1918 - }
3.1919 -
3.1920 - /// @}
3.1921 -
3.1922 - /// \name Dual Solution
3.1923 - /// Functions to get the dual solution.\n
3.1924 - /// Either \ref run() or \ref start() function should be called before
3.1925 - /// using them.
3.1926 -
3.1927 - /// @{
3.1928 -
3.1929 - /// \brief Return the value of the dual solution.
3.1930 - ///
3.1931 - /// This function returns the value of the dual solution.
3.1932 - /// It should be equal to the primal value scaled by \ref dualScale
3.1933 - /// "dual scale".
3.1934 - ///
3.1935 - /// \pre Either run() or start() must be called before using this function.
3.1936 - Value dualValue() const {
3.1937 - Value sum = 0;
3.1938 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.1939 - sum += nodeValue(n);
3.1940 - }
3.1941 - for (int i = 0; i < blossomNum(); ++i) {
3.1942 - sum += blossomValue(i) * (blossomSize(i) / 2);
3.1943 - }
3.1944 - return sum;
3.1945 - }
3.1946 -
3.1947 - /// \brief Return the dual value (potential) of the given node.
3.1948 - ///
3.1949 - /// This function returns the dual value (potential) of the given node.
3.1950 - ///
3.1951 - /// \pre Either run() or start() must be called before using this function.
3.1952 - Value nodeValue(const Node& n) const {
3.1953 - return (*_node_potential)[n];
3.1954 - }
3.1955 -
3.1956 - /// \brief Return the number of the blossoms in the basis.
3.1957 - ///
3.1958 - /// This function returns the number of the blossoms in the basis.
3.1959 - ///
3.1960 - /// \pre Either run() or start() must be called before using this function.
3.1961 - /// \see BlossomIt
3.1962 - int blossomNum() const {
3.1963 - return _blossom_potential.size();
3.1964 - }
3.1965 -
3.1966 - /// \brief Return the number of the nodes in the given blossom.
3.1967 - ///
3.1968 - /// This function returns the number of the nodes in the given blossom.
3.1969 - ///
3.1970 - /// \pre Either run() or start() must be called before using this function.
3.1971 - /// \see BlossomIt
3.1972 - int blossomSize(int k) const {
3.1973 - return _blossom_potential[k].end - _blossom_potential[k].begin;
3.1974 - }
3.1975 -
3.1976 - /// \brief Return the dual value (ptential) of the given blossom.
3.1977 - ///
3.1978 - /// This function returns the dual value (ptential) of the given blossom.
3.1979 - ///
3.1980 - /// \pre Either run() or start() must be called before using this function.
3.1981 - Value blossomValue(int k) const {
3.1982 - return _blossom_potential[k].value;
3.1983 - }
3.1984 -
3.1985 - /// \brief Iterator for obtaining the nodes of a blossom.
3.1986 - ///
3.1987 - /// This class provides an iterator for obtaining the nodes of the
3.1988 - /// given blossom. It lists a subset of the nodes.
3.1989 - /// Before using this iterator, you must allocate a
3.1990 - /// MaxWeightedMatching class and execute it.
3.1991 - class BlossomIt {
3.1992 - public:
3.1993 -
3.1994 - /// \brief Constructor.
3.1995 - ///
3.1996 - /// Constructor to get the nodes of the given variable.
3.1997 - ///
3.1998 - /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
3.1999 - /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
3.2000 - /// called before initializing this iterator.
3.2001 - BlossomIt(const MaxWeightedMatching& algorithm, int variable)
3.2002 - : _algorithm(&algorithm)
3.2003 - {
3.2004 - _index = _algorithm->_blossom_potential[variable].begin;
3.2005 - _last = _algorithm->_blossom_potential[variable].end;
3.2006 - }
3.2007 -
3.2008 - /// \brief Conversion to \c Node.
3.2009 - ///
3.2010 - /// Conversion to \c Node.
3.2011 - operator Node() const {
3.2012 - return _algorithm->_blossom_node_list[_index];
3.2013 - }
3.2014 -
3.2015 - /// \brief Increment operator.
3.2016 - ///
3.2017 - /// Increment operator.
3.2018 - BlossomIt& operator++() {
3.2019 - ++_index;
3.2020 - return *this;
3.2021 - }
3.2022 -
3.2023 - /// \brief Validity checking
3.2024 - ///
3.2025 - /// Checks whether the iterator is invalid.
3.2026 - bool operator==(Invalid) const { return _index == _last; }
3.2027 -
3.2028 - /// \brief Validity checking
3.2029 - ///
3.2030 - /// Checks whether the iterator is valid.
3.2031 - bool operator!=(Invalid) const { return _index != _last; }
3.2032 -
3.2033 - private:
3.2034 - const MaxWeightedMatching* _algorithm;
3.2035 - int _last;
3.2036 - int _index;
3.2037 - };
3.2038 -
3.2039 - /// @}
3.2040 -
3.2041 - };
3.2042 -
3.2043 - /// \ingroup matching
3.2044 - ///
3.2045 - /// \brief Weighted perfect matching in general graphs
3.2046 - ///
3.2047 - /// This class provides an efficient implementation of Edmond's
3.2048 - /// maximum weighted perfect matching algorithm. The implementation
3.2049 - /// is based on extensive use of priority queues and provides
3.2050 - /// \f$O(nm\log n)\f$ time complexity.
3.2051 - ///
3.2052 - /// The maximum weighted perfect matching problem is to find a subset of
3.2053 - /// the edges in an undirected graph with maximum overall weight for which
3.2054 - /// each node has exactly one incident edge.
3.2055 - /// It can be formulated with the following linear program.
3.2056 - /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
3.2057 - /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
3.2058 - \quad \forall B\in\mathcal{O}\f] */
3.2059 - /// \f[x_e \ge 0\quad \forall e\in E\f]
3.2060 - /// \f[\max \sum_{e\in E}x_ew_e\f]
3.2061 - /// where \f$\delta(X)\f$ is the set of edges incident to a node in
3.2062 - /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
3.2063 - /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
3.2064 - /// subsets of the nodes.
3.2065 - ///
3.2066 - /// The algorithm calculates an optimal matching and a proof of the
3.2067 - /// optimality. The solution of the dual problem can be used to check
3.2068 - /// the result of the algorithm. The dual linear problem is the
3.2069 - /// following.
3.2070 - /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
3.2071 - w_{uv} \quad \forall uv\in E\f] */
3.2072 - /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
3.2073 - /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
3.2074 - \frac{\vert B \vert - 1}{2}z_B\f] */
3.2075 - ///
3.2076 - /// The algorithm can be executed with the run() function.
3.2077 - /// After it the matching (the primal solution) and the dual solution
3.2078 - /// can be obtained using the query functions and the
3.2079 - /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
3.2080 - /// which is able to iterate on the nodes of a blossom.
3.2081 - /// If the value type is integer, then the dual solution is multiplied
3.2082 - /// by \ref MaxWeightedMatching::dualScale "4".
3.2083 - ///
3.2084 - /// \tparam GR The undirected graph type the algorithm runs on.
3.2085 - /// \tparam WM The type edge weight map. The default type is
3.2086 - /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
3.2087 -#ifdef DOXYGEN
3.2088 - template <typename GR, typename WM>
3.2089 -#else
3.2090 - template <typename GR,
3.2091 - typename WM = typename GR::template EdgeMap<int> >
3.2092 -#endif
3.2093 - class MaxWeightedPerfectMatching {
3.2094 - public:
3.2095 -
3.2096 - /// The graph type of the algorithm
3.2097 - typedef GR Graph;
3.2098 - /// The type of the edge weight map
3.2099 - typedef WM WeightMap;
3.2100 - /// The value type of the edge weights
3.2101 - typedef typename WeightMap::Value Value;
3.2102 -
3.2103 - /// \brief Scaling factor for dual solution
3.2104 - ///
3.2105 - /// Scaling factor for dual solution, it is equal to 4 or 1
3.2106 - /// according to the value type.
3.2107 - static const int dualScale =
3.2108 - std::numeric_limits<Value>::is_integer ? 4 : 1;
3.2109 -
3.2110 - /// The type of the matching map
3.2111 - typedef typename Graph::template NodeMap<typename Graph::Arc>
3.2112 - MatchingMap;
3.2113 -
3.2114 - private:
3.2115 -
3.2116 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
3.2117 -
3.2118 - typedef typename Graph::template NodeMap<Value> NodePotential;
3.2119 - typedef std::vector<Node> BlossomNodeList;
3.2120 -
3.2121 - struct BlossomVariable {
3.2122 - int begin, end;
3.2123 - Value value;
3.2124 -
3.2125 - BlossomVariable(int _begin, int _end, Value _value)
3.2126 - : begin(_begin), end(_end), value(_value) {}
3.2127 -
3.2128 - };
3.2129 -
3.2130 - typedef std::vector<BlossomVariable> BlossomPotential;
3.2131 -
3.2132 - const Graph& _graph;
3.2133 - const WeightMap& _weight;
3.2134 -
3.2135 - MatchingMap* _matching;
3.2136 -
3.2137 - NodePotential* _node_potential;
3.2138 -
3.2139 - BlossomPotential _blossom_potential;
3.2140 - BlossomNodeList _blossom_node_list;
3.2141 -
3.2142 - int _node_num;
3.2143 - int _blossom_num;
3.2144 -
3.2145 - typedef RangeMap<int> IntIntMap;
3.2146 -
3.2147 - enum Status {
3.2148 - EVEN = -1, MATCHED = 0, ODD = 1
3.2149 - };
3.2150 -
3.2151 - typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
3.2152 - struct BlossomData {
3.2153 - int tree;
3.2154 - Status status;
3.2155 - Arc pred, next;
3.2156 - Value pot, offset;
3.2157 - };
3.2158 -
3.2159 - IntNodeMap *_blossom_index;
3.2160 - BlossomSet *_blossom_set;
3.2161 - RangeMap<BlossomData>* _blossom_data;
3.2162 -
3.2163 - IntNodeMap *_node_index;
3.2164 - IntArcMap *_node_heap_index;
3.2165 -
3.2166 - struct NodeData {
3.2167 -
3.2168 - NodeData(IntArcMap& node_heap_index)
3.2169 - : heap(node_heap_index) {}
3.2170 -
3.2171 - int blossom;
3.2172 - Value pot;
3.2173 - BinHeap<Value, IntArcMap> heap;
3.2174 - std::map<int, Arc> heap_index;
3.2175 -
3.2176 - int tree;
3.2177 - };
3.2178 -
3.2179 - RangeMap<NodeData>* _node_data;
3.2180 -
3.2181 - typedef ExtendFindEnum<IntIntMap> TreeSet;
3.2182 -
3.2183 - IntIntMap *_tree_set_index;
3.2184 - TreeSet *_tree_set;
3.2185 -
3.2186 - IntIntMap *_delta2_index;
3.2187 - BinHeap<Value, IntIntMap> *_delta2;
3.2188 -
3.2189 - IntEdgeMap *_delta3_index;
3.2190 - BinHeap<Value, IntEdgeMap> *_delta3;
3.2191 -
3.2192 - IntIntMap *_delta4_index;
3.2193 - BinHeap<Value, IntIntMap> *_delta4;
3.2194 -
3.2195 - Value _delta_sum;
3.2196 -
3.2197 - void createStructures() {
3.2198 - _node_num = countNodes(_graph);
3.2199 - _blossom_num = _node_num * 3 / 2;
3.2200 -
3.2201 - if (!_matching) {
3.2202 - _matching = new MatchingMap(_graph);
3.2203 - }
3.2204 - if (!_node_potential) {
3.2205 - _node_potential = new NodePotential(_graph);
3.2206 - }
3.2207 - if (!_blossom_set) {
3.2208 - _blossom_index = new IntNodeMap(_graph);
3.2209 - _blossom_set = new BlossomSet(*_blossom_index);
3.2210 - _blossom_data = new RangeMap<BlossomData>(_blossom_num);
3.2211 - }
3.2212 -
3.2213 - if (!_node_index) {
3.2214 - _node_index = new IntNodeMap(_graph);
3.2215 - _node_heap_index = new IntArcMap(_graph);
3.2216 - _node_data = new RangeMap<NodeData>(_node_num,
3.2217 - NodeData(*_node_heap_index));
3.2218 - }
3.2219 -
3.2220 - if (!_tree_set) {
3.2221 - _tree_set_index = new IntIntMap(_blossom_num);
3.2222 - _tree_set = new TreeSet(*_tree_set_index);
3.2223 - }
3.2224 - if (!_delta2) {
3.2225 - _delta2_index = new IntIntMap(_blossom_num);
3.2226 - _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
3.2227 - }
3.2228 - if (!_delta3) {
3.2229 - _delta3_index = new IntEdgeMap(_graph);
3.2230 - _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
3.2231 - }
3.2232 - if (!_delta4) {
3.2233 - _delta4_index = new IntIntMap(_blossom_num);
3.2234 - _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
3.2235 - }
3.2236 - }
3.2237 -
3.2238 - void destroyStructures() {
3.2239 - _node_num = countNodes(_graph);
3.2240 - _blossom_num = _node_num * 3 / 2;
3.2241 -
3.2242 - if (_matching) {
3.2243 - delete _matching;
3.2244 - }
3.2245 - if (_node_potential) {
3.2246 - delete _node_potential;
3.2247 - }
3.2248 - if (_blossom_set) {
3.2249 - delete _blossom_index;
3.2250 - delete _blossom_set;
3.2251 - delete _blossom_data;
3.2252 - }
3.2253 -
3.2254 - if (_node_index) {
3.2255 - delete _node_index;
3.2256 - delete _node_heap_index;
3.2257 - delete _node_data;
3.2258 - }
3.2259 -
3.2260 - if (_tree_set) {
3.2261 - delete _tree_set_index;
3.2262 - delete _tree_set;
3.2263 - }
3.2264 - if (_delta2) {
3.2265 - delete _delta2_index;
3.2266 - delete _delta2;
3.2267 - }
3.2268 - if (_delta3) {
3.2269 - delete _delta3_index;
3.2270 - delete _delta3;
3.2271 - }
3.2272 - if (_delta4) {
3.2273 - delete _delta4_index;
3.2274 - delete _delta4;
3.2275 - }
3.2276 - }
3.2277 -
3.2278 - void matchedToEven(int blossom, int tree) {
3.2279 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
3.2280 - _delta2->erase(blossom);
3.2281 - }
3.2282 -
3.2283 - if (!_blossom_set->trivial(blossom)) {
3.2284 - (*_blossom_data)[blossom].pot -=
3.2285 - 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
3.2286 - }
3.2287 -
3.2288 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.2289 - n != INVALID; ++n) {
3.2290 -
3.2291 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
3.2292 - int ni = (*_node_index)[n];
3.2293 -
3.2294 - (*_node_data)[ni].heap.clear();
3.2295 - (*_node_data)[ni].heap_index.clear();
3.2296 -
3.2297 - (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
3.2298 -
3.2299 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
3.2300 - Node v = _graph.source(e);
3.2301 - int vb = _blossom_set->find(v);
3.2302 - int vi = (*_node_index)[v];
3.2303 -
3.2304 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.2305 - dualScale * _weight[e];
3.2306 -
3.2307 - if ((*_blossom_data)[vb].status == EVEN) {
3.2308 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
3.2309 - _delta3->push(e, rw / 2);
3.2310 - }
3.2311 - } else {
3.2312 - typename std::map<int, Arc>::iterator it =
3.2313 - (*_node_data)[vi].heap_index.find(tree);
3.2314 -
3.2315 - if (it != (*_node_data)[vi].heap_index.end()) {
3.2316 - if ((*_node_data)[vi].heap[it->second] > rw) {
3.2317 - (*_node_data)[vi].heap.replace(it->second, e);
3.2318 - (*_node_data)[vi].heap.decrease(e, rw);
3.2319 - it->second = e;
3.2320 - }
3.2321 - } else {
3.2322 - (*_node_data)[vi].heap.push(e, rw);
3.2323 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
3.2324 - }
3.2325 -
3.2326 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
3.2327 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
3.2328 -
3.2329 - if ((*_blossom_data)[vb].status == MATCHED) {
3.2330 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
3.2331 - _delta2->push(vb, _blossom_set->classPrio(vb) -
3.2332 - (*_blossom_data)[vb].offset);
3.2333 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
3.2334 - (*_blossom_data)[vb].offset){
3.2335 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
3.2336 - (*_blossom_data)[vb].offset);
3.2337 - }
3.2338 - }
3.2339 - }
3.2340 - }
3.2341 - }
3.2342 - }
3.2343 - (*_blossom_data)[blossom].offset = 0;
3.2344 - }
3.2345 -
3.2346 - void matchedToOdd(int blossom) {
3.2347 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
3.2348 - _delta2->erase(blossom);
3.2349 - }
3.2350 - (*_blossom_data)[blossom].offset += _delta_sum;
3.2351 - if (!_blossom_set->trivial(blossom)) {
3.2352 - _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
3.2353 - (*_blossom_data)[blossom].offset);
3.2354 - }
3.2355 - }
3.2356 -
3.2357 - void evenToMatched(int blossom, int tree) {
3.2358 - if (!_blossom_set->trivial(blossom)) {
3.2359 - (*_blossom_data)[blossom].pot += 2 * _delta_sum;
3.2360 - }
3.2361 -
3.2362 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.2363 - n != INVALID; ++n) {
3.2364 - int ni = (*_node_index)[n];
3.2365 - (*_node_data)[ni].pot -= _delta_sum;
3.2366 -
3.2367 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
3.2368 - Node v = _graph.source(e);
3.2369 - int vb = _blossom_set->find(v);
3.2370 - int vi = (*_node_index)[v];
3.2371 -
3.2372 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.2373 - dualScale * _weight[e];
3.2374 -
3.2375 - if (vb == blossom) {
3.2376 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.2377 - _delta3->erase(e);
3.2378 - }
3.2379 - } else if ((*_blossom_data)[vb].status == EVEN) {
3.2380 -
3.2381 - if (_delta3->state(e) == _delta3->IN_HEAP) {
3.2382 - _delta3->erase(e);
3.2383 - }
3.2384 -
3.2385 - int vt = _tree_set->find(vb);
3.2386 -
3.2387 - if (vt != tree) {
3.2388 -
3.2389 - Arc r = _graph.oppositeArc(e);
3.2390 -
3.2391 - typename std::map<int, Arc>::iterator it =
3.2392 - (*_node_data)[ni].heap_index.find(vt);
3.2393 -
3.2394 - if (it != (*_node_data)[ni].heap_index.end()) {
3.2395 - if ((*_node_data)[ni].heap[it->second] > rw) {
3.2396 - (*_node_data)[ni].heap.replace(it->second, r);
3.2397 - (*_node_data)[ni].heap.decrease(r, rw);
3.2398 - it->second = r;
3.2399 - }
3.2400 - } else {
3.2401 - (*_node_data)[ni].heap.push(r, rw);
3.2402 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
3.2403 - }
3.2404 -
3.2405 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
3.2406 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3.2407 -
3.2408 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
3.2409 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
3.2410 - (*_blossom_data)[blossom].offset);
3.2411 - } else if ((*_delta2)[blossom] >
3.2412 - _blossom_set->classPrio(blossom) -
3.2413 - (*_blossom_data)[blossom].offset){
3.2414 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
3.2415 - (*_blossom_data)[blossom].offset);
3.2416 - }
3.2417 - }
3.2418 - }
3.2419 - } else {
3.2420 -
3.2421 - typename std::map<int, Arc>::iterator it =
3.2422 - (*_node_data)[vi].heap_index.find(tree);
3.2423 -
3.2424 - if (it != (*_node_data)[vi].heap_index.end()) {
3.2425 - (*_node_data)[vi].heap.erase(it->second);
3.2426 - (*_node_data)[vi].heap_index.erase(it);
3.2427 - if ((*_node_data)[vi].heap.empty()) {
3.2428 - _blossom_set->increase(v, std::numeric_limits<Value>::max());
3.2429 - } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
3.2430 - _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
3.2431 - }
3.2432 -
3.2433 - if ((*_blossom_data)[vb].status == MATCHED) {
3.2434 - if (_blossom_set->classPrio(vb) ==
3.2435 - std::numeric_limits<Value>::max()) {
3.2436 - _delta2->erase(vb);
3.2437 - } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
3.2438 - (*_blossom_data)[vb].offset) {
3.2439 - _delta2->increase(vb, _blossom_set->classPrio(vb) -
3.2440 - (*_blossom_data)[vb].offset);
3.2441 - }
3.2442 - }
3.2443 - }
3.2444 - }
3.2445 - }
3.2446 - }
3.2447 - }
3.2448 -
3.2449 - void oddToMatched(int blossom) {
3.2450 - (*_blossom_data)[blossom].offset -= _delta_sum;
3.2451 -
3.2452 - if (_blossom_set->classPrio(blossom) !=
3.2453 - std::numeric_limits<Value>::max()) {
3.2454 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
3.2455 - (*_blossom_data)[blossom].offset);
3.2456 - }
3.2457 -
3.2458 - if (!_blossom_set->trivial(blossom)) {
3.2459 - _delta4->erase(blossom);
3.2460 - }
3.2461 - }
3.2462 -
3.2463 - void oddToEven(int blossom, int tree) {
3.2464 - if (!_blossom_set->trivial(blossom)) {
3.2465 - _delta4->erase(blossom);
3.2466 - (*_blossom_data)[blossom].pot -=
3.2467 - 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
3.2468 - }
3.2469 -
3.2470 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
3.2471 - n != INVALID; ++n) {
3.2472 - int ni = (*_node_index)[n];
3.2473 -
3.2474 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
3.2475 -
3.2476 - (*_node_data)[ni].heap.clear();
3.2477 - (*_node_data)[ni].heap_index.clear();
3.2478 - (*_node_data)[ni].pot +=
3.2479 - 2 * _delta_sum - (*_blossom_data)[blossom].offset;
3.2480 -
3.2481 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
3.2482 - Node v = _graph.source(e);
3.2483 - int vb = _blossom_set->find(v);
3.2484 - int vi = (*_node_index)[v];
3.2485 -
3.2486 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3.2487 - dualScale * _weight[e];
3.2488 -
3.2489 - if ((*_blossom_data)[vb].status == EVEN) {
3.2490 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
3.2491 - _delta3->push(e, rw / 2);
3.2492 - }
3.2493 - } else {
3.2494 -
3.2495 - typename std::map<int, Arc>::iterator it =
3.2496 - (*_node_data)[vi].heap_index.find(tree);
3.2497 -
3.2498 - if (it != (*_node_data)[vi].heap_index.end()) {
3.2499 - if ((*_node_data)[vi].heap[it->second] > rw) {
3.2500 - (*_node_data)[vi].heap.replace(it->second, e);
3.2501 - (*_node_data)[vi].heap.decrease(e, rw);
3.2502 - it->second = e;
3.2503 - }
3.2504 - } else {
3.2505 - (*_node_data)[vi].heap.push(e, rw);
3.2506 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
3.2507 - }
3.2508 -
3.2509 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
3.2510 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
3.2511 -
3.2512 - if ((*_blossom_data)[vb].status == MATCHED) {
3.2513 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
3.2514 - _delta2->push(vb, _blossom_set->classPrio(vb) -
3.2515 - (*_blossom_data)[vb].offset);
3.2516 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
3.2517 - (*_blossom_data)[vb].offset) {
3.2518 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
3.2519 - (*_blossom_data)[vb].offset);
3.2520 - }
3.2521 - }
3.2522 - }
3.2523 - }
3.2524 - }
3.2525 - }
3.2526 - (*_blossom_data)[blossom].offset = 0;
3.2527 - }
3.2528 -
3.2529 - void alternatePath(int even, int tree) {
3.2530 - int odd;
3.2531 -
3.2532 - evenToMatched(even, tree);
3.2533 - (*_blossom_data)[even].status = MATCHED;
3.2534 -
3.2535 - while ((*_blossom_data)[even].pred != INVALID) {
3.2536 - odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
3.2537 - (*_blossom_data)[odd].status = MATCHED;
3.2538 - oddToMatched(odd);
3.2539 - (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
3.2540 -
3.2541 - even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
3.2542 - (*_blossom_data)[even].status = MATCHED;
3.2543 - evenToMatched(even, tree);
3.2544 - (*_blossom_data)[even].next =
3.2545 - _graph.oppositeArc((*_blossom_data)[odd].pred);
3.2546 - }
3.2547 -
3.2548 - }
3.2549 -
3.2550 - void destroyTree(int tree) {
3.2551 - for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
3.2552 - if ((*_blossom_data)[b].status == EVEN) {
3.2553 - (*_blossom_data)[b].status = MATCHED;
3.2554 - evenToMatched(b, tree);
3.2555 - } else if ((*_blossom_data)[b].status == ODD) {
3.2556 - (*_blossom_data)[b].status = MATCHED;
3.2557 - oddToMatched(b);
3.2558 - }
3.2559 - }
3.2560 - _tree_set->eraseClass(tree);
3.2561 - }
3.2562 -
3.2563 - void augmentOnEdge(const Edge& edge) {
3.2564 -
3.2565 - int left = _blossom_set->find(_graph.u(edge));
3.2566 - int right = _blossom_set->find(_graph.v(edge));
3.2567 -
3.2568 - int left_tree = _tree_set->find(left);
3.2569 - alternatePath(left, left_tree);
3.2570 - destroyTree(left_tree);
3.2571 -
3.2572 - int right_tree = _tree_set->find(right);
3.2573 - alternatePath(right, right_tree);
3.2574 - destroyTree(right_tree);
3.2575 -
3.2576 - (*_blossom_data)[left].next = _graph.direct(edge, true);
3.2577 - (*_blossom_data)[right].next = _graph.direct(edge, false);
3.2578 - }
3.2579 -
3.2580 - void extendOnArc(const Arc& arc) {
3.2581 - int base = _blossom_set->find(_graph.target(arc));
3.2582 - int tree = _tree_set->find(base);
3.2583 -
3.2584 - int odd = _blossom_set->find(_graph.source(arc));
3.2585 - _tree_set->insert(odd, tree);
3.2586 - (*_blossom_data)[odd].status = ODD;
3.2587 - matchedToOdd(odd);
3.2588 - (*_blossom_data)[odd].pred = arc;
3.2589 -
3.2590 - int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
3.2591 - (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
3.2592 - _tree_set->insert(even, tree);
3.2593 - (*_blossom_data)[even].status = EVEN;
3.2594 - matchedToEven(even, tree);
3.2595 - }
3.2596 -
3.2597 - void shrinkOnEdge(const Edge& edge, int tree) {
3.2598 - int nca = -1;
3.2599 - std::vector<int> left_path, right_path;
3.2600 -
3.2601 - {
3.2602 - std::set<int> left_set, right_set;
3.2603 - int left = _blossom_set->find(_graph.u(edge));
3.2604 - left_path.push_back(left);
3.2605 - left_set.insert(left);
3.2606 -
3.2607 - int right = _blossom_set->find(_graph.v(edge));
3.2608 - right_path.push_back(right);
3.2609 - right_set.insert(right);
3.2610 -
3.2611 - while (true) {
3.2612 -
3.2613 - if ((*_blossom_data)[left].pred == INVALID) break;
3.2614 -
3.2615 - left =
3.2616 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
3.2617 - left_path.push_back(left);
3.2618 - left =
3.2619 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
3.2620 - left_path.push_back(left);
3.2621 -
3.2622 - left_set.insert(left);
3.2623 -
3.2624 - if (right_set.find(left) != right_set.end()) {
3.2625 - nca = left;
3.2626 - break;
3.2627 - }
3.2628 -
3.2629 - if ((*_blossom_data)[right].pred == INVALID) break;
3.2630 -
3.2631 - right =
3.2632 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
3.2633 - right_path.push_back(right);
3.2634 - right =
3.2635 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
3.2636 - right_path.push_back(right);
3.2637 -
3.2638 - right_set.insert(right);
3.2639 -
3.2640 - if (left_set.find(right) != left_set.end()) {
3.2641 - nca = right;
3.2642 - break;
3.2643 - }
3.2644 -
3.2645 - }
3.2646 -
3.2647 - if (nca == -1) {
3.2648 - if ((*_blossom_data)[left].pred == INVALID) {
3.2649 - nca = right;
3.2650 - while (left_set.find(nca) == left_set.end()) {
3.2651 - nca =
3.2652 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.2653 - right_path.push_back(nca);
3.2654 - nca =
3.2655 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.2656 - right_path.push_back(nca);
3.2657 - }
3.2658 - } else {
3.2659 - nca = left;
3.2660 - while (right_set.find(nca) == right_set.end()) {
3.2661 - nca =
3.2662 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.2663 - left_path.push_back(nca);
3.2664 - nca =
3.2665 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
3.2666 - left_path.push_back(nca);
3.2667 - }
3.2668 - }
3.2669 - }
3.2670 - }
3.2671 -
3.2672 - std::vector<int> subblossoms;
3.2673 - Arc prev;
3.2674 -
3.2675 - prev = _graph.direct(edge, true);
3.2676 - for (int i = 0; left_path[i] != nca; i += 2) {
3.2677 - subblossoms.push_back(left_path[i]);
3.2678 - (*_blossom_data)[left_path[i]].next = prev;
3.2679 - _tree_set->erase(left_path[i]);
3.2680 -
3.2681 - subblossoms.push_back(left_path[i + 1]);
3.2682 - (*_blossom_data)[left_path[i + 1]].status = EVEN;
3.2683 - oddToEven(left_path[i + 1], tree);
3.2684 - _tree_set->erase(left_path[i + 1]);
3.2685 - prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
3.2686 - }
3.2687 -
3.2688 - int k = 0;
3.2689 - while (right_path[k] != nca) ++k;
3.2690 -
3.2691 - subblossoms.push_back(nca);
3.2692 - (*_blossom_data)[nca].next = prev;
3.2693 -
3.2694 - for (int i = k - 2; i >= 0; i -= 2) {
3.2695 - subblossoms.push_back(right_path[i + 1]);
3.2696 - (*_blossom_data)[right_path[i + 1]].status = EVEN;
3.2697 - oddToEven(right_path[i + 1], tree);
3.2698 - _tree_set->erase(right_path[i + 1]);
3.2699 -
3.2700 - (*_blossom_data)[right_path[i + 1]].next =
3.2701 - (*_blossom_data)[right_path[i + 1]].pred;
3.2702 -
3.2703 - subblossoms.push_back(right_path[i]);
3.2704 - _tree_set->erase(right_path[i]);
3.2705 - }
3.2706 -
3.2707 - int surface =
3.2708 - _blossom_set->join(subblossoms.begin(), subblossoms.end());
3.2709 -
3.2710 - for (int i = 0; i < int(subblossoms.size()); ++i) {
3.2711 - if (!_blossom_set->trivial(subblossoms[i])) {
3.2712 - (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
3.2713 - }
3.2714 - (*_blossom_data)[subblossoms[i]].status = MATCHED;
3.2715 - }
3.2716 -
3.2717 - (*_blossom_data)[surface].pot = -2 * _delta_sum;
3.2718 - (*_blossom_data)[surface].offset = 0;
3.2719 - (*_blossom_data)[surface].status = EVEN;
3.2720 - (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
3.2721 - (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
3.2722 -
3.2723 - _tree_set->insert(surface, tree);
3.2724 - _tree_set->erase(nca);
3.2725 - }
3.2726 -
3.2727 - void splitBlossom(int blossom) {
3.2728 - Arc next = (*_blossom_data)[blossom].next;
3.2729 - Arc pred = (*_blossom_data)[blossom].pred;
3.2730 -
3.2731 - int tree = _tree_set->find(blossom);
3.2732 -
3.2733 - (*_blossom_data)[blossom].status = MATCHED;
3.2734 - oddToMatched(blossom);
3.2735 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
3.2736 - _delta2->erase(blossom);
3.2737 - }
3.2738 -
3.2739 - std::vector<int> subblossoms;
3.2740 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
3.2741 -
3.2742 - Value offset = (*_blossom_data)[blossom].offset;
3.2743 - int b = _blossom_set->find(_graph.source(pred));
3.2744 - int d = _blossom_set->find(_graph.source(next));
3.2745 -
3.2746 - int ib = -1, id = -1;
3.2747 - for (int i = 0; i < int(subblossoms.size()); ++i) {
3.2748 - if (subblossoms[i] == b) ib = i;
3.2749 - if (subblossoms[i] == d) id = i;
3.2750 -
3.2751 - (*_blossom_data)[subblossoms[i]].offset = offset;
3.2752 - if (!_blossom_set->trivial(subblossoms[i])) {
3.2753 - (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
3.2754 - }
3.2755 - if (_blossom_set->classPrio(subblossoms[i]) !=
3.2756 - std::numeric_limits<Value>::max()) {
3.2757 - _delta2->push(subblossoms[i],
3.2758 - _blossom_set->classPrio(subblossoms[i]) -
3.2759 - (*_blossom_data)[subblossoms[i]].offset);
3.2760 - }
3.2761 - }
3.2762 -
3.2763 - if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
3.2764 - for (int i = (id + 1) % subblossoms.size();
3.2765 - i != ib; i = (i + 2) % subblossoms.size()) {
3.2766 - int sb = subblossoms[i];
3.2767 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.2768 - (*_blossom_data)[sb].next =
3.2769 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.2770 - }
3.2771 -
3.2772 - for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
3.2773 - int sb = subblossoms[i];
3.2774 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.2775 - int ub = subblossoms[(i + 2) % subblossoms.size()];
3.2776 -
3.2777 - (*_blossom_data)[sb].status = ODD;
3.2778 - matchedToOdd(sb);
3.2779 - _tree_set->insert(sb, tree);
3.2780 - (*_blossom_data)[sb].pred = pred;
3.2781 - (*_blossom_data)[sb].next =
3.2782 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.2783 -
3.2784 - pred = (*_blossom_data)[ub].next;
3.2785 -
3.2786 - (*_blossom_data)[tb].status = EVEN;
3.2787 - matchedToEven(tb, tree);
3.2788 - _tree_set->insert(tb, tree);
3.2789 - (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
3.2790 - }
3.2791 -
3.2792 - (*_blossom_data)[subblossoms[id]].status = ODD;
3.2793 - matchedToOdd(subblossoms[id]);
3.2794 - _tree_set->insert(subblossoms[id], tree);
3.2795 - (*_blossom_data)[subblossoms[id]].next = next;
3.2796 - (*_blossom_data)[subblossoms[id]].pred = pred;
3.2797 -
3.2798 - } else {
3.2799 -
3.2800 - for (int i = (ib + 1) % subblossoms.size();
3.2801 - i != id; i = (i + 2) % subblossoms.size()) {
3.2802 - int sb = subblossoms[i];
3.2803 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.2804 - (*_blossom_data)[sb].next =
3.2805 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.2806 - }
3.2807 -
3.2808 - for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
3.2809 - int sb = subblossoms[i];
3.2810 - int tb = subblossoms[(i + 1) % subblossoms.size()];
3.2811 - int ub = subblossoms[(i + 2) % subblossoms.size()];
3.2812 -
3.2813 - (*_blossom_data)[sb].status = ODD;
3.2814 - matchedToOdd(sb);
3.2815 - _tree_set->insert(sb, tree);
3.2816 - (*_blossom_data)[sb].next = next;
3.2817 - (*_blossom_data)[sb].pred =
3.2818 - _graph.oppositeArc((*_blossom_data)[tb].next);
3.2819 -
3.2820 - (*_blossom_data)[tb].status = EVEN;
3.2821 - matchedToEven(tb, tree);
3.2822 - _tree_set->insert(tb, tree);
3.2823 - (*_blossom_data)[tb].pred =
3.2824 - (*_blossom_data)[tb].next =
3.2825 - _graph.oppositeArc((*_blossom_data)[ub].next);
3.2826 - next = (*_blossom_data)[ub].next;
3.2827 - }
3.2828 -
3.2829 - (*_blossom_data)[subblossoms[ib]].status = ODD;
3.2830 - matchedToOdd(subblossoms[ib]);
3.2831 - _tree_set->insert(subblossoms[ib], tree);
3.2832 - (*_blossom_data)[subblossoms[ib]].next = next;
3.2833 - (*_blossom_data)[subblossoms[ib]].pred = pred;
3.2834 - }
3.2835 - _tree_set->erase(blossom);
3.2836 - }
3.2837 -
3.2838 - void extractBlossom(int blossom, const Node& base, const Arc& matching) {
3.2839 - if (_blossom_set->trivial(blossom)) {
3.2840 - int bi = (*_node_index)[base];
3.2841 - Value pot = (*_node_data)[bi].pot;
3.2842 -
3.2843 - (*_matching)[base] = matching;
3.2844 - _blossom_node_list.push_back(base);
3.2845 - (*_node_potential)[base] = pot;
3.2846 - } else {
3.2847 -
3.2848 - Value pot = (*_blossom_data)[blossom].pot;
3.2849 - int bn = _blossom_node_list.size();
3.2850 -
3.2851 - std::vector<int> subblossoms;
3.2852 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
3.2853 - int b = _blossom_set->find(base);
3.2854 - int ib = -1;
3.2855 - for (int i = 0; i < int(subblossoms.size()); ++i) {
3.2856 - if (subblossoms[i] == b) { ib = i; break; }
3.2857 - }
3.2858 -
3.2859 - for (int i = 1; i < int(subblossoms.size()); i += 2) {
3.2860 - int sb = subblossoms[(ib + i) % subblossoms.size()];
3.2861 - int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
3.2862 -
3.2863 - Arc m = (*_blossom_data)[tb].next;
3.2864 - extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
3.2865 - extractBlossom(tb, _graph.source(m), m);
3.2866 - }
3.2867 - extractBlossom(subblossoms[ib], base, matching);
3.2868 -
3.2869 - int en = _blossom_node_list.size();
3.2870 -
3.2871 - _blossom_potential.push_back(BlossomVariable(bn, en, pot));
3.2872 - }
3.2873 - }
3.2874 -
3.2875 - void extractMatching() {
3.2876 - std::vector<int> blossoms;
3.2877 - for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
3.2878 - blossoms.push_back(c);
3.2879 - }
3.2880 -
3.2881 - for (int i = 0; i < int(blossoms.size()); ++i) {
3.2882 -
3.2883 - Value offset = (*_blossom_data)[blossoms[i]].offset;
3.2884 - (*_blossom_data)[blossoms[i]].pot += 2 * offset;
3.2885 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
3.2886 - n != INVALID; ++n) {
3.2887 - (*_node_data)[(*_node_index)[n]].pot -= offset;
3.2888 - }
3.2889 -
3.2890 - Arc matching = (*_blossom_data)[blossoms[i]].next;
3.2891 - Node base = _graph.source(matching);
3.2892 - extractBlossom(blossoms[i], base, matching);
3.2893 - }
3.2894 - }
3.2895 -
3.2896 - public:
3.2897 -
3.2898 - /// \brief Constructor
3.2899 - ///
3.2900 - /// Constructor.
3.2901 - MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
3.2902 - : _graph(graph), _weight(weight), _matching(0),
3.2903 - _node_potential(0), _blossom_potential(), _blossom_node_list(),
3.2904 - _node_num(0), _blossom_num(0),
3.2905 -
3.2906 - _blossom_index(0), _blossom_set(0), _blossom_data(0),
3.2907 - _node_index(0), _node_heap_index(0), _node_data(0),
3.2908 - _tree_set_index(0), _tree_set(0),
3.2909 -
3.2910 - _delta2_index(0), _delta2(0),
3.2911 - _delta3_index(0), _delta3(0),
3.2912 - _delta4_index(0), _delta4(0),
3.2913 -
3.2914 - _delta_sum() {}
3.2915 -
3.2916 - ~MaxWeightedPerfectMatching() {
3.2917 - destroyStructures();
3.2918 - }
3.2919 -
3.2920 - /// \name Execution Control
3.2921 - /// The simplest way to execute the algorithm is to use the
3.2922 - /// \ref run() member function.
3.2923 -
3.2924 - ///@{
3.2925 -
3.2926 - /// \brief Initialize the algorithm
3.2927 - ///
3.2928 - /// This function initializes the algorithm.
3.2929 - void init() {
3.2930 - createStructures();
3.2931 -
3.2932 - for (ArcIt e(_graph); e != INVALID; ++e) {
3.2933 - (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3.2934 - }
3.2935 - for (EdgeIt e(_graph); e != INVALID; ++e) {
3.2936 - (*_delta3_index)[e] = _delta3->PRE_HEAP;
3.2937 - }
3.2938 - for (int i = 0; i < _blossom_num; ++i) {
3.2939 - (*_delta2_index)[i] = _delta2->PRE_HEAP;
3.2940 - (*_delta4_index)[i] = _delta4->PRE_HEAP;
3.2941 - }
3.2942 -
3.2943 - int index = 0;
3.2944 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.2945 - Value max = - std::numeric_limits<Value>::max();
3.2946 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3.2947 - if (_graph.target(e) == n) continue;
3.2948 - if ((dualScale * _weight[e]) / 2 > max) {
3.2949 - max = (dualScale * _weight[e]) / 2;
3.2950 - }
3.2951 - }
3.2952 - (*_node_index)[n] = index;
3.2953 - (*_node_data)[index].pot = max;
3.2954 - int blossom =
3.2955 - _blossom_set->insert(n, std::numeric_limits<Value>::max());
3.2956 -
3.2957 - _tree_set->insert(blossom);
3.2958 -
3.2959 - (*_blossom_data)[blossom].status = EVEN;
3.2960 - (*_blossom_data)[blossom].pred = INVALID;
3.2961 - (*_blossom_data)[blossom].next = INVALID;
3.2962 - (*_blossom_data)[blossom].pot = 0;
3.2963 - (*_blossom_data)[blossom].offset = 0;
3.2964 - ++index;
3.2965 - }
3.2966 - for (EdgeIt e(_graph); e != INVALID; ++e) {
3.2967 - int si = (*_node_index)[_graph.u(e)];
3.2968 - int ti = (*_node_index)[_graph.v(e)];
3.2969 - if (_graph.u(e) != _graph.v(e)) {
3.2970 - _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3.2971 - dualScale * _weight[e]) / 2);
3.2972 - }
3.2973 - }
3.2974 - }
3.2975 -
3.2976 - /// \brief Start the algorithm
3.2977 - ///
3.2978 - /// This function starts the algorithm.
3.2979 - ///
3.2980 - /// \pre \ref init() must be called before using this function.
3.2981 - bool start() {
3.2982 - enum OpType {
3.2983 - D2, D3, D4
3.2984 - };
3.2985 -
3.2986 - int unmatched = _node_num;
3.2987 - while (unmatched > 0) {
3.2988 - Value d2 = !_delta2->empty() ?
3.2989 - _delta2->prio() : std::numeric_limits<Value>::max();
3.2990 -
3.2991 - Value d3 = !_delta3->empty() ?
3.2992 - _delta3->prio() : std::numeric_limits<Value>::max();
3.2993 -
3.2994 - Value d4 = !_delta4->empty() ?
3.2995 - _delta4->prio() : std::numeric_limits<Value>::max();
3.2996 -
3.2997 - _delta_sum = d2; OpType ot = D2;
3.2998 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
3.2999 - if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
3.3000 -
3.3001 - if (_delta_sum == std::numeric_limits<Value>::max()) {
3.3002 - return false;
3.3003 - }
3.3004 -
3.3005 - switch (ot) {
3.3006 - case D2:
3.3007 - {
3.3008 - int blossom = _delta2->top();
3.3009 - Node n = _blossom_set->classTop(blossom);
3.3010 - Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3.3011 - extendOnArc(e);
3.3012 - }
3.3013 - break;
3.3014 - case D3:
3.3015 - {
3.3016 - Edge e = _delta3->top();
3.3017 -
3.3018 - int left_blossom = _blossom_set->find(_graph.u(e));
3.3019 - int right_blossom = _blossom_set->find(_graph.v(e));
3.3020 -
3.3021 - if (left_blossom == right_blossom) {
3.3022 - _delta3->pop();
3.3023 - } else {
3.3024 - int left_tree = _tree_set->find(left_blossom);
3.3025 - int right_tree = _tree_set->find(right_blossom);
3.3026 -
3.3027 - if (left_tree == right_tree) {
3.3028 - shrinkOnEdge(e, left_tree);
3.3029 - } else {
3.3030 - augmentOnEdge(e);
3.3031 - unmatched -= 2;
3.3032 - }
3.3033 - }
3.3034 - } break;
3.3035 - case D4:
3.3036 - splitBlossom(_delta4->top());
3.3037 - break;
3.3038 - }
3.3039 - }
3.3040 - extractMatching();
3.3041 - return true;
3.3042 - }
3.3043 -
3.3044 - /// \brief Run the algorithm.
3.3045 - ///
3.3046 - /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3.3047 - ///
3.3048 - /// \note mwpm.run() is just a shortcut of the following code.
3.3049 - /// \code
3.3050 - /// mwpm.init();
3.3051 - /// mwpm.start();
3.3052 - /// \endcode
3.3053 - bool run() {
3.3054 - init();
3.3055 - return start();
3.3056 - }
3.3057 -
3.3058 - /// @}
3.3059 -
3.3060 - /// \name Primal Solution
3.3061 - /// Functions to get the primal solution, i.e. the maximum weighted
3.3062 - /// perfect matching.\n
3.3063 - /// Either \ref run() or \ref start() function should be called before
3.3064 - /// using them.
3.3065 -
3.3066 - /// @{
3.3067 -
3.3068 - /// \brief Return the weight of the matching.
3.3069 - ///
3.3070 - /// This function returns the weight of the found matching.
3.3071 - ///
3.3072 - /// \pre Either run() or start() must be called before using this function.
3.3073 - Value matchingWeight() const {
3.3074 - Value sum = 0;
3.3075 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.3076 - if ((*_matching)[n] != INVALID) {
3.3077 - sum += _weight[(*_matching)[n]];
3.3078 - }
3.3079 - }
3.3080 - return sum /= 2;
3.3081 - }
3.3082 -
3.3083 - /// \brief Return \c true if the given edge is in the matching.
3.3084 - ///
3.3085 - /// This function returns \c true if the given edge is in the found
3.3086 - /// matching.
3.3087 - ///
3.3088 - /// \pre Either run() or start() must be called before using this function.
3.3089 - bool matching(const Edge& edge) const {
3.3090 - return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3.3091 - }
3.3092 -
3.3093 - /// \brief Return the matching arc (or edge) incident to the given node.
3.3094 - ///
3.3095 - /// This function returns the matching arc (or edge) incident to the
3.3096 - /// given node in the found matching or \c INVALID if the node is
3.3097 - /// not covered by the matching.
3.3098 - ///
3.3099 - /// \pre Either run() or start() must be called before using this function.
3.3100 - Arc matching(const Node& node) const {
3.3101 - return (*_matching)[node];
3.3102 - }
3.3103 -
3.3104 - /// \brief Return a const reference to the matching map.
3.3105 - ///
3.3106 - /// This function returns a const reference to a node map that stores
3.3107 - /// the matching arc (or edge) incident to each node.
3.3108 - const MatchingMap& matchingMap() const {
3.3109 - return *_matching;
3.3110 - }
3.3111 -
3.3112 - /// \brief Return the mate of the given node.
3.3113 - ///
3.3114 - /// This function returns the mate of the given node in the found
3.3115 - /// matching or \c INVALID if the node is not covered by the matching.
3.3116 - ///
3.3117 - /// \pre Either run() or start() must be called before using this function.
3.3118 - Node mate(const Node& node) const {
3.3119 - return _graph.target((*_matching)[node]);
3.3120 - }
3.3121 -
3.3122 - /// @}
3.3123 -
3.3124 - /// \name Dual Solution
3.3125 - /// Functions to get the dual solution.\n
3.3126 - /// Either \ref run() or \ref start() function should be called before
3.3127 - /// using them.
3.3128 -
3.3129 - /// @{
3.3130 -
3.3131 - /// \brief Return the value of the dual solution.
3.3132 - ///
3.3133 - /// This function returns the value of the dual solution.
3.3134 - /// It should be equal to the primal value scaled by \ref dualScale
3.3135 - /// "dual scale".
3.3136 - ///
3.3137 - /// \pre Either run() or start() must be called before using this function.
3.3138 - Value dualValue() const {
3.3139 - Value sum = 0;
3.3140 - for (NodeIt n(_graph); n != INVALID; ++n) {
3.3141 - sum += nodeValue(n);
3.3142 - }
3.3143 - for (int i = 0; i < blossomNum(); ++i) {
3.3144 - sum += blossomValue(i) * (blossomSize(i) / 2);
3.3145 - }
3.3146 - return sum;
3.3147 - }
3.3148 -
3.3149 - /// \brief Return the dual value (potential) of the given node.
3.3150 - ///
3.3151 - /// This function returns the dual value (potential) of the given node.
3.3152 - ///
3.3153 - /// \pre Either run() or start() must be called before using this function.
3.3154 - Value nodeValue(const Node& n) const {
3.3155 - return (*_node_potential)[n];
3.3156 - }
3.3157 -
3.3158 - /// \brief Return the number of the blossoms in the basis.
3.3159 - ///
3.3160 - /// This function returns the number of the blossoms in the basis.
3.3161 - ///
3.3162 - /// \pre Either run() or start() must be called before using this function.
3.3163 - /// \see BlossomIt
3.3164 - int blossomNum() const {
3.3165 - return _blossom_potential.size();
3.3166 - }
3.3167 -
3.3168 - /// \brief Return the number of the nodes in the given blossom.
3.3169 - ///
3.3170 - /// This function returns the number of the nodes in the given blossom.
3.3171 - ///
3.3172 - /// \pre Either run() or start() must be called before using this function.
3.3173 - /// \see BlossomIt
3.3174 - int blossomSize(int k) const {
3.3175 - return _blossom_potential[k].end - _blossom_potential[k].begin;
3.3176 - }
3.3177 -
3.3178 - /// \brief Return the dual value (ptential) of the given blossom.
3.3179 - ///
3.3180 - /// This function returns the dual value (ptential) of the given blossom.
3.3181 - ///
3.3182 - /// \pre Either run() or start() must be called before using this function.
3.3183 - Value blossomValue(int k) const {
3.3184 - return _blossom_potential[k].value;
3.3185 - }
3.3186 -
3.3187 - /// \brief Iterator for obtaining the nodes of a blossom.
3.3188 - ///
3.3189 - /// This class provides an iterator for obtaining the nodes of the
3.3190 - /// given blossom. It lists a subset of the nodes.
3.3191 - /// Before using this iterator, you must allocate a
3.3192 - /// MaxWeightedPerfectMatching class and execute it.
3.3193 - class BlossomIt {
3.3194 - public:
3.3195 -
3.3196 - /// \brief Constructor.
3.3197 - ///
3.3198 - /// Constructor to get the nodes of the given variable.
3.3199 - ///
3.3200 - /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3.3201 - /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3.3202 - /// must be called before initializing this iterator.
3.3203 - BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3.3204 - : _algorithm(&algorithm)
3.3205 - {
3.3206 - _index = _algorithm->_blossom_potential[variable].begin;
3.3207 - _last = _algorithm->_blossom_potential[variable].end;
3.3208 - }
3.3209 -
3.3210 - /// \brief Conversion to \c Node.
3.3211 - ///
3.3212 - /// Conversion to \c Node.
3.3213 - operator Node() const {
3.3214 - return _algorithm->_blossom_node_list[_index];
3.3215 - }
3.3216 -
3.3217 - /// \brief Increment operator.
3.3218 - ///
3.3219 - /// Increment operator.
3.3220 - BlossomIt& operator++() {
3.3221 - ++_index;
3.3222 - return *this;
3.3223 - }
3.3224 -
3.3225 - /// \brief Validity checking
3.3226 - ///
3.3227 - /// This function checks whether the iterator is invalid.
3.3228 - bool operator==(Invalid) const { return _index == _last; }
3.3229 -
3.3230 - /// \brief Validity checking
3.3231 - ///
3.3232 - /// This function checks whether the iterator is valid.
3.3233 - bool operator!=(Invalid) const { return _index != _last; }
3.3234 -
3.3235 - private:
3.3236 - const MaxWeightedPerfectMatching* _algorithm;
3.3237 - int _last;
3.3238 - int _index;
3.3239 - };
3.3240 -
3.3241 - /// @}
3.3242 -
3.3243 - };
3.3244 -
3.3245 -} //END OF NAMESPACE LEMON
3.3246 -
3.3247 -#endif //LEMON_MAX_MATCHING_H
4.1 --- a/test/CMakeLists.txt Fri Apr 17 09:54:14 2009 +0200
4.2 +++ b/test/CMakeLists.txt Fri Apr 17 09:58:50 2009 +0200
4.3 @@ -29,7 +29,7 @@
4.4 heap_test
4.5 kruskal_test
4.6 maps_test
4.7 - max_matching_test
4.8 + matching_test
4.9 min_cost_arborescence_test
4.10 path_test
4.11 preflow_test
5.1 --- a/test/Makefile.am Fri Apr 17 09:54:14 2009 +0200
5.2 +++ b/test/Makefile.am Fri Apr 17 09:58:50 2009 +0200
5.3 @@ -25,7 +25,7 @@
5.4 test/heap_test \
5.5 test/kruskal_test \
5.6 test/maps_test \
5.7 - test/max_matching_test \
5.8 + test/matching_test \
5.9 test/min_cost_arborescence_test \
5.10 test/path_test \
5.11 test/preflow_test \
5.12 @@ -70,7 +70,7 @@
5.13 test_lp_test_SOURCES = test/lp_test.cc
5.14 test_maps_test_SOURCES = test/maps_test.cc
5.15 test_mip_test_SOURCES = test/mip_test.cc
5.16 -test_max_matching_test_SOURCES = test/max_matching_test.cc
5.17 +test_matching_test_SOURCES = test/matching_test.cc
5.18 test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
5.19 test_path_test_SOURCES = test/path_test.cc
5.20 test_preflow_test_SOURCES = test/preflow_test.cc
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/test/matching_test.cc Fri Apr 17 09:58:50 2009 +0200
6.3 @@ -0,0 +1,424 @@
6.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
6.5 + *
6.6 + * This file is a part of LEMON, a generic C++ optimization library.
6.7 + *
6.8 + * Copyright (C) 2003-2009
6.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
6.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
6.11 + *
6.12 + * Permission to use, modify and distribute this software is granted
6.13 + * provided that this copyright notice appears in all copies. For
6.14 + * precise terms see the accompanying LICENSE file.
6.15 + *
6.16 + * This software is provided "AS IS" with no warranty of any kind,
6.17 + * express or implied, and with no claim as to its suitability for any
6.18 + * purpose.
6.19 + *
6.20 + */
6.21 +
6.22 +#include <iostream>
6.23 +#include <sstream>
6.24 +#include <vector>
6.25 +#include <queue>
6.26 +#include <cstdlib>
6.27 +
6.28 +#include <lemon/matching.h>
6.29 +#include <lemon/smart_graph.h>
6.30 +#include <lemon/concepts/graph.h>
6.31 +#include <lemon/concepts/maps.h>
6.32 +#include <lemon/lgf_reader.h>
6.33 +#include <lemon/math.h>
6.34 +
6.35 +#include "test_tools.h"
6.36 +
6.37 +using namespace std;
6.38 +using namespace lemon;
6.39 +
6.40 +GRAPH_TYPEDEFS(SmartGraph);
6.41 +
6.42 +
6.43 +const int lgfn = 3;
6.44 +const std::string lgf[lgfn] = {
6.45 + "@nodes\n"
6.46 + "label\n"
6.47 + "0\n"
6.48 + "1\n"
6.49 + "2\n"
6.50 + "3\n"
6.51 + "4\n"
6.52 + "5\n"
6.53 + "6\n"
6.54 + "7\n"
6.55 + "@edges\n"
6.56 + " label weight\n"
6.57 + "7 4 0 984\n"
6.58 + "0 7 1 73\n"
6.59 + "7 1 2 204\n"
6.60 + "2 3 3 583\n"
6.61 + "2 7 4 565\n"
6.62 + "2 1 5 582\n"
6.63 + "0 4 6 551\n"
6.64 + "2 5 7 385\n"
6.65 + "1 5 8 561\n"
6.66 + "5 3 9 484\n"
6.67 + "7 5 10 904\n"
6.68 + "3 6 11 47\n"
6.69 + "7 6 12 888\n"
6.70 + "3 0 13 747\n"
6.71 + "6 1 14 310\n",
6.72 +
6.73 + "@nodes\n"
6.74 + "label\n"
6.75 + "0\n"
6.76 + "1\n"
6.77 + "2\n"
6.78 + "3\n"
6.79 + "4\n"
6.80 + "5\n"
6.81 + "6\n"
6.82 + "7\n"
6.83 + "@edges\n"
6.84 + " label weight\n"
6.85 + "2 5 0 710\n"
6.86 + "0 5 1 241\n"
6.87 + "2 4 2 856\n"
6.88 + "2 6 3 762\n"
6.89 + "4 1 4 747\n"
6.90 + "6 1 5 962\n"
6.91 + "4 7 6 723\n"
6.92 + "1 7 7 661\n"
6.93 + "2 3 8 376\n"
6.94 + "1 0 9 416\n"
6.95 + "6 7 10 391\n",
6.96 +
6.97 + "@nodes\n"
6.98 + "label\n"
6.99 + "0\n"
6.100 + "1\n"
6.101 + "2\n"
6.102 + "3\n"
6.103 + "4\n"
6.104 + "5\n"
6.105 + "6\n"
6.106 + "7\n"
6.107 + "@edges\n"
6.108 + " label weight\n"
6.109 + "6 2 0 553\n"
6.110 + "0 7 1 653\n"
6.111 + "6 3 2 22\n"
6.112 + "4 7 3 846\n"
6.113 + "7 2 4 981\n"
6.114 + "7 6 5 250\n"
6.115 + "5 2 6 539\n",
6.116 +};
6.117 +
6.118 +void checkMaxMatchingCompile()
6.119 +{
6.120 + typedef concepts::Graph Graph;
6.121 + typedef Graph::Node Node;
6.122 + typedef Graph::Edge Edge;
6.123 + typedef Graph::EdgeMap<bool> MatMap;
6.124 +
6.125 + Graph g;
6.126 + Node n;
6.127 + Edge e;
6.128 + MatMap mat(g);
6.129 +
6.130 + MaxMatching<Graph> mat_test(g);
6.131 + const MaxMatching<Graph>&
6.132 + const_mat_test = mat_test;
6.133 +
6.134 + mat_test.init();
6.135 + mat_test.greedyInit();
6.136 + mat_test.matchingInit(mat);
6.137 + mat_test.startSparse();
6.138 + mat_test.startDense();
6.139 + mat_test.run();
6.140 +
6.141 + const_mat_test.matchingSize();
6.142 + const_mat_test.matching(e);
6.143 + const_mat_test.matching(n);
6.144 + const MaxMatching<Graph>::MatchingMap& mmap =
6.145 + const_mat_test.matchingMap();
6.146 + e = mmap[n];
6.147 + const_mat_test.mate(n);
6.148 +
6.149 + MaxMatching<Graph>::Status stat =
6.150 + const_mat_test.status(n);
6.151 + const MaxMatching<Graph>::StatusMap& smap =
6.152 + const_mat_test.statusMap();
6.153 + stat = smap[n];
6.154 + const_mat_test.barrier(n);
6.155 +}
6.156 +
6.157 +void checkMaxWeightedMatchingCompile()
6.158 +{
6.159 + typedef concepts::Graph Graph;
6.160 + typedef Graph::Node Node;
6.161 + typedef Graph::Edge Edge;
6.162 + typedef Graph::EdgeMap<int> WeightMap;
6.163 +
6.164 + Graph g;
6.165 + Node n;
6.166 + Edge e;
6.167 + WeightMap w(g);
6.168 +
6.169 + MaxWeightedMatching<Graph> mat_test(g, w);
6.170 + const MaxWeightedMatching<Graph>&
6.171 + const_mat_test = mat_test;
6.172 +
6.173 + mat_test.init();
6.174 + mat_test.start();
6.175 + mat_test.run();
6.176 +
6.177 + const_mat_test.matchingWeight();
6.178 + const_mat_test.matchingSize();
6.179 + const_mat_test.matching(e);
6.180 + const_mat_test.matching(n);
6.181 + const MaxWeightedMatching<Graph>::MatchingMap& mmap =
6.182 + const_mat_test.matchingMap();
6.183 + e = mmap[n];
6.184 + const_mat_test.mate(n);
6.185 +
6.186 + int k = 0;
6.187 + const_mat_test.dualValue();
6.188 + const_mat_test.nodeValue(n);
6.189 + const_mat_test.blossomNum();
6.190 + const_mat_test.blossomSize(k);
6.191 + const_mat_test.blossomValue(k);
6.192 +}
6.193 +
6.194 +void checkMaxWeightedPerfectMatchingCompile()
6.195 +{
6.196 + typedef concepts::Graph Graph;
6.197 + typedef Graph::Node Node;
6.198 + typedef Graph::Edge Edge;
6.199 + typedef Graph::EdgeMap<int> WeightMap;
6.200 +
6.201 + Graph g;
6.202 + Node n;
6.203 + Edge e;
6.204 + WeightMap w(g);
6.205 +
6.206 + MaxWeightedPerfectMatching<Graph> mat_test(g, w);
6.207 + const MaxWeightedPerfectMatching<Graph>&
6.208 + const_mat_test = mat_test;
6.209 +
6.210 + mat_test.init();
6.211 + mat_test.start();
6.212 + mat_test.run();
6.213 +
6.214 + const_mat_test.matchingWeight();
6.215 + const_mat_test.matching(e);
6.216 + const_mat_test.matching(n);
6.217 + const MaxWeightedPerfectMatching<Graph>::MatchingMap& mmap =
6.218 + const_mat_test.matchingMap();
6.219 + e = mmap[n];
6.220 + const_mat_test.mate(n);
6.221 +
6.222 + int k = 0;
6.223 + const_mat_test.dualValue();
6.224 + const_mat_test.nodeValue(n);
6.225 + const_mat_test.blossomNum();
6.226 + const_mat_test.blossomSize(k);
6.227 + const_mat_test.blossomValue(k);
6.228 +}
6.229 +
6.230 +void checkMatching(const SmartGraph& graph,
6.231 + const MaxMatching<SmartGraph>& mm) {
6.232 + int num = 0;
6.233 +
6.234 + IntNodeMap comp_index(graph);
6.235 + UnionFind<IntNodeMap> comp(comp_index);
6.236 +
6.237 + int barrier_num = 0;
6.238 +
6.239 + for (NodeIt n(graph); n != INVALID; ++n) {
6.240 + check(mm.status(n) == MaxMatching<SmartGraph>::EVEN ||
6.241 + mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
6.242 + if (mm.status(n) == MaxMatching<SmartGraph>::ODD) {
6.243 + ++barrier_num;
6.244 + } else {
6.245 + comp.insert(n);
6.246 + }
6.247 + }
6.248 +
6.249 + for (EdgeIt e(graph); e != INVALID; ++e) {
6.250 + if (mm.matching(e)) {
6.251 + check(e == mm.matching(graph.u(e)), "Wrong matching");
6.252 + check(e == mm.matching(graph.v(e)), "Wrong matching");
6.253 + ++num;
6.254 + }
6.255 + check(mm.status(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
6.256 + mm.status(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
6.257 + "Wrong Gallai-Edmonds decomposition");
6.258 +
6.259 + check(mm.status(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
6.260 + mm.status(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
6.261 + "Wrong Gallai-Edmonds decomposition");
6.262 +
6.263 + if (mm.status(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
6.264 + mm.status(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
6.265 + comp.join(graph.u(e), graph.v(e));
6.266 + }
6.267 + }
6.268 +
6.269 + std::set<int> comp_root;
6.270 + int odd_comp_num = 0;
6.271 + for (NodeIt n(graph); n != INVALID; ++n) {
6.272 + if (mm.status(n) != MaxMatching<SmartGraph>::ODD) {
6.273 + int root = comp.find(n);
6.274 + if (comp_root.find(root) == comp_root.end()) {
6.275 + comp_root.insert(root);
6.276 + if (comp.size(n) % 2 == 1) {
6.277 + ++odd_comp_num;
6.278 + }
6.279 + }
6.280 + }
6.281 + }
6.282 +
6.283 + check(mm.matchingSize() == num, "Wrong matching");
6.284 + check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
6.285 + "Wrong matching");
6.286 + return;
6.287 +}
6.288 +
6.289 +void checkWeightedMatching(const SmartGraph& graph,
6.290 + const SmartGraph::EdgeMap<int>& weight,
6.291 + const MaxWeightedMatching<SmartGraph>& mwm) {
6.292 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
6.293 + if (graph.u(e) == graph.v(e)) continue;
6.294 + int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
6.295 +
6.296 + for (int i = 0; i < mwm.blossomNum(); ++i) {
6.297 + bool s = false, t = false;
6.298 + for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
6.299 + n != INVALID; ++n) {
6.300 + if (graph.u(e) == n) s = true;
6.301 + if (graph.v(e) == n) t = true;
6.302 + }
6.303 + if (s == true && t == true) {
6.304 + rw += mwm.blossomValue(i);
6.305 + }
6.306 + }
6.307 + rw -= weight[e] * mwm.dualScale;
6.308 +
6.309 + check(rw >= 0, "Negative reduced weight");
6.310 + check(rw == 0 || !mwm.matching(e),
6.311 + "Non-zero reduced weight on matching edge");
6.312 + }
6.313 +
6.314 + int pv = 0;
6.315 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
6.316 + if (mwm.matching(n) != INVALID) {
6.317 + check(mwm.nodeValue(n) >= 0, "Invalid node value");
6.318 + pv += weight[mwm.matching(n)];
6.319 + SmartGraph::Node o = graph.target(mwm.matching(n));
6.320 + check(mwm.mate(n) == o, "Invalid matching");
6.321 + check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
6.322 + "Invalid matching");
6.323 + } else {
6.324 + check(mwm.mate(n) == INVALID, "Invalid matching");
6.325 + check(mwm.nodeValue(n) == 0, "Invalid matching");
6.326 + }
6.327 + }
6.328 +
6.329 + int dv = 0;
6.330 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
6.331 + dv += mwm.nodeValue(n);
6.332 + }
6.333 +
6.334 + for (int i = 0; i < mwm.blossomNum(); ++i) {
6.335 + check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
6.336 + check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
6.337 + dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
6.338 + }
6.339 +
6.340 + check(pv * mwm.dualScale == dv * 2, "Wrong duality");
6.341 +
6.342 + return;
6.343 +}
6.344 +
6.345 +void checkWeightedPerfectMatching(const SmartGraph& graph,
6.346 + const SmartGraph::EdgeMap<int>& weight,
6.347 + const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
6.348 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
6.349 + if (graph.u(e) == graph.v(e)) continue;
6.350 + int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
6.351 +
6.352 + for (int i = 0; i < mwpm.blossomNum(); ++i) {
6.353 + bool s = false, t = false;
6.354 + for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
6.355 + n != INVALID; ++n) {
6.356 + if (graph.u(e) == n) s = true;
6.357 + if (graph.v(e) == n) t = true;
6.358 + }
6.359 + if (s == true && t == true) {
6.360 + rw += mwpm.blossomValue(i);
6.361 + }
6.362 + }
6.363 + rw -= weight[e] * mwpm.dualScale;
6.364 +
6.365 + check(rw >= 0, "Negative reduced weight");
6.366 + check(rw == 0 || !mwpm.matching(e),
6.367 + "Non-zero reduced weight on matching edge");
6.368 + }
6.369 +
6.370 + int pv = 0;
6.371 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
6.372 + check(mwpm.matching(n) != INVALID, "Non perfect");
6.373 + pv += weight[mwpm.matching(n)];
6.374 + SmartGraph::Node o = graph.target(mwpm.matching(n));
6.375 + check(mwpm.mate(n) == o, "Invalid matching");
6.376 + check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
6.377 + "Invalid matching");
6.378 + }
6.379 +
6.380 + int dv = 0;
6.381 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
6.382 + dv += mwpm.nodeValue(n);
6.383 + }
6.384 +
6.385 + for (int i = 0; i < mwpm.blossomNum(); ++i) {
6.386 + check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
6.387 + check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
6.388 + dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
6.389 + }
6.390 +
6.391 + check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
6.392 +
6.393 + return;
6.394 +}
6.395 +
6.396 +
6.397 +int main() {
6.398 +
6.399 + for (int i = 0; i < lgfn; ++i) {
6.400 + SmartGraph graph;
6.401 + SmartGraph::EdgeMap<int> weight(graph);
6.402 +
6.403 + istringstream lgfs(lgf[i]);
6.404 + graphReader(graph, lgfs).
6.405 + edgeMap("weight", weight).run();
6.406 +
6.407 + MaxMatching<SmartGraph> mm(graph);
6.408 + mm.run();
6.409 + checkMatching(graph, mm);
6.410 +
6.411 + MaxWeightedMatching<SmartGraph> mwm(graph, weight);
6.412 + mwm.run();
6.413 + checkWeightedMatching(graph, weight, mwm);
6.414 +
6.415 + MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
6.416 + bool perfect = mwpm.run();
6.417 +
6.418 + check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
6.419 + "Perfect matching found");
6.420 +
6.421 + if (perfect) {
6.422 + checkWeightedPerfectMatching(graph, weight, mwpm);
6.423 + }
6.424 + }
6.425 +
6.426 + return 0;
6.427 +}
7.1 --- a/test/max_matching_test.cc Fri Apr 17 09:54:14 2009 +0200
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,424 +0,0 @@
7.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
7.5 - *
7.6 - * This file is a part of LEMON, a generic C++ optimization library.
7.7 - *
7.8 - * Copyright (C) 2003-2009
7.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
7.11 - *
7.12 - * Permission to use, modify and distribute this software is granted
7.13 - * provided that this copyright notice appears in all copies. For
7.14 - * precise terms see the accompanying LICENSE file.
7.15 - *
7.16 - * This software is provided "AS IS" with no warranty of any kind,
7.17 - * express or implied, and with no claim as to its suitability for any
7.18 - * purpose.
7.19 - *
7.20 - */
7.21 -
7.22 -#include <iostream>
7.23 -#include <sstream>
7.24 -#include <vector>
7.25 -#include <queue>
7.26 -#include <cstdlib>
7.27 -
7.28 -#include <lemon/max_matching.h>
7.29 -#include <lemon/smart_graph.h>
7.30 -#include <lemon/concepts/graph.h>
7.31 -#include <lemon/concepts/maps.h>
7.32 -#include <lemon/lgf_reader.h>
7.33 -#include <lemon/math.h>
7.34 -
7.35 -#include "test_tools.h"
7.36 -
7.37 -using namespace std;
7.38 -using namespace lemon;
7.39 -
7.40 -GRAPH_TYPEDEFS(SmartGraph);
7.41 -
7.42 -
7.43 -const int lgfn = 3;
7.44 -const std::string lgf[lgfn] = {
7.45 - "@nodes\n"
7.46 - "label\n"
7.47 - "0\n"
7.48 - "1\n"
7.49 - "2\n"
7.50 - "3\n"
7.51 - "4\n"
7.52 - "5\n"
7.53 - "6\n"
7.54 - "7\n"
7.55 - "@edges\n"
7.56 - " label weight\n"
7.57 - "7 4 0 984\n"
7.58 - "0 7 1 73\n"
7.59 - "7 1 2 204\n"
7.60 - "2 3 3 583\n"
7.61 - "2 7 4 565\n"
7.62 - "2 1 5 582\n"
7.63 - "0 4 6 551\n"
7.64 - "2 5 7 385\n"
7.65 - "1 5 8 561\n"
7.66 - "5 3 9 484\n"
7.67 - "7 5 10 904\n"
7.68 - "3 6 11 47\n"
7.69 - "7 6 12 888\n"
7.70 - "3 0 13 747\n"
7.71 - "6 1 14 310\n",
7.72 -
7.73 - "@nodes\n"
7.74 - "label\n"
7.75 - "0\n"
7.76 - "1\n"
7.77 - "2\n"
7.78 - "3\n"
7.79 - "4\n"
7.80 - "5\n"
7.81 - "6\n"
7.82 - "7\n"
7.83 - "@edges\n"
7.84 - " label weight\n"
7.85 - "2 5 0 710\n"
7.86 - "0 5 1 241\n"
7.87 - "2 4 2 856\n"
7.88 - "2 6 3 762\n"
7.89 - "4 1 4 747\n"
7.90 - "6 1 5 962\n"
7.91 - "4 7 6 723\n"
7.92 - "1 7 7 661\n"
7.93 - "2 3 8 376\n"
7.94 - "1 0 9 416\n"
7.95 - "6 7 10 391\n",
7.96 -
7.97 - "@nodes\n"
7.98 - "label\n"
7.99 - "0\n"
7.100 - "1\n"
7.101 - "2\n"
7.102 - "3\n"
7.103 - "4\n"
7.104 - "5\n"
7.105 - "6\n"
7.106 - "7\n"
7.107 - "@edges\n"
7.108 - " label weight\n"
7.109 - "6 2 0 553\n"
7.110 - "0 7 1 653\n"
7.111 - "6 3 2 22\n"
7.112 - "4 7 3 846\n"
7.113 - "7 2 4 981\n"
7.114 - "7 6 5 250\n"
7.115 - "5 2 6 539\n",
7.116 -};
7.117 -
7.118 -void checkMaxMatchingCompile()
7.119 -{
7.120 - typedef concepts::Graph Graph;
7.121 - typedef Graph::Node Node;
7.122 - typedef Graph::Edge Edge;
7.123 - typedef Graph::EdgeMap<bool> MatMap;
7.124 -
7.125 - Graph g;
7.126 - Node n;
7.127 - Edge e;
7.128 - MatMap mat(g);
7.129 -
7.130 - MaxMatching<Graph> mat_test(g);
7.131 - const MaxMatching<Graph>&
7.132 - const_mat_test = mat_test;
7.133 -
7.134 - mat_test.init();
7.135 - mat_test.greedyInit();
7.136 - mat_test.matchingInit(mat);
7.137 - mat_test.startSparse();
7.138 - mat_test.startDense();
7.139 - mat_test.run();
7.140 -
7.141 - const_mat_test.matchingSize();
7.142 - const_mat_test.matching(e);
7.143 - const_mat_test.matching(n);
7.144 - const MaxMatching<Graph>::MatchingMap& mmap =
7.145 - const_mat_test.matchingMap();
7.146 - e = mmap[n];
7.147 - const_mat_test.mate(n);
7.148 -
7.149 - MaxMatching<Graph>::Status stat =
7.150 - const_mat_test.status(n);
7.151 - const MaxMatching<Graph>::StatusMap& smap =
7.152 - const_mat_test.statusMap();
7.153 - stat = smap[n];
7.154 - const_mat_test.barrier(n);
7.155 -}
7.156 -
7.157 -void checkMaxWeightedMatchingCompile()
7.158 -{
7.159 - typedef concepts::Graph Graph;
7.160 - typedef Graph::Node Node;
7.161 - typedef Graph::Edge Edge;
7.162 - typedef Graph::EdgeMap<int> WeightMap;
7.163 -
7.164 - Graph g;
7.165 - Node n;
7.166 - Edge e;
7.167 - WeightMap w(g);
7.168 -
7.169 - MaxWeightedMatching<Graph> mat_test(g, w);
7.170 - const MaxWeightedMatching<Graph>&
7.171 - const_mat_test = mat_test;
7.172 -
7.173 - mat_test.init();
7.174 - mat_test.start();
7.175 - mat_test.run();
7.176 -
7.177 - const_mat_test.matchingWeight();
7.178 - const_mat_test.matchingSize();
7.179 - const_mat_test.matching(e);
7.180 - const_mat_test.matching(n);
7.181 - const MaxWeightedMatching<Graph>::MatchingMap& mmap =
7.182 - const_mat_test.matchingMap();
7.183 - e = mmap[n];
7.184 - const_mat_test.mate(n);
7.185 -
7.186 - int k = 0;
7.187 - const_mat_test.dualValue();
7.188 - const_mat_test.nodeValue(n);
7.189 - const_mat_test.blossomNum();
7.190 - const_mat_test.blossomSize(k);
7.191 - const_mat_test.blossomValue(k);
7.192 -}
7.193 -
7.194 -void checkMaxWeightedPerfectMatchingCompile()
7.195 -{
7.196 - typedef concepts::Graph Graph;
7.197 - typedef Graph::Node Node;
7.198 - typedef Graph::Edge Edge;
7.199 - typedef Graph::EdgeMap<int> WeightMap;
7.200 -
7.201 - Graph g;
7.202 - Node n;
7.203 - Edge e;
7.204 - WeightMap w(g);
7.205 -
7.206 - MaxWeightedPerfectMatching<Graph> mat_test(g, w);
7.207 - const MaxWeightedPerfectMatching<Graph>&
7.208 - const_mat_test = mat_test;
7.209 -
7.210 - mat_test.init();
7.211 - mat_test.start();
7.212 - mat_test.run();
7.213 -
7.214 - const_mat_test.matchingWeight();
7.215 - const_mat_test.matching(e);
7.216 - const_mat_test.matching(n);
7.217 - const MaxWeightedPerfectMatching<Graph>::MatchingMap& mmap =
7.218 - const_mat_test.matchingMap();
7.219 - e = mmap[n];
7.220 - const_mat_test.mate(n);
7.221 -
7.222 - int k = 0;
7.223 - const_mat_test.dualValue();
7.224 - const_mat_test.nodeValue(n);
7.225 - const_mat_test.blossomNum();
7.226 - const_mat_test.blossomSize(k);
7.227 - const_mat_test.blossomValue(k);
7.228 -}
7.229 -
7.230 -void checkMatching(const SmartGraph& graph,
7.231 - const MaxMatching<SmartGraph>& mm) {
7.232 - int num = 0;
7.233 -
7.234 - IntNodeMap comp_index(graph);
7.235 - UnionFind<IntNodeMap> comp(comp_index);
7.236 -
7.237 - int barrier_num = 0;
7.238 -
7.239 - for (NodeIt n(graph); n != INVALID; ++n) {
7.240 - check(mm.status(n) == MaxMatching<SmartGraph>::EVEN ||
7.241 - mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
7.242 - if (mm.status(n) == MaxMatching<SmartGraph>::ODD) {
7.243 - ++barrier_num;
7.244 - } else {
7.245 - comp.insert(n);
7.246 - }
7.247 - }
7.248 -
7.249 - for (EdgeIt e(graph); e != INVALID; ++e) {
7.250 - if (mm.matching(e)) {
7.251 - check(e == mm.matching(graph.u(e)), "Wrong matching");
7.252 - check(e == mm.matching(graph.v(e)), "Wrong matching");
7.253 - ++num;
7.254 - }
7.255 - check(mm.status(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
7.256 - mm.status(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
7.257 - "Wrong Gallai-Edmonds decomposition");
7.258 -
7.259 - check(mm.status(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
7.260 - mm.status(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
7.261 - "Wrong Gallai-Edmonds decomposition");
7.262 -
7.263 - if (mm.status(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
7.264 - mm.status(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
7.265 - comp.join(graph.u(e), graph.v(e));
7.266 - }
7.267 - }
7.268 -
7.269 - std::set<int> comp_root;
7.270 - int odd_comp_num = 0;
7.271 - for (NodeIt n(graph); n != INVALID; ++n) {
7.272 - if (mm.status(n) != MaxMatching<SmartGraph>::ODD) {
7.273 - int root = comp.find(n);
7.274 - if (comp_root.find(root) == comp_root.end()) {
7.275 - comp_root.insert(root);
7.276 - if (comp.size(n) % 2 == 1) {
7.277 - ++odd_comp_num;
7.278 - }
7.279 - }
7.280 - }
7.281 - }
7.282 -
7.283 - check(mm.matchingSize() == num, "Wrong matching");
7.284 - check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
7.285 - "Wrong matching");
7.286 - return;
7.287 -}
7.288 -
7.289 -void checkWeightedMatching(const SmartGraph& graph,
7.290 - const SmartGraph::EdgeMap<int>& weight,
7.291 - const MaxWeightedMatching<SmartGraph>& mwm) {
7.292 - for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
7.293 - if (graph.u(e) == graph.v(e)) continue;
7.294 - int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
7.295 -
7.296 - for (int i = 0; i < mwm.blossomNum(); ++i) {
7.297 - bool s = false, t = false;
7.298 - for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
7.299 - n != INVALID; ++n) {
7.300 - if (graph.u(e) == n) s = true;
7.301 - if (graph.v(e) == n) t = true;
7.302 - }
7.303 - if (s == true && t == true) {
7.304 - rw += mwm.blossomValue(i);
7.305 - }
7.306 - }
7.307 - rw -= weight[e] * mwm.dualScale;
7.308 -
7.309 - check(rw >= 0, "Negative reduced weight");
7.310 - check(rw == 0 || !mwm.matching(e),
7.311 - "Non-zero reduced weight on matching edge");
7.312 - }
7.313 -
7.314 - int pv = 0;
7.315 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
7.316 - if (mwm.matching(n) != INVALID) {
7.317 - check(mwm.nodeValue(n) >= 0, "Invalid node value");
7.318 - pv += weight[mwm.matching(n)];
7.319 - SmartGraph::Node o = graph.target(mwm.matching(n));
7.320 - check(mwm.mate(n) == o, "Invalid matching");
7.321 - check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
7.322 - "Invalid matching");
7.323 - } else {
7.324 - check(mwm.mate(n) == INVALID, "Invalid matching");
7.325 - check(mwm.nodeValue(n) == 0, "Invalid matching");
7.326 - }
7.327 - }
7.328 -
7.329 - int dv = 0;
7.330 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
7.331 - dv += mwm.nodeValue(n);
7.332 - }
7.333 -
7.334 - for (int i = 0; i < mwm.blossomNum(); ++i) {
7.335 - check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
7.336 - check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
7.337 - dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
7.338 - }
7.339 -
7.340 - check(pv * mwm.dualScale == dv * 2, "Wrong duality");
7.341 -
7.342 - return;
7.343 -}
7.344 -
7.345 -void checkWeightedPerfectMatching(const SmartGraph& graph,
7.346 - const SmartGraph::EdgeMap<int>& weight,
7.347 - const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
7.348 - for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
7.349 - if (graph.u(e) == graph.v(e)) continue;
7.350 - int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
7.351 -
7.352 - for (int i = 0; i < mwpm.blossomNum(); ++i) {
7.353 - bool s = false, t = false;
7.354 - for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
7.355 - n != INVALID; ++n) {
7.356 - if (graph.u(e) == n) s = true;
7.357 - if (graph.v(e) == n) t = true;
7.358 - }
7.359 - if (s == true && t == true) {
7.360 - rw += mwpm.blossomValue(i);
7.361 - }
7.362 - }
7.363 - rw -= weight[e] * mwpm.dualScale;
7.364 -
7.365 - check(rw >= 0, "Negative reduced weight");
7.366 - check(rw == 0 || !mwpm.matching(e),
7.367 - "Non-zero reduced weight on matching edge");
7.368 - }
7.369 -
7.370 - int pv = 0;
7.371 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
7.372 - check(mwpm.matching(n) != INVALID, "Non perfect");
7.373 - pv += weight[mwpm.matching(n)];
7.374 - SmartGraph::Node o = graph.target(mwpm.matching(n));
7.375 - check(mwpm.mate(n) == o, "Invalid matching");
7.376 - check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
7.377 - "Invalid matching");
7.378 - }
7.379 -
7.380 - int dv = 0;
7.381 - for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
7.382 - dv += mwpm.nodeValue(n);
7.383 - }
7.384 -
7.385 - for (int i = 0; i < mwpm.blossomNum(); ++i) {
7.386 - check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
7.387 - check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
7.388 - dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
7.389 - }
7.390 -
7.391 - check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
7.392 -
7.393 - return;
7.394 -}
7.395 -
7.396 -
7.397 -int main() {
7.398 -
7.399 - for (int i = 0; i < lgfn; ++i) {
7.400 - SmartGraph graph;
7.401 - SmartGraph::EdgeMap<int> weight(graph);
7.402 -
7.403 - istringstream lgfs(lgf[i]);
7.404 - graphReader(graph, lgfs).
7.405 - edgeMap("weight", weight).run();
7.406 -
7.407 - MaxMatching<SmartGraph> mm(graph);
7.408 - mm.run();
7.409 - checkMatching(graph, mm);
7.410 -
7.411 - MaxWeightedMatching<SmartGraph> mwm(graph, weight);
7.412 - mwm.run();
7.413 - checkWeightedMatching(graph, weight, mwm);
7.414 -
7.415 - MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
7.416 - bool perfect = mwpm.run();
7.417 -
7.418 - check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
7.419 - "Perfect matching found");
7.420 -
7.421 - if (perfect) {
7.422 - checkWeightedPerfectMatching(graph, weight, mwpm);
7.423 - }
7.424 - }
7.425 -
7.426 - return 0;
7.427 -}
8.1 --- a/tools/dimacs-solver.cc Fri Apr 17 09:54:14 2009 +0200
8.2 +++ b/tools/dimacs-solver.cc Fri Apr 17 09:58:50 2009 +0200
8.3 @@ -42,7 +42,7 @@
8.4
8.5 #include <lemon/dijkstra.h>
8.6 #include <lemon/preflow.h>
8.7 -#include <lemon/max_matching.h>
8.8 +#include <lemon/matching.h>
8.9
8.10 using namespace lemon;
8.11 typedef SmartDigraph Digraph;