1.1 --- a/lemon/max_matching.h Tue Apr 21 10:34:49 2009 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,3107 +0,0 @@
1.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
1.5 - *
1.6 - * This file is a part of LEMON, a generic C++ optimization library.
1.7 - *
1.8 - * Copyright (C) 2003-2009
1.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.11 - *
1.12 - * Permission to use, modify and distribute this software is granted
1.13 - * provided that this copyright notice appears in all copies. For
1.14 - * precise terms see the accompanying LICENSE file.
1.15 - *
1.16 - * This software is provided "AS IS" with no warranty of any kind,
1.17 - * express or implied, and with no claim as to its suitability for any
1.18 - * purpose.
1.19 - *
1.20 - */
1.21 -
1.22 -#ifndef LEMON_MAX_MATCHING_H
1.23 -#define LEMON_MAX_MATCHING_H
1.24 -
1.25 -#include <vector>
1.26 -#include <queue>
1.27 -#include <set>
1.28 -#include <limits>
1.29 -
1.30 -#include <lemon/core.h>
1.31 -#include <lemon/unionfind.h>
1.32 -#include <lemon/bin_heap.h>
1.33 -#include <lemon/maps.h>
1.34 -
1.35 -///\ingroup matching
1.36 -///\file
1.37 -///\brief Maximum matching algorithms in general graphs.
1.38 -
1.39 -namespace lemon {
1.40 -
1.41 - /// \ingroup matching
1.42 - ///
1.43 - /// \brief Edmonds' alternating forest maximum matching algorithm.
1.44 - ///
1.45 - /// This class implements Edmonds' alternating forest matching
1.46 - /// algorithm. The algorithm can be started from an arbitrary initial
1.47 - /// matching (the default is the empty one)
1.48 - ///
1.49 - /// The dual solution of the problem is a map of the nodes to
1.50 - /// MaxMatching::Status, having values \c EVEN/D, \c ODD/A and \c
1.51 - /// MATCHED/C showing the Gallai-Edmonds decomposition of the
1.52 - /// graph. The nodes in \c EVEN/D induce a graph with
1.53 - /// factor-critical components, the nodes in \c ODD/A form the
1.54 - /// barrier, and the nodes in \c MATCHED/C induce a graph having a
1.55 - /// perfect matching. The number of the factor-critical components
1.56 - /// minus the number of barrier nodes is a lower bound on the
1.57 - /// unmatched nodes, and the matching is optimal if and only if this bound is
1.58 - /// tight. This decomposition can be attained by calling \c
1.59 - /// decomposition() after running the algorithm.
1.60 - ///
1.61 - /// \param GR The graph type the algorithm runs on.
1.62 - template <typename GR>
1.63 - class MaxMatching {
1.64 - public:
1.65 -
1.66 - typedef GR Graph;
1.67 - typedef typename Graph::template NodeMap<typename Graph::Arc>
1.68 - MatchingMap;
1.69 -
1.70 - ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
1.71 - ///
1.72 - ///Indicates the Gallai-Edmonds decomposition of the graph. The
1.73 - ///nodes with Status \c EVEN/D induce a graph with factor-critical
1.74 - ///components, the nodes in \c ODD/A form the canonical barrier,
1.75 - ///and the nodes in \c MATCHED/C induce a graph having a perfect
1.76 - ///matching.
1.77 - enum Status {
1.78 - EVEN = 1, D = 1, MATCHED = 0, C = 0, ODD = -1, A = -1, UNMATCHED = -2
1.79 - };
1.80 -
1.81 - typedef typename Graph::template NodeMap<Status> StatusMap;
1.82 -
1.83 - private:
1.84 -
1.85 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
1.86 -
1.87 - typedef UnionFindEnum<IntNodeMap> BlossomSet;
1.88 - typedef ExtendFindEnum<IntNodeMap> TreeSet;
1.89 - typedef RangeMap<Node> NodeIntMap;
1.90 - typedef MatchingMap EarMap;
1.91 - typedef std::vector<Node> NodeQueue;
1.92 -
1.93 - const Graph& _graph;
1.94 - MatchingMap* _matching;
1.95 - StatusMap* _status;
1.96 -
1.97 - EarMap* _ear;
1.98 -
1.99 - IntNodeMap* _blossom_set_index;
1.100 - BlossomSet* _blossom_set;
1.101 - NodeIntMap* _blossom_rep;
1.102 -
1.103 - IntNodeMap* _tree_set_index;
1.104 - TreeSet* _tree_set;
1.105 -
1.106 - NodeQueue _node_queue;
1.107 - int _process, _postpone, _last;
1.108 -
1.109 - int _node_num;
1.110 -
1.111 - private:
1.112 -
1.113 - void createStructures() {
1.114 - _node_num = countNodes(_graph);
1.115 - if (!_matching) {
1.116 - _matching = new MatchingMap(_graph);
1.117 - }
1.118 - if (!_status) {
1.119 - _status = new StatusMap(_graph);
1.120 - }
1.121 - if (!_ear) {
1.122 - _ear = new EarMap(_graph);
1.123 - }
1.124 - if (!_blossom_set) {
1.125 - _blossom_set_index = new IntNodeMap(_graph);
1.126 - _blossom_set = new BlossomSet(*_blossom_set_index);
1.127 - }
1.128 - if (!_blossom_rep) {
1.129 - _blossom_rep = new NodeIntMap(_node_num);
1.130 - }
1.131 - if (!_tree_set) {
1.132 - _tree_set_index = new IntNodeMap(_graph);
1.133 - _tree_set = new TreeSet(*_tree_set_index);
1.134 - }
1.135 - _node_queue.resize(_node_num);
1.136 - }
1.137 -
1.138 - void destroyStructures() {
1.139 - if (_matching) {
1.140 - delete _matching;
1.141 - }
1.142 - if (_status) {
1.143 - delete _status;
1.144 - }
1.145 - if (_ear) {
1.146 - delete _ear;
1.147 - }
1.148 - if (_blossom_set) {
1.149 - delete _blossom_set;
1.150 - delete _blossom_set_index;
1.151 - }
1.152 - if (_blossom_rep) {
1.153 - delete _blossom_rep;
1.154 - }
1.155 - if (_tree_set) {
1.156 - delete _tree_set_index;
1.157 - delete _tree_set;
1.158 - }
1.159 - }
1.160 -
1.161 - void processDense(const Node& n) {
1.162 - _process = _postpone = _last = 0;
1.163 - _node_queue[_last++] = n;
1.164 -
1.165 - while (_process != _last) {
1.166 - Node u = _node_queue[_process++];
1.167 - for (OutArcIt a(_graph, u); a != INVALID; ++a) {
1.168 - Node v = _graph.target(a);
1.169 - if ((*_status)[v] == MATCHED) {
1.170 - extendOnArc(a);
1.171 - } else if ((*_status)[v] == UNMATCHED) {
1.172 - augmentOnArc(a);
1.173 - return;
1.174 - }
1.175 - }
1.176 - }
1.177 -
1.178 - while (_postpone != _last) {
1.179 - Node u = _node_queue[_postpone++];
1.180 -
1.181 - for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
1.182 - Node v = _graph.target(a);
1.183 -
1.184 - if ((*_status)[v] == EVEN) {
1.185 - if (_blossom_set->find(u) != _blossom_set->find(v)) {
1.186 - shrinkOnEdge(a);
1.187 - }
1.188 - }
1.189 -
1.190 - while (_process != _last) {
1.191 - Node w = _node_queue[_process++];
1.192 - for (OutArcIt b(_graph, w); b != INVALID; ++b) {
1.193 - Node x = _graph.target(b);
1.194 - if ((*_status)[x] == MATCHED) {
1.195 - extendOnArc(b);
1.196 - } else if ((*_status)[x] == UNMATCHED) {
1.197 - augmentOnArc(b);
1.198 - return;
1.199 - }
1.200 - }
1.201 - }
1.202 - }
1.203 - }
1.204 - }
1.205 -
1.206 - void processSparse(const Node& n) {
1.207 - _process = _last = 0;
1.208 - _node_queue[_last++] = n;
1.209 - while (_process != _last) {
1.210 - Node u = _node_queue[_process++];
1.211 - for (OutArcIt a(_graph, u); a != INVALID; ++a) {
1.212 - Node v = _graph.target(a);
1.213 -
1.214 - if ((*_status)[v] == EVEN) {
1.215 - if (_blossom_set->find(u) != _blossom_set->find(v)) {
1.216 - shrinkOnEdge(a);
1.217 - }
1.218 - } else if ((*_status)[v] == MATCHED) {
1.219 - extendOnArc(a);
1.220 - } else if ((*_status)[v] == UNMATCHED) {
1.221 - augmentOnArc(a);
1.222 - return;
1.223 - }
1.224 - }
1.225 - }
1.226 - }
1.227 -
1.228 - void shrinkOnEdge(const Edge& e) {
1.229 - Node nca = INVALID;
1.230 -
1.231 - {
1.232 - std::set<Node> left_set, right_set;
1.233 -
1.234 - Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
1.235 - left_set.insert(left);
1.236 -
1.237 - Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
1.238 - right_set.insert(right);
1.239 -
1.240 - while (true) {
1.241 - if ((*_matching)[left] == INVALID) break;
1.242 - left = _graph.target((*_matching)[left]);
1.243 - left = (*_blossom_rep)[_blossom_set->
1.244 - find(_graph.target((*_ear)[left]))];
1.245 - if (right_set.find(left) != right_set.end()) {
1.246 - nca = left;
1.247 - break;
1.248 - }
1.249 - left_set.insert(left);
1.250 -
1.251 - if ((*_matching)[right] == INVALID) break;
1.252 - right = _graph.target((*_matching)[right]);
1.253 - right = (*_blossom_rep)[_blossom_set->
1.254 - find(_graph.target((*_ear)[right]))];
1.255 - if (left_set.find(right) != left_set.end()) {
1.256 - nca = right;
1.257 - break;
1.258 - }
1.259 - right_set.insert(right);
1.260 - }
1.261 -
1.262 - if (nca == INVALID) {
1.263 - if ((*_matching)[left] == INVALID) {
1.264 - nca = right;
1.265 - while (left_set.find(nca) == left_set.end()) {
1.266 - nca = _graph.target((*_matching)[nca]);
1.267 - nca =(*_blossom_rep)[_blossom_set->
1.268 - find(_graph.target((*_ear)[nca]))];
1.269 - }
1.270 - } else {
1.271 - nca = left;
1.272 - while (right_set.find(nca) == right_set.end()) {
1.273 - nca = _graph.target((*_matching)[nca]);
1.274 - nca = (*_blossom_rep)[_blossom_set->
1.275 - find(_graph.target((*_ear)[nca]))];
1.276 - }
1.277 - }
1.278 - }
1.279 - }
1.280 -
1.281 - {
1.282 -
1.283 - Node node = _graph.u(e);
1.284 - Arc arc = _graph.direct(e, true);
1.285 - Node base = (*_blossom_rep)[_blossom_set->find(node)];
1.286 -
1.287 - while (base != nca) {
1.288 - (*_ear)[node] = arc;
1.289 -
1.290 - Node n = node;
1.291 - while (n != base) {
1.292 - n = _graph.target((*_matching)[n]);
1.293 - Arc a = (*_ear)[n];
1.294 - n = _graph.target(a);
1.295 - (*_ear)[n] = _graph.oppositeArc(a);
1.296 - }
1.297 - node = _graph.target((*_matching)[base]);
1.298 - _tree_set->erase(base);
1.299 - _tree_set->erase(node);
1.300 - _blossom_set->insert(node, _blossom_set->find(base));
1.301 - (*_status)[node] = EVEN;
1.302 - _node_queue[_last++] = node;
1.303 - arc = _graph.oppositeArc((*_ear)[node]);
1.304 - node = _graph.target((*_ear)[node]);
1.305 - base = (*_blossom_rep)[_blossom_set->find(node)];
1.306 - _blossom_set->join(_graph.target(arc), base);
1.307 - }
1.308 - }
1.309 -
1.310 - (*_blossom_rep)[_blossom_set->find(nca)] = nca;
1.311 -
1.312 - {
1.313 -
1.314 - Node node = _graph.v(e);
1.315 - Arc arc = _graph.direct(e, false);
1.316 - Node base = (*_blossom_rep)[_blossom_set->find(node)];
1.317 -
1.318 - while (base != nca) {
1.319 - (*_ear)[node] = arc;
1.320 -
1.321 - Node n = node;
1.322 - while (n != base) {
1.323 - n = _graph.target((*_matching)[n]);
1.324 - Arc a = (*_ear)[n];
1.325 - n = _graph.target(a);
1.326 - (*_ear)[n] = _graph.oppositeArc(a);
1.327 - }
1.328 - node = _graph.target((*_matching)[base]);
1.329 - _tree_set->erase(base);
1.330 - _tree_set->erase(node);
1.331 - _blossom_set->insert(node, _blossom_set->find(base));
1.332 - (*_status)[node] = EVEN;
1.333 - _node_queue[_last++] = node;
1.334 - arc = _graph.oppositeArc((*_ear)[node]);
1.335 - node = _graph.target((*_ear)[node]);
1.336 - base = (*_blossom_rep)[_blossom_set->find(node)];
1.337 - _blossom_set->join(_graph.target(arc), base);
1.338 - }
1.339 - }
1.340 -
1.341 - (*_blossom_rep)[_blossom_set->find(nca)] = nca;
1.342 - }
1.343 -
1.344 -
1.345 -
1.346 - void extendOnArc(const Arc& a) {
1.347 - Node base = _graph.source(a);
1.348 - Node odd = _graph.target(a);
1.349 -
1.350 - (*_ear)[odd] = _graph.oppositeArc(a);
1.351 - Node even = _graph.target((*_matching)[odd]);
1.352 - (*_blossom_rep)[_blossom_set->insert(even)] = even;
1.353 - (*_status)[odd] = ODD;
1.354 - (*_status)[even] = EVEN;
1.355 - int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
1.356 - _tree_set->insert(odd, tree);
1.357 - _tree_set->insert(even, tree);
1.358 - _node_queue[_last++] = even;
1.359 -
1.360 - }
1.361 -
1.362 - void augmentOnArc(const Arc& a) {
1.363 - Node even = _graph.source(a);
1.364 - Node odd = _graph.target(a);
1.365 -
1.366 - int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
1.367 -
1.368 - (*_matching)[odd] = _graph.oppositeArc(a);
1.369 - (*_status)[odd] = MATCHED;
1.370 -
1.371 - Arc arc = (*_matching)[even];
1.372 - (*_matching)[even] = a;
1.373 -
1.374 - while (arc != INVALID) {
1.375 - odd = _graph.target(arc);
1.376 - arc = (*_ear)[odd];
1.377 - even = _graph.target(arc);
1.378 - (*_matching)[odd] = arc;
1.379 - arc = (*_matching)[even];
1.380 - (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
1.381 - }
1.382 -
1.383 - for (typename TreeSet::ItemIt it(*_tree_set, tree);
1.384 - it != INVALID; ++it) {
1.385 - if ((*_status)[it] == ODD) {
1.386 - (*_status)[it] = MATCHED;
1.387 - } else {
1.388 - int blossom = _blossom_set->find(it);
1.389 - for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
1.390 - jt != INVALID; ++jt) {
1.391 - (*_status)[jt] = MATCHED;
1.392 - }
1.393 - _blossom_set->eraseClass(blossom);
1.394 - }
1.395 - }
1.396 - _tree_set->eraseClass(tree);
1.397 -
1.398 - }
1.399 -
1.400 - public:
1.401 -
1.402 - /// \brief Constructor
1.403 - ///
1.404 - /// Constructor.
1.405 - MaxMatching(const Graph& graph)
1.406 - : _graph(graph), _matching(0), _status(0), _ear(0),
1.407 - _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
1.408 - _tree_set_index(0), _tree_set(0) {}
1.409 -
1.410 - ~MaxMatching() {
1.411 - destroyStructures();
1.412 - }
1.413 -
1.414 - /// \name Execution control
1.415 - /// The simplest way to execute the algorithm is to use the
1.416 - /// \c run() member function.
1.417 - /// \n
1.418 -
1.419 - /// If you need better control on the execution, you must call
1.420 - /// \ref init(), \ref greedyInit() or \ref matchingInit()
1.421 - /// functions first, then you can start the algorithm with the \ref
1.422 - /// startSparse() or startDense() functions.
1.423 -
1.424 - ///@{
1.425 -
1.426 - /// \brief Sets the actual matching to the empty matching.
1.427 - ///
1.428 - /// Sets the actual matching to the empty matching.
1.429 - ///
1.430 - void init() {
1.431 - createStructures();
1.432 - for(NodeIt n(_graph); n != INVALID; ++n) {
1.433 - (*_matching)[n] = INVALID;
1.434 - (*_status)[n] = UNMATCHED;
1.435 - }
1.436 - }
1.437 -
1.438 - ///\brief Finds an initial matching in a greedy way
1.439 - ///
1.440 - ///It finds an initial matching in a greedy way.
1.441 - void greedyInit() {
1.442 - createStructures();
1.443 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.444 - (*_matching)[n] = INVALID;
1.445 - (*_status)[n] = UNMATCHED;
1.446 - }
1.447 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.448 - if ((*_matching)[n] == INVALID) {
1.449 - for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
1.450 - Node v = _graph.target(a);
1.451 - if ((*_matching)[v] == INVALID && v != n) {
1.452 - (*_matching)[n] = a;
1.453 - (*_status)[n] = MATCHED;
1.454 - (*_matching)[v] = _graph.oppositeArc(a);
1.455 - (*_status)[v] = MATCHED;
1.456 - break;
1.457 - }
1.458 - }
1.459 - }
1.460 - }
1.461 - }
1.462 -
1.463 -
1.464 - /// \brief Initialize the matching from a map containing.
1.465 - ///
1.466 - /// Initialize the matching from a \c bool valued \c Edge map. This
1.467 - /// map must have the property that there are no two incident edges
1.468 - /// with true value, ie. it contains a matching.
1.469 - /// \return \c true if the map contains a matching.
1.470 - template <typename MatchingMap>
1.471 - bool matchingInit(const MatchingMap& matching) {
1.472 - createStructures();
1.473 -
1.474 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.475 - (*_matching)[n] = INVALID;
1.476 - (*_status)[n] = UNMATCHED;
1.477 - }
1.478 - for(EdgeIt e(_graph); e!=INVALID; ++e) {
1.479 - if (matching[e]) {
1.480 -
1.481 - Node u = _graph.u(e);
1.482 - if ((*_matching)[u] != INVALID) return false;
1.483 - (*_matching)[u] = _graph.direct(e, true);
1.484 - (*_status)[u] = MATCHED;
1.485 -
1.486 - Node v = _graph.v(e);
1.487 - if ((*_matching)[v] != INVALID) return false;
1.488 - (*_matching)[v] = _graph.direct(e, false);
1.489 - (*_status)[v] = MATCHED;
1.490 - }
1.491 - }
1.492 - return true;
1.493 - }
1.494 -
1.495 - /// \brief Starts Edmonds' algorithm
1.496 - ///
1.497 - /// If runs the original Edmonds' algorithm.
1.498 - void startSparse() {
1.499 - for(NodeIt n(_graph); n != INVALID; ++n) {
1.500 - if ((*_status)[n] == UNMATCHED) {
1.501 - (*_blossom_rep)[_blossom_set->insert(n)] = n;
1.502 - _tree_set->insert(n);
1.503 - (*_status)[n] = EVEN;
1.504 - processSparse(n);
1.505 - }
1.506 - }
1.507 - }
1.508 -
1.509 - /// \brief Starts Edmonds' algorithm.
1.510 - ///
1.511 - /// It runs Edmonds' algorithm with a heuristic of postponing
1.512 - /// shrinks, therefore resulting in a faster algorithm for dense graphs.
1.513 - void startDense() {
1.514 - for(NodeIt n(_graph); n != INVALID; ++n) {
1.515 - if ((*_status)[n] == UNMATCHED) {
1.516 - (*_blossom_rep)[_blossom_set->insert(n)] = n;
1.517 - _tree_set->insert(n);
1.518 - (*_status)[n] = EVEN;
1.519 - processDense(n);
1.520 - }
1.521 - }
1.522 - }
1.523 -
1.524 -
1.525 - /// \brief Runs Edmonds' algorithm
1.526 - ///
1.527 - /// Runs Edmonds' algorithm for sparse graphs (<tt>m<2*n</tt>)
1.528 - /// or Edmonds' algorithm with a heuristic of
1.529 - /// postponing shrinks for dense graphs.
1.530 - void run() {
1.531 - if (countEdges(_graph) < 2 * countNodes(_graph)) {
1.532 - greedyInit();
1.533 - startSparse();
1.534 - } else {
1.535 - init();
1.536 - startDense();
1.537 - }
1.538 - }
1.539 -
1.540 - /// @}
1.541 -
1.542 - /// \name Primal solution
1.543 - /// Functions to get the primal solution, ie. the matching.
1.544 -
1.545 - /// @{
1.546 -
1.547 - ///\brief Returns the size of the current matching.
1.548 - ///
1.549 - ///Returns the size of the current matching. After \ref
1.550 - ///run() it returns the size of the maximum matching in the graph.
1.551 - int matchingSize() const {
1.552 - int size = 0;
1.553 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.554 - if ((*_matching)[n] != INVALID) {
1.555 - ++size;
1.556 - }
1.557 - }
1.558 - return size / 2;
1.559 - }
1.560 -
1.561 - /// \brief Returns true when the edge is in the matching.
1.562 - ///
1.563 - /// Returns true when the edge is in the matching.
1.564 - bool matching(const Edge& edge) const {
1.565 - return edge == (*_matching)[_graph.u(edge)];
1.566 - }
1.567 -
1.568 - /// \brief Returns the matching edge incident to the given node.
1.569 - ///
1.570 - /// Returns the matching edge of a \c node in the actual matching or
1.571 - /// INVALID if the \c node is not covered by the actual matching.
1.572 - Arc matching(const Node& n) const {
1.573 - return (*_matching)[n];
1.574 - }
1.575 -
1.576 - ///\brief Returns the mate of a node in the actual matching.
1.577 - ///
1.578 - ///Returns the mate of a \c node in the actual matching or
1.579 - ///INVALID if the \c node is not covered by the actual matching.
1.580 - Node mate(const Node& n) const {
1.581 - return (*_matching)[n] != INVALID ?
1.582 - _graph.target((*_matching)[n]) : INVALID;
1.583 - }
1.584 -
1.585 - /// @}
1.586 -
1.587 - /// \name Dual solution
1.588 - /// Functions to get the dual solution, ie. the decomposition.
1.589 -
1.590 - /// @{
1.591 -
1.592 - /// \brief Returns the class of the node in the Edmonds-Gallai
1.593 - /// decomposition.
1.594 - ///
1.595 - /// Returns the class of the node in the Edmonds-Gallai
1.596 - /// decomposition.
1.597 - Status decomposition(const Node& n) const {
1.598 - return (*_status)[n];
1.599 - }
1.600 -
1.601 - /// \brief Returns true when the node is in the barrier.
1.602 - ///
1.603 - /// Returns true when the node is in the barrier.
1.604 - bool barrier(const Node& n) const {
1.605 - return (*_status)[n] == ODD;
1.606 - }
1.607 -
1.608 - /// @}
1.609 -
1.610 - };
1.611 -
1.612 - /// \ingroup matching
1.613 - ///
1.614 - /// \brief Weighted matching in general graphs
1.615 - ///
1.616 - /// This class provides an efficient implementation of Edmond's
1.617 - /// maximum weighted matching algorithm. The implementation is based
1.618 - /// on extensive use of priority queues and provides
1.619 - /// \f$O(nm\log n)\f$ time complexity.
1.620 - ///
1.621 - /// The maximum weighted matching problem is to find undirected
1.622 - /// edges in the graph with maximum overall weight and no two of
1.623 - /// them shares their ends. The problem can be formulated with the
1.624 - /// following linear program.
1.625 - /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
1.626 - /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
1.627 - \quad \forall B\in\mathcal{O}\f] */
1.628 - /// \f[x_e \ge 0\quad \forall e\in E\f]
1.629 - /// \f[\max \sum_{e\in E}x_ew_e\f]
1.630 - /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1.631 - /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
1.632 - /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
1.633 - /// subsets of the nodes.
1.634 - ///
1.635 - /// The algorithm calculates an optimal matching and a proof of the
1.636 - /// optimality. The solution of the dual problem can be used to check
1.637 - /// the result of the algorithm. The dual linear problem is the
1.638 - /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
1.639 - z_B \ge w_{uv} \quad \forall uv\in E\f] */
1.640 - /// \f[y_u \ge 0 \quad \forall u \in V\f]
1.641 - /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
1.642 - /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
1.643 - \frac{\vert B \vert - 1}{2}z_B\f] */
1.644 - ///
1.645 - /// The algorithm can be executed with \c run() or the \c init() and
1.646 - /// then the \c start() member functions. After it the matching can
1.647 - /// be asked with \c matching() or mate() functions. The dual
1.648 - /// solution can be get with \c nodeValue(), \c blossomNum() and \c
1.649 - /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
1.650 - /// "BlossomIt" nested class, which is able to iterate on the nodes
1.651 - /// of a blossom. If the value type is integral then the dual
1.652 - /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
1.653 - template <typename GR,
1.654 - typename WM = typename GR::template EdgeMap<int> >
1.655 - class MaxWeightedMatching {
1.656 - public:
1.657 -
1.658 - ///\e
1.659 - typedef GR Graph;
1.660 - ///\e
1.661 - typedef WM WeightMap;
1.662 - ///\e
1.663 - typedef typename WeightMap::Value Value;
1.664 -
1.665 - /// \brief Scaling factor for dual solution
1.666 - ///
1.667 - /// Scaling factor for dual solution, it is equal to 4 or 1
1.668 - /// according to the value type.
1.669 - static const int dualScale =
1.670 - std::numeric_limits<Value>::is_integer ? 4 : 1;
1.671 -
1.672 - typedef typename Graph::template NodeMap<typename Graph::Arc>
1.673 - MatchingMap;
1.674 -
1.675 - private:
1.676 -
1.677 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
1.678 -
1.679 - typedef typename Graph::template NodeMap<Value> NodePotential;
1.680 - typedef std::vector<Node> BlossomNodeList;
1.681 -
1.682 - struct BlossomVariable {
1.683 - int begin, end;
1.684 - Value value;
1.685 -
1.686 - BlossomVariable(int _begin, int _end, Value _value)
1.687 - : begin(_begin), end(_end), value(_value) {}
1.688 -
1.689 - };
1.690 -
1.691 - typedef std::vector<BlossomVariable> BlossomPotential;
1.692 -
1.693 - const Graph& _graph;
1.694 - const WeightMap& _weight;
1.695 -
1.696 - MatchingMap* _matching;
1.697 -
1.698 - NodePotential* _node_potential;
1.699 -
1.700 - BlossomPotential _blossom_potential;
1.701 - BlossomNodeList _blossom_node_list;
1.702 -
1.703 - int _node_num;
1.704 - int _blossom_num;
1.705 -
1.706 - typedef RangeMap<int> IntIntMap;
1.707 -
1.708 - enum Status {
1.709 - EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
1.710 - };
1.711 -
1.712 - typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
1.713 - struct BlossomData {
1.714 - int tree;
1.715 - Status status;
1.716 - Arc pred, next;
1.717 - Value pot, offset;
1.718 - Node base;
1.719 - };
1.720 -
1.721 - IntNodeMap *_blossom_index;
1.722 - BlossomSet *_blossom_set;
1.723 - RangeMap<BlossomData>* _blossom_data;
1.724 -
1.725 - IntNodeMap *_node_index;
1.726 - IntArcMap *_node_heap_index;
1.727 -
1.728 - struct NodeData {
1.729 -
1.730 - NodeData(IntArcMap& node_heap_index)
1.731 - : heap(node_heap_index) {}
1.732 -
1.733 - int blossom;
1.734 - Value pot;
1.735 - BinHeap<Value, IntArcMap> heap;
1.736 - std::map<int, Arc> heap_index;
1.737 -
1.738 - int tree;
1.739 - };
1.740 -
1.741 - RangeMap<NodeData>* _node_data;
1.742 -
1.743 - typedef ExtendFindEnum<IntIntMap> TreeSet;
1.744 -
1.745 - IntIntMap *_tree_set_index;
1.746 - TreeSet *_tree_set;
1.747 -
1.748 - IntNodeMap *_delta1_index;
1.749 - BinHeap<Value, IntNodeMap> *_delta1;
1.750 -
1.751 - IntIntMap *_delta2_index;
1.752 - BinHeap<Value, IntIntMap> *_delta2;
1.753 -
1.754 - IntEdgeMap *_delta3_index;
1.755 - BinHeap<Value, IntEdgeMap> *_delta3;
1.756 -
1.757 - IntIntMap *_delta4_index;
1.758 - BinHeap<Value, IntIntMap> *_delta4;
1.759 -
1.760 - Value _delta_sum;
1.761 -
1.762 - void createStructures() {
1.763 - _node_num = countNodes(_graph);
1.764 - _blossom_num = _node_num * 3 / 2;
1.765 -
1.766 - if (!_matching) {
1.767 - _matching = new MatchingMap(_graph);
1.768 - }
1.769 - if (!_node_potential) {
1.770 - _node_potential = new NodePotential(_graph);
1.771 - }
1.772 - if (!_blossom_set) {
1.773 - _blossom_index = new IntNodeMap(_graph);
1.774 - _blossom_set = new BlossomSet(*_blossom_index);
1.775 - _blossom_data = new RangeMap<BlossomData>(_blossom_num);
1.776 - }
1.777 -
1.778 - if (!_node_index) {
1.779 - _node_index = new IntNodeMap(_graph);
1.780 - _node_heap_index = new IntArcMap(_graph);
1.781 - _node_data = new RangeMap<NodeData>(_node_num,
1.782 - NodeData(*_node_heap_index));
1.783 - }
1.784 -
1.785 - if (!_tree_set) {
1.786 - _tree_set_index = new IntIntMap(_blossom_num);
1.787 - _tree_set = new TreeSet(*_tree_set_index);
1.788 - }
1.789 - if (!_delta1) {
1.790 - _delta1_index = new IntNodeMap(_graph);
1.791 - _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
1.792 - }
1.793 - if (!_delta2) {
1.794 - _delta2_index = new IntIntMap(_blossom_num);
1.795 - _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
1.796 - }
1.797 - if (!_delta3) {
1.798 - _delta3_index = new IntEdgeMap(_graph);
1.799 - _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
1.800 - }
1.801 - if (!_delta4) {
1.802 - _delta4_index = new IntIntMap(_blossom_num);
1.803 - _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
1.804 - }
1.805 - }
1.806 -
1.807 - void destroyStructures() {
1.808 - _node_num = countNodes(_graph);
1.809 - _blossom_num = _node_num * 3 / 2;
1.810 -
1.811 - if (_matching) {
1.812 - delete _matching;
1.813 - }
1.814 - if (_node_potential) {
1.815 - delete _node_potential;
1.816 - }
1.817 - if (_blossom_set) {
1.818 - delete _blossom_index;
1.819 - delete _blossom_set;
1.820 - delete _blossom_data;
1.821 - }
1.822 -
1.823 - if (_node_index) {
1.824 - delete _node_index;
1.825 - delete _node_heap_index;
1.826 - delete _node_data;
1.827 - }
1.828 -
1.829 - if (_tree_set) {
1.830 - delete _tree_set_index;
1.831 - delete _tree_set;
1.832 - }
1.833 - if (_delta1) {
1.834 - delete _delta1_index;
1.835 - delete _delta1;
1.836 - }
1.837 - if (_delta2) {
1.838 - delete _delta2_index;
1.839 - delete _delta2;
1.840 - }
1.841 - if (_delta3) {
1.842 - delete _delta3_index;
1.843 - delete _delta3;
1.844 - }
1.845 - if (_delta4) {
1.846 - delete _delta4_index;
1.847 - delete _delta4;
1.848 - }
1.849 - }
1.850 -
1.851 - void matchedToEven(int blossom, int tree) {
1.852 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1.853 - _delta2->erase(blossom);
1.854 - }
1.855 -
1.856 - if (!_blossom_set->trivial(blossom)) {
1.857 - (*_blossom_data)[blossom].pot -=
1.858 - 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
1.859 - }
1.860 -
1.861 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.862 - n != INVALID; ++n) {
1.863 -
1.864 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
1.865 - int ni = (*_node_index)[n];
1.866 -
1.867 - (*_node_data)[ni].heap.clear();
1.868 - (*_node_data)[ni].heap_index.clear();
1.869 -
1.870 - (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
1.871 -
1.872 - _delta1->push(n, (*_node_data)[ni].pot);
1.873 -
1.874 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
1.875 - Node v = _graph.source(e);
1.876 - int vb = _blossom_set->find(v);
1.877 - int vi = (*_node_index)[v];
1.878 -
1.879 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.880 - dualScale * _weight[e];
1.881 -
1.882 - if ((*_blossom_data)[vb].status == EVEN) {
1.883 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1.884 - _delta3->push(e, rw / 2);
1.885 - }
1.886 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1.887 - if (_delta3->state(e) != _delta3->IN_HEAP) {
1.888 - _delta3->push(e, rw);
1.889 - }
1.890 - } else {
1.891 - typename std::map<int, Arc>::iterator it =
1.892 - (*_node_data)[vi].heap_index.find(tree);
1.893 -
1.894 - if (it != (*_node_data)[vi].heap_index.end()) {
1.895 - if ((*_node_data)[vi].heap[it->second] > rw) {
1.896 - (*_node_data)[vi].heap.replace(it->second, e);
1.897 - (*_node_data)[vi].heap.decrease(e, rw);
1.898 - it->second = e;
1.899 - }
1.900 - } else {
1.901 - (*_node_data)[vi].heap.push(e, rw);
1.902 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1.903 - }
1.904 -
1.905 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1.906 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1.907 -
1.908 - if ((*_blossom_data)[vb].status == MATCHED) {
1.909 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
1.910 - _delta2->push(vb, _blossom_set->classPrio(vb) -
1.911 - (*_blossom_data)[vb].offset);
1.912 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1.913 - (*_blossom_data)[vb].offset){
1.914 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1.915 - (*_blossom_data)[vb].offset);
1.916 - }
1.917 - }
1.918 - }
1.919 - }
1.920 - }
1.921 - }
1.922 - (*_blossom_data)[blossom].offset = 0;
1.923 - }
1.924 -
1.925 - void matchedToOdd(int blossom) {
1.926 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1.927 - _delta2->erase(blossom);
1.928 - }
1.929 - (*_blossom_data)[blossom].offset += _delta_sum;
1.930 - if (!_blossom_set->trivial(blossom)) {
1.931 - _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
1.932 - (*_blossom_data)[blossom].offset);
1.933 - }
1.934 - }
1.935 -
1.936 - void evenToMatched(int blossom, int tree) {
1.937 - if (!_blossom_set->trivial(blossom)) {
1.938 - (*_blossom_data)[blossom].pot += 2 * _delta_sum;
1.939 - }
1.940 -
1.941 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.942 - n != INVALID; ++n) {
1.943 - int ni = (*_node_index)[n];
1.944 - (*_node_data)[ni].pot -= _delta_sum;
1.945 -
1.946 - _delta1->erase(n);
1.947 -
1.948 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
1.949 - Node v = _graph.source(e);
1.950 - int vb = _blossom_set->find(v);
1.951 - int vi = (*_node_index)[v];
1.952 -
1.953 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.954 - dualScale * _weight[e];
1.955 -
1.956 - if (vb == blossom) {
1.957 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.958 - _delta3->erase(e);
1.959 - }
1.960 - } else if ((*_blossom_data)[vb].status == EVEN) {
1.961 -
1.962 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.963 - _delta3->erase(e);
1.964 - }
1.965 -
1.966 - int vt = _tree_set->find(vb);
1.967 -
1.968 - if (vt != tree) {
1.969 -
1.970 - Arc r = _graph.oppositeArc(e);
1.971 -
1.972 - typename std::map<int, Arc>::iterator it =
1.973 - (*_node_data)[ni].heap_index.find(vt);
1.974 -
1.975 - if (it != (*_node_data)[ni].heap_index.end()) {
1.976 - if ((*_node_data)[ni].heap[it->second] > rw) {
1.977 - (*_node_data)[ni].heap.replace(it->second, r);
1.978 - (*_node_data)[ni].heap.decrease(r, rw);
1.979 - it->second = r;
1.980 - }
1.981 - } else {
1.982 - (*_node_data)[ni].heap.push(r, rw);
1.983 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1.984 - }
1.985 -
1.986 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1.987 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1.988 -
1.989 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1.990 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1.991 - (*_blossom_data)[blossom].offset);
1.992 - } else if ((*_delta2)[blossom] >
1.993 - _blossom_set->classPrio(blossom) -
1.994 - (*_blossom_data)[blossom].offset){
1.995 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1.996 - (*_blossom_data)[blossom].offset);
1.997 - }
1.998 - }
1.999 - }
1.1000 -
1.1001 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1.1002 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.1003 - _delta3->erase(e);
1.1004 - }
1.1005 - } else {
1.1006 -
1.1007 - typename std::map<int, Arc>::iterator it =
1.1008 - (*_node_data)[vi].heap_index.find(tree);
1.1009 -
1.1010 - if (it != (*_node_data)[vi].heap_index.end()) {
1.1011 - (*_node_data)[vi].heap.erase(it->second);
1.1012 - (*_node_data)[vi].heap_index.erase(it);
1.1013 - if ((*_node_data)[vi].heap.empty()) {
1.1014 - _blossom_set->increase(v, std::numeric_limits<Value>::max());
1.1015 - } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1.1016 - _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1.1017 - }
1.1018 -
1.1019 - if ((*_blossom_data)[vb].status == MATCHED) {
1.1020 - if (_blossom_set->classPrio(vb) ==
1.1021 - std::numeric_limits<Value>::max()) {
1.1022 - _delta2->erase(vb);
1.1023 - } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1.1024 - (*_blossom_data)[vb].offset) {
1.1025 - _delta2->increase(vb, _blossom_set->classPrio(vb) -
1.1026 - (*_blossom_data)[vb].offset);
1.1027 - }
1.1028 - }
1.1029 - }
1.1030 - }
1.1031 - }
1.1032 - }
1.1033 - }
1.1034 -
1.1035 - void oddToMatched(int blossom) {
1.1036 - (*_blossom_data)[blossom].offset -= _delta_sum;
1.1037 -
1.1038 - if (_blossom_set->classPrio(blossom) !=
1.1039 - std::numeric_limits<Value>::max()) {
1.1040 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1.1041 - (*_blossom_data)[blossom].offset);
1.1042 - }
1.1043 -
1.1044 - if (!_blossom_set->trivial(blossom)) {
1.1045 - _delta4->erase(blossom);
1.1046 - }
1.1047 - }
1.1048 -
1.1049 - void oddToEven(int blossom, int tree) {
1.1050 - if (!_blossom_set->trivial(blossom)) {
1.1051 - _delta4->erase(blossom);
1.1052 - (*_blossom_data)[blossom].pot -=
1.1053 - 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1.1054 - }
1.1055 -
1.1056 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.1057 - n != INVALID; ++n) {
1.1058 - int ni = (*_node_index)[n];
1.1059 -
1.1060 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
1.1061 -
1.1062 - (*_node_data)[ni].heap.clear();
1.1063 - (*_node_data)[ni].heap_index.clear();
1.1064 - (*_node_data)[ni].pot +=
1.1065 - 2 * _delta_sum - (*_blossom_data)[blossom].offset;
1.1066 -
1.1067 - _delta1->push(n, (*_node_data)[ni].pot);
1.1068 -
1.1069 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
1.1070 - Node v = _graph.source(e);
1.1071 - int vb = _blossom_set->find(v);
1.1072 - int vi = (*_node_index)[v];
1.1073 -
1.1074 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.1075 - dualScale * _weight[e];
1.1076 -
1.1077 - if ((*_blossom_data)[vb].status == EVEN) {
1.1078 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1.1079 - _delta3->push(e, rw / 2);
1.1080 - }
1.1081 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1.1082 - if (_delta3->state(e) != _delta3->IN_HEAP) {
1.1083 - _delta3->push(e, rw);
1.1084 - }
1.1085 - } else {
1.1086 -
1.1087 - typename std::map<int, Arc>::iterator it =
1.1088 - (*_node_data)[vi].heap_index.find(tree);
1.1089 -
1.1090 - if (it != (*_node_data)[vi].heap_index.end()) {
1.1091 - if ((*_node_data)[vi].heap[it->second] > rw) {
1.1092 - (*_node_data)[vi].heap.replace(it->second, e);
1.1093 - (*_node_data)[vi].heap.decrease(e, rw);
1.1094 - it->second = e;
1.1095 - }
1.1096 - } else {
1.1097 - (*_node_data)[vi].heap.push(e, rw);
1.1098 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1.1099 - }
1.1100 -
1.1101 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1.1102 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1.1103 -
1.1104 - if ((*_blossom_data)[vb].status == MATCHED) {
1.1105 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
1.1106 - _delta2->push(vb, _blossom_set->classPrio(vb) -
1.1107 - (*_blossom_data)[vb].offset);
1.1108 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1.1109 - (*_blossom_data)[vb].offset) {
1.1110 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1.1111 - (*_blossom_data)[vb].offset);
1.1112 - }
1.1113 - }
1.1114 - }
1.1115 - }
1.1116 - }
1.1117 - }
1.1118 - (*_blossom_data)[blossom].offset = 0;
1.1119 - }
1.1120 -
1.1121 -
1.1122 - void matchedToUnmatched(int blossom) {
1.1123 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1.1124 - _delta2->erase(blossom);
1.1125 - }
1.1126 -
1.1127 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.1128 - n != INVALID; ++n) {
1.1129 - int ni = (*_node_index)[n];
1.1130 -
1.1131 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
1.1132 -
1.1133 - (*_node_data)[ni].heap.clear();
1.1134 - (*_node_data)[ni].heap_index.clear();
1.1135 -
1.1136 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1.1137 - Node v = _graph.target(e);
1.1138 - int vb = _blossom_set->find(v);
1.1139 - int vi = (*_node_index)[v];
1.1140 -
1.1141 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.1142 - dualScale * _weight[e];
1.1143 -
1.1144 - if ((*_blossom_data)[vb].status == EVEN) {
1.1145 - if (_delta3->state(e) != _delta3->IN_HEAP) {
1.1146 - _delta3->push(e, rw);
1.1147 - }
1.1148 - }
1.1149 - }
1.1150 - }
1.1151 - }
1.1152 -
1.1153 - void unmatchedToMatched(int blossom) {
1.1154 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.1155 - n != INVALID; ++n) {
1.1156 - int ni = (*_node_index)[n];
1.1157 -
1.1158 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
1.1159 - Node v = _graph.source(e);
1.1160 - int vb = _blossom_set->find(v);
1.1161 - int vi = (*_node_index)[v];
1.1162 -
1.1163 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.1164 - dualScale * _weight[e];
1.1165 -
1.1166 - if (vb == blossom) {
1.1167 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.1168 - _delta3->erase(e);
1.1169 - }
1.1170 - } else if ((*_blossom_data)[vb].status == EVEN) {
1.1171 -
1.1172 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.1173 - _delta3->erase(e);
1.1174 - }
1.1175 -
1.1176 - int vt = _tree_set->find(vb);
1.1177 -
1.1178 - Arc r = _graph.oppositeArc(e);
1.1179 -
1.1180 - typename std::map<int, Arc>::iterator it =
1.1181 - (*_node_data)[ni].heap_index.find(vt);
1.1182 -
1.1183 - if (it != (*_node_data)[ni].heap_index.end()) {
1.1184 - if ((*_node_data)[ni].heap[it->second] > rw) {
1.1185 - (*_node_data)[ni].heap.replace(it->second, r);
1.1186 - (*_node_data)[ni].heap.decrease(r, rw);
1.1187 - it->second = r;
1.1188 - }
1.1189 - } else {
1.1190 - (*_node_data)[ni].heap.push(r, rw);
1.1191 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1.1192 - }
1.1193 -
1.1194 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1.1195 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1.1196 -
1.1197 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1.1198 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1.1199 - (*_blossom_data)[blossom].offset);
1.1200 - } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
1.1201 - (*_blossom_data)[blossom].offset){
1.1202 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1.1203 - (*_blossom_data)[blossom].offset);
1.1204 - }
1.1205 - }
1.1206 -
1.1207 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1.1208 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.1209 - _delta3->erase(e);
1.1210 - }
1.1211 - }
1.1212 - }
1.1213 - }
1.1214 - }
1.1215 -
1.1216 - void alternatePath(int even, int tree) {
1.1217 - int odd;
1.1218 -
1.1219 - evenToMatched(even, tree);
1.1220 - (*_blossom_data)[even].status = MATCHED;
1.1221 -
1.1222 - while ((*_blossom_data)[even].pred != INVALID) {
1.1223 - odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1.1224 - (*_blossom_data)[odd].status = MATCHED;
1.1225 - oddToMatched(odd);
1.1226 - (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1.1227 -
1.1228 - even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1.1229 - (*_blossom_data)[even].status = MATCHED;
1.1230 - evenToMatched(even, tree);
1.1231 - (*_blossom_data)[even].next =
1.1232 - _graph.oppositeArc((*_blossom_data)[odd].pred);
1.1233 - }
1.1234 -
1.1235 - }
1.1236 -
1.1237 - void destroyTree(int tree) {
1.1238 - for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1.1239 - if ((*_blossom_data)[b].status == EVEN) {
1.1240 - (*_blossom_data)[b].status = MATCHED;
1.1241 - evenToMatched(b, tree);
1.1242 - } else if ((*_blossom_data)[b].status == ODD) {
1.1243 - (*_blossom_data)[b].status = MATCHED;
1.1244 - oddToMatched(b);
1.1245 - }
1.1246 - }
1.1247 - _tree_set->eraseClass(tree);
1.1248 - }
1.1249 -
1.1250 -
1.1251 - void unmatchNode(const Node& node) {
1.1252 - int blossom = _blossom_set->find(node);
1.1253 - int tree = _tree_set->find(blossom);
1.1254 -
1.1255 - alternatePath(blossom, tree);
1.1256 - destroyTree(tree);
1.1257 -
1.1258 - (*_blossom_data)[blossom].status = UNMATCHED;
1.1259 - (*_blossom_data)[blossom].base = node;
1.1260 - matchedToUnmatched(blossom);
1.1261 - }
1.1262 -
1.1263 -
1.1264 - void augmentOnEdge(const Edge& edge) {
1.1265 -
1.1266 - int left = _blossom_set->find(_graph.u(edge));
1.1267 - int right = _blossom_set->find(_graph.v(edge));
1.1268 -
1.1269 - if ((*_blossom_data)[left].status == EVEN) {
1.1270 - int left_tree = _tree_set->find(left);
1.1271 - alternatePath(left, left_tree);
1.1272 - destroyTree(left_tree);
1.1273 - } else {
1.1274 - (*_blossom_data)[left].status = MATCHED;
1.1275 - unmatchedToMatched(left);
1.1276 - }
1.1277 -
1.1278 - if ((*_blossom_data)[right].status == EVEN) {
1.1279 - int right_tree = _tree_set->find(right);
1.1280 - alternatePath(right, right_tree);
1.1281 - destroyTree(right_tree);
1.1282 - } else {
1.1283 - (*_blossom_data)[right].status = MATCHED;
1.1284 - unmatchedToMatched(right);
1.1285 - }
1.1286 -
1.1287 - (*_blossom_data)[left].next = _graph.direct(edge, true);
1.1288 - (*_blossom_data)[right].next = _graph.direct(edge, false);
1.1289 - }
1.1290 -
1.1291 - void extendOnArc(const Arc& arc) {
1.1292 - int base = _blossom_set->find(_graph.target(arc));
1.1293 - int tree = _tree_set->find(base);
1.1294 -
1.1295 - int odd = _blossom_set->find(_graph.source(arc));
1.1296 - _tree_set->insert(odd, tree);
1.1297 - (*_blossom_data)[odd].status = ODD;
1.1298 - matchedToOdd(odd);
1.1299 - (*_blossom_data)[odd].pred = arc;
1.1300 -
1.1301 - int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1.1302 - (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1.1303 - _tree_set->insert(even, tree);
1.1304 - (*_blossom_data)[even].status = EVEN;
1.1305 - matchedToEven(even, tree);
1.1306 - }
1.1307 -
1.1308 - void shrinkOnEdge(const Edge& edge, int tree) {
1.1309 - int nca = -1;
1.1310 - std::vector<int> left_path, right_path;
1.1311 -
1.1312 - {
1.1313 - std::set<int> left_set, right_set;
1.1314 - int left = _blossom_set->find(_graph.u(edge));
1.1315 - left_path.push_back(left);
1.1316 - left_set.insert(left);
1.1317 -
1.1318 - int right = _blossom_set->find(_graph.v(edge));
1.1319 - right_path.push_back(right);
1.1320 - right_set.insert(right);
1.1321 -
1.1322 - while (true) {
1.1323 -
1.1324 - if ((*_blossom_data)[left].pred == INVALID) break;
1.1325 -
1.1326 - left =
1.1327 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1.1328 - left_path.push_back(left);
1.1329 - left =
1.1330 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1.1331 - left_path.push_back(left);
1.1332 -
1.1333 - left_set.insert(left);
1.1334 -
1.1335 - if (right_set.find(left) != right_set.end()) {
1.1336 - nca = left;
1.1337 - break;
1.1338 - }
1.1339 -
1.1340 - if ((*_blossom_data)[right].pred == INVALID) break;
1.1341 -
1.1342 - right =
1.1343 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1.1344 - right_path.push_back(right);
1.1345 - right =
1.1346 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1.1347 - right_path.push_back(right);
1.1348 -
1.1349 - right_set.insert(right);
1.1350 -
1.1351 - if (left_set.find(right) != left_set.end()) {
1.1352 - nca = right;
1.1353 - break;
1.1354 - }
1.1355 -
1.1356 - }
1.1357 -
1.1358 - if (nca == -1) {
1.1359 - if ((*_blossom_data)[left].pred == INVALID) {
1.1360 - nca = right;
1.1361 - while (left_set.find(nca) == left_set.end()) {
1.1362 - nca =
1.1363 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.1364 - right_path.push_back(nca);
1.1365 - nca =
1.1366 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.1367 - right_path.push_back(nca);
1.1368 - }
1.1369 - } else {
1.1370 - nca = left;
1.1371 - while (right_set.find(nca) == right_set.end()) {
1.1372 - nca =
1.1373 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.1374 - left_path.push_back(nca);
1.1375 - nca =
1.1376 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.1377 - left_path.push_back(nca);
1.1378 - }
1.1379 - }
1.1380 - }
1.1381 - }
1.1382 -
1.1383 - std::vector<int> subblossoms;
1.1384 - Arc prev;
1.1385 -
1.1386 - prev = _graph.direct(edge, true);
1.1387 - for (int i = 0; left_path[i] != nca; i += 2) {
1.1388 - subblossoms.push_back(left_path[i]);
1.1389 - (*_blossom_data)[left_path[i]].next = prev;
1.1390 - _tree_set->erase(left_path[i]);
1.1391 -
1.1392 - subblossoms.push_back(left_path[i + 1]);
1.1393 - (*_blossom_data)[left_path[i + 1]].status = EVEN;
1.1394 - oddToEven(left_path[i + 1], tree);
1.1395 - _tree_set->erase(left_path[i + 1]);
1.1396 - prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1.1397 - }
1.1398 -
1.1399 - int k = 0;
1.1400 - while (right_path[k] != nca) ++k;
1.1401 -
1.1402 - subblossoms.push_back(nca);
1.1403 - (*_blossom_data)[nca].next = prev;
1.1404 -
1.1405 - for (int i = k - 2; i >= 0; i -= 2) {
1.1406 - subblossoms.push_back(right_path[i + 1]);
1.1407 - (*_blossom_data)[right_path[i + 1]].status = EVEN;
1.1408 - oddToEven(right_path[i + 1], tree);
1.1409 - _tree_set->erase(right_path[i + 1]);
1.1410 -
1.1411 - (*_blossom_data)[right_path[i + 1]].next =
1.1412 - (*_blossom_data)[right_path[i + 1]].pred;
1.1413 -
1.1414 - subblossoms.push_back(right_path[i]);
1.1415 - _tree_set->erase(right_path[i]);
1.1416 - }
1.1417 -
1.1418 - int surface =
1.1419 - _blossom_set->join(subblossoms.begin(), subblossoms.end());
1.1420 -
1.1421 - for (int i = 0; i < int(subblossoms.size()); ++i) {
1.1422 - if (!_blossom_set->trivial(subblossoms[i])) {
1.1423 - (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1.1424 - }
1.1425 - (*_blossom_data)[subblossoms[i]].status = MATCHED;
1.1426 - }
1.1427 -
1.1428 - (*_blossom_data)[surface].pot = -2 * _delta_sum;
1.1429 - (*_blossom_data)[surface].offset = 0;
1.1430 - (*_blossom_data)[surface].status = EVEN;
1.1431 - (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1.1432 - (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1.1433 -
1.1434 - _tree_set->insert(surface, tree);
1.1435 - _tree_set->erase(nca);
1.1436 - }
1.1437 -
1.1438 - void splitBlossom(int blossom) {
1.1439 - Arc next = (*_blossom_data)[blossom].next;
1.1440 - Arc pred = (*_blossom_data)[blossom].pred;
1.1441 -
1.1442 - int tree = _tree_set->find(blossom);
1.1443 -
1.1444 - (*_blossom_data)[blossom].status = MATCHED;
1.1445 - oddToMatched(blossom);
1.1446 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1.1447 - _delta2->erase(blossom);
1.1448 - }
1.1449 -
1.1450 - std::vector<int> subblossoms;
1.1451 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
1.1452 -
1.1453 - Value offset = (*_blossom_data)[blossom].offset;
1.1454 - int b = _blossom_set->find(_graph.source(pred));
1.1455 - int d = _blossom_set->find(_graph.source(next));
1.1456 -
1.1457 - int ib = -1, id = -1;
1.1458 - for (int i = 0; i < int(subblossoms.size()); ++i) {
1.1459 - if (subblossoms[i] == b) ib = i;
1.1460 - if (subblossoms[i] == d) id = i;
1.1461 -
1.1462 - (*_blossom_data)[subblossoms[i]].offset = offset;
1.1463 - if (!_blossom_set->trivial(subblossoms[i])) {
1.1464 - (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1.1465 - }
1.1466 - if (_blossom_set->classPrio(subblossoms[i]) !=
1.1467 - std::numeric_limits<Value>::max()) {
1.1468 - _delta2->push(subblossoms[i],
1.1469 - _blossom_set->classPrio(subblossoms[i]) -
1.1470 - (*_blossom_data)[subblossoms[i]].offset);
1.1471 - }
1.1472 - }
1.1473 -
1.1474 - if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1.1475 - for (int i = (id + 1) % subblossoms.size();
1.1476 - i != ib; i = (i + 2) % subblossoms.size()) {
1.1477 - int sb = subblossoms[i];
1.1478 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.1479 - (*_blossom_data)[sb].next =
1.1480 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.1481 - }
1.1482 -
1.1483 - for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1.1484 - int sb = subblossoms[i];
1.1485 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.1486 - int ub = subblossoms[(i + 2) % subblossoms.size()];
1.1487 -
1.1488 - (*_blossom_data)[sb].status = ODD;
1.1489 - matchedToOdd(sb);
1.1490 - _tree_set->insert(sb, tree);
1.1491 - (*_blossom_data)[sb].pred = pred;
1.1492 - (*_blossom_data)[sb].next =
1.1493 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.1494 -
1.1495 - pred = (*_blossom_data)[ub].next;
1.1496 -
1.1497 - (*_blossom_data)[tb].status = EVEN;
1.1498 - matchedToEven(tb, tree);
1.1499 - _tree_set->insert(tb, tree);
1.1500 - (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1.1501 - }
1.1502 -
1.1503 - (*_blossom_data)[subblossoms[id]].status = ODD;
1.1504 - matchedToOdd(subblossoms[id]);
1.1505 - _tree_set->insert(subblossoms[id], tree);
1.1506 - (*_blossom_data)[subblossoms[id]].next = next;
1.1507 - (*_blossom_data)[subblossoms[id]].pred = pred;
1.1508 -
1.1509 - } else {
1.1510 -
1.1511 - for (int i = (ib + 1) % subblossoms.size();
1.1512 - i != id; i = (i + 2) % subblossoms.size()) {
1.1513 - int sb = subblossoms[i];
1.1514 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.1515 - (*_blossom_data)[sb].next =
1.1516 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.1517 - }
1.1518 -
1.1519 - for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1.1520 - int sb = subblossoms[i];
1.1521 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.1522 - int ub = subblossoms[(i + 2) % subblossoms.size()];
1.1523 -
1.1524 - (*_blossom_data)[sb].status = ODD;
1.1525 - matchedToOdd(sb);
1.1526 - _tree_set->insert(sb, tree);
1.1527 - (*_blossom_data)[sb].next = next;
1.1528 - (*_blossom_data)[sb].pred =
1.1529 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.1530 -
1.1531 - (*_blossom_data)[tb].status = EVEN;
1.1532 - matchedToEven(tb, tree);
1.1533 - _tree_set->insert(tb, tree);
1.1534 - (*_blossom_data)[tb].pred =
1.1535 - (*_blossom_data)[tb].next =
1.1536 - _graph.oppositeArc((*_blossom_data)[ub].next);
1.1537 - next = (*_blossom_data)[ub].next;
1.1538 - }
1.1539 -
1.1540 - (*_blossom_data)[subblossoms[ib]].status = ODD;
1.1541 - matchedToOdd(subblossoms[ib]);
1.1542 - _tree_set->insert(subblossoms[ib], tree);
1.1543 - (*_blossom_data)[subblossoms[ib]].next = next;
1.1544 - (*_blossom_data)[subblossoms[ib]].pred = pred;
1.1545 - }
1.1546 - _tree_set->erase(blossom);
1.1547 - }
1.1548 -
1.1549 - void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1.1550 - if (_blossom_set->trivial(blossom)) {
1.1551 - int bi = (*_node_index)[base];
1.1552 - Value pot = (*_node_data)[bi].pot;
1.1553 -
1.1554 - (*_matching)[base] = matching;
1.1555 - _blossom_node_list.push_back(base);
1.1556 - (*_node_potential)[base] = pot;
1.1557 - } else {
1.1558 -
1.1559 - Value pot = (*_blossom_data)[blossom].pot;
1.1560 - int bn = _blossom_node_list.size();
1.1561 -
1.1562 - std::vector<int> subblossoms;
1.1563 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
1.1564 - int b = _blossom_set->find(base);
1.1565 - int ib = -1;
1.1566 - for (int i = 0; i < int(subblossoms.size()); ++i) {
1.1567 - if (subblossoms[i] == b) { ib = i; break; }
1.1568 - }
1.1569 -
1.1570 - for (int i = 1; i < int(subblossoms.size()); i += 2) {
1.1571 - int sb = subblossoms[(ib + i) % subblossoms.size()];
1.1572 - int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1.1573 -
1.1574 - Arc m = (*_blossom_data)[tb].next;
1.1575 - extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1.1576 - extractBlossom(tb, _graph.source(m), m);
1.1577 - }
1.1578 - extractBlossom(subblossoms[ib], base, matching);
1.1579 -
1.1580 - int en = _blossom_node_list.size();
1.1581 -
1.1582 - _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1.1583 - }
1.1584 - }
1.1585 -
1.1586 - void extractMatching() {
1.1587 - std::vector<int> blossoms;
1.1588 - for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1.1589 - blossoms.push_back(c);
1.1590 - }
1.1591 -
1.1592 - for (int i = 0; i < int(blossoms.size()); ++i) {
1.1593 - if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
1.1594 -
1.1595 - Value offset = (*_blossom_data)[blossoms[i]].offset;
1.1596 - (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1.1597 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1.1598 - n != INVALID; ++n) {
1.1599 - (*_node_data)[(*_node_index)[n]].pot -= offset;
1.1600 - }
1.1601 -
1.1602 - Arc matching = (*_blossom_data)[blossoms[i]].next;
1.1603 - Node base = _graph.source(matching);
1.1604 - extractBlossom(blossoms[i], base, matching);
1.1605 - } else {
1.1606 - Node base = (*_blossom_data)[blossoms[i]].base;
1.1607 - extractBlossom(blossoms[i], base, INVALID);
1.1608 - }
1.1609 - }
1.1610 - }
1.1611 -
1.1612 - public:
1.1613 -
1.1614 - /// \brief Constructor
1.1615 - ///
1.1616 - /// Constructor.
1.1617 - MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1.1618 - : _graph(graph), _weight(weight), _matching(0),
1.1619 - _node_potential(0), _blossom_potential(), _blossom_node_list(),
1.1620 - _node_num(0), _blossom_num(0),
1.1621 -
1.1622 - _blossom_index(0), _blossom_set(0), _blossom_data(0),
1.1623 - _node_index(0), _node_heap_index(0), _node_data(0),
1.1624 - _tree_set_index(0), _tree_set(0),
1.1625 -
1.1626 - _delta1_index(0), _delta1(0),
1.1627 - _delta2_index(0), _delta2(0),
1.1628 - _delta3_index(0), _delta3(0),
1.1629 - _delta4_index(0), _delta4(0),
1.1630 -
1.1631 - _delta_sum() {}
1.1632 -
1.1633 - ~MaxWeightedMatching() {
1.1634 - destroyStructures();
1.1635 - }
1.1636 -
1.1637 - /// \name Execution control
1.1638 - /// The simplest way to execute the algorithm is to use the
1.1639 - /// \c run() member function.
1.1640 -
1.1641 - ///@{
1.1642 -
1.1643 - /// \brief Initialize the algorithm
1.1644 - ///
1.1645 - /// Initialize the algorithm
1.1646 - void init() {
1.1647 - createStructures();
1.1648 -
1.1649 - for (ArcIt e(_graph); e != INVALID; ++e) {
1.1650 - (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1.1651 - }
1.1652 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.1653 - (*_delta1_index)[n] = _delta1->PRE_HEAP;
1.1654 - }
1.1655 - for (EdgeIt e(_graph); e != INVALID; ++e) {
1.1656 - (*_delta3_index)[e] = _delta3->PRE_HEAP;
1.1657 - }
1.1658 - for (int i = 0; i < _blossom_num; ++i) {
1.1659 - (*_delta2_index)[i] = _delta2->PRE_HEAP;
1.1660 - (*_delta4_index)[i] = _delta4->PRE_HEAP;
1.1661 - }
1.1662 -
1.1663 - int index = 0;
1.1664 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.1665 - Value max = 0;
1.1666 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1.1667 - if (_graph.target(e) == n) continue;
1.1668 - if ((dualScale * _weight[e]) / 2 > max) {
1.1669 - max = (dualScale * _weight[e]) / 2;
1.1670 - }
1.1671 - }
1.1672 - (*_node_index)[n] = index;
1.1673 - (*_node_data)[index].pot = max;
1.1674 - _delta1->push(n, max);
1.1675 - int blossom =
1.1676 - _blossom_set->insert(n, std::numeric_limits<Value>::max());
1.1677 -
1.1678 - _tree_set->insert(blossom);
1.1679 -
1.1680 - (*_blossom_data)[blossom].status = EVEN;
1.1681 - (*_blossom_data)[blossom].pred = INVALID;
1.1682 - (*_blossom_data)[blossom].next = INVALID;
1.1683 - (*_blossom_data)[blossom].pot = 0;
1.1684 - (*_blossom_data)[blossom].offset = 0;
1.1685 - ++index;
1.1686 - }
1.1687 - for (EdgeIt e(_graph); e != INVALID; ++e) {
1.1688 - int si = (*_node_index)[_graph.u(e)];
1.1689 - int ti = (*_node_index)[_graph.v(e)];
1.1690 - if (_graph.u(e) != _graph.v(e)) {
1.1691 - _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1.1692 - dualScale * _weight[e]) / 2);
1.1693 - }
1.1694 - }
1.1695 - }
1.1696 -
1.1697 - /// \brief Starts the algorithm
1.1698 - ///
1.1699 - /// Starts the algorithm
1.1700 - void start() {
1.1701 - enum OpType {
1.1702 - D1, D2, D3, D4
1.1703 - };
1.1704 -
1.1705 - int unmatched = _node_num;
1.1706 - while (unmatched > 0) {
1.1707 - Value d1 = !_delta1->empty() ?
1.1708 - _delta1->prio() : std::numeric_limits<Value>::max();
1.1709 -
1.1710 - Value d2 = !_delta2->empty() ?
1.1711 - _delta2->prio() : std::numeric_limits<Value>::max();
1.1712 -
1.1713 - Value d3 = !_delta3->empty() ?
1.1714 - _delta3->prio() : std::numeric_limits<Value>::max();
1.1715 -
1.1716 - Value d4 = !_delta4->empty() ?
1.1717 - _delta4->prio() : std::numeric_limits<Value>::max();
1.1718 -
1.1719 - _delta_sum = d1; OpType ot = D1;
1.1720 - if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1.1721 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1.1722 - if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1.1723 -
1.1724 -
1.1725 - switch (ot) {
1.1726 - case D1:
1.1727 - {
1.1728 - Node n = _delta1->top();
1.1729 - unmatchNode(n);
1.1730 - --unmatched;
1.1731 - }
1.1732 - break;
1.1733 - case D2:
1.1734 - {
1.1735 - int blossom = _delta2->top();
1.1736 - Node n = _blossom_set->classTop(blossom);
1.1737 - Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1.1738 - extendOnArc(e);
1.1739 - }
1.1740 - break;
1.1741 - case D3:
1.1742 - {
1.1743 - Edge e = _delta3->top();
1.1744 -
1.1745 - int left_blossom = _blossom_set->find(_graph.u(e));
1.1746 - int right_blossom = _blossom_set->find(_graph.v(e));
1.1747 -
1.1748 - if (left_blossom == right_blossom) {
1.1749 - _delta3->pop();
1.1750 - } else {
1.1751 - int left_tree;
1.1752 - if ((*_blossom_data)[left_blossom].status == EVEN) {
1.1753 - left_tree = _tree_set->find(left_blossom);
1.1754 - } else {
1.1755 - left_tree = -1;
1.1756 - ++unmatched;
1.1757 - }
1.1758 - int right_tree;
1.1759 - if ((*_blossom_data)[right_blossom].status == EVEN) {
1.1760 - right_tree = _tree_set->find(right_blossom);
1.1761 - } else {
1.1762 - right_tree = -1;
1.1763 - ++unmatched;
1.1764 - }
1.1765 -
1.1766 - if (left_tree == right_tree) {
1.1767 - shrinkOnEdge(e, left_tree);
1.1768 - } else {
1.1769 - augmentOnEdge(e);
1.1770 - unmatched -= 2;
1.1771 - }
1.1772 - }
1.1773 - } break;
1.1774 - case D4:
1.1775 - splitBlossom(_delta4->top());
1.1776 - break;
1.1777 - }
1.1778 - }
1.1779 - extractMatching();
1.1780 - }
1.1781 -
1.1782 - /// \brief Runs %MaxWeightedMatching algorithm.
1.1783 - ///
1.1784 - /// This method runs the %MaxWeightedMatching algorithm.
1.1785 - ///
1.1786 - /// \note mwm.run() is just a shortcut of the following code.
1.1787 - /// \code
1.1788 - /// mwm.init();
1.1789 - /// mwm.start();
1.1790 - /// \endcode
1.1791 - void run() {
1.1792 - init();
1.1793 - start();
1.1794 - }
1.1795 -
1.1796 - /// @}
1.1797 -
1.1798 - /// \name Primal solution
1.1799 - /// Functions to get the primal solution, ie. the matching.
1.1800 -
1.1801 - /// @{
1.1802 -
1.1803 - /// \brief Returns the weight of the matching.
1.1804 - ///
1.1805 - /// Returns the weight of the matching.
1.1806 - Value matchingValue() const {
1.1807 - Value sum = 0;
1.1808 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.1809 - if ((*_matching)[n] != INVALID) {
1.1810 - sum += _weight[(*_matching)[n]];
1.1811 - }
1.1812 - }
1.1813 - return sum /= 2;
1.1814 - }
1.1815 -
1.1816 - /// \brief Returns the cardinality of the matching.
1.1817 - ///
1.1818 - /// Returns the cardinality of the matching.
1.1819 - int matchingSize() const {
1.1820 - int num = 0;
1.1821 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.1822 - if ((*_matching)[n] != INVALID) {
1.1823 - ++num;
1.1824 - }
1.1825 - }
1.1826 - return num /= 2;
1.1827 - }
1.1828 -
1.1829 - /// \brief Returns true when the edge is in the matching.
1.1830 - ///
1.1831 - /// Returns true when the edge is in the matching.
1.1832 - bool matching(const Edge& edge) const {
1.1833 - return edge == (*_matching)[_graph.u(edge)];
1.1834 - }
1.1835 -
1.1836 - /// \brief Returns the incident matching arc.
1.1837 - ///
1.1838 - /// Returns the incident matching arc from given node. If the
1.1839 - /// node is not matched then it gives back \c INVALID.
1.1840 - Arc matching(const Node& node) const {
1.1841 - return (*_matching)[node];
1.1842 - }
1.1843 -
1.1844 - /// \brief Returns the mate of the node.
1.1845 - ///
1.1846 - /// Returns the adjancent node in a mathcing arc. If the node is
1.1847 - /// not matched then it gives back \c INVALID.
1.1848 - Node mate(const Node& node) const {
1.1849 - return (*_matching)[node] != INVALID ?
1.1850 - _graph.target((*_matching)[node]) : INVALID;
1.1851 - }
1.1852 -
1.1853 - /// @}
1.1854 -
1.1855 - /// \name Dual solution
1.1856 - /// Functions to get the dual solution.
1.1857 -
1.1858 - /// @{
1.1859 -
1.1860 - /// \brief Returns the value of the dual solution.
1.1861 - ///
1.1862 - /// Returns the value of the dual solution. It should be equal to
1.1863 - /// the primal value scaled by \ref dualScale "dual scale".
1.1864 - Value dualValue() const {
1.1865 - Value sum = 0;
1.1866 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.1867 - sum += nodeValue(n);
1.1868 - }
1.1869 - for (int i = 0; i < blossomNum(); ++i) {
1.1870 - sum += blossomValue(i) * (blossomSize(i) / 2);
1.1871 - }
1.1872 - return sum;
1.1873 - }
1.1874 -
1.1875 - /// \brief Returns the value of the node.
1.1876 - ///
1.1877 - /// Returns the the value of the node.
1.1878 - Value nodeValue(const Node& n) const {
1.1879 - return (*_node_potential)[n];
1.1880 - }
1.1881 -
1.1882 - /// \brief Returns the number of the blossoms in the basis.
1.1883 - ///
1.1884 - /// Returns the number of the blossoms in the basis.
1.1885 - /// \see BlossomIt
1.1886 - int blossomNum() const {
1.1887 - return _blossom_potential.size();
1.1888 - }
1.1889 -
1.1890 -
1.1891 - /// \brief Returns the number of the nodes in the blossom.
1.1892 - ///
1.1893 - /// Returns the number of the nodes in the blossom.
1.1894 - int blossomSize(int k) const {
1.1895 - return _blossom_potential[k].end - _blossom_potential[k].begin;
1.1896 - }
1.1897 -
1.1898 - /// \brief Returns the value of the blossom.
1.1899 - ///
1.1900 - /// Returns the the value of the blossom.
1.1901 - /// \see BlossomIt
1.1902 - Value blossomValue(int k) const {
1.1903 - return _blossom_potential[k].value;
1.1904 - }
1.1905 -
1.1906 - /// \brief Iterator for obtaining the nodes of the blossom.
1.1907 - ///
1.1908 - /// Iterator for obtaining the nodes of the blossom. This class
1.1909 - /// provides a common lemon style iterator for listing a
1.1910 - /// subset of the nodes.
1.1911 - class BlossomIt {
1.1912 - public:
1.1913 -
1.1914 - /// \brief Constructor.
1.1915 - ///
1.1916 - /// Constructor to get the nodes of the variable.
1.1917 - BlossomIt(const MaxWeightedMatching& algorithm, int variable)
1.1918 - : _algorithm(&algorithm)
1.1919 - {
1.1920 - _index = _algorithm->_blossom_potential[variable].begin;
1.1921 - _last = _algorithm->_blossom_potential[variable].end;
1.1922 - }
1.1923 -
1.1924 - /// \brief Conversion to node.
1.1925 - ///
1.1926 - /// Conversion to node.
1.1927 - operator Node() const {
1.1928 - return _algorithm->_blossom_node_list[_index];
1.1929 - }
1.1930 -
1.1931 - /// \brief Increment operator.
1.1932 - ///
1.1933 - /// Increment operator.
1.1934 - BlossomIt& operator++() {
1.1935 - ++_index;
1.1936 - return *this;
1.1937 - }
1.1938 -
1.1939 - /// \brief Validity checking
1.1940 - ///
1.1941 - /// Checks whether the iterator is invalid.
1.1942 - bool operator==(Invalid) const { return _index == _last; }
1.1943 -
1.1944 - /// \brief Validity checking
1.1945 - ///
1.1946 - /// Checks whether the iterator is valid.
1.1947 - bool operator!=(Invalid) const { return _index != _last; }
1.1948 -
1.1949 - private:
1.1950 - const MaxWeightedMatching* _algorithm;
1.1951 - int _last;
1.1952 - int _index;
1.1953 - };
1.1954 -
1.1955 - /// @}
1.1956 -
1.1957 - };
1.1958 -
1.1959 - /// \ingroup matching
1.1960 - ///
1.1961 - /// \brief Weighted perfect matching in general graphs
1.1962 - ///
1.1963 - /// This class provides an efficient implementation of Edmond's
1.1964 - /// maximum weighted perfect matching algorithm. The implementation
1.1965 - /// is based on extensive use of priority queues and provides
1.1966 - /// \f$O(nm\log n)\f$ time complexity.
1.1967 - ///
1.1968 - /// The maximum weighted matching problem is to find undirected
1.1969 - /// edges in the graph with maximum overall weight and no two of
1.1970 - /// them shares their ends and covers all nodes. The problem can be
1.1971 - /// formulated with the following linear program.
1.1972 - /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1.1973 - /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
1.1974 - \quad \forall B\in\mathcal{O}\f] */
1.1975 - /// \f[x_e \ge 0\quad \forall e\in E\f]
1.1976 - /// \f[\max \sum_{e\in E}x_ew_e\f]
1.1977 - /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1.1978 - /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
1.1979 - /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
1.1980 - /// subsets of the nodes.
1.1981 - ///
1.1982 - /// The algorithm calculates an optimal matching and a proof of the
1.1983 - /// optimality. The solution of the dual problem can be used to check
1.1984 - /// the result of the algorithm. The dual linear problem is the
1.1985 - /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
1.1986 - w_{uv} \quad \forall uv\in E\f] */
1.1987 - /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
1.1988 - /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
1.1989 - \frac{\vert B \vert - 1}{2}z_B\f] */
1.1990 - ///
1.1991 - /// The algorithm can be executed with \c run() or the \c init() and
1.1992 - /// then the \c start() member functions. After it the matching can
1.1993 - /// be asked with \c matching() or mate() functions. The dual
1.1994 - /// solution can be get with \c nodeValue(), \c blossomNum() and \c
1.1995 - /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
1.1996 - /// "BlossomIt" nested class which is able to iterate on the nodes
1.1997 - /// of a blossom. If the value type is integral then the dual
1.1998 - /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
1.1999 - template <typename GR,
1.2000 - typename WM = typename GR::template EdgeMap<int> >
1.2001 - class MaxWeightedPerfectMatching {
1.2002 - public:
1.2003 -
1.2004 - typedef GR Graph;
1.2005 - typedef WM WeightMap;
1.2006 - typedef typename WeightMap::Value Value;
1.2007 -
1.2008 - /// \brief Scaling factor for dual solution
1.2009 - ///
1.2010 - /// Scaling factor for dual solution, it is equal to 4 or 1
1.2011 - /// according to the value type.
1.2012 - static const int dualScale =
1.2013 - std::numeric_limits<Value>::is_integer ? 4 : 1;
1.2014 -
1.2015 - typedef typename Graph::template NodeMap<typename Graph::Arc>
1.2016 - MatchingMap;
1.2017 -
1.2018 - private:
1.2019 -
1.2020 - TEMPLATE_GRAPH_TYPEDEFS(Graph);
1.2021 -
1.2022 - typedef typename Graph::template NodeMap<Value> NodePotential;
1.2023 - typedef std::vector<Node> BlossomNodeList;
1.2024 -
1.2025 - struct BlossomVariable {
1.2026 - int begin, end;
1.2027 - Value value;
1.2028 -
1.2029 - BlossomVariable(int _begin, int _end, Value _value)
1.2030 - : begin(_begin), end(_end), value(_value) {}
1.2031 -
1.2032 - };
1.2033 -
1.2034 - typedef std::vector<BlossomVariable> BlossomPotential;
1.2035 -
1.2036 - const Graph& _graph;
1.2037 - const WeightMap& _weight;
1.2038 -
1.2039 - MatchingMap* _matching;
1.2040 -
1.2041 - NodePotential* _node_potential;
1.2042 -
1.2043 - BlossomPotential _blossom_potential;
1.2044 - BlossomNodeList _blossom_node_list;
1.2045 -
1.2046 - int _node_num;
1.2047 - int _blossom_num;
1.2048 -
1.2049 - typedef RangeMap<int> IntIntMap;
1.2050 -
1.2051 - enum Status {
1.2052 - EVEN = -1, MATCHED = 0, ODD = 1
1.2053 - };
1.2054 -
1.2055 - typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
1.2056 - struct BlossomData {
1.2057 - int tree;
1.2058 - Status status;
1.2059 - Arc pred, next;
1.2060 - Value pot, offset;
1.2061 - };
1.2062 -
1.2063 - IntNodeMap *_blossom_index;
1.2064 - BlossomSet *_blossom_set;
1.2065 - RangeMap<BlossomData>* _blossom_data;
1.2066 -
1.2067 - IntNodeMap *_node_index;
1.2068 - IntArcMap *_node_heap_index;
1.2069 -
1.2070 - struct NodeData {
1.2071 -
1.2072 - NodeData(IntArcMap& node_heap_index)
1.2073 - : heap(node_heap_index) {}
1.2074 -
1.2075 - int blossom;
1.2076 - Value pot;
1.2077 - BinHeap<Value, IntArcMap> heap;
1.2078 - std::map<int, Arc> heap_index;
1.2079 -
1.2080 - int tree;
1.2081 - };
1.2082 -
1.2083 - RangeMap<NodeData>* _node_data;
1.2084 -
1.2085 - typedef ExtendFindEnum<IntIntMap> TreeSet;
1.2086 -
1.2087 - IntIntMap *_tree_set_index;
1.2088 - TreeSet *_tree_set;
1.2089 -
1.2090 - IntIntMap *_delta2_index;
1.2091 - BinHeap<Value, IntIntMap> *_delta2;
1.2092 -
1.2093 - IntEdgeMap *_delta3_index;
1.2094 - BinHeap<Value, IntEdgeMap> *_delta3;
1.2095 -
1.2096 - IntIntMap *_delta4_index;
1.2097 - BinHeap<Value, IntIntMap> *_delta4;
1.2098 -
1.2099 - Value _delta_sum;
1.2100 -
1.2101 - void createStructures() {
1.2102 - _node_num = countNodes(_graph);
1.2103 - _blossom_num = _node_num * 3 / 2;
1.2104 -
1.2105 - if (!_matching) {
1.2106 - _matching = new MatchingMap(_graph);
1.2107 - }
1.2108 - if (!_node_potential) {
1.2109 - _node_potential = new NodePotential(_graph);
1.2110 - }
1.2111 - if (!_blossom_set) {
1.2112 - _blossom_index = new IntNodeMap(_graph);
1.2113 - _blossom_set = new BlossomSet(*_blossom_index);
1.2114 - _blossom_data = new RangeMap<BlossomData>(_blossom_num);
1.2115 - }
1.2116 -
1.2117 - if (!_node_index) {
1.2118 - _node_index = new IntNodeMap(_graph);
1.2119 - _node_heap_index = new IntArcMap(_graph);
1.2120 - _node_data = new RangeMap<NodeData>(_node_num,
1.2121 - NodeData(*_node_heap_index));
1.2122 - }
1.2123 -
1.2124 - if (!_tree_set) {
1.2125 - _tree_set_index = new IntIntMap(_blossom_num);
1.2126 - _tree_set = new TreeSet(*_tree_set_index);
1.2127 - }
1.2128 - if (!_delta2) {
1.2129 - _delta2_index = new IntIntMap(_blossom_num);
1.2130 - _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
1.2131 - }
1.2132 - if (!_delta3) {
1.2133 - _delta3_index = new IntEdgeMap(_graph);
1.2134 - _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
1.2135 - }
1.2136 - if (!_delta4) {
1.2137 - _delta4_index = new IntIntMap(_blossom_num);
1.2138 - _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
1.2139 - }
1.2140 - }
1.2141 -
1.2142 - void destroyStructures() {
1.2143 - _node_num = countNodes(_graph);
1.2144 - _blossom_num = _node_num * 3 / 2;
1.2145 -
1.2146 - if (_matching) {
1.2147 - delete _matching;
1.2148 - }
1.2149 - if (_node_potential) {
1.2150 - delete _node_potential;
1.2151 - }
1.2152 - if (_blossom_set) {
1.2153 - delete _blossom_index;
1.2154 - delete _blossom_set;
1.2155 - delete _blossom_data;
1.2156 - }
1.2157 -
1.2158 - if (_node_index) {
1.2159 - delete _node_index;
1.2160 - delete _node_heap_index;
1.2161 - delete _node_data;
1.2162 - }
1.2163 -
1.2164 - if (_tree_set) {
1.2165 - delete _tree_set_index;
1.2166 - delete _tree_set;
1.2167 - }
1.2168 - if (_delta2) {
1.2169 - delete _delta2_index;
1.2170 - delete _delta2;
1.2171 - }
1.2172 - if (_delta3) {
1.2173 - delete _delta3_index;
1.2174 - delete _delta3;
1.2175 - }
1.2176 - if (_delta4) {
1.2177 - delete _delta4_index;
1.2178 - delete _delta4;
1.2179 - }
1.2180 - }
1.2181 -
1.2182 - void matchedToEven(int blossom, int tree) {
1.2183 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1.2184 - _delta2->erase(blossom);
1.2185 - }
1.2186 -
1.2187 - if (!_blossom_set->trivial(blossom)) {
1.2188 - (*_blossom_data)[blossom].pot -=
1.2189 - 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
1.2190 - }
1.2191 -
1.2192 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.2193 - n != INVALID; ++n) {
1.2194 -
1.2195 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
1.2196 - int ni = (*_node_index)[n];
1.2197 -
1.2198 - (*_node_data)[ni].heap.clear();
1.2199 - (*_node_data)[ni].heap_index.clear();
1.2200 -
1.2201 - (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
1.2202 -
1.2203 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
1.2204 - Node v = _graph.source(e);
1.2205 - int vb = _blossom_set->find(v);
1.2206 - int vi = (*_node_index)[v];
1.2207 -
1.2208 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.2209 - dualScale * _weight[e];
1.2210 -
1.2211 - if ((*_blossom_data)[vb].status == EVEN) {
1.2212 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1.2213 - _delta3->push(e, rw / 2);
1.2214 - }
1.2215 - } else {
1.2216 - typename std::map<int, Arc>::iterator it =
1.2217 - (*_node_data)[vi].heap_index.find(tree);
1.2218 -
1.2219 - if (it != (*_node_data)[vi].heap_index.end()) {
1.2220 - if ((*_node_data)[vi].heap[it->second] > rw) {
1.2221 - (*_node_data)[vi].heap.replace(it->second, e);
1.2222 - (*_node_data)[vi].heap.decrease(e, rw);
1.2223 - it->second = e;
1.2224 - }
1.2225 - } else {
1.2226 - (*_node_data)[vi].heap.push(e, rw);
1.2227 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1.2228 - }
1.2229 -
1.2230 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1.2231 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1.2232 -
1.2233 - if ((*_blossom_data)[vb].status == MATCHED) {
1.2234 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
1.2235 - _delta2->push(vb, _blossom_set->classPrio(vb) -
1.2236 - (*_blossom_data)[vb].offset);
1.2237 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1.2238 - (*_blossom_data)[vb].offset){
1.2239 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1.2240 - (*_blossom_data)[vb].offset);
1.2241 - }
1.2242 - }
1.2243 - }
1.2244 - }
1.2245 - }
1.2246 - }
1.2247 - (*_blossom_data)[blossom].offset = 0;
1.2248 - }
1.2249 -
1.2250 - void matchedToOdd(int blossom) {
1.2251 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1.2252 - _delta2->erase(blossom);
1.2253 - }
1.2254 - (*_blossom_data)[blossom].offset += _delta_sum;
1.2255 - if (!_blossom_set->trivial(blossom)) {
1.2256 - _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
1.2257 - (*_blossom_data)[blossom].offset);
1.2258 - }
1.2259 - }
1.2260 -
1.2261 - void evenToMatched(int blossom, int tree) {
1.2262 - if (!_blossom_set->trivial(blossom)) {
1.2263 - (*_blossom_data)[blossom].pot += 2 * _delta_sum;
1.2264 - }
1.2265 -
1.2266 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.2267 - n != INVALID; ++n) {
1.2268 - int ni = (*_node_index)[n];
1.2269 - (*_node_data)[ni].pot -= _delta_sum;
1.2270 -
1.2271 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
1.2272 - Node v = _graph.source(e);
1.2273 - int vb = _blossom_set->find(v);
1.2274 - int vi = (*_node_index)[v];
1.2275 -
1.2276 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.2277 - dualScale * _weight[e];
1.2278 -
1.2279 - if (vb == blossom) {
1.2280 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.2281 - _delta3->erase(e);
1.2282 - }
1.2283 - } else if ((*_blossom_data)[vb].status == EVEN) {
1.2284 -
1.2285 - if (_delta3->state(e) == _delta3->IN_HEAP) {
1.2286 - _delta3->erase(e);
1.2287 - }
1.2288 -
1.2289 - int vt = _tree_set->find(vb);
1.2290 -
1.2291 - if (vt != tree) {
1.2292 -
1.2293 - Arc r = _graph.oppositeArc(e);
1.2294 -
1.2295 - typename std::map<int, Arc>::iterator it =
1.2296 - (*_node_data)[ni].heap_index.find(vt);
1.2297 -
1.2298 - if (it != (*_node_data)[ni].heap_index.end()) {
1.2299 - if ((*_node_data)[ni].heap[it->second] > rw) {
1.2300 - (*_node_data)[ni].heap.replace(it->second, r);
1.2301 - (*_node_data)[ni].heap.decrease(r, rw);
1.2302 - it->second = r;
1.2303 - }
1.2304 - } else {
1.2305 - (*_node_data)[ni].heap.push(r, rw);
1.2306 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1.2307 - }
1.2308 -
1.2309 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1.2310 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1.2311 -
1.2312 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1.2313 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1.2314 - (*_blossom_data)[blossom].offset);
1.2315 - } else if ((*_delta2)[blossom] >
1.2316 - _blossom_set->classPrio(blossom) -
1.2317 - (*_blossom_data)[blossom].offset){
1.2318 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1.2319 - (*_blossom_data)[blossom].offset);
1.2320 - }
1.2321 - }
1.2322 - }
1.2323 - } else {
1.2324 -
1.2325 - typename std::map<int, Arc>::iterator it =
1.2326 - (*_node_data)[vi].heap_index.find(tree);
1.2327 -
1.2328 - if (it != (*_node_data)[vi].heap_index.end()) {
1.2329 - (*_node_data)[vi].heap.erase(it->second);
1.2330 - (*_node_data)[vi].heap_index.erase(it);
1.2331 - if ((*_node_data)[vi].heap.empty()) {
1.2332 - _blossom_set->increase(v, std::numeric_limits<Value>::max());
1.2333 - } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1.2334 - _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1.2335 - }
1.2336 -
1.2337 - if ((*_blossom_data)[vb].status == MATCHED) {
1.2338 - if (_blossom_set->classPrio(vb) ==
1.2339 - std::numeric_limits<Value>::max()) {
1.2340 - _delta2->erase(vb);
1.2341 - } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1.2342 - (*_blossom_data)[vb].offset) {
1.2343 - _delta2->increase(vb, _blossom_set->classPrio(vb) -
1.2344 - (*_blossom_data)[vb].offset);
1.2345 - }
1.2346 - }
1.2347 - }
1.2348 - }
1.2349 - }
1.2350 - }
1.2351 - }
1.2352 -
1.2353 - void oddToMatched(int blossom) {
1.2354 - (*_blossom_data)[blossom].offset -= _delta_sum;
1.2355 -
1.2356 - if (_blossom_set->classPrio(blossom) !=
1.2357 - std::numeric_limits<Value>::max()) {
1.2358 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1.2359 - (*_blossom_data)[blossom].offset);
1.2360 - }
1.2361 -
1.2362 - if (!_blossom_set->trivial(blossom)) {
1.2363 - _delta4->erase(blossom);
1.2364 - }
1.2365 - }
1.2366 -
1.2367 - void oddToEven(int blossom, int tree) {
1.2368 - if (!_blossom_set->trivial(blossom)) {
1.2369 - _delta4->erase(blossom);
1.2370 - (*_blossom_data)[blossom].pot -=
1.2371 - 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1.2372 - }
1.2373 -
1.2374 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1.2375 - n != INVALID; ++n) {
1.2376 - int ni = (*_node_index)[n];
1.2377 -
1.2378 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
1.2379 -
1.2380 - (*_node_data)[ni].heap.clear();
1.2381 - (*_node_data)[ni].heap_index.clear();
1.2382 - (*_node_data)[ni].pot +=
1.2383 - 2 * _delta_sum - (*_blossom_data)[blossom].offset;
1.2384 -
1.2385 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
1.2386 - Node v = _graph.source(e);
1.2387 - int vb = _blossom_set->find(v);
1.2388 - int vi = (*_node_index)[v];
1.2389 -
1.2390 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1.2391 - dualScale * _weight[e];
1.2392 -
1.2393 - if ((*_blossom_data)[vb].status == EVEN) {
1.2394 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1.2395 - _delta3->push(e, rw / 2);
1.2396 - }
1.2397 - } else {
1.2398 -
1.2399 - typename std::map<int, Arc>::iterator it =
1.2400 - (*_node_data)[vi].heap_index.find(tree);
1.2401 -
1.2402 - if (it != (*_node_data)[vi].heap_index.end()) {
1.2403 - if ((*_node_data)[vi].heap[it->second] > rw) {
1.2404 - (*_node_data)[vi].heap.replace(it->second, e);
1.2405 - (*_node_data)[vi].heap.decrease(e, rw);
1.2406 - it->second = e;
1.2407 - }
1.2408 - } else {
1.2409 - (*_node_data)[vi].heap.push(e, rw);
1.2410 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1.2411 - }
1.2412 -
1.2413 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1.2414 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1.2415 -
1.2416 - if ((*_blossom_data)[vb].status == MATCHED) {
1.2417 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
1.2418 - _delta2->push(vb, _blossom_set->classPrio(vb) -
1.2419 - (*_blossom_data)[vb].offset);
1.2420 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1.2421 - (*_blossom_data)[vb].offset) {
1.2422 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1.2423 - (*_blossom_data)[vb].offset);
1.2424 - }
1.2425 - }
1.2426 - }
1.2427 - }
1.2428 - }
1.2429 - }
1.2430 - (*_blossom_data)[blossom].offset = 0;
1.2431 - }
1.2432 -
1.2433 - void alternatePath(int even, int tree) {
1.2434 - int odd;
1.2435 -
1.2436 - evenToMatched(even, tree);
1.2437 - (*_blossom_data)[even].status = MATCHED;
1.2438 -
1.2439 - while ((*_blossom_data)[even].pred != INVALID) {
1.2440 - odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1.2441 - (*_blossom_data)[odd].status = MATCHED;
1.2442 - oddToMatched(odd);
1.2443 - (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1.2444 -
1.2445 - even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1.2446 - (*_blossom_data)[even].status = MATCHED;
1.2447 - evenToMatched(even, tree);
1.2448 - (*_blossom_data)[even].next =
1.2449 - _graph.oppositeArc((*_blossom_data)[odd].pred);
1.2450 - }
1.2451 -
1.2452 - }
1.2453 -
1.2454 - void destroyTree(int tree) {
1.2455 - for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1.2456 - if ((*_blossom_data)[b].status == EVEN) {
1.2457 - (*_blossom_data)[b].status = MATCHED;
1.2458 - evenToMatched(b, tree);
1.2459 - } else if ((*_blossom_data)[b].status == ODD) {
1.2460 - (*_blossom_data)[b].status = MATCHED;
1.2461 - oddToMatched(b);
1.2462 - }
1.2463 - }
1.2464 - _tree_set->eraseClass(tree);
1.2465 - }
1.2466 -
1.2467 - void augmentOnEdge(const Edge& edge) {
1.2468 -
1.2469 - int left = _blossom_set->find(_graph.u(edge));
1.2470 - int right = _blossom_set->find(_graph.v(edge));
1.2471 -
1.2472 - int left_tree = _tree_set->find(left);
1.2473 - alternatePath(left, left_tree);
1.2474 - destroyTree(left_tree);
1.2475 -
1.2476 - int right_tree = _tree_set->find(right);
1.2477 - alternatePath(right, right_tree);
1.2478 - destroyTree(right_tree);
1.2479 -
1.2480 - (*_blossom_data)[left].next = _graph.direct(edge, true);
1.2481 - (*_blossom_data)[right].next = _graph.direct(edge, false);
1.2482 - }
1.2483 -
1.2484 - void extendOnArc(const Arc& arc) {
1.2485 - int base = _blossom_set->find(_graph.target(arc));
1.2486 - int tree = _tree_set->find(base);
1.2487 -
1.2488 - int odd = _blossom_set->find(_graph.source(arc));
1.2489 - _tree_set->insert(odd, tree);
1.2490 - (*_blossom_data)[odd].status = ODD;
1.2491 - matchedToOdd(odd);
1.2492 - (*_blossom_data)[odd].pred = arc;
1.2493 -
1.2494 - int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1.2495 - (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1.2496 - _tree_set->insert(even, tree);
1.2497 - (*_blossom_data)[even].status = EVEN;
1.2498 - matchedToEven(even, tree);
1.2499 - }
1.2500 -
1.2501 - void shrinkOnEdge(const Edge& edge, int tree) {
1.2502 - int nca = -1;
1.2503 - std::vector<int> left_path, right_path;
1.2504 -
1.2505 - {
1.2506 - std::set<int> left_set, right_set;
1.2507 - int left = _blossom_set->find(_graph.u(edge));
1.2508 - left_path.push_back(left);
1.2509 - left_set.insert(left);
1.2510 -
1.2511 - int right = _blossom_set->find(_graph.v(edge));
1.2512 - right_path.push_back(right);
1.2513 - right_set.insert(right);
1.2514 -
1.2515 - while (true) {
1.2516 -
1.2517 - if ((*_blossom_data)[left].pred == INVALID) break;
1.2518 -
1.2519 - left =
1.2520 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1.2521 - left_path.push_back(left);
1.2522 - left =
1.2523 - _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1.2524 - left_path.push_back(left);
1.2525 -
1.2526 - left_set.insert(left);
1.2527 -
1.2528 - if (right_set.find(left) != right_set.end()) {
1.2529 - nca = left;
1.2530 - break;
1.2531 - }
1.2532 -
1.2533 - if ((*_blossom_data)[right].pred == INVALID) break;
1.2534 -
1.2535 - right =
1.2536 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1.2537 - right_path.push_back(right);
1.2538 - right =
1.2539 - _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1.2540 - right_path.push_back(right);
1.2541 -
1.2542 - right_set.insert(right);
1.2543 -
1.2544 - if (left_set.find(right) != left_set.end()) {
1.2545 - nca = right;
1.2546 - break;
1.2547 - }
1.2548 -
1.2549 - }
1.2550 -
1.2551 - if (nca == -1) {
1.2552 - if ((*_blossom_data)[left].pred == INVALID) {
1.2553 - nca = right;
1.2554 - while (left_set.find(nca) == left_set.end()) {
1.2555 - nca =
1.2556 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.2557 - right_path.push_back(nca);
1.2558 - nca =
1.2559 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.2560 - right_path.push_back(nca);
1.2561 - }
1.2562 - } else {
1.2563 - nca = left;
1.2564 - while (right_set.find(nca) == right_set.end()) {
1.2565 - nca =
1.2566 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.2567 - left_path.push_back(nca);
1.2568 - nca =
1.2569 - _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1.2570 - left_path.push_back(nca);
1.2571 - }
1.2572 - }
1.2573 - }
1.2574 - }
1.2575 -
1.2576 - std::vector<int> subblossoms;
1.2577 - Arc prev;
1.2578 -
1.2579 - prev = _graph.direct(edge, true);
1.2580 - for (int i = 0; left_path[i] != nca; i += 2) {
1.2581 - subblossoms.push_back(left_path[i]);
1.2582 - (*_blossom_data)[left_path[i]].next = prev;
1.2583 - _tree_set->erase(left_path[i]);
1.2584 -
1.2585 - subblossoms.push_back(left_path[i + 1]);
1.2586 - (*_blossom_data)[left_path[i + 1]].status = EVEN;
1.2587 - oddToEven(left_path[i + 1], tree);
1.2588 - _tree_set->erase(left_path[i + 1]);
1.2589 - prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1.2590 - }
1.2591 -
1.2592 - int k = 0;
1.2593 - while (right_path[k] != nca) ++k;
1.2594 -
1.2595 - subblossoms.push_back(nca);
1.2596 - (*_blossom_data)[nca].next = prev;
1.2597 -
1.2598 - for (int i = k - 2; i >= 0; i -= 2) {
1.2599 - subblossoms.push_back(right_path[i + 1]);
1.2600 - (*_blossom_data)[right_path[i + 1]].status = EVEN;
1.2601 - oddToEven(right_path[i + 1], tree);
1.2602 - _tree_set->erase(right_path[i + 1]);
1.2603 -
1.2604 - (*_blossom_data)[right_path[i + 1]].next =
1.2605 - (*_blossom_data)[right_path[i + 1]].pred;
1.2606 -
1.2607 - subblossoms.push_back(right_path[i]);
1.2608 - _tree_set->erase(right_path[i]);
1.2609 - }
1.2610 -
1.2611 - int surface =
1.2612 - _blossom_set->join(subblossoms.begin(), subblossoms.end());
1.2613 -
1.2614 - for (int i = 0; i < int(subblossoms.size()); ++i) {
1.2615 - if (!_blossom_set->trivial(subblossoms[i])) {
1.2616 - (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1.2617 - }
1.2618 - (*_blossom_data)[subblossoms[i]].status = MATCHED;
1.2619 - }
1.2620 -
1.2621 - (*_blossom_data)[surface].pot = -2 * _delta_sum;
1.2622 - (*_blossom_data)[surface].offset = 0;
1.2623 - (*_blossom_data)[surface].status = EVEN;
1.2624 - (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1.2625 - (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1.2626 -
1.2627 - _tree_set->insert(surface, tree);
1.2628 - _tree_set->erase(nca);
1.2629 - }
1.2630 -
1.2631 - void splitBlossom(int blossom) {
1.2632 - Arc next = (*_blossom_data)[blossom].next;
1.2633 - Arc pred = (*_blossom_data)[blossom].pred;
1.2634 -
1.2635 - int tree = _tree_set->find(blossom);
1.2636 -
1.2637 - (*_blossom_data)[blossom].status = MATCHED;
1.2638 - oddToMatched(blossom);
1.2639 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1.2640 - _delta2->erase(blossom);
1.2641 - }
1.2642 -
1.2643 - std::vector<int> subblossoms;
1.2644 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
1.2645 -
1.2646 - Value offset = (*_blossom_data)[blossom].offset;
1.2647 - int b = _blossom_set->find(_graph.source(pred));
1.2648 - int d = _blossom_set->find(_graph.source(next));
1.2649 -
1.2650 - int ib = -1, id = -1;
1.2651 - for (int i = 0; i < int(subblossoms.size()); ++i) {
1.2652 - if (subblossoms[i] == b) ib = i;
1.2653 - if (subblossoms[i] == d) id = i;
1.2654 -
1.2655 - (*_blossom_data)[subblossoms[i]].offset = offset;
1.2656 - if (!_blossom_set->trivial(subblossoms[i])) {
1.2657 - (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1.2658 - }
1.2659 - if (_blossom_set->classPrio(subblossoms[i]) !=
1.2660 - std::numeric_limits<Value>::max()) {
1.2661 - _delta2->push(subblossoms[i],
1.2662 - _blossom_set->classPrio(subblossoms[i]) -
1.2663 - (*_blossom_data)[subblossoms[i]].offset);
1.2664 - }
1.2665 - }
1.2666 -
1.2667 - if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1.2668 - for (int i = (id + 1) % subblossoms.size();
1.2669 - i != ib; i = (i + 2) % subblossoms.size()) {
1.2670 - int sb = subblossoms[i];
1.2671 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.2672 - (*_blossom_data)[sb].next =
1.2673 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.2674 - }
1.2675 -
1.2676 - for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1.2677 - int sb = subblossoms[i];
1.2678 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.2679 - int ub = subblossoms[(i + 2) % subblossoms.size()];
1.2680 -
1.2681 - (*_blossom_data)[sb].status = ODD;
1.2682 - matchedToOdd(sb);
1.2683 - _tree_set->insert(sb, tree);
1.2684 - (*_blossom_data)[sb].pred = pred;
1.2685 - (*_blossom_data)[sb].next =
1.2686 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.2687 -
1.2688 - pred = (*_blossom_data)[ub].next;
1.2689 -
1.2690 - (*_blossom_data)[tb].status = EVEN;
1.2691 - matchedToEven(tb, tree);
1.2692 - _tree_set->insert(tb, tree);
1.2693 - (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1.2694 - }
1.2695 -
1.2696 - (*_blossom_data)[subblossoms[id]].status = ODD;
1.2697 - matchedToOdd(subblossoms[id]);
1.2698 - _tree_set->insert(subblossoms[id], tree);
1.2699 - (*_blossom_data)[subblossoms[id]].next = next;
1.2700 - (*_blossom_data)[subblossoms[id]].pred = pred;
1.2701 -
1.2702 - } else {
1.2703 -
1.2704 - for (int i = (ib + 1) % subblossoms.size();
1.2705 - i != id; i = (i + 2) % subblossoms.size()) {
1.2706 - int sb = subblossoms[i];
1.2707 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.2708 - (*_blossom_data)[sb].next =
1.2709 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.2710 - }
1.2711 -
1.2712 - for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1.2713 - int sb = subblossoms[i];
1.2714 - int tb = subblossoms[(i + 1) % subblossoms.size()];
1.2715 - int ub = subblossoms[(i + 2) % subblossoms.size()];
1.2716 -
1.2717 - (*_blossom_data)[sb].status = ODD;
1.2718 - matchedToOdd(sb);
1.2719 - _tree_set->insert(sb, tree);
1.2720 - (*_blossom_data)[sb].next = next;
1.2721 - (*_blossom_data)[sb].pred =
1.2722 - _graph.oppositeArc((*_blossom_data)[tb].next);
1.2723 -
1.2724 - (*_blossom_data)[tb].status = EVEN;
1.2725 - matchedToEven(tb, tree);
1.2726 - _tree_set->insert(tb, tree);
1.2727 - (*_blossom_data)[tb].pred =
1.2728 - (*_blossom_data)[tb].next =
1.2729 - _graph.oppositeArc((*_blossom_data)[ub].next);
1.2730 - next = (*_blossom_data)[ub].next;
1.2731 - }
1.2732 -
1.2733 - (*_blossom_data)[subblossoms[ib]].status = ODD;
1.2734 - matchedToOdd(subblossoms[ib]);
1.2735 - _tree_set->insert(subblossoms[ib], tree);
1.2736 - (*_blossom_data)[subblossoms[ib]].next = next;
1.2737 - (*_blossom_data)[subblossoms[ib]].pred = pred;
1.2738 - }
1.2739 - _tree_set->erase(blossom);
1.2740 - }
1.2741 -
1.2742 - void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1.2743 - if (_blossom_set->trivial(blossom)) {
1.2744 - int bi = (*_node_index)[base];
1.2745 - Value pot = (*_node_data)[bi].pot;
1.2746 -
1.2747 - (*_matching)[base] = matching;
1.2748 - _blossom_node_list.push_back(base);
1.2749 - (*_node_potential)[base] = pot;
1.2750 - } else {
1.2751 -
1.2752 - Value pot = (*_blossom_data)[blossom].pot;
1.2753 - int bn = _blossom_node_list.size();
1.2754 -
1.2755 - std::vector<int> subblossoms;
1.2756 - _blossom_set->split(blossom, std::back_inserter(subblossoms));
1.2757 - int b = _blossom_set->find(base);
1.2758 - int ib = -1;
1.2759 - for (int i = 0; i < int(subblossoms.size()); ++i) {
1.2760 - if (subblossoms[i] == b) { ib = i; break; }
1.2761 - }
1.2762 -
1.2763 - for (int i = 1; i < int(subblossoms.size()); i += 2) {
1.2764 - int sb = subblossoms[(ib + i) % subblossoms.size()];
1.2765 - int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1.2766 -
1.2767 - Arc m = (*_blossom_data)[tb].next;
1.2768 - extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1.2769 - extractBlossom(tb, _graph.source(m), m);
1.2770 - }
1.2771 - extractBlossom(subblossoms[ib], base, matching);
1.2772 -
1.2773 - int en = _blossom_node_list.size();
1.2774 -
1.2775 - _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1.2776 - }
1.2777 - }
1.2778 -
1.2779 - void extractMatching() {
1.2780 - std::vector<int> blossoms;
1.2781 - for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1.2782 - blossoms.push_back(c);
1.2783 - }
1.2784 -
1.2785 - for (int i = 0; i < int(blossoms.size()); ++i) {
1.2786 -
1.2787 - Value offset = (*_blossom_data)[blossoms[i]].offset;
1.2788 - (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1.2789 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1.2790 - n != INVALID; ++n) {
1.2791 - (*_node_data)[(*_node_index)[n]].pot -= offset;
1.2792 - }
1.2793 -
1.2794 - Arc matching = (*_blossom_data)[blossoms[i]].next;
1.2795 - Node base = _graph.source(matching);
1.2796 - extractBlossom(blossoms[i], base, matching);
1.2797 - }
1.2798 - }
1.2799 -
1.2800 - public:
1.2801 -
1.2802 - /// \brief Constructor
1.2803 - ///
1.2804 - /// Constructor.
1.2805 - MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
1.2806 - : _graph(graph), _weight(weight), _matching(0),
1.2807 - _node_potential(0), _blossom_potential(), _blossom_node_list(),
1.2808 - _node_num(0), _blossom_num(0),
1.2809 -
1.2810 - _blossom_index(0), _blossom_set(0), _blossom_data(0),
1.2811 - _node_index(0), _node_heap_index(0), _node_data(0),
1.2812 - _tree_set_index(0), _tree_set(0),
1.2813 -
1.2814 - _delta2_index(0), _delta2(0),
1.2815 - _delta3_index(0), _delta3(0),
1.2816 - _delta4_index(0), _delta4(0),
1.2817 -
1.2818 - _delta_sum() {}
1.2819 -
1.2820 - ~MaxWeightedPerfectMatching() {
1.2821 - destroyStructures();
1.2822 - }
1.2823 -
1.2824 - /// \name Execution control
1.2825 - /// The simplest way to execute the algorithm is to use the
1.2826 - /// \c run() member function.
1.2827 -
1.2828 - ///@{
1.2829 -
1.2830 - /// \brief Initialize the algorithm
1.2831 - ///
1.2832 - /// Initialize the algorithm
1.2833 - void init() {
1.2834 - createStructures();
1.2835 -
1.2836 - for (ArcIt e(_graph); e != INVALID; ++e) {
1.2837 - (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1.2838 - }
1.2839 - for (EdgeIt e(_graph); e != INVALID; ++e) {
1.2840 - (*_delta3_index)[e] = _delta3->PRE_HEAP;
1.2841 - }
1.2842 - for (int i = 0; i < _blossom_num; ++i) {
1.2843 - (*_delta2_index)[i] = _delta2->PRE_HEAP;
1.2844 - (*_delta4_index)[i] = _delta4->PRE_HEAP;
1.2845 - }
1.2846 -
1.2847 - int index = 0;
1.2848 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.2849 - Value max = - std::numeric_limits<Value>::max();
1.2850 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1.2851 - if (_graph.target(e) == n) continue;
1.2852 - if ((dualScale * _weight[e]) / 2 > max) {
1.2853 - max = (dualScale * _weight[e]) / 2;
1.2854 - }
1.2855 - }
1.2856 - (*_node_index)[n] = index;
1.2857 - (*_node_data)[index].pot = max;
1.2858 - int blossom =
1.2859 - _blossom_set->insert(n, std::numeric_limits<Value>::max());
1.2860 -
1.2861 - _tree_set->insert(blossom);
1.2862 -
1.2863 - (*_blossom_data)[blossom].status = EVEN;
1.2864 - (*_blossom_data)[blossom].pred = INVALID;
1.2865 - (*_blossom_data)[blossom].next = INVALID;
1.2866 - (*_blossom_data)[blossom].pot = 0;
1.2867 - (*_blossom_data)[blossom].offset = 0;
1.2868 - ++index;
1.2869 - }
1.2870 - for (EdgeIt e(_graph); e != INVALID; ++e) {
1.2871 - int si = (*_node_index)[_graph.u(e)];
1.2872 - int ti = (*_node_index)[_graph.v(e)];
1.2873 - if (_graph.u(e) != _graph.v(e)) {
1.2874 - _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1.2875 - dualScale * _weight[e]) / 2);
1.2876 - }
1.2877 - }
1.2878 - }
1.2879 -
1.2880 - /// \brief Starts the algorithm
1.2881 - ///
1.2882 - /// Starts the algorithm
1.2883 - bool start() {
1.2884 - enum OpType {
1.2885 - D2, D3, D4
1.2886 - };
1.2887 -
1.2888 - int unmatched = _node_num;
1.2889 - while (unmatched > 0) {
1.2890 - Value d2 = !_delta2->empty() ?
1.2891 - _delta2->prio() : std::numeric_limits<Value>::max();
1.2892 -
1.2893 - Value d3 = !_delta3->empty() ?
1.2894 - _delta3->prio() : std::numeric_limits<Value>::max();
1.2895 -
1.2896 - Value d4 = !_delta4->empty() ?
1.2897 - _delta4->prio() : std::numeric_limits<Value>::max();
1.2898 -
1.2899 - _delta_sum = d2; OpType ot = D2;
1.2900 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1.2901 - if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1.2902 -
1.2903 - if (_delta_sum == std::numeric_limits<Value>::max()) {
1.2904 - return false;
1.2905 - }
1.2906 -
1.2907 - switch (ot) {
1.2908 - case D2:
1.2909 - {
1.2910 - int blossom = _delta2->top();
1.2911 - Node n = _blossom_set->classTop(blossom);
1.2912 - Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1.2913 - extendOnArc(e);
1.2914 - }
1.2915 - break;
1.2916 - case D3:
1.2917 - {
1.2918 - Edge e = _delta3->top();
1.2919 -
1.2920 - int left_blossom = _blossom_set->find(_graph.u(e));
1.2921 - int right_blossom = _blossom_set->find(_graph.v(e));
1.2922 -
1.2923 - if (left_blossom == right_blossom) {
1.2924 - _delta3->pop();
1.2925 - } else {
1.2926 - int left_tree = _tree_set->find(left_blossom);
1.2927 - int right_tree = _tree_set->find(right_blossom);
1.2928 -
1.2929 - if (left_tree == right_tree) {
1.2930 - shrinkOnEdge(e, left_tree);
1.2931 - } else {
1.2932 - augmentOnEdge(e);
1.2933 - unmatched -= 2;
1.2934 - }
1.2935 - }
1.2936 - } break;
1.2937 - case D4:
1.2938 - splitBlossom(_delta4->top());
1.2939 - break;
1.2940 - }
1.2941 - }
1.2942 - extractMatching();
1.2943 - return true;
1.2944 - }
1.2945 -
1.2946 - /// \brief Runs %MaxWeightedPerfectMatching algorithm.
1.2947 - ///
1.2948 - /// This method runs the %MaxWeightedPerfectMatching algorithm.
1.2949 - ///
1.2950 - /// \note mwm.run() is just a shortcut of the following code.
1.2951 - /// \code
1.2952 - /// mwm.init();
1.2953 - /// mwm.start();
1.2954 - /// \endcode
1.2955 - bool run() {
1.2956 - init();
1.2957 - return start();
1.2958 - }
1.2959 -
1.2960 - /// @}
1.2961 -
1.2962 - /// \name Primal solution
1.2963 - /// Functions to get the primal solution, ie. the matching.
1.2964 -
1.2965 - /// @{
1.2966 -
1.2967 - /// \brief Returns the matching value.
1.2968 - ///
1.2969 - /// Returns the matching value.
1.2970 - Value matchingValue() const {
1.2971 - Value sum = 0;
1.2972 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.2973 - if ((*_matching)[n] != INVALID) {
1.2974 - sum += _weight[(*_matching)[n]];
1.2975 - }
1.2976 - }
1.2977 - return sum /= 2;
1.2978 - }
1.2979 -
1.2980 - /// \brief Returns true when the edge is in the matching.
1.2981 - ///
1.2982 - /// Returns true when the edge is in the matching.
1.2983 - bool matching(const Edge& edge) const {
1.2984 - return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
1.2985 - }
1.2986 -
1.2987 - /// \brief Returns the incident matching edge.
1.2988 - ///
1.2989 - /// Returns the incident matching arc from given edge.
1.2990 - Arc matching(const Node& node) const {
1.2991 - return (*_matching)[node];
1.2992 - }
1.2993 -
1.2994 - /// \brief Returns the mate of the node.
1.2995 - ///
1.2996 - /// Returns the adjancent node in a mathcing arc.
1.2997 - Node mate(const Node& node) const {
1.2998 - return _graph.target((*_matching)[node]);
1.2999 - }
1.3000 -
1.3001 - /// @}
1.3002 -
1.3003 - /// \name Dual solution
1.3004 - /// Functions to get the dual solution.
1.3005 -
1.3006 - /// @{
1.3007 -
1.3008 - /// \brief Returns the value of the dual solution.
1.3009 - ///
1.3010 - /// Returns the value of the dual solution. It should be equal to
1.3011 - /// the primal value scaled by \ref dualScale "dual scale".
1.3012 - Value dualValue() const {
1.3013 - Value sum = 0;
1.3014 - for (NodeIt n(_graph); n != INVALID; ++n) {
1.3015 - sum += nodeValue(n);
1.3016 - }
1.3017 - for (int i = 0; i < blossomNum(); ++i) {
1.3018 - sum += blossomValue(i) * (blossomSize(i) / 2);
1.3019 - }
1.3020 - return sum;
1.3021 - }
1.3022 -
1.3023 - /// \brief Returns the value of the node.
1.3024 - ///
1.3025 - /// Returns the the value of the node.
1.3026 - Value nodeValue(const Node& n) const {
1.3027 - return (*_node_potential)[n];
1.3028 - }
1.3029 -
1.3030 - /// \brief Returns the number of the blossoms in the basis.
1.3031 - ///
1.3032 - /// Returns the number of the blossoms in the basis.
1.3033 - /// \see BlossomIt
1.3034 - int blossomNum() const {
1.3035 - return _blossom_potential.size();
1.3036 - }
1.3037 -
1.3038 -
1.3039 - /// \brief Returns the number of the nodes in the blossom.
1.3040 - ///
1.3041 - /// Returns the number of the nodes in the blossom.
1.3042 - int blossomSize(int k) const {
1.3043 - return _blossom_potential[k].end - _blossom_potential[k].begin;
1.3044 - }
1.3045 -
1.3046 - /// \brief Returns the value of the blossom.
1.3047 - ///
1.3048 - /// Returns the the value of the blossom.
1.3049 - /// \see BlossomIt
1.3050 - Value blossomValue(int k) const {
1.3051 - return _blossom_potential[k].value;
1.3052 - }
1.3053 -
1.3054 - /// \brief Iterator for obtaining the nodes of the blossom.
1.3055 - ///
1.3056 - /// Iterator for obtaining the nodes of the blossom. This class
1.3057 - /// provides a common lemon style iterator for listing a
1.3058 - /// subset of the nodes.
1.3059 - class BlossomIt {
1.3060 - public:
1.3061 -
1.3062 - /// \brief Constructor.
1.3063 - ///
1.3064 - /// Constructor to get the nodes of the variable.
1.3065 - BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
1.3066 - : _algorithm(&algorithm)
1.3067 - {
1.3068 - _index = _algorithm->_blossom_potential[variable].begin;
1.3069 - _last = _algorithm->_blossom_potential[variable].end;
1.3070 - }
1.3071 -
1.3072 - /// \brief Conversion to node.
1.3073 - ///
1.3074 - /// Conversion to node.
1.3075 - operator Node() const {
1.3076 - return _algorithm->_blossom_node_list[_index];
1.3077 - }
1.3078 -
1.3079 - /// \brief Increment operator.
1.3080 - ///
1.3081 - /// Increment operator.
1.3082 - BlossomIt& operator++() {
1.3083 - ++_index;
1.3084 - return *this;
1.3085 - }
1.3086 -
1.3087 - /// \brief Validity checking
1.3088 - ///
1.3089 - /// Checks whether the iterator is invalid.
1.3090 - bool operator==(Invalid) const { return _index == _last; }
1.3091 -
1.3092 - /// \brief Validity checking
1.3093 - ///
1.3094 - /// Checks whether the iterator is valid.
1.3095 - bool operator!=(Invalid) const { return _index != _last; }
1.3096 -
1.3097 - private:
1.3098 - const MaxWeightedPerfectMatching* _algorithm;
1.3099 - int _last;
1.3100 - int _index;
1.3101 - };
1.3102 -
1.3103 - /// @}
1.3104 -
1.3105 - };
1.3106 -
1.3107 -
1.3108 -} //END OF NAMESPACE LEMON
1.3109 -
1.3110 -#endif //LEMON_MAX_MATCHING_H