gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Fractional matching initialization of weighted matchings (#314)
0 2 0
default
2 files changed with 349 insertions and 28 deletions:
↑ Collapse diff ↑
Ignore white space 768 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_MATCHING_H
20 20
#define LEMON_MATCHING_H
21 21

	
22 22
#include <vector>
23 23
#include <queue>
24 24
#include <set>
25 25
#include <limits>
26 26

	
27 27
#include <lemon/core.h>
28 28
#include <lemon/unionfind.h>
29 29
#include <lemon/bin_heap.h>
30 30
#include <lemon/maps.h>
31
#include <lemon/fractional_matching.h>
31 32

	
32 33
///\ingroup matching
33 34
///\file
34 35
///\brief Maximum matching algorithms in general graphs.
35 36

	
36 37
namespace lemon {
37 38

	
38 39
  /// \ingroup matching
39 40
  ///
40 41
  /// \brief Maximum cardinality matching in general graphs
41 42
  ///
42 43
  /// This class implements Edmonds' alternating forest matching algorithm
43 44
  /// for finding a maximum cardinality matching in a general undirected graph.
44 45
  /// It can be started from an arbitrary initial matching
45 46
  /// (the default is the empty one).
46 47
  ///
47 48
  /// The dual solution of the problem is a map of the nodes to
48 49
  /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
49 50
  /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
50 51
  /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
51 52
  /// with factor-critical components, the nodes in \c ODD/A form the
52 53
  /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
53 54
  /// a perfect matching. The number of the factor-critical components
54 55
  /// minus the number of barrier nodes is a lower bound on the
55 56
  /// unmatched nodes, and the matching is optimal if and only if this bound is
56 57
  /// tight. This decomposition can be obtained using \ref status() or
57 58
  /// \ref statusMap() after running the algorithm.
58 59
  ///
59 60
  /// \tparam GR The undirected graph type the algorithm runs on.
60 61
  template <typename GR>
61 62
  class MaxMatching {
62 63
  public:
63 64

	
64 65
    /// The graph type of the algorithm
65 66
    typedef GR Graph;
66 67
    /// The type of the matching map
67 68
    typedef typename Graph::template NodeMap<typename Graph::Arc>
68 69
    MatchingMap;
69 70

	
70 71
    ///\brief Status constants for Gallai-Edmonds decomposition.
71 72
    ///
72 73
    ///These constants are used for indicating the Gallai-Edmonds
73 74
    ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
74 75
    ///induce a subgraph with factor-critical components, the nodes with
75 76
    ///status \c ODD (or \c A) form the canonical barrier, and the nodes
76 77
    ///with status \c MATCHED (or \c C) induce a subgraph having a
77 78
    ///perfect matching.
78 79
    enum Status {
79 80
      EVEN = 1,       ///< = 1. (\c D is an alias for \c EVEN.)
80 81
      D = 1,
81 82
      MATCHED = 0,    ///< = 0. (\c C is an alias for \c MATCHED.)
82 83
      C = 0,
83 84
      ODD = -1,       ///< = -1. (\c A is an alias for \c ODD.)
84 85
      A = -1,
85 86
      UNMATCHED = -2  ///< = -2.
86 87
    };
87 88

	
88 89
    /// The type of the status map
89 90
    typedef typename Graph::template NodeMap<Status> StatusMap;
90 91

	
91 92
  private:
92 93

	
93 94
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
94 95

	
95 96
    typedef UnionFindEnum<IntNodeMap> BlossomSet;
96 97
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
97 98
    typedef RangeMap<Node> NodeIntMap;
98 99
    typedef MatchingMap EarMap;
99 100
    typedef std::vector<Node> NodeQueue;
100 101

	
101 102
    const Graph& _graph;
102 103
    MatchingMap* _matching;
103 104
    StatusMap* _status;
104 105

	
105 106
    EarMap* _ear;
106 107

	
107 108
    IntNodeMap* _blossom_set_index;
108 109
    BlossomSet* _blossom_set;
109 110
    NodeIntMap* _blossom_rep;
110 111

	
111 112
    IntNodeMap* _tree_set_index;
112 113
    TreeSet* _tree_set;
113 114

	
114 115
    NodeQueue _node_queue;
115 116
    int _process, _postpone, _last;
116 117

	
117 118
    int _node_num;
118 119

	
119 120
  private:
120 121

	
121 122
    void createStructures() {
122 123
      _node_num = countNodes(_graph);
123 124
      if (!_matching) {
124 125
        _matching = new MatchingMap(_graph);
125 126
      }
126 127
      if (!_status) {
127 128
        _status = new StatusMap(_graph);
128 129
      }
129 130
      if (!_ear) {
130 131
        _ear = new EarMap(_graph);
131 132
      }
132 133
      if (!_blossom_set) {
133 134
        _blossom_set_index = new IntNodeMap(_graph);
134 135
        _blossom_set = new BlossomSet(*_blossom_set_index);
135 136
      }
136 137
      if (!_blossom_rep) {
137 138
        _blossom_rep = new NodeIntMap(_node_num);
138 139
      }
139 140
      if (!_tree_set) {
140 141
        _tree_set_index = new IntNodeMap(_graph);
141 142
        _tree_set = new TreeSet(*_tree_set_index);
142 143
      }
143 144
      _node_queue.resize(_node_num);
144 145
    }
145 146

	
146 147
    void destroyStructures() {
147 148
      if (_matching) {
148 149
        delete _matching;
149 150
      }
150 151
      if (_status) {
151 152
        delete _status;
152 153
      }
153 154
      if (_ear) {
154 155
        delete _ear;
155 156
      }
156 157
      if (_blossom_set) {
157 158
        delete _blossom_set;
158 159
        delete _blossom_set_index;
159 160
      }
160 161
      if (_blossom_rep) {
161 162
        delete _blossom_rep;
162 163
      }
163 164
      if (_tree_set) {
164 165
        delete _tree_set_index;
165 166
        delete _tree_set;
166 167
      }
167 168
    }
168 169

	
169 170
    void processDense(const Node& n) {
170 171
      _process = _postpone = _last = 0;
171 172
      _node_queue[_last++] = n;
172 173

	
173 174
      while (_process != _last) {
174 175
        Node u = _node_queue[_process++];
175 176
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
176 177
          Node v = _graph.target(a);
177 178
          if ((*_status)[v] == MATCHED) {
178 179
            extendOnArc(a);
179 180
          } else if ((*_status)[v] == UNMATCHED) {
180 181
            augmentOnArc(a);
181 182
            return;
182 183
          }
183 184
        }
184 185
      }
185 186

	
186 187
      while (_postpone != _last) {
187 188
        Node u = _node_queue[_postpone++];
188 189

	
189 190
        for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
190 191
          Node v = _graph.target(a);
191 192

	
192 193
          if ((*_status)[v] == EVEN) {
193 194
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
194 195
              shrinkOnEdge(a);
195 196
            }
196 197
          }
197 198

	
198 199
          while (_process != _last) {
199 200
            Node w = _node_queue[_process++];
200 201
            for (OutArcIt b(_graph, w); b != INVALID; ++b) {
201 202
              Node x = _graph.target(b);
202 203
              if ((*_status)[x] == MATCHED) {
203 204
                extendOnArc(b);
204 205
              } else if ((*_status)[x] == UNMATCHED) {
205 206
                augmentOnArc(b);
206 207
                return;
207 208
              }
208 209
            }
209 210
          }
210 211
        }
211 212
      }
212 213
    }
213 214

	
214 215
    void processSparse(const Node& n) {
215 216
      _process = _last = 0;
216 217
      _node_queue[_last++] = n;
217 218
      while (_process != _last) {
218 219
        Node u = _node_queue[_process++];
219 220
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
220 221
          Node v = _graph.target(a);
221 222

	
222 223
          if ((*_status)[v] == EVEN) {
223 224
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
224 225
              shrinkOnEdge(a);
225 226
            }
226 227
          } else if ((*_status)[v] == MATCHED) {
227 228
            extendOnArc(a);
228 229
          } else if ((*_status)[v] == UNMATCHED) {
229 230
            augmentOnArc(a);
230 231
            return;
231 232
          }
232 233
        }
233 234
      }
234 235
    }
235 236

	
236 237
    void shrinkOnEdge(const Edge& e) {
237 238
      Node nca = INVALID;
238 239

	
239 240
      {
240 241
        std::set<Node> left_set, right_set;
241 242

	
242 243
        Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
243 244
        left_set.insert(left);
244 245

	
245 246
        Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
246 247
        right_set.insert(right);
247 248

	
248 249
        while (true) {
249 250
          if ((*_matching)[left] == INVALID) break;
250 251
          left = _graph.target((*_matching)[left]);
251 252
          left = (*_blossom_rep)[_blossom_set->
252 253
                                 find(_graph.target((*_ear)[left]))];
253 254
          if (right_set.find(left) != right_set.end()) {
254 255
            nca = left;
255 256
            break;
256 257
          }
257 258
          left_set.insert(left);
258 259

	
259 260
          if ((*_matching)[right] == INVALID) break;
260 261
          right = _graph.target((*_matching)[right]);
261 262
          right = (*_blossom_rep)[_blossom_set->
262 263
                                  find(_graph.target((*_ear)[right]))];
263 264
          if (left_set.find(right) != left_set.end()) {
264 265
            nca = right;
265 266
            break;
266 267
          }
267 268
          right_set.insert(right);
268 269
        }
269 270

	
270 271
        if (nca == INVALID) {
271 272
          if ((*_matching)[left] == INVALID) {
272 273
            nca = right;
273 274
            while (left_set.find(nca) == left_set.end()) {
274 275
              nca = _graph.target((*_matching)[nca]);
275 276
              nca =(*_blossom_rep)[_blossom_set->
276 277
                                   find(_graph.target((*_ear)[nca]))];
277 278
            }
278 279
          } else {
279 280
            nca = left;
280 281
            while (right_set.find(nca) == right_set.end()) {
281 282
              nca = _graph.target((*_matching)[nca]);
282 283
              nca = (*_blossom_rep)[_blossom_set->
283 284
                                   find(_graph.target((*_ear)[nca]))];
284 285
            }
285 286
          }
286 287
        }
287 288
      }
288 289

	
289 290
      {
290 291

	
291 292
        Node node = _graph.u(e);
292 293
        Arc arc = _graph.direct(e, true);
293 294
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
294 295

	
295 296
        while (base != nca) {
296 297
          (*_ear)[node] = arc;
297 298

	
298 299
          Node n = node;
299 300
          while (n != base) {
300 301
            n = _graph.target((*_matching)[n]);
301 302
            Arc a = (*_ear)[n];
302 303
            n = _graph.target(a);
303 304
            (*_ear)[n] = _graph.oppositeArc(a);
304 305
          }
305 306
          node = _graph.target((*_matching)[base]);
306 307
          _tree_set->erase(base);
307 308
          _tree_set->erase(node);
308 309
          _blossom_set->insert(node, _blossom_set->find(base));
309 310
          (*_status)[node] = EVEN;
310 311
          _node_queue[_last++] = node;
311 312
          arc = _graph.oppositeArc((*_ear)[node]);
312 313
          node = _graph.target((*_ear)[node]);
313 314
          base = (*_blossom_rep)[_blossom_set->find(node)];
314 315
          _blossom_set->join(_graph.target(arc), base);
315 316
        }
316 317
      }
317 318

	
318 319
      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
319 320

	
320 321
      {
321 322

	
322 323
        Node node = _graph.v(e);
323 324
        Arc arc = _graph.direct(e, false);
324 325
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
325 326

	
326 327
        while (base != nca) {
327 328
          (*_ear)[node] = arc;
328 329

	
329 330
          Node n = node;
330 331
          while (n != base) {
331 332
            n = _graph.target((*_matching)[n]);
332 333
            Arc a = (*_ear)[n];
333 334
            n = _graph.target(a);
334 335
            (*_ear)[n] = _graph.oppositeArc(a);
335 336
          }
336 337
          node = _graph.target((*_matching)[base]);
337 338
          _tree_set->erase(base);
338 339
          _tree_set->erase(node);
339 340
          _blossom_set->insert(node, _blossom_set->find(base));
340 341
          (*_status)[node] = EVEN;
341 342
          _node_queue[_last++] = node;
342 343
          arc = _graph.oppositeArc((*_ear)[node]);
343 344
          node = _graph.target((*_ear)[node]);
344 345
          base = (*_blossom_rep)[_blossom_set->find(node)];
345 346
          _blossom_set->join(_graph.target(arc), base);
346 347
        }
347 348
      }
348 349

	
349 350
      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
350 351
    }
351 352

	
352 353
    void extendOnArc(const Arc& a) {
353 354
      Node base = _graph.source(a);
354 355
      Node odd = _graph.target(a);
355 356

	
356 357
      (*_ear)[odd] = _graph.oppositeArc(a);
357 358
      Node even = _graph.target((*_matching)[odd]);
358 359
      (*_blossom_rep)[_blossom_set->insert(even)] = even;
359 360
      (*_status)[odd] = ODD;
360 361
      (*_status)[even] = EVEN;
361 362
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
362 363
      _tree_set->insert(odd, tree);
363 364
      _tree_set->insert(even, tree);
364 365
      _node_queue[_last++] = even;
365 366

	
366 367
    }
367 368

	
368 369
    void augmentOnArc(const Arc& a) {
369 370
      Node even = _graph.source(a);
370 371
      Node odd = _graph.target(a);
371 372

	
372 373
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
373 374

	
374 375
      (*_matching)[odd] = _graph.oppositeArc(a);
375 376
      (*_status)[odd] = MATCHED;
376 377

	
377 378
      Arc arc = (*_matching)[even];
378 379
      (*_matching)[even] = a;
379 380

	
380 381
      while (arc != INVALID) {
381 382
        odd = _graph.target(arc);
382 383
        arc = (*_ear)[odd];
383 384
        even = _graph.target(arc);
384 385
        (*_matching)[odd] = arc;
385 386
        arc = (*_matching)[even];
386 387
        (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
387 388
      }
388 389

	
389 390
      for (typename TreeSet::ItemIt it(*_tree_set, tree);
390 391
           it != INVALID; ++it) {
391 392
        if ((*_status)[it] == ODD) {
392 393
          (*_status)[it] = MATCHED;
393 394
        } else {
394 395
          int blossom = _blossom_set->find(it);
395 396
          for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
396 397
               jt != INVALID; ++jt) {
397 398
            (*_status)[jt] = MATCHED;
398 399
          }
399 400
          _blossom_set->eraseClass(blossom);
400 401
        }
401 402
      }
402 403
      _tree_set->eraseClass(tree);
403 404

	
404 405
    }
405 406

	
406 407
  public:
407 408

	
408 409
    /// \brief Constructor
409 410
    ///
410 411
    /// Constructor.
411 412
    MaxMatching(const Graph& graph)
412 413
      : _graph(graph), _matching(0), _status(0), _ear(0),
413 414
        _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
414 415
        _tree_set_index(0), _tree_set(0) {}
... ...
@@ -416,2710 +417,3006 @@
416 417
    ~MaxMatching() {
417 418
      destroyStructures();
418 419
    }
419 420

	
420 421
    /// \name Execution Control
421 422
    /// The simplest way to execute the algorithm is to use the
422 423
    /// \c run() member function.\n
423 424
    /// If you need better control on the execution, you have to call
424 425
    /// one of the functions \ref init(), \ref greedyInit() or
425 426
    /// \ref matchingInit() first, then you can start the algorithm with
426 427
    /// \ref startSparse() or \ref startDense().
427 428

	
428 429
    ///@{
429 430

	
430 431
    /// \brief Set the initial matching to the empty matching.
431 432
    ///
432 433
    /// This function sets the initial matching to the empty matching.
433 434
    void init() {
434 435
      createStructures();
435 436
      for(NodeIt n(_graph); n != INVALID; ++n) {
436 437
        (*_matching)[n] = INVALID;
437 438
        (*_status)[n] = UNMATCHED;
438 439
      }
439 440
    }
440 441

	
441 442
    /// \brief Find an initial matching in a greedy way.
442 443
    ///
443 444
    /// This function finds an initial matching in a greedy way.
444 445
    void greedyInit() {
445 446
      createStructures();
446 447
      for (NodeIt n(_graph); n != INVALID; ++n) {
447 448
        (*_matching)[n] = INVALID;
448 449
        (*_status)[n] = UNMATCHED;
449 450
      }
450 451
      for (NodeIt n(_graph); n != INVALID; ++n) {
451 452
        if ((*_matching)[n] == INVALID) {
452 453
          for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
453 454
            Node v = _graph.target(a);
454 455
            if ((*_matching)[v] == INVALID && v != n) {
455 456
              (*_matching)[n] = a;
456 457
              (*_status)[n] = MATCHED;
457 458
              (*_matching)[v] = _graph.oppositeArc(a);
458 459
              (*_status)[v] = MATCHED;
459 460
              break;
460 461
            }
461 462
          }
462 463
        }
463 464
      }
464 465
    }
465 466

	
466 467

	
467 468
    /// \brief Initialize the matching from a map.
468 469
    ///
469 470
    /// This function initializes the matching from a \c bool valued edge
470 471
    /// map. This map should have the property that there are no two incident
471 472
    /// edges with \c true value, i.e. it really contains a matching.
472 473
    /// \return \c true if the map contains a matching.
473 474
    template <typename MatchingMap>
474 475
    bool matchingInit(const MatchingMap& matching) {
475 476
      createStructures();
476 477

	
477 478
      for (NodeIt n(_graph); n != INVALID; ++n) {
478 479
        (*_matching)[n] = INVALID;
479 480
        (*_status)[n] = UNMATCHED;
480 481
      }
481 482
      for(EdgeIt e(_graph); e!=INVALID; ++e) {
482 483
        if (matching[e]) {
483 484

	
484 485
          Node u = _graph.u(e);
485 486
          if ((*_matching)[u] != INVALID) return false;
486 487
          (*_matching)[u] = _graph.direct(e, true);
487 488
          (*_status)[u] = MATCHED;
488 489

	
489 490
          Node v = _graph.v(e);
490 491
          if ((*_matching)[v] != INVALID) return false;
491 492
          (*_matching)[v] = _graph.direct(e, false);
492 493
          (*_status)[v] = MATCHED;
493 494
        }
494 495
      }
495 496
      return true;
496 497
    }
497 498

	
498 499
    /// \brief Start Edmonds' algorithm
499 500
    ///
500 501
    /// This function runs the original Edmonds' algorithm.
501 502
    ///
502 503
    /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
503 504
    /// called before using this function.
504 505
    void startSparse() {
505 506
      for(NodeIt n(_graph); n != INVALID; ++n) {
506 507
        if ((*_status)[n] == UNMATCHED) {
507 508
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
508 509
          _tree_set->insert(n);
509 510
          (*_status)[n] = EVEN;
510 511
          processSparse(n);
511 512
        }
512 513
      }
513 514
    }
514 515

	
515 516
    /// \brief Start Edmonds' algorithm with a heuristic improvement
516 517
    /// for dense graphs
517 518
    ///
518 519
    /// This function runs Edmonds' algorithm with a heuristic of postponing
519 520
    /// shrinks, therefore resulting in a faster algorithm for dense graphs.
520 521
    ///
521 522
    /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
522 523
    /// called before using this function.
523 524
    void startDense() {
524 525
      for(NodeIt n(_graph); n != INVALID; ++n) {
525 526
        if ((*_status)[n] == UNMATCHED) {
526 527
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
527 528
          _tree_set->insert(n);
528 529
          (*_status)[n] = EVEN;
529 530
          processDense(n);
530 531
        }
531 532
      }
532 533
    }
533 534

	
534 535

	
535 536
    /// \brief Run Edmonds' algorithm
536 537
    ///
537 538
    /// This function runs Edmonds' algorithm. An additional heuristic of
538 539
    /// postponing shrinks is used for relatively dense graphs
539 540
    /// (for which <tt>m>=2*n</tt> holds).
540 541
    void run() {
541 542
      if (countEdges(_graph) < 2 * countNodes(_graph)) {
542 543
        greedyInit();
543 544
        startSparse();
544 545
      } else {
545 546
        init();
546 547
        startDense();
547 548
      }
548 549
    }
549 550

	
550 551
    /// @}
551 552

	
552 553
    /// \name Primal Solution
553 554
    /// Functions to get the primal solution, i.e. the maximum matching.
554 555

	
555 556
    /// @{
556 557

	
557 558
    /// \brief Return the size (cardinality) of the matching.
558 559
    ///
559 560
    /// This function returns the size (cardinality) of the current matching.
560 561
    /// After run() it returns the size of the maximum matching in the graph.
561 562
    int matchingSize() const {
562 563
      int size = 0;
563 564
      for (NodeIt n(_graph); n != INVALID; ++n) {
564 565
        if ((*_matching)[n] != INVALID) {
565 566
          ++size;
566 567
        }
567 568
      }
568 569
      return size / 2;
569 570
    }
570 571

	
571 572
    /// \brief Return \c true if the given edge is in the matching.
572 573
    ///
573 574
    /// This function returns \c true if the given edge is in the current
574 575
    /// matching.
575 576
    bool matching(const Edge& edge) const {
576 577
      return edge == (*_matching)[_graph.u(edge)];
577 578
    }
578 579

	
579 580
    /// \brief Return the matching arc (or edge) incident to the given node.
580 581
    ///
581 582
    /// This function returns the matching arc (or edge) incident to the
582 583
    /// given node in the current matching or \c INVALID if the node is
583 584
    /// not covered by the matching.
584 585
    Arc matching(const Node& n) const {
585 586
      return (*_matching)[n];
586 587
    }
587 588

	
588 589
    /// \brief Return a const reference to the matching map.
589 590
    ///
590 591
    /// This function returns a const reference to a node map that stores
591 592
    /// the matching arc (or edge) incident to each node.
592 593
    const MatchingMap& matchingMap() const {
593 594
      return *_matching;
594 595
    }
595 596

	
596 597
    /// \brief Return the mate of the given node.
597 598
    ///
598 599
    /// This function returns the mate of the given node in the current
599 600
    /// matching or \c INVALID if the node is not covered by the matching.
600 601
    Node mate(const Node& n) const {
601 602
      return (*_matching)[n] != INVALID ?
602 603
        _graph.target((*_matching)[n]) : INVALID;
603 604
    }
604 605

	
605 606
    /// @}
606 607

	
607 608
    /// \name Dual Solution
608 609
    /// Functions to get the dual solution, i.e. the Gallai-Edmonds
609 610
    /// decomposition.
610 611

	
611 612
    /// @{
612 613

	
613 614
    /// \brief Return the status of the given node in the Edmonds-Gallai
614 615
    /// decomposition.
615 616
    ///
616 617
    /// This function returns the \ref Status "status" of the given node
617 618
    /// in the Edmonds-Gallai decomposition.
618 619
    Status status(const Node& n) const {
619 620
      return (*_status)[n];
620 621
    }
621 622

	
622 623
    /// \brief Return a const reference to the status map, which stores
623 624
    /// the Edmonds-Gallai decomposition.
624 625
    ///
625 626
    /// This function returns a const reference to a node map that stores the
626 627
    /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
627 628
    const StatusMap& statusMap() const {
628 629
      return *_status;
629 630
    }
630 631

	
631 632
    /// \brief Return \c true if the given node is in the barrier.
632 633
    ///
633 634
    /// This function returns \c true if the given node is in the barrier.
634 635
    bool barrier(const Node& n) const {
635 636
      return (*_status)[n] == ODD;
636 637
    }
637 638

	
638 639
    /// @}
639 640

	
640 641
  };
641 642

	
642 643
  /// \ingroup matching
643 644
  ///
644 645
  /// \brief Weighted matching in general graphs
645 646
  ///
646 647
  /// This class provides an efficient implementation of Edmond's
647 648
  /// maximum weighted matching algorithm. The implementation is based
648 649
  /// on extensive use of priority queues and provides
649 650
  /// \f$O(nm\log n)\f$ time complexity.
650 651
  ///
651 652
  /// The maximum weighted matching problem is to find a subset of the
652 653
  /// edges in an undirected graph with maximum overall weight for which
653 654
  /// each node has at most one incident edge.
654 655
  /// It can be formulated with the following linear program.
655 656
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
656 657
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
657 658
      \quad \forall B\in\mathcal{O}\f] */
658 659
  /// \f[x_e \ge 0\quad \forall e\in E\f]
659 660
  /// \f[\max \sum_{e\in E}x_ew_e\f]
660 661
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
661 662
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
662 663
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
663 664
  /// subsets of the nodes.
664 665
  ///
665 666
  /// The algorithm calculates an optimal matching and a proof of the
666 667
  /// optimality. The solution of the dual problem can be used to check
667 668
  /// the result of the algorithm. The dual linear problem is the
668 669
  /// following.
669 670
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
670 671
      z_B \ge w_{uv} \quad \forall uv\in E\f] */
671 672
  /// \f[y_u \ge 0 \quad \forall u \in V\f]
672 673
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
673 674
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
674 675
      \frac{\vert B \vert - 1}{2}z_B\f] */
675 676
  ///
676 677
  /// The algorithm can be executed with the run() function.
677 678
  /// After it the matching (the primal solution) and the dual solution
678 679
  /// can be obtained using the query functions and the
679 680
  /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
680 681
  /// which is able to iterate on the nodes of a blossom.
681 682
  /// If the value type is integer, then the dual solution is multiplied
682 683
  /// by \ref MaxWeightedMatching::dualScale "4".
683 684
  ///
684 685
  /// \tparam GR The undirected graph type the algorithm runs on.
685 686
  /// \tparam WM The type edge weight map. The default type is
686 687
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
687 688
#ifdef DOXYGEN
688 689
  template <typename GR, typename WM>
689 690
#else
690 691
  template <typename GR,
691 692
            typename WM = typename GR::template EdgeMap<int> >
692 693
#endif
693 694
  class MaxWeightedMatching {
694 695
  public:
695 696

	
696 697
    /// The graph type of the algorithm
697 698
    typedef GR Graph;
698 699
    /// The type of the edge weight map
699 700
    typedef WM WeightMap;
700 701
    /// The value type of the edge weights
701 702
    typedef typename WeightMap::Value Value;
702 703

	
703 704
    /// The type of the matching map
704 705
    typedef typename Graph::template NodeMap<typename Graph::Arc>
705 706
    MatchingMap;
706 707

	
707 708
    /// \brief Scaling factor for dual solution
708 709
    ///
709 710
    /// Scaling factor for dual solution. It is equal to 4 or 1
710 711
    /// according to the value type.
711 712
    static const int dualScale =
712 713
      std::numeric_limits<Value>::is_integer ? 4 : 1;
713 714

	
714 715
  private:
715 716

	
716 717
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
717 718

	
718 719
    typedef typename Graph::template NodeMap<Value> NodePotential;
719 720
    typedef std::vector<Node> BlossomNodeList;
720 721

	
721 722
    struct BlossomVariable {
722 723
      int begin, end;
723 724
      Value value;
724 725

	
725 726
      BlossomVariable(int _begin, int _end, Value _value)
726 727
        : begin(_begin), end(_end), value(_value) {}
727 728

	
728 729
    };
729 730

	
730 731
    typedef std::vector<BlossomVariable> BlossomPotential;
731 732

	
732 733
    const Graph& _graph;
733 734
    const WeightMap& _weight;
734 735

	
735 736
    MatchingMap* _matching;
736 737

	
737 738
    NodePotential* _node_potential;
738 739

	
739 740
    BlossomPotential _blossom_potential;
740 741
    BlossomNodeList _blossom_node_list;
741 742

	
742 743
    int _node_num;
743 744
    int _blossom_num;
744 745

	
745 746
    typedef RangeMap<int> IntIntMap;
746 747

	
747 748
    enum Status {
748 749
      EVEN = -1, MATCHED = 0, ODD = 1
749 750
    };
750 751

	
751 752
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
752 753
    struct BlossomData {
753 754
      int tree;
754 755
      Status status;
755 756
      Arc pred, next;
756 757
      Value pot, offset;
757 758
      Node base;
758 759
    };
759 760

	
760 761
    IntNodeMap *_blossom_index;
761 762
    BlossomSet *_blossom_set;
762 763
    RangeMap<BlossomData>* _blossom_data;
763 764

	
764 765
    IntNodeMap *_node_index;
765 766
    IntArcMap *_node_heap_index;
766 767

	
767 768
    struct NodeData {
768 769

	
769 770
      NodeData(IntArcMap& node_heap_index)
770 771
        : heap(node_heap_index) {}
771 772

	
772 773
      int blossom;
773 774
      Value pot;
774 775
      BinHeap<Value, IntArcMap> heap;
775 776
      std::map<int, Arc> heap_index;
776 777

	
777 778
      int tree;
778 779
    };
779 780

	
780 781
    RangeMap<NodeData>* _node_data;
781 782

	
782 783
    typedef ExtendFindEnum<IntIntMap> TreeSet;
783 784

	
784 785
    IntIntMap *_tree_set_index;
785 786
    TreeSet *_tree_set;
786 787

	
787 788
    IntNodeMap *_delta1_index;
788 789
    BinHeap<Value, IntNodeMap> *_delta1;
789 790

	
790 791
    IntIntMap *_delta2_index;
791 792
    BinHeap<Value, IntIntMap> *_delta2;
792 793

	
793 794
    IntEdgeMap *_delta3_index;
794 795
    BinHeap<Value, IntEdgeMap> *_delta3;
795 796

	
796 797
    IntIntMap *_delta4_index;
797 798
    BinHeap<Value, IntIntMap> *_delta4;
798 799

	
799 800
    Value _delta_sum;
801
    int _unmatched;
802

	
803
    typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
804
    FractionalMatching *_fractional;
800 805

	
801 806
    void createStructures() {
802 807
      _node_num = countNodes(_graph);
803 808
      _blossom_num = _node_num * 3 / 2;
804 809

	
805 810
      if (!_matching) {
806 811
        _matching = new MatchingMap(_graph);
807 812
      }
808 813
      if (!_node_potential) {
809 814
        _node_potential = new NodePotential(_graph);
810 815
      }
811 816
      if (!_blossom_set) {
812 817
        _blossom_index = new IntNodeMap(_graph);
813 818
        _blossom_set = new BlossomSet(*_blossom_index);
814 819
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
815 820
      }
816 821

	
817 822
      if (!_node_index) {
818 823
        _node_index = new IntNodeMap(_graph);
819 824
        _node_heap_index = new IntArcMap(_graph);
820 825
        _node_data = new RangeMap<NodeData>(_node_num,
821 826
                                              NodeData(*_node_heap_index));
822 827
      }
823 828

	
824 829
      if (!_tree_set) {
825 830
        _tree_set_index = new IntIntMap(_blossom_num);
826 831
        _tree_set = new TreeSet(*_tree_set_index);
827 832
      }
828 833
      if (!_delta1) {
829 834
        _delta1_index = new IntNodeMap(_graph);
830 835
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
831 836
      }
832 837
      if (!_delta2) {
833 838
        _delta2_index = new IntIntMap(_blossom_num);
834 839
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
835 840
      }
836 841
      if (!_delta3) {
837 842
        _delta3_index = new IntEdgeMap(_graph);
838 843
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
839 844
      }
840 845
      if (!_delta4) {
841 846
        _delta4_index = new IntIntMap(_blossom_num);
842 847
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
843 848
      }
844 849
    }
845 850

	
846 851
    void destroyStructures() {
847 852
      if (_matching) {
848 853
        delete _matching;
849 854
      }
850 855
      if (_node_potential) {
851 856
        delete _node_potential;
852 857
      }
853 858
      if (_blossom_set) {
854 859
        delete _blossom_index;
855 860
        delete _blossom_set;
856 861
        delete _blossom_data;
857 862
      }
858 863

	
859 864
      if (_node_index) {
860 865
        delete _node_index;
861 866
        delete _node_heap_index;
862 867
        delete _node_data;
863 868
      }
864 869

	
865 870
      if (_tree_set) {
866 871
        delete _tree_set_index;
867 872
        delete _tree_set;
868 873
      }
869 874
      if (_delta1) {
870 875
        delete _delta1_index;
871 876
        delete _delta1;
872 877
      }
873 878
      if (_delta2) {
874 879
        delete _delta2_index;
875 880
        delete _delta2;
876 881
      }
877 882
      if (_delta3) {
878 883
        delete _delta3_index;
879 884
        delete _delta3;
880 885
      }
881 886
      if (_delta4) {
882 887
        delete _delta4_index;
883 888
        delete _delta4;
884 889
      }
885 890
    }
886 891

	
887 892
    void matchedToEven(int blossom, int tree) {
888 893
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
889 894
        _delta2->erase(blossom);
890 895
      }
891 896

	
892 897
      if (!_blossom_set->trivial(blossom)) {
893 898
        (*_blossom_data)[blossom].pot -=
894 899
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
895 900
      }
896 901

	
897 902
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
898 903
           n != INVALID; ++n) {
899 904

	
900 905
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
901 906
        int ni = (*_node_index)[n];
902 907

	
903 908
        (*_node_data)[ni].heap.clear();
904 909
        (*_node_data)[ni].heap_index.clear();
905 910

	
906 911
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
907 912

	
908 913
        _delta1->push(n, (*_node_data)[ni].pot);
909 914

	
910 915
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
911 916
          Node v = _graph.source(e);
912 917
          int vb = _blossom_set->find(v);
913 918
          int vi = (*_node_index)[v];
914 919

	
915 920
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
916 921
            dualScale * _weight[e];
917 922

	
918 923
          if ((*_blossom_data)[vb].status == EVEN) {
919 924
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
920 925
              _delta3->push(e, rw / 2);
921 926
            }
922 927
          } else {
923 928
            typename std::map<int, Arc>::iterator it =
924 929
              (*_node_data)[vi].heap_index.find(tree);
925 930

	
926 931
            if (it != (*_node_data)[vi].heap_index.end()) {
927 932
              if ((*_node_data)[vi].heap[it->second] > rw) {
928 933
                (*_node_data)[vi].heap.replace(it->second, e);
929 934
                (*_node_data)[vi].heap.decrease(e, rw);
930 935
                it->second = e;
931 936
              }
932 937
            } else {
933 938
              (*_node_data)[vi].heap.push(e, rw);
934 939
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
935 940
            }
936 941

	
937 942
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
938 943
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
939 944

	
940 945
              if ((*_blossom_data)[vb].status == MATCHED) {
941 946
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
942 947
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
943 948
                               (*_blossom_data)[vb].offset);
944 949
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
945 950
                           (*_blossom_data)[vb].offset) {
946 951
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
947 952
                                   (*_blossom_data)[vb].offset);
948 953
                }
949 954
              }
950 955
            }
951 956
          }
952 957
        }
953 958
      }
954 959
      (*_blossom_data)[blossom].offset = 0;
955 960
    }
956 961

	
957 962
    void matchedToOdd(int blossom) {
958 963
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
959 964
        _delta2->erase(blossom);
960 965
      }
961 966
      (*_blossom_data)[blossom].offset += _delta_sum;
962 967
      if (!_blossom_set->trivial(blossom)) {
963 968
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
964 969
                      (*_blossom_data)[blossom].offset);
965 970
      }
966 971
    }
967 972

	
968 973
    void evenToMatched(int blossom, int tree) {
969 974
      if (!_blossom_set->trivial(blossom)) {
970 975
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
971 976
      }
972 977

	
973 978
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
974 979
           n != INVALID; ++n) {
975 980
        int ni = (*_node_index)[n];
976 981
        (*_node_data)[ni].pot -= _delta_sum;
977 982

	
978 983
        _delta1->erase(n);
979 984

	
980 985
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
981 986
          Node v = _graph.source(e);
982 987
          int vb = _blossom_set->find(v);
983 988
          int vi = (*_node_index)[v];
984 989

	
985 990
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
986 991
            dualScale * _weight[e];
987 992

	
988 993
          if (vb == blossom) {
989 994
            if (_delta3->state(e) == _delta3->IN_HEAP) {
990 995
              _delta3->erase(e);
991 996
            }
992 997
          } else if ((*_blossom_data)[vb].status == EVEN) {
993 998

	
994 999
            if (_delta3->state(e) == _delta3->IN_HEAP) {
995 1000
              _delta3->erase(e);
996 1001
            }
997 1002

	
998 1003
            int vt = _tree_set->find(vb);
999 1004

	
1000 1005
            if (vt != tree) {
1001 1006

	
1002 1007
              Arc r = _graph.oppositeArc(e);
1003 1008

	
1004 1009
              typename std::map<int, Arc>::iterator it =
1005 1010
                (*_node_data)[ni].heap_index.find(vt);
1006 1011

	
1007 1012
              if (it != (*_node_data)[ni].heap_index.end()) {
1008 1013
                if ((*_node_data)[ni].heap[it->second] > rw) {
1009 1014
                  (*_node_data)[ni].heap.replace(it->second, r);
1010 1015
                  (*_node_data)[ni].heap.decrease(r, rw);
1011 1016
                  it->second = r;
1012 1017
                }
1013 1018
              } else {
1014 1019
                (*_node_data)[ni].heap.push(r, rw);
1015 1020
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1016 1021
              }
1017 1022

	
1018 1023
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1019 1024
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1020 1025

	
1021 1026
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1022 1027
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1023 1028
                               (*_blossom_data)[blossom].offset);
1024 1029
                } else if ((*_delta2)[blossom] >
1025 1030
                           _blossom_set->classPrio(blossom) -
1026 1031
                           (*_blossom_data)[blossom].offset){
1027 1032
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1028 1033
                                   (*_blossom_data)[blossom].offset);
1029 1034
                }
1030 1035
              }
1031 1036
            }
1032 1037
          } else {
1033 1038

	
1034 1039
            typename std::map<int, Arc>::iterator it =
1035 1040
              (*_node_data)[vi].heap_index.find(tree);
1036 1041

	
1037 1042
            if (it != (*_node_data)[vi].heap_index.end()) {
1038 1043
              (*_node_data)[vi].heap.erase(it->second);
1039 1044
              (*_node_data)[vi].heap_index.erase(it);
1040 1045
              if ((*_node_data)[vi].heap.empty()) {
1041 1046
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
1042 1047
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1043 1048
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1044 1049
              }
1045 1050

	
1046 1051
              if ((*_blossom_data)[vb].status == MATCHED) {
1047 1052
                if (_blossom_set->classPrio(vb) ==
1048 1053
                    std::numeric_limits<Value>::max()) {
1049 1054
                  _delta2->erase(vb);
1050 1055
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1051 1056
                           (*_blossom_data)[vb].offset) {
1052 1057
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
1053 1058
                                   (*_blossom_data)[vb].offset);
1054 1059
                }
1055 1060
              }
1056 1061
            }
1057 1062
          }
1058 1063
        }
1059 1064
      }
1060 1065
    }
1061 1066

	
1062 1067
    void oddToMatched(int blossom) {
1063 1068
      (*_blossom_data)[blossom].offset -= _delta_sum;
1064 1069

	
1065 1070
      if (_blossom_set->classPrio(blossom) !=
1066 1071
          std::numeric_limits<Value>::max()) {
1067 1072
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1068 1073
                      (*_blossom_data)[blossom].offset);
1069 1074
      }
1070 1075

	
1071 1076
      if (!_blossom_set->trivial(blossom)) {
1072 1077
        _delta4->erase(blossom);
1073 1078
      }
1074 1079
    }
1075 1080

	
1076 1081
    void oddToEven(int blossom, int tree) {
1077 1082
      if (!_blossom_set->trivial(blossom)) {
1078 1083
        _delta4->erase(blossom);
1079 1084
        (*_blossom_data)[blossom].pot -=
1080 1085
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1081 1086
      }
1082 1087

	
1083 1088
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1084 1089
           n != INVALID; ++n) {
1085 1090
        int ni = (*_node_index)[n];
1086 1091

	
1087 1092
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1088 1093

	
1089 1094
        (*_node_data)[ni].heap.clear();
1090 1095
        (*_node_data)[ni].heap_index.clear();
1091 1096
        (*_node_data)[ni].pot +=
1092 1097
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
1093 1098

	
1094 1099
        _delta1->push(n, (*_node_data)[ni].pot);
1095 1100

	
1096 1101
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1097 1102
          Node v = _graph.source(e);
1098 1103
          int vb = _blossom_set->find(v);
1099 1104
          int vi = (*_node_index)[v];
1100 1105

	
1101 1106
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1102 1107
            dualScale * _weight[e];
1103 1108

	
1104 1109
          if ((*_blossom_data)[vb].status == EVEN) {
1105 1110
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1106 1111
              _delta3->push(e, rw / 2);
1107 1112
            }
1108 1113
          } else {
1109 1114

	
1110 1115
            typename std::map<int, Arc>::iterator it =
1111 1116
              (*_node_data)[vi].heap_index.find(tree);
1112 1117

	
1113 1118
            if (it != (*_node_data)[vi].heap_index.end()) {
1114 1119
              if ((*_node_data)[vi].heap[it->second] > rw) {
1115 1120
                (*_node_data)[vi].heap.replace(it->second, e);
1116 1121
                (*_node_data)[vi].heap.decrease(e, rw);
1117 1122
                it->second = e;
1118 1123
              }
1119 1124
            } else {
1120 1125
              (*_node_data)[vi].heap.push(e, rw);
1121 1126
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1122 1127
            }
1123 1128

	
1124 1129
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1125 1130
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1126 1131

	
1127 1132
              if ((*_blossom_data)[vb].status == MATCHED) {
1128 1133
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
1129 1134
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
1130 1135
                               (*_blossom_data)[vb].offset);
1131 1136
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1132 1137
                           (*_blossom_data)[vb].offset) {
1133 1138
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1134 1139
                                   (*_blossom_data)[vb].offset);
1135 1140
                }
1136 1141
              }
1137 1142
            }
1138 1143
          }
1139 1144
        }
1140 1145
      }
1141 1146
      (*_blossom_data)[blossom].offset = 0;
1142 1147
    }
1143 1148

	
1144 1149
    void alternatePath(int even, int tree) {
1145 1150
      int odd;
1146 1151

	
1147 1152
      evenToMatched(even, tree);
1148 1153
      (*_blossom_data)[even].status = MATCHED;
1149 1154

	
1150 1155
      while ((*_blossom_data)[even].pred != INVALID) {
1151 1156
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1152 1157
        (*_blossom_data)[odd].status = MATCHED;
1153 1158
        oddToMatched(odd);
1154 1159
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1155 1160

	
1156 1161
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1157 1162
        (*_blossom_data)[even].status = MATCHED;
1158 1163
        evenToMatched(even, tree);
1159 1164
        (*_blossom_data)[even].next =
1160 1165
          _graph.oppositeArc((*_blossom_data)[odd].pred);
1161 1166
      }
1162 1167

	
1163 1168
    }
1164 1169

	
1165 1170
    void destroyTree(int tree) {
1166 1171
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1167 1172
        if ((*_blossom_data)[b].status == EVEN) {
1168 1173
          (*_blossom_data)[b].status = MATCHED;
1169 1174
          evenToMatched(b, tree);
1170 1175
        } else if ((*_blossom_data)[b].status == ODD) {
1171 1176
          (*_blossom_data)[b].status = MATCHED;
1172 1177
          oddToMatched(b);
1173 1178
        }
1174 1179
      }
1175 1180
      _tree_set->eraseClass(tree);
1176 1181
    }
1177 1182

	
1178 1183

	
1179 1184
    void unmatchNode(const Node& node) {
1180 1185
      int blossom = _blossom_set->find(node);
1181 1186
      int tree = _tree_set->find(blossom);
1182 1187

	
1183 1188
      alternatePath(blossom, tree);
1184 1189
      destroyTree(tree);
1185 1190

	
1186 1191
      (*_blossom_data)[blossom].base = node;
1187 1192
      (*_blossom_data)[blossom].next = INVALID;
1188 1193
    }
1189 1194

	
1190 1195
    void augmentOnEdge(const Edge& edge) {
1191 1196

	
1192 1197
      int left = _blossom_set->find(_graph.u(edge));
1193 1198
      int right = _blossom_set->find(_graph.v(edge));
1194 1199

	
1195 1200
      int left_tree = _tree_set->find(left);
1196 1201
      alternatePath(left, left_tree);
1197 1202
      destroyTree(left_tree);
1198 1203

	
1199 1204
      int right_tree = _tree_set->find(right);
1200 1205
      alternatePath(right, right_tree);
1201 1206
      destroyTree(right_tree);
1202 1207

	
1203 1208
      (*_blossom_data)[left].next = _graph.direct(edge, true);
1204 1209
      (*_blossom_data)[right].next = _graph.direct(edge, false);
1205 1210
    }
1206 1211

	
1207 1212
    void augmentOnArc(const Arc& arc) {
1208 1213

	
1209 1214
      int left = _blossom_set->find(_graph.source(arc));
1210 1215
      int right = _blossom_set->find(_graph.target(arc));
1211 1216

	
1212 1217
      (*_blossom_data)[left].status = MATCHED;
1213 1218

	
1214 1219
      int right_tree = _tree_set->find(right);
1215 1220
      alternatePath(right, right_tree);
1216 1221
      destroyTree(right_tree);
1217 1222

	
1218 1223
      (*_blossom_data)[left].next = arc;
1219 1224
      (*_blossom_data)[right].next = _graph.oppositeArc(arc);
1220 1225
    }
1221 1226

	
1222 1227
    void extendOnArc(const Arc& arc) {
1223 1228
      int base = _blossom_set->find(_graph.target(arc));
1224 1229
      int tree = _tree_set->find(base);
1225 1230

	
1226 1231
      int odd = _blossom_set->find(_graph.source(arc));
1227 1232
      _tree_set->insert(odd, tree);
1228 1233
      (*_blossom_data)[odd].status = ODD;
1229 1234
      matchedToOdd(odd);
1230 1235
      (*_blossom_data)[odd].pred = arc;
1231 1236

	
1232 1237
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1233 1238
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1234 1239
      _tree_set->insert(even, tree);
1235 1240
      (*_blossom_data)[even].status = EVEN;
1236 1241
      matchedToEven(even, tree);
1237 1242
    }
1238 1243

	
1239 1244
    void shrinkOnEdge(const Edge& edge, int tree) {
1240 1245
      int nca = -1;
1241 1246
      std::vector<int> left_path, right_path;
1242 1247

	
1243 1248
      {
1244 1249
        std::set<int> left_set, right_set;
1245 1250
        int left = _blossom_set->find(_graph.u(edge));
1246 1251
        left_path.push_back(left);
1247 1252
        left_set.insert(left);
1248 1253

	
1249 1254
        int right = _blossom_set->find(_graph.v(edge));
1250 1255
        right_path.push_back(right);
1251 1256
        right_set.insert(right);
1252 1257

	
1253 1258
        while (true) {
1254 1259

	
1255 1260
          if ((*_blossom_data)[left].pred == INVALID) break;
1256 1261

	
1257 1262
          left =
1258 1263
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1259 1264
          left_path.push_back(left);
1260 1265
          left =
1261 1266
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1262 1267
          left_path.push_back(left);
1263 1268

	
1264 1269
          left_set.insert(left);
1265 1270

	
1266 1271
          if (right_set.find(left) != right_set.end()) {
1267 1272
            nca = left;
1268 1273
            break;
1269 1274
          }
1270 1275

	
1271 1276
          if ((*_blossom_data)[right].pred == INVALID) break;
1272 1277

	
1273 1278
          right =
1274 1279
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1275 1280
          right_path.push_back(right);
1276 1281
          right =
1277 1282
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1278 1283
          right_path.push_back(right);
1279 1284

	
1280 1285
          right_set.insert(right);
1281 1286

	
1282 1287
          if (left_set.find(right) != left_set.end()) {
1283 1288
            nca = right;
1284 1289
            break;
1285 1290
          }
1286 1291

	
1287 1292
        }
1288 1293

	
1289 1294
        if (nca == -1) {
1290 1295
          if ((*_blossom_data)[left].pred == INVALID) {
1291 1296
            nca = right;
1292 1297
            while (left_set.find(nca) == left_set.end()) {
1293 1298
              nca =
1294 1299
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1295 1300
              right_path.push_back(nca);
1296 1301
              nca =
1297 1302
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1298 1303
              right_path.push_back(nca);
1299 1304
            }
1300 1305
          } else {
1301 1306
            nca = left;
1302 1307
            while (right_set.find(nca) == right_set.end()) {
1303 1308
              nca =
1304 1309
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1305 1310
              left_path.push_back(nca);
1306 1311
              nca =
1307 1312
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1308 1313
              left_path.push_back(nca);
1309 1314
            }
1310 1315
          }
1311 1316
        }
1312 1317
      }
1313 1318

	
1314 1319
      std::vector<int> subblossoms;
1315 1320
      Arc prev;
1316 1321

	
1317 1322
      prev = _graph.direct(edge, true);
1318 1323
      for (int i = 0; left_path[i] != nca; i += 2) {
1319 1324
        subblossoms.push_back(left_path[i]);
1320 1325
        (*_blossom_data)[left_path[i]].next = prev;
1321 1326
        _tree_set->erase(left_path[i]);
1322 1327

	
1323 1328
        subblossoms.push_back(left_path[i + 1]);
1324 1329
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
1325 1330
        oddToEven(left_path[i + 1], tree);
1326 1331
        _tree_set->erase(left_path[i + 1]);
1327 1332
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1328 1333
      }
1329 1334

	
1330 1335
      int k = 0;
1331 1336
      while (right_path[k] != nca) ++k;
1332 1337

	
1333 1338
      subblossoms.push_back(nca);
1334 1339
      (*_blossom_data)[nca].next = prev;
1335 1340

	
1336 1341
      for (int i = k - 2; i >= 0; i -= 2) {
1337 1342
        subblossoms.push_back(right_path[i + 1]);
1338 1343
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
1339 1344
        oddToEven(right_path[i + 1], tree);
1340 1345
        _tree_set->erase(right_path[i + 1]);
1341 1346

	
1342 1347
        (*_blossom_data)[right_path[i + 1]].next =
1343 1348
          (*_blossom_data)[right_path[i + 1]].pred;
1344 1349

	
1345 1350
        subblossoms.push_back(right_path[i]);
1346 1351
        _tree_set->erase(right_path[i]);
1347 1352
      }
1348 1353

	
1349 1354
      int surface =
1350 1355
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
1351 1356

	
1352 1357
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1353 1358
        if (!_blossom_set->trivial(subblossoms[i])) {
1354 1359
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1355 1360
        }
1356 1361
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
1357 1362
      }
1358 1363

	
1359 1364
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
1360 1365
      (*_blossom_data)[surface].offset = 0;
1361 1366
      (*_blossom_data)[surface].status = EVEN;
1362 1367
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1363 1368
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1364 1369

	
1365 1370
      _tree_set->insert(surface, tree);
1366 1371
      _tree_set->erase(nca);
1367 1372
    }
1368 1373

	
1369 1374
    void splitBlossom(int blossom) {
1370 1375
      Arc next = (*_blossom_data)[blossom].next;
1371 1376
      Arc pred = (*_blossom_data)[blossom].pred;
1372 1377

	
1373 1378
      int tree = _tree_set->find(blossom);
1374 1379

	
1375 1380
      (*_blossom_data)[blossom].status = MATCHED;
1376 1381
      oddToMatched(blossom);
1377 1382
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1378 1383
        _delta2->erase(blossom);
1379 1384
      }
1380 1385

	
1381 1386
      std::vector<int> subblossoms;
1382 1387
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
1383 1388

	
1384 1389
      Value offset = (*_blossom_data)[blossom].offset;
1385 1390
      int b = _blossom_set->find(_graph.source(pred));
1386 1391
      int d = _blossom_set->find(_graph.source(next));
1387 1392

	
1388 1393
      int ib = -1, id = -1;
1389 1394
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1390 1395
        if (subblossoms[i] == b) ib = i;
1391 1396
        if (subblossoms[i] == d) id = i;
1392 1397

	
1393 1398
        (*_blossom_data)[subblossoms[i]].offset = offset;
1394 1399
        if (!_blossom_set->trivial(subblossoms[i])) {
1395 1400
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1396 1401
        }
1397 1402
        if (_blossom_set->classPrio(subblossoms[i]) !=
1398 1403
            std::numeric_limits<Value>::max()) {
1399 1404
          _delta2->push(subblossoms[i],
1400 1405
                        _blossom_set->classPrio(subblossoms[i]) -
1401 1406
                        (*_blossom_data)[subblossoms[i]].offset);
1402 1407
        }
1403 1408
      }
1404 1409

	
1405 1410
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1406 1411
        for (int i = (id + 1) % subblossoms.size();
1407 1412
             i != ib; i = (i + 2) % subblossoms.size()) {
1408 1413
          int sb = subblossoms[i];
1409 1414
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1410 1415
          (*_blossom_data)[sb].next =
1411 1416
            _graph.oppositeArc((*_blossom_data)[tb].next);
1412 1417
        }
1413 1418

	
1414 1419
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1415 1420
          int sb = subblossoms[i];
1416 1421
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1417 1422
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1418 1423

	
1419 1424
          (*_blossom_data)[sb].status = ODD;
1420 1425
          matchedToOdd(sb);
1421 1426
          _tree_set->insert(sb, tree);
1422 1427
          (*_blossom_data)[sb].pred = pred;
1423 1428
          (*_blossom_data)[sb].next =
1424 1429
            _graph.oppositeArc((*_blossom_data)[tb].next);
1425 1430

	
1426 1431
          pred = (*_blossom_data)[ub].next;
1427 1432

	
1428 1433
          (*_blossom_data)[tb].status = EVEN;
1429 1434
          matchedToEven(tb, tree);
1430 1435
          _tree_set->insert(tb, tree);
1431 1436
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1432 1437
        }
1433 1438

	
1434 1439
        (*_blossom_data)[subblossoms[id]].status = ODD;
1435 1440
        matchedToOdd(subblossoms[id]);
1436 1441
        _tree_set->insert(subblossoms[id], tree);
1437 1442
        (*_blossom_data)[subblossoms[id]].next = next;
1438 1443
        (*_blossom_data)[subblossoms[id]].pred = pred;
1439 1444

	
1440 1445
      } else {
1441 1446

	
1442 1447
        for (int i = (ib + 1) % subblossoms.size();
1443 1448
             i != id; i = (i + 2) % subblossoms.size()) {
1444 1449
          int sb = subblossoms[i];
1445 1450
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1446 1451
          (*_blossom_data)[sb].next =
1447 1452
            _graph.oppositeArc((*_blossom_data)[tb].next);
1448 1453
        }
1449 1454

	
1450 1455
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1451 1456
          int sb = subblossoms[i];
1452 1457
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1453 1458
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1454 1459

	
1455 1460
          (*_blossom_data)[sb].status = ODD;
1456 1461
          matchedToOdd(sb);
1457 1462
          _tree_set->insert(sb, tree);
1458 1463
          (*_blossom_data)[sb].next = next;
1459 1464
          (*_blossom_data)[sb].pred =
1460 1465
            _graph.oppositeArc((*_blossom_data)[tb].next);
1461 1466

	
1462 1467
          (*_blossom_data)[tb].status = EVEN;
1463 1468
          matchedToEven(tb, tree);
1464 1469
          _tree_set->insert(tb, tree);
1465 1470
          (*_blossom_data)[tb].pred =
1466 1471
            (*_blossom_data)[tb].next =
1467 1472
            _graph.oppositeArc((*_blossom_data)[ub].next);
1468 1473
          next = (*_blossom_data)[ub].next;
1469 1474
        }
1470 1475

	
1471 1476
        (*_blossom_data)[subblossoms[ib]].status = ODD;
1472 1477
        matchedToOdd(subblossoms[ib]);
1473 1478
        _tree_set->insert(subblossoms[ib], tree);
1474 1479
        (*_blossom_data)[subblossoms[ib]].next = next;
1475 1480
        (*_blossom_data)[subblossoms[ib]].pred = pred;
1476 1481
      }
1477 1482
      _tree_set->erase(blossom);
1478 1483
    }
1479 1484

	
1480 1485
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1481 1486
      if (_blossom_set->trivial(blossom)) {
1482 1487
        int bi = (*_node_index)[base];
1483 1488
        Value pot = (*_node_data)[bi].pot;
1484 1489

	
1485 1490
        (*_matching)[base] = matching;
1486 1491
        _blossom_node_list.push_back(base);
1487 1492
        (*_node_potential)[base] = pot;
1488 1493
      } else {
1489 1494

	
1490 1495
        Value pot = (*_blossom_data)[blossom].pot;
1491 1496
        int bn = _blossom_node_list.size();
1492 1497

	
1493 1498
        std::vector<int> subblossoms;
1494 1499
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
1495 1500
        int b = _blossom_set->find(base);
1496 1501
        int ib = -1;
1497 1502
        for (int i = 0; i < int(subblossoms.size()); ++i) {
1498 1503
          if (subblossoms[i] == b) { ib = i; break; }
1499 1504
        }
1500 1505

	
1501 1506
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
1502 1507
          int sb = subblossoms[(ib + i) % subblossoms.size()];
1503 1508
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1504 1509

	
1505 1510
          Arc m = (*_blossom_data)[tb].next;
1506 1511
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1507 1512
          extractBlossom(tb, _graph.source(m), m);
1508 1513
        }
1509 1514
        extractBlossom(subblossoms[ib], base, matching);
1510 1515

	
1511 1516
        int en = _blossom_node_list.size();
1512 1517

	
1513 1518
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1514 1519
      }
1515 1520
    }
1516 1521

	
1517 1522
    void extractMatching() {
1518 1523
      std::vector<int> blossoms;
1519 1524
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1520 1525
        blossoms.push_back(c);
1521 1526
      }
1522 1527

	
1523 1528
      for (int i = 0; i < int(blossoms.size()); ++i) {
1524 1529
        if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1525 1530

	
1526 1531
          Value offset = (*_blossom_data)[blossoms[i]].offset;
1527 1532
          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1528 1533
          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1529 1534
               n != INVALID; ++n) {
1530 1535
            (*_node_data)[(*_node_index)[n]].pot -= offset;
1531 1536
          }
1532 1537

	
1533 1538
          Arc matching = (*_blossom_data)[blossoms[i]].next;
1534 1539
          Node base = _graph.source(matching);
1535 1540
          extractBlossom(blossoms[i], base, matching);
1536 1541
        } else {
1537 1542
          Node base = (*_blossom_data)[blossoms[i]].base;
1538 1543
          extractBlossom(blossoms[i], base, INVALID);
1539 1544
        }
1540 1545
      }
1541 1546
    }
1542 1547

	
1543 1548
  public:
1544 1549

	
1545 1550
    /// \brief Constructor
1546 1551
    ///
1547 1552
    /// Constructor.
1548 1553
    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1549 1554
      : _graph(graph), _weight(weight), _matching(0),
1550 1555
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
1551 1556
        _node_num(0), _blossom_num(0),
1552 1557

	
1553 1558
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
1554 1559
        _node_index(0), _node_heap_index(0), _node_data(0),
1555 1560
        _tree_set_index(0), _tree_set(0),
1556 1561

	
1557 1562
        _delta1_index(0), _delta1(0),
1558 1563
        _delta2_index(0), _delta2(0),
1559 1564
        _delta3_index(0), _delta3(0),
1560 1565
        _delta4_index(0), _delta4(0),
1561 1566

	
1562
        _delta_sum() {}
1567
        _delta_sum(), _unmatched(0),
1568

	
1569
        _fractional(0)
1570
    {}
1563 1571

	
1564 1572
    ~MaxWeightedMatching() {
1565 1573
      destroyStructures();
1574
      if (_fractional) {
1575
        delete _fractional;
1576
      }
1566 1577
    }
1567 1578

	
1568 1579
    /// \name Execution Control
1569 1580
    /// The simplest way to execute the algorithm is to use the
1570 1581
    /// \ref run() member function.
1571 1582

	
1572 1583
    ///@{
1573 1584

	
1574 1585
    /// \brief Initialize the algorithm
1575 1586
    ///
1576 1587
    /// This function initializes the algorithm.
1577 1588
    void init() {
1578 1589
      createStructures();
1579 1590

	
1580 1591
      for (ArcIt e(_graph); e != INVALID; ++e) {
1581 1592
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1582 1593
      }
1583 1594
      for (NodeIt n(_graph); n != INVALID; ++n) {
1584 1595
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1585 1596
      }
1586 1597
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1587 1598
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1588 1599
      }
1589 1600
      for (int i = 0; i < _blossom_num; ++i) {
1590 1601
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
1591 1602
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1592 1603
      }
1593 1604

	
1605
      _unmatched = _node_num;
1606

	
1594 1607
      int index = 0;
1595 1608
      for (NodeIt n(_graph); n != INVALID; ++n) {
1596 1609
        Value max = 0;
1597 1610
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1598 1611
          if (_graph.target(e) == n) continue;
1599 1612
          if ((dualScale * _weight[e]) / 2 > max) {
1600 1613
            max = (dualScale * _weight[e]) / 2;
1601 1614
          }
1602 1615
        }
1603 1616
        (*_node_index)[n] = index;
1604 1617
        (*_node_data)[index].pot = max;
1605 1618
        _delta1->push(n, max);
1606 1619
        int blossom =
1607 1620
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1608 1621

	
1609 1622
        _tree_set->insert(blossom);
1610 1623

	
1611 1624
        (*_blossom_data)[blossom].status = EVEN;
1612 1625
        (*_blossom_data)[blossom].pred = INVALID;
1613 1626
        (*_blossom_data)[blossom].next = INVALID;
1614 1627
        (*_blossom_data)[blossom].pot = 0;
1615 1628
        (*_blossom_data)[blossom].offset = 0;
1616 1629
        ++index;
1617 1630
      }
1618 1631
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1619 1632
        int si = (*_node_index)[_graph.u(e)];
1620 1633
        int ti = (*_node_index)[_graph.v(e)];
1621 1634
        if (_graph.u(e) != _graph.v(e)) {
1622 1635
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1623 1636
                            dualScale * _weight[e]) / 2);
1624 1637
        }
1625 1638
      }
1626 1639
    }
1627 1640

	
1641
    /// \brief Initialize the algorithm with fractional matching
1642
    ///
1643
    /// This function initializes the algorithm with a fractional
1644
    /// matching. This initialization is also called jumpstart heuristic.
1645
    void fractionalInit() {
1646
      createStructures();
1647
      
1648
      if (_fractional == 0) {
1649
        _fractional = new FractionalMatching(_graph, _weight, false);
1650
      }
1651
      _fractional->run();
1652

	
1653
      for (ArcIt e(_graph); e != INVALID; ++e) {
1654
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1655
      }
1656
      for (NodeIt n(_graph); n != INVALID; ++n) {
1657
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1658
      }
1659
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1660
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1661
      }
1662
      for (int i = 0; i < _blossom_num; ++i) {
1663
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
1664
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1665
      }
1666

	
1667
      _unmatched = 0;
1668

	
1669
      int index = 0;
1670
      for (NodeIt n(_graph); n != INVALID; ++n) {
1671
        Value pot = _fractional->nodeValue(n);
1672
        (*_node_index)[n] = index;
1673
        (*_node_data)[index].pot = pot;
1674
        int blossom =
1675
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1676

	
1677
        (*_blossom_data)[blossom].status = MATCHED;
1678
        (*_blossom_data)[blossom].pred = INVALID;
1679
        (*_blossom_data)[blossom].next = _fractional->matching(n);
1680
        if (_fractional->matching(n) == INVALID) {
1681
          (*_blossom_data)[blossom].base = n;
1682
        }
1683
        (*_blossom_data)[blossom].pot = 0;
1684
        (*_blossom_data)[blossom].offset = 0;
1685
        ++index;
1686
      }
1687

	
1688
      typename Graph::template NodeMap<bool> processed(_graph, false);
1689
      for (NodeIt n(_graph); n != INVALID; ++n) {
1690
        if (processed[n]) continue;
1691
        processed[n] = true;
1692
        if (_fractional->matching(n) == INVALID) continue;
1693
        int num = 1;
1694
        Node v = _graph.target(_fractional->matching(n));
1695
        while (n != v) {
1696
          processed[v] = true;
1697
          v = _graph.target(_fractional->matching(v));
1698
          ++num;
1699
        }
1700

	
1701
        if (num % 2 == 1) {
1702
          std::vector<int> subblossoms(num);
1703

	
1704
          subblossoms[--num] = _blossom_set->find(n);
1705
          _delta1->push(n, _fractional->nodeValue(n));
1706
          v = _graph.target(_fractional->matching(n));
1707
          while (n != v) {
1708
            subblossoms[--num] = _blossom_set->find(v);
1709
            _delta1->push(v, _fractional->nodeValue(v));
1710
            v = _graph.target(_fractional->matching(v));            
1711
          }
1712
          
1713
          int surface = 
1714
            _blossom_set->join(subblossoms.begin(), subblossoms.end());
1715
          (*_blossom_data)[surface].status = EVEN;
1716
          (*_blossom_data)[surface].pred = INVALID;
1717
          (*_blossom_data)[surface].next = INVALID;
1718
          (*_blossom_data)[surface].pot = 0;
1719
          (*_blossom_data)[surface].offset = 0;
1720
          
1721
          _tree_set->insert(surface);
1722
          ++_unmatched;
1723
        }
1724
      }
1725

	
1726
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1727
        int si = (*_node_index)[_graph.u(e)];
1728
        int sb = _blossom_set->find(_graph.u(e));
1729
        int ti = (*_node_index)[_graph.v(e)];
1730
        int tb = _blossom_set->find(_graph.v(e));
1731
        if ((*_blossom_data)[sb].status == EVEN &&
1732
            (*_blossom_data)[tb].status == EVEN && sb != tb) {
1733
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1734
                            dualScale * _weight[e]) / 2);
1735
        }
1736
      }
1737

	
1738
      for (NodeIt n(_graph); n != INVALID; ++n) {
1739
        int nb = _blossom_set->find(n);
1740
        if ((*_blossom_data)[nb].status != MATCHED) continue;
1741
        int ni = (*_node_index)[n];
1742

	
1743
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1744
          Node v = _graph.target(e);
1745
          int vb = _blossom_set->find(v);
1746
          int vi = (*_node_index)[v];
1747

	
1748
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1749
            dualScale * _weight[e];
1750

	
1751
          if ((*_blossom_data)[vb].status == EVEN) {
1752

	
1753
            int vt = _tree_set->find(vb);
1754

	
1755
            typename std::map<int, Arc>::iterator it =
1756
              (*_node_data)[ni].heap_index.find(vt);
1757

	
1758
            if (it != (*_node_data)[ni].heap_index.end()) {
1759
              if ((*_node_data)[ni].heap[it->second] > rw) {
1760
                (*_node_data)[ni].heap.replace(it->second, e);
1761
                (*_node_data)[ni].heap.decrease(e, rw);
1762
                it->second = e;
1763
              }
1764
            } else {
1765
              (*_node_data)[ni].heap.push(e, rw);
1766
              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
1767
            }
1768
          }
1769
        }
1770
            
1771
        if (!(*_node_data)[ni].heap.empty()) {
1772
          _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1773
          _delta2->push(nb, _blossom_set->classPrio(nb));
1774
        }
1775
      }
1776
    }
1777

	
1628 1778
    /// \brief Start the algorithm
1629 1779
    ///
1630 1780
    /// This function starts the algorithm.
1631 1781
    ///
1632
    /// \pre \ref init() must be called before using this function.
1782
    /// \pre \ref init() or \ref fractionalInit() must be called
1783
    /// before using this function.
1633 1784
    void start() {
1634 1785
      enum OpType {
1635 1786
        D1, D2, D3, D4
1636 1787
      };
1637 1788

	
1638
      int unmatched = _node_num;
1639
      while (unmatched > 0) {
1789
      while (_unmatched > 0) {
1640 1790
        Value d1 = !_delta1->empty() ?
1641 1791
          _delta1->prio() : std::numeric_limits<Value>::max();
1642 1792

	
1643 1793
        Value d2 = !_delta2->empty() ?
1644 1794
          _delta2->prio() : std::numeric_limits<Value>::max();
1645 1795

	
1646 1796
        Value d3 = !_delta3->empty() ?
1647 1797
          _delta3->prio() : std::numeric_limits<Value>::max();
1648 1798

	
1649 1799
        Value d4 = !_delta4->empty() ?
1650 1800
          _delta4->prio() : std::numeric_limits<Value>::max();
1651 1801

	
1652 1802
        _delta_sum = d3; OpType ot = D3;
1653 1803
        if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1654 1804
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1655 1805
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1656 1806

	
1657 1807
        switch (ot) {
1658 1808
        case D1:
1659 1809
          {
1660 1810
            Node n = _delta1->top();
1661 1811
            unmatchNode(n);
1662
            --unmatched;
1812
            --_unmatched;
1663 1813
          }
1664 1814
          break;
1665 1815
        case D2:
1666 1816
          {
1667 1817
            int blossom = _delta2->top();
1668 1818
            Node n = _blossom_set->classTop(blossom);
1669 1819
            Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
1670 1820
            if ((*_blossom_data)[blossom].next == INVALID) {
1671 1821
              augmentOnArc(a);
1672
              --unmatched;
1822
              --_unmatched;
1673 1823
            } else {
1674 1824
              extendOnArc(a);
1675 1825
            }
1676 1826
          }
1677 1827
          break;
1678 1828
        case D3:
1679 1829
          {
1680 1830
            Edge e = _delta3->top();
1681 1831

	
1682 1832
            int left_blossom = _blossom_set->find(_graph.u(e));
1683 1833
            int right_blossom = _blossom_set->find(_graph.v(e));
1684 1834

	
1685 1835
            if (left_blossom == right_blossom) {
1686 1836
              _delta3->pop();
1687 1837
            } else {
1688 1838
              int left_tree = _tree_set->find(left_blossom);
1689 1839
              int right_tree = _tree_set->find(right_blossom);
1690 1840

	
1691 1841
              if (left_tree == right_tree) {
1692 1842
                shrinkOnEdge(e, left_tree);
1693 1843
              } else {
1694 1844
                augmentOnEdge(e);
1695
                unmatched -= 2;
1845
                _unmatched -= 2;
1696 1846
              }
1697 1847
            }
1698 1848
          } break;
1699 1849
        case D4:
1700 1850
          splitBlossom(_delta4->top());
1701 1851
          break;
1702 1852
        }
1703 1853
      }
1704 1854
      extractMatching();
1705 1855
    }
1706 1856

	
1707 1857
    /// \brief Run the algorithm.
1708 1858
    ///
1709 1859
    /// This method runs the \c %MaxWeightedMatching algorithm.
1710 1860
    ///
1711 1861
    /// \note mwm.run() is just a shortcut of the following code.
1712 1862
    /// \code
1713
    ///   mwm.init();
1863
    ///   mwm.fractionalInit();
1714 1864
    ///   mwm.start();
1715 1865
    /// \endcode
1716 1866
    void run() {
1717
      init();
1867
      fractionalInit();
1718 1868
      start();
1719 1869
    }
1720 1870

	
1721 1871
    /// @}
1722 1872

	
1723 1873
    /// \name Primal Solution
1724 1874
    /// Functions to get the primal solution, i.e. the maximum weighted
1725 1875
    /// matching.\n
1726 1876
    /// Either \ref run() or \ref start() function should be called before
1727 1877
    /// using them.
1728 1878

	
1729 1879
    /// @{
1730 1880

	
1731 1881
    /// \brief Return the weight of the matching.
1732 1882
    ///
1733 1883
    /// This function returns the weight of the found matching.
1734 1884
    ///
1735 1885
    /// \pre Either run() or start() must be called before using this function.
1736 1886
    Value matchingWeight() const {
1737 1887
      Value sum = 0;
1738 1888
      for (NodeIt n(_graph); n != INVALID; ++n) {
1739 1889
        if ((*_matching)[n] != INVALID) {
1740 1890
          sum += _weight[(*_matching)[n]];
1741 1891
        }
1742 1892
      }
1743 1893
      return sum / 2;
1744 1894
    }
1745 1895

	
1746 1896
    /// \brief Return the size (cardinality) of the matching.
1747 1897
    ///
1748 1898
    /// This function returns the size (cardinality) of the found matching.
1749 1899
    ///
1750 1900
    /// \pre Either run() or start() must be called before using this function.
1751 1901
    int matchingSize() const {
1752 1902
      int num = 0;
1753 1903
      for (NodeIt n(_graph); n != INVALID; ++n) {
1754 1904
        if ((*_matching)[n] != INVALID) {
1755 1905
          ++num;
1756 1906
        }
1757 1907
      }
1758 1908
      return num /= 2;
1759 1909
    }
1760 1910

	
1761 1911
    /// \brief Return \c true if the given edge is in the matching.
1762 1912
    ///
1763 1913
    /// This function returns \c true if the given edge is in the found
1764 1914
    /// matching.
1765 1915
    ///
1766 1916
    /// \pre Either run() or start() must be called before using this function.
1767 1917
    bool matching(const Edge& edge) const {
1768 1918
      return edge == (*_matching)[_graph.u(edge)];
1769 1919
    }
1770 1920

	
1771 1921
    /// \brief Return the matching arc (or edge) incident to the given node.
1772 1922
    ///
1773 1923
    /// This function returns the matching arc (or edge) incident to the
1774 1924
    /// given node in the found matching or \c INVALID if the node is
1775 1925
    /// not covered by the matching.
1776 1926
    ///
1777 1927
    /// \pre Either run() or start() must be called before using this function.
1778 1928
    Arc matching(const Node& node) const {
1779 1929
      return (*_matching)[node];
1780 1930
    }
1781 1931

	
1782 1932
    /// \brief Return a const reference to the matching map.
1783 1933
    ///
1784 1934
    /// This function returns a const reference to a node map that stores
1785 1935
    /// the matching arc (or edge) incident to each node.
1786 1936
    const MatchingMap& matchingMap() const {
1787 1937
      return *_matching;
1788 1938
    }
1789 1939

	
1790 1940
    /// \brief Return the mate of the given node.
1791 1941
    ///
1792 1942
    /// This function returns the mate of the given node in the found
1793 1943
    /// matching or \c INVALID if the node is not covered by the matching.
1794 1944
    ///
1795 1945
    /// \pre Either run() or start() must be called before using this function.
1796 1946
    Node mate(const Node& node) const {
1797 1947
      return (*_matching)[node] != INVALID ?
1798 1948
        _graph.target((*_matching)[node]) : INVALID;
1799 1949
    }
1800 1950

	
1801 1951
    /// @}
1802 1952

	
1803 1953
    /// \name Dual Solution
1804 1954
    /// Functions to get the dual solution.\n
1805 1955
    /// Either \ref run() or \ref start() function should be called before
1806 1956
    /// using them.
1807 1957

	
1808 1958
    /// @{
1809 1959

	
1810 1960
    /// \brief Return the value of the dual solution.
1811 1961
    ///
1812 1962
    /// This function returns the value of the dual solution.
1813 1963
    /// It should be equal to the primal value scaled by \ref dualScale
1814 1964
    /// "dual scale".
1815 1965
    ///
1816 1966
    /// \pre Either run() or start() must be called before using this function.
1817 1967
    Value dualValue() const {
1818 1968
      Value sum = 0;
1819 1969
      for (NodeIt n(_graph); n != INVALID; ++n) {
1820 1970
        sum += nodeValue(n);
1821 1971
      }
1822 1972
      for (int i = 0; i < blossomNum(); ++i) {
1823 1973
        sum += blossomValue(i) * (blossomSize(i) / 2);
1824 1974
      }
1825 1975
      return sum;
1826 1976
    }
1827 1977

	
1828 1978
    /// \brief Return the dual value (potential) of the given node.
1829 1979
    ///
1830 1980
    /// This function returns the dual value (potential) of the given node.
1831 1981
    ///
1832 1982
    /// \pre Either run() or start() must be called before using this function.
1833 1983
    Value nodeValue(const Node& n) const {
1834 1984
      return (*_node_potential)[n];
1835 1985
    }
1836 1986

	
1837 1987
    /// \brief Return the number of the blossoms in the basis.
1838 1988
    ///
1839 1989
    /// This function returns the number of the blossoms in the basis.
1840 1990
    ///
1841 1991
    /// \pre Either run() or start() must be called before using this function.
1842 1992
    /// \see BlossomIt
1843 1993
    int blossomNum() const {
1844 1994
      return _blossom_potential.size();
1845 1995
    }
1846 1996

	
1847 1997
    /// \brief Return the number of the nodes in the given blossom.
1848 1998
    ///
1849 1999
    /// This function returns the number of the nodes in the given blossom.
1850 2000
    ///
1851 2001
    /// \pre Either run() or start() must be called before using this function.
1852 2002
    /// \see BlossomIt
1853 2003
    int blossomSize(int k) const {
1854 2004
      return _blossom_potential[k].end - _blossom_potential[k].begin;
1855 2005
    }
1856 2006

	
1857 2007
    /// \brief Return the dual value (ptential) of the given blossom.
1858 2008
    ///
1859 2009
    /// This function returns the dual value (ptential) of the given blossom.
1860 2010
    ///
1861 2011
    /// \pre Either run() or start() must be called before using this function.
1862 2012
    Value blossomValue(int k) const {
1863 2013
      return _blossom_potential[k].value;
1864 2014
    }
1865 2015

	
1866 2016
    /// \brief Iterator for obtaining the nodes of a blossom.
1867 2017
    ///
1868 2018
    /// This class provides an iterator for obtaining the nodes of the
1869 2019
    /// given blossom. It lists a subset of the nodes.
1870 2020
    /// Before using this iterator, you must allocate a
1871 2021
    /// MaxWeightedMatching class and execute it.
1872 2022
    class BlossomIt {
1873 2023
    public:
1874 2024

	
1875 2025
      /// \brief Constructor.
1876 2026
      ///
1877 2027
      /// Constructor to get the nodes of the given variable.
1878 2028
      ///
1879 2029
      /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
1880 2030
      /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
1881 2031
      /// called before initializing this iterator.
1882 2032
      BlossomIt(const MaxWeightedMatching& algorithm, int variable)
1883 2033
        : _algorithm(&algorithm)
1884 2034
      {
1885 2035
        _index = _algorithm->_blossom_potential[variable].begin;
1886 2036
        _last = _algorithm->_blossom_potential[variable].end;
1887 2037
      }
1888 2038

	
1889 2039
      /// \brief Conversion to \c Node.
1890 2040
      ///
1891 2041
      /// Conversion to \c Node.
1892 2042
      operator Node() const {
1893 2043
        return _algorithm->_blossom_node_list[_index];
1894 2044
      }
1895 2045

	
1896 2046
      /// \brief Increment operator.
1897 2047
      ///
1898 2048
      /// Increment operator.
1899 2049
      BlossomIt& operator++() {
1900 2050
        ++_index;
1901 2051
        return *this;
1902 2052
      }
1903 2053

	
1904 2054
      /// \brief Validity checking
1905 2055
      ///
1906 2056
      /// Checks whether the iterator is invalid.
1907 2057
      bool operator==(Invalid) const { return _index == _last; }
1908 2058

	
1909 2059
      /// \brief Validity checking
1910 2060
      ///
1911 2061
      /// Checks whether the iterator is valid.
1912 2062
      bool operator!=(Invalid) const { return _index != _last; }
1913 2063

	
1914 2064
    private:
1915 2065
      const MaxWeightedMatching* _algorithm;
1916 2066
      int _last;
1917 2067
      int _index;
1918 2068
    };
1919 2069

	
1920 2070
    /// @}
1921 2071

	
1922 2072
  };
1923 2073

	
1924 2074
  /// \ingroup matching
1925 2075
  ///
1926 2076
  /// \brief Weighted perfect matching in general graphs
1927 2077
  ///
1928 2078
  /// This class provides an efficient implementation of Edmond's
1929 2079
  /// maximum weighted perfect matching algorithm. The implementation
1930 2080
  /// is based on extensive use of priority queues and provides
1931 2081
  /// \f$O(nm\log n)\f$ time complexity.
1932 2082
  ///
1933 2083
  /// The maximum weighted perfect matching problem is to find a subset of
1934 2084
  /// the edges in an undirected graph with maximum overall weight for which
1935 2085
  /// each node has exactly one incident edge.
1936 2086
  /// It can be formulated with the following linear program.
1937 2087
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1938 2088
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
1939 2089
      \quad \forall B\in\mathcal{O}\f] */
1940 2090
  /// \f[x_e \ge 0\quad \forall e\in E\f]
1941 2091
  /// \f[\max \sum_{e\in E}x_ew_e\f]
1942 2092
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1943 2093
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
1944 2094
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
1945 2095
  /// subsets of the nodes.
1946 2096
  ///
1947 2097
  /// The algorithm calculates an optimal matching and a proof of the
1948 2098
  /// optimality. The solution of the dual problem can be used to check
1949 2099
  /// the result of the algorithm. The dual linear problem is the
1950 2100
  /// following.
1951 2101
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
1952 2102
      w_{uv} \quad \forall uv\in E\f] */
1953 2103
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
1954 2104
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
1955 2105
      \frac{\vert B \vert - 1}{2}z_B\f] */
1956 2106
  ///
1957 2107
  /// The algorithm can be executed with the run() function.
1958 2108
  /// After it the matching (the primal solution) and the dual solution
1959 2109
  /// can be obtained using the query functions and the
1960 2110
  /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
1961 2111
  /// which is able to iterate on the nodes of a blossom.
1962 2112
  /// If the value type is integer, then the dual solution is multiplied
1963 2113
  /// by \ref MaxWeightedMatching::dualScale "4".
1964 2114
  ///
1965 2115
  /// \tparam GR The undirected graph type the algorithm runs on.
1966 2116
  /// \tparam WM The type edge weight map. The default type is
1967 2117
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
1968 2118
#ifdef DOXYGEN
1969 2119
  template <typename GR, typename WM>
1970 2120
#else
1971 2121
  template <typename GR,
1972 2122
            typename WM = typename GR::template EdgeMap<int> >
1973 2123
#endif
1974 2124
  class MaxWeightedPerfectMatching {
1975 2125
  public:
1976 2126

	
1977 2127
    /// The graph type of the algorithm
1978 2128
    typedef GR Graph;
1979 2129
    /// The type of the edge weight map
1980 2130
    typedef WM WeightMap;
1981 2131
    /// The value type of the edge weights
1982 2132
    typedef typename WeightMap::Value Value;
1983 2133

	
1984 2134
    /// \brief Scaling factor for dual solution
1985 2135
    ///
1986 2136
    /// Scaling factor for dual solution, it is equal to 4 or 1
1987 2137
    /// according to the value type.
1988 2138
    static const int dualScale =
1989 2139
      std::numeric_limits<Value>::is_integer ? 4 : 1;
1990 2140

	
1991 2141
    /// The type of the matching map
1992 2142
    typedef typename Graph::template NodeMap<typename Graph::Arc>
1993 2143
    MatchingMap;
1994 2144

	
1995 2145
  private:
1996 2146

	
1997 2147
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1998 2148

	
1999 2149
    typedef typename Graph::template NodeMap<Value> NodePotential;
2000 2150
    typedef std::vector<Node> BlossomNodeList;
2001 2151

	
2002 2152
    struct BlossomVariable {
2003 2153
      int begin, end;
2004 2154
      Value value;
2005 2155

	
2006 2156
      BlossomVariable(int _begin, int _end, Value _value)
2007 2157
        : begin(_begin), end(_end), value(_value) {}
2008 2158

	
2009 2159
    };
2010 2160

	
2011 2161
    typedef std::vector<BlossomVariable> BlossomPotential;
2012 2162

	
2013 2163
    const Graph& _graph;
2014 2164
    const WeightMap& _weight;
2015 2165

	
2016 2166
    MatchingMap* _matching;
2017 2167

	
2018 2168
    NodePotential* _node_potential;
2019 2169

	
2020 2170
    BlossomPotential _blossom_potential;
2021 2171
    BlossomNodeList _blossom_node_list;
2022 2172

	
2023 2173
    int _node_num;
2024 2174
    int _blossom_num;
2025 2175

	
2026 2176
    typedef RangeMap<int> IntIntMap;
2027 2177

	
2028 2178
    enum Status {
2029 2179
      EVEN = -1, MATCHED = 0, ODD = 1
2030 2180
    };
2031 2181

	
2032 2182
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2033 2183
    struct BlossomData {
2034 2184
      int tree;
2035 2185
      Status status;
2036 2186
      Arc pred, next;
2037 2187
      Value pot, offset;
2038 2188
    };
2039 2189

	
2040 2190
    IntNodeMap *_blossom_index;
2041 2191
    BlossomSet *_blossom_set;
2042 2192
    RangeMap<BlossomData>* _blossom_data;
2043 2193

	
2044 2194
    IntNodeMap *_node_index;
2045 2195
    IntArcMap *_node_heap_index;
2046 2196

	
2047 2197
    struct NodeData {
2048 2198

	
2049 2199
      NodeData(IntArcMap& node_heap_index)
2050 2200
        : heap(node_heap_index) {}
2051 2201

	
2052 2202
      int blossom;
2053 2203
      Value pot;
2054 2204
      BinHeap<Value, IntArcMap> heap;
2055 2205
      std::map<int, Arc> heap_index;
2056 2206

	
2057 2207
      int tree;
2058 2208
    };
2059 2209

	
2060 2210
    RangeMap<NodeData>* _node_data;
2061 2211

	
2062 2212
    typedef ExtendFindEnum<IntIntMap> TreeSet;
2063 2213

	
2064 2214
    IntIntMap *_tree_set_index;
2065 2215
    TreeSet *_tree_set;
2066 2216

	
2067 2217
    IntIntMap *_delta2_index;
2068 2218
    BinHeap<Value, IntIntMap> *_delta2;
2069 2219

	
2070 2220
    IntEdgeMap *_delta3_index;
2071 2221
    BinHeap<Value, IntEdgeMap> *_delta3;
2072 2222

	
2073 2223
    IntIntMap *_delta4_index;
2074 2224
    BinHeap<Value, IntIntMap> *_delta4;
2075 2225

	
2076 2226
    Value _delta_sum;
2227
    int _unmatched;
2228

	
2229
    typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap> 
2230
    FractionalMatching;
2231
    FractionalMatching *_fractional;
2077 2232

	
2078 2233
    void createStructures() {
2079 2234
      _node_num = countNodes(_graph);
2080 2235
      _blossom_num = _node_num * 3 / 2;
2081 2236

	
2082 2237
      if (!_matching) {
2083 2238
        _matching = new MatchingMap(_graph);
2084 2239
      }
2085 2240
      if (!_node_potential) {
2086 2241
        _node_potential = new NodePotential(_graph);
2087 2242
      }
2088 2243
      if (!_blossom_set) {
2089 2244
        _blossom_index = new IntNodeMap(_graph);
2090 2245
        _blossom_set = new BlossomSet(*_blossom_index);
2091 2246
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2092 2247
      }
2093 2248

	
2094 2249
      if (!_node_index) {
2095 2250
        _node_index = new IntNodeMap(_graph);
2096 2251
        _node_heap_index = new IntArcMap(_graph);
2097 2252
        _node_data = new RangeMap<NodeData>(_node_num,
2098 2253
                                            NodeData(*_node_heap_index));
2099 2254
      }
2100 2255

	
2101 2256
      if (!_tree_set) {
2102 2257
        _tree_set_index = new IntIntMap(_blossom_num);
2103 2258
        _tree_set = new TreeSet(*_tree_set_index);
2104 2259
      }
2105 2260
      if (!_delta2) {
2106 2261
        _delta2_index = new IntIntMap(_blossom_num);
2107 2262
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2108 2263
      }
2109 2264
      if (!_delta3) {
2110 2265
        _delta3_index = new IntEdgeMap(_graph);
2111 2266
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2112 2267
      }
2113 2268
      if (!_delta4) {
2114 2269
        _delta4_index = new IntIntMap(_blossom_num);
2115 2270
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2116 2271
      }
2117 2272
    }
2118 2273

	
2119 2274
    void destroyStructures() {
2120 2275
      if (_matching) {
2121 2276
        delete _matching;
2122 2277
      }
2123 2278
      if (_node_potential) {
2124 2279
        delete _node_potential;
2125 2280
      }
2126 2281
      if (_blossom_set) {
2127 2282
        delete _blossom_index;
2128 2283
        delete _blossom_set;
2129 2284
        delete _blossom_data;
2130 2285
      }
2131 2286

	
2132 2287
      if (_node_index) {
2133 2288
        delete _node_index;
2134 2289
        delete _node_heap_index;
2135 2290
        delete _node_data;
2136 2291
      }
2137 2292

	
2138 2293
      if (_tree_set) {
2139 2294
        delete _tree_set_index;
2140 2295
        delete _tree_set;
2141 2296
      }
2142 2297
      if (_delta2) {
2143 2298
        delete _delta2_index;
2144 2299
        delete _delta2;
2145 2300
      }
2146 2301
      if (_delta3) {
2147 2302
        delete _delta3_index;
2148 2303
        delete _delta3;
2149 2304
      }
2150 2305
      if (_delta4) {
2151 2306
        delete _delta4_index;
2152 2307
        delete _delta4;
2153 2308
      }
2154 2309
    }
2155 2310

	
2156 2311
    void matchedToEven(int blossom, int tree) {
2157 2312
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2158 2313
        _delta2->erase(blossom);
2159 2314
      }
2160 2315

	
2161 2316
      if (!_blossom_set->trivial(blossom)) {
2162 2317
        (*_blossom_data)[blossom].pot -=
2163 2318
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2164 2319
      }
2165 2320

	
2166 2321
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2167 2322
           n != INVALID; ++n) {
2168 2323

	
2169 2324
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2170 2325
        int ni = (*_node_index)[n];
2171 2326

	
2172 2327
        (*_node_data)[ni].heap.clear();
2173 2328
        (*_node_data)[ni].heap_index.clear();
2174 2329

	
2175 2330
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2176 2331

	
2177 2332
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2178 2333
          Node v = _graph.source(e);
2179 2334
          int vb = _blossom_set->find(v);
2180 2335
          int vi = (*_node_index)[v];
2181 2336

	
2182 2337
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2183 2338
            dualScale * _weight[e];
2184 2339

	
2185 2340
          if ((*_blossom_data)[vb].status == EVEN) {
2186 2341
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2187 2342
              _delta3->push(e, rw / 2);
2188 2343
            }
2189 2344
          } else {
2190 2345
            typename std::map<int, Arc>::iterator it =
2191 2346
              (*_node_data)[vi].heap_index.find(tree);
2192 2347

	
2193 2348
            if (it != (*_node_data)[vi].heap_index.end()) {
2194 2349
              if ((*_node_data)[vi].heap[it->second] > rw) {
2195 2350
                (*_node_data)[vi].heap.replace(it->second, e);
2196 2351
                (*_node_data)[vi].heap.decrease(e, rw);
2197 2352
                it->second = e;
2198 2353
              }
2199 2354
            } else {
2200 2355
              (*_node_data)[vi].heap.push(e, rw);
2201 2356
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2202 2357
            }
2203 2358

	
2204 2359
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2205 2360
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2206 2361

	
2207 2362
              if ((*_blossom_data)[vb].status == MATCHED) {
2208 2363
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2209 2364
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2210 2365
                               (*_blossom_data)[vb].offset);
2211 2366
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2212 2367
                           (*_blossom_data)[vb].offset){
2213 2368
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2214 2369
                                   (*_blossom_data)[vb].offset);
2215 2370
                }
2216 2371
              }
2217 2372
            }
2218 2373
          }
2219 2374
        }
2220 2375
      }
2221 2376
      (*_blossom_data)[blossom].offset = 0;
2222 2377
    }
2223 2378

	
2224 2379
    void matchedToOdd(int blossom) {
2225 2380
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2226 2381
        _delta2->erase(blossom);
2227 2382
      }
2228 2383
      (*_blossom_data)[blossom].offset += _delta_sum;
2229 2384
      if (!_blossom_set->trivial(blossom)) {
2230 2385
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2231 2386
                     (*_blossom_data)[blossom].offset);
2232 2387
      }
2233 2388
    }
2234 2389

	
2235 2390
    void evenToMatched(int blossom, int tree) {
2236 2391
      if (!_blossom_set->trivial(blossom)) {
2237 2392
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2238 2393
      }
2239 2394

	
2240 2395
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2241 2396
           n != INVALID; ++n) {
2242 2397
        int ni = (*_node_index)[n];
2243 2398
        (*_node_data)[ni].pot -= _delta_sum;
2244 2399

	
2245 2400
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2246 2401
          Node v = _graph.source(e);
2247 2402
          int vb = _blossom_set->find(v);
2248 2403
          int vi = (*_node_index)[v];
2249 2404

	
2250 2405
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2251 2406
            dualScale * _weight[e];
2252 2407

	
2253 2408
          if (vb == blossom) {
2254 2409
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2255 2410
              _delta3->erase(e);
2256 2411
            }
2257 2412
          } else if ((*_blossom_data)[vb].status == EVEN) {
2258 2413

	
2259 2414
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2260 2415
              _delta3->erase(e);
2261 2416
            }
2262 2417

	
2263 2418
            int vt = _tree_set->find(vb);
2264 2419

	
2265 2420
            if (vt != tree) {
2266 2421

	
2267 2422
              Arc r = _graph.oppositeArc(e);
2268 2423

	
2269 2424
              typename std::map<int, Arc>::iterator it =
2270 2425
                (*_node_data)[ni].heap_index.find(vt);
2271 2426

	
2272 2427
              if (it != (*_node_data)[ni].heap_index.end()) {
2273 2428
                if ((*_node_data)[ni].heap[it->second] > rw) {
2274 2429
                  (*_node_data)[ni].heap.replace(it->second, r);
2275 2430
                  (*_node_data)[ni].heap.decrease(r, rw);
2276 2431
                  it->second = r;
2277 2432
                }
2278 2433
              } else {
2279 2434
                (*_node_data)[ni].heap.push(r, rw);
2280 2435
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2281 2436
              }
2282 2437

	
2283 2438
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2284 2439
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2285 2440

	
2286 2441
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2287 2442
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2288 2443
                               (*_blossom_data)[blossom].offset);
2289 2444
                } else if ((*_delta2)[blossom] >
2290 2445
                           _blossom_set->classPrio(blossom) -
2291 2446
                           (*_blossom_data)[blossom].offset){
2292 2447
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2293 2448
                                   (*_blossom_data)[blossom].offset);
2294 2449
                }
2295 2450
              }
2296 2451
            }
2297 2452
          } else {
2298 2453

	
2299 2454
            typename std::map<int, Arc>::iterator it =
2300 2455
              (*_node_data)[vi].heap_index.find(tree);
2301 2456

	
2302 2457
            if (it != (*_node_data)[vi].heap_index.end()) {
2303 2458
              (*_node_data)[vi].heap.erase(it->second);
2304 2459
              (*_node_data)[vi].heap_index.erase(it);
2305 2460
              if ((*_node_data)[vi].heap.empty()) {
2306 2461
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
2307 2462
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2308 2463
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2309 2464
              }
2310 2465

	
2311 2466
              if ((*_blossom_data)[vb].status == MATCHED) {
2312 2467
                if (_blossom_set->classPrio(vb) ==
2313 2468
                    std::numeric_limits<Value>::max()) {
2314 2469
                  _delta2->erase(vb);
2315 2470
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2316 2471
                           (*_blossom_data)[vb].offset) {
2317 2472
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
2318 2473
                                   (*_blossom_data)[vb].offset);
2319 2474
                }
2320 2475
              }
2321 2476
            }
2322 2477
          }
2323 2478
        }
2324 2479
      }
2325 2480
    }
2326 2481

	
2327 2482
    void oddToMatched(int blossom) {
2328 2483
      (*_blossom_data)[blossom].offset -= _delta_sum;
2329 2484

	
2330 2485
      if (_blossom_set->classPrio(blossom) !=
2331 2486
          std::numeric_limits<Value>::max()) {
2332 2487
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2333 2488
                       (*_blossom_data)[blossom].offset);
2334 2489
      }
2335 2490

	
2336 2491
      if (!_blossom_set->trivial(blossom)) {
2337 2492
        _delta4->erase(blossom);
2338 2493
      }
2339 2494
    }
2340 2495

	
2341 2496
    void oddToEven(int blossom, int tree) {
2342 2497
      if (!_blossom_set->trivial(blossom)) {
2343 2498
        _delta4->erase(blossom);
2344 2499
        (*_blossom_data)[blossom].pot -=
2345 2500
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2346 2501
      }
2347 2502

	
2348 2503
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2349 2504
           n != INVALID; ++n) {
2350 2505
        int ni = (*_node_index)[n];
2351 2506

	
2352 2507
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2353 2508

	
2354 2509
        (*_node_data)[ni].heap.clear();
2355 2510
        (*_node_data)[ni].heap_index.clear();
2356 2511
        (*_node_data)[ni].pot +=
2357 2512
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
2358 2513

	
2359 2514
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2360 2515
          Node v = _graph.source(e);
2361 2516
          int vb = _blossom_set->find(v);
2362 2517
          int vi = (*_node_index)[v];
2363 2518

	
2364 2519
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2365 2520
            dualScale * _weight[e];
2366 2521

	
2367 2522
          if ((*_blossom_data)[vb].status == EVEN) {
2368 2523
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2369 2524
              _delta3->push(e, rw / 2);
2370 2525
            }
2371 2526
          } else {
2372 2527

	
2373 2528
            typename std::map<int, Arc>::iterator it =
2374 2529
              (*_node_data)[vi].heap_index.find(tree);
2375 2530

	
2376 2531
            if (it != (*_node_data)[vi].heap_index.end()) {
2377 2532
              if ((*_node_data)[vi].heap[it->second] > rw) {
2378 2533
                (*_node_data)[vi].heap.replace(it->second, e);
2379 2534
                (*_node_data)[vi].heap.decrease(e, rw);
2380 2535
                it->second = e;
2381 2536
              }
2382 2537
            } else {
2383 2538
              (*_node_data)[vi].heap.push(e, rw);
2384 2539
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2385 2540
            }
2386 2541

	
2387 2542
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2388 2543
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2389 2544

	
2390 2545
              if ((*_blossom_data)[vb].status == MATCHED) {
2391 2546
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2392 2547
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2393 2548
                               (*_blossom_data)[vb].offset);
2394 2549
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2395 2550
                           (*_blossom_data)[vb].offset) {
2396 2551
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2397 2552
                                   (*_blossom_data)[vb].offset);
2398 2553
                }
2399 2554
              }
2400 2555
            }
2401 2556
          }
2402 2557
        }
2403 2558
      }
2404 2559
      (*_blossom_data)[blossom].offset = 0;
2405 2560
    }
2406 2561

	
2407 2562
    void alternatePath(int even, int tree) {
2408 2563
      int odd;
2409 2564

	
2410 2565
      evenToMatched(even, tree);
2411 2566
      (*_blossom_data)[even].status = MATCHED;
2412 2567

	
2413 2568
      while ((*_blossom_data)[even].pred != INVALID) {
2414 2569
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2415 2570
        (*_blossom_data)[odd].status = MATCHED;
2416 2571
        oddToMatched(odd);
2417 2572
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2418 2573

	
2419 2574
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2420 2575
        (*_blossom_data)[even].status = MATCHED;
2421 2576
        evenToMatched(even, tree);
2422 2577
        (*_blossom_data)[even].next =
2423 2578
          _graph.oppositeArc((*_blossom_data)[odd].pred);
2424 2579
      }
2425 2580

	
2426 2581
    }
2427 2582

	
2428 2583
    void destroyTree(int tree) {
2429 2584
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2430 2585
        if ((*_blossom_data)[b].status == EVEN) {
2431 2586
          (*_blossom_data)[b].status = MATCHED;
2432 2587
          evenToMatched(b, tree);
2433 2588
        } else if ((*_blossom_data)[b].status == ODD) {
2434 2589
          (*_blossom_data)[b].status = MATCHED;
2435 2590
          oddToMatched(b);
2436 2591
        }
2437 2592
      }
2438 2593
      _tree_set->eraseClass(tree);
2439 2594
    }
2440 2595

	
2441 2596
    void augmentOnEdge(const Edge& edge) {
2442 2597

	
2443 2598
      int left = _blossom_set->find(_graph.u(edge));
2444 2599
      int right = _blossom_set->find(_graph.v(edge));
2445 2600

	
2446 2601
      int left_tree = _tree_set->find(left);
2447 2602
      alternatePath(left, left_tree);
2448 2603
      destroyTree(left_tree);
2449 2604

	
2450 2605
      int right_tree = _tree_set->find(right);
2451 2606
      alternatePath(right, right_tree);
2452 2607
      destroyTree(right_tree);
2453 2608

	
2454 2609
      (*_blossom_data)[left].next = _graph.direct(edge, true);
2455 2610
      (*_blossom_data)[right].next = _graph.direct(edge, false);
2456 2611
    }
2457 2612

	
2458 2613
    void extendOnArc(const Arc& arc) {
2459 2614
      int base = _blossom_set->find(_graph.target(arc));
2460 2615
      int tree = _tree_set->find(base);
2461 2616

	
2462 2617
      int odd = _blossom_set->find(_graph.source(arc));
2463 2618
      _tree_set->insert(odd, tree);
2464 2619
      (*_blossom_data)[odd].status = ODD;
2465 2620
      matchedToOdd(odd);
2466 2621
      (*_blossom_data)[odd].pred = arc;
2467 2622

	
2468 2623
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2469 2624
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2470 2625
      _tree_set->insert(even, tree);
2471 2626
      (*_blossom_data)[even].status = EVEN;
2472 2627
      matchedToEven(even, tree);
2473 2628
    }
2474 2629

	
2475 2630
    void shrinkOnEdge(const Edge& edge, int tree) {
2476 2631
      int nca = -1;
2477 2632
      std::vector<int> left_path, right_path;
2478 2633

	
2479 2634
      {
2480 2635
        std::set<int> left_set, right_set;
2481 2636
        int left = _blossom_set->find(_graph.u(edge));
2482 2637
        left_path.push_back(left);
2483 2638
        left_set.insert(left);
2484 2639

	
2485 2640
        int right = _blossom_set->find(_graph.v(edge));
2486 2641
        right_path.push_back(right);
2487 2642
        right_set.insert(right);
2488 2643

	
2489 2644
        while (true) {
2490 2645

	
2491 2646
          if ((*_blossom_data)[left].pred == INVALID) break;
2492 2647

	
2493 2648
          left =
2494 2649
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2495 2650
          left_path.push_back(left);
2496 2651
          left =
2497 2652
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2498 2653
          left_path.push_back(left);
2499 2654

	
2500 2655
          left_set.insert(left);
2501 2656

	
2502 2657
          if (right_set.find(left) != right_set.end()) {
2503 2658
            nca = left;
2504 2659
            break;
2505 2660
          }
2506 2661

	
2507 2662
          if ((*_blossom_data)[right].pred == INVALID) break;
2508 2663

	
2509 2664
          right =
2510 2665
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2511 2666
          right_path.push_back(right);
2512 2667
          right =
2513 2668
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2514 2669
          right_path.push_back(right);
2515 2670

	
2516 2671
          right_set.insert(right);
2517 2672

	
2518 2673
          if (left_set.find(right) != left_set.end()) {
2519 2674
            nca = right;
2520 2675
            break;
2521 2676
          }
2522 2677

	
2523 2678
        }
2524 2679

	
2525 2680
        if (nca == -1) {
2526 2681
          if ((*_blossom_data)[left].pred == INVALID) {
2527 2682
            nca = right;
2528 2683
            while (left_set.find(nca) == left_set.end()) {
2529 2684
              nca =
2530 2685
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2531 2686
              right_path.push_back(nca);
2532 2687
              nca =
2533 2688
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2534 2689
              right_path.push_back(nca);
2535 2690
            }
2536 2691
          } else {
2537 2692
            nca = left;
2538 2693
            while (right_set.find(nca) == right_set.end()) {
2539 2694
              nca =
2540 2695
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2541 2696
              left_path.push_back(nca);
2542 2697
              nca =
2543 2698
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2544 2699
              left_path.push_back(nca);
2545 2700
            }
2546 2701
          }
2547 2702
        }
2548 2703
      }
2549 2704

	
2550 2705
      std::vector<int> subblossoms;
2551 2706
      Arc prev;
2552 2707

	
2553 2708
      prev = _graph.direct(edge, true);
2554 2709
      for (int i = 0; left_path[i] != nca; i += 2) {
2555 2710
        subblossoms.push_back(left_path[i]);
2556 2711
        (*_blossom_data)[left_path[i]].next = prev;
2557 2712
        _tree_set->erase(left_path[i]);
2558 2713

	
2559 2714
        subblossoms.push_back(left_path[i + 1]);
2560 2715
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
2561 2716
        oddToEven(left_path[i + 1], tree);
2562 2717
        _tree_set->erase(left_path[i + 1]);
2563 2718
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2564 2719
      }
2565 2720

	
2566 2721
      int k = 0;
2567 2722
      while (right_path[k] != nca) ++k;
2568 2723

	
2569 2724
      subblossoms.push_back(nca);
2570 2725
      (*_blossom_data)[nca].next = prev;
2571 2726

	
2572 2727
      for (int i = k - 2; i >= 0; i -= 2) {
2573 2728
        subblossoms.push_back(right_path[i + 1]);
2574 2729
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
2575 2730
        oddToEven(right_path[i + 1], tree);
2576 2731
        _tree_set->erase(right_path[i + 1]);
2577 2732

	
2578 2733
        (*_blossom_data)[right_path[i + 1]].next =
2579 2734
          (*_blossom_data)[right_path[i + 1]].pred;
2580 2735

	
2581 2736
        subblossoms.push_back(right_path[i]);
2582 2737
        _tree_set->erase(right_path[i]);
2583 2738
      }
2584 2739

	
2585 2740
      int surface =
2586 2741
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
2587 2742

	
2588 2743
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2589 2744
        if (!_blossom_set->trivial(subblossoms[i])) {
2590 2745
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2591 2746
        }
2592 2747
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
2593 2748
      }
2594 2749

	
2595 2750
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
2596 2751
      (*_blossom_data)[surface].offset = 0;
2597 2752
      (*_blossom_data)[surface].status = EVEN;
2598 2753
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2599 2754
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2600 2755

	
2601 2756
      _tree_set->insert(surface, tree);
2602 2757
      _tree_set->erase(nca);
2603 2758
    }
2604 2759

	
2605 2760
    void splitBlossom(int blossom) {
2606 2761
      Arc next = (*_blossom_data)[blossom].next;
2607 2762
      Arc pred = (*_blossom_data)[blossom].pred;
2608 2763

	
2609 2764
      int tree = _tree_set->find(blossom);
2610 2765

	
2611 2766
      (*_blossom_data)[blossom].status = MATCHED;
2612 2767
      oddToMatched(blossom);
2613 2768
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2614 2769
        _delta2->erase(blossom);
2615 2770
      }
2616 2771

	
2617 2772
      std::vector<int> subblossoms;
2618 2773
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
2619 2774

	
2620 2775
      Value offset = (*_blossom_data)[blossom].offset;
2621 2776
      int b = _blossom_set->find(_graph.source(pred));
2622 2777
      int d = _blossom_set->find(_graph.source(next));
2623 2778

	
2624 2779
      int ib = -1, id = -1;
2625 2780
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2626 2781
        if (subblossoms[i] == b) ib = i;
2627 2782
        if (subblossoms[i] == d) id = i;
2628 2783

	
2629 2784
        (*_blossom_data)[subblossoms[i]].offset = offset;
2630 2785
        if (!_blossom_set->trivial(subblossoms[i])) {
2631 2786
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2632 2787
        }
2633 2788
        if (_blossom_set->classPrio(subblossoms[i]) !=
2634 2789
            std::numeric_limits<Value>::max()) {
2635 2790
          _delta2->push(subblossoms[i],
2636 2791
                        _blossom_set->classPrio(subblossoms[i]) -
2637 2792
                        (*_blossom_data)[subblossoms[i]].offset);
2638 2793
        }
2639 2794
      }
2640 2795

	
2641 2796
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2642 2797
        for (int i = (id + 1) % subblossoms.size();
2643 2798
             i != ib; i = (i + 2) % subblossoms.size()) {
2644 2799
          int sb = subblossoms[i];
2645 2800
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2646 2801
          (*_blossom_data)[sb].next =
2647 2802
            _graph.oppositeArc((*_blossom_data)[tb].next);
2648 2803
        }
2649 2804

	
2650 2805
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2651 2806
          int sb = subblossoms[i];
2652 2807
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2653 2808
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2654 2809

	
2655 2810
          (*_blossom_data)[sb].status = ODD;
2656 2811
          matchedToOdd(sb);
2657 2812
          _tree_set->insert(sb, tree);
2658 2813
          (*_blossom_data)[sb].pred = pred;
2659 2814
          (*_blossom_data)[sb].next =
2660 2815
                           _graph.oppositeArc((*_blossom_data)[tb].next);
2661 2816

	
2662 2817
          pred = (*_blossom_data)[ub].next;
2663 2818

	
2664 2819
          (*_blossom_data)[tb].status = EVEN;
2665 2820
          matchedToEven(tb, tree);
2666 2821
          _tree_set->insert(tb, tree);
2667 2822
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2668 2823
        }
2669 2824

	
2670 2825
        (*_blossom_data)[subblossoms[id]].status = ODD;
2671 2826
        matchedToOdd(subblossoms[id]);
2672 2827
        _tree_set->insert(subblossoms[id], tree);
2673 2828
        (*_blossom_data)[subblossoms[id]].next = next;
2674 2829
        (*_blossom_data)[subblossoms[id]].pred = pred;
2675 2830

	
2676 2831
      } else {
2677 2832

	
2678 2833
        for (int i = (ib + 1) % subblossoms.size();
2679 2834
             i != id; i = (i + 2) % subblossoms.size()) {
2680 2835
          int sb = subblossoms[i];
2681 2836
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2682 2837
          (*_blossom_data)[sb].next =
2683 2838
            _graph.oppositeArc((*_blossom_data)[tb].next);
2684 2839
        }
2685 2840

	
2686 2841
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2687 2842
          int sb = subblossoms[i];
2688 2843
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2689 2844
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2690 2845

	
2691 2846
          (*_blossom_data)[sb].status = ODD;
2692 2847
          matchedToOdd(sb);
2693 2848
          _tree_set->insert(sb, tree);
2694 2849
          (*_blossom_data)[sb].next = next;
2695 2850
          (*_blossom_data)[sb].pred =
2696 2851
            _graph.oppositeArc((*_blossom_data)[tb].next);
2697 2852

	
2698 2853
          (*_blossom_data)[tb].status = EVEN;
2699 2854
          matchedToEven(tb, tree);
2700 2855
          _tree_set->insert(tb, tree);
2701 2856
          (*_blossom_data)[tb].pred =
2702 2857
            (*_blossom_data)[tb].next =
2703 2858
            _graph.oppositeArc((*_blossom_data)[ub].next);
2704 2859
          next = (*_blossom_data)[ub].next;
2705 2860
        }
2706 2861

	
2707 2862
        (*_blossom_data)[subblossoms[ib]].status = ODD;
2708 2863
        matchedToOdd(subblossoms[ib]);
2709 2864
        _tree_set->insert(subblossoms[ib], tree);
2710 2865
        (*_blossom_data)[subblossoms[ib]].next = next;
2711 2866
        (*_blossom_data)[subblossoms[ib]].pred = pred;
2712 2867
      }
2713 2868
      _tree_set->erase(blossom);
2714 2869
    }
2715 2870

	
2716 2871
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2717 2872
      if (_blossom_set->trivial(blossom)) {
2718 2873
        int bi = (*_node_index)[base];
2719 2874
        Value pot = (*_node_data)[bi].pot;
2720 2875

	
2721 2876
        (*_matching)[base] = matching;
2722 2877
        _blossom_node_list.push_back(base);
2723 2878
        (*_node_potential)[base] = pot;
2724 2879
      } else {
2725 2880

	
2726 2881
        Value pot = (*_blossom_data)[blossom].pot;
2727 2882
        int bn = _blossom_node_list.size();
2728 2883

	
2729 2884
        std::vector<int> subblossoms;
2730 2885
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
2731 2886
        int b = _blossom_set->find(base);
2732 2887
        int ib = -1;
2733 2888
        for (int i = 0; i < int(subblossoms.size()); ++i) {
2734 2889
          if (subblossoms[i] == b) { ib = i; break; }
2735 2890
        }
2736 2891

	
2737 2892
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
2738 2893
          int sb = subblossoms[(ib + i) % subblossoms.size()];
2739 2894
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2740 2895

	
2741 2896
          Arc m = (*_blossom_data)[tb].next;
2742 2897
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2743 2898
          extractBlossom(tb, _graph.source(m), m);
2744 2899
        }
2745 2900
        extractBlossom(subblossoms[ib], base, matching);
2746 2901

	
2747 2902
        int en = _blossom_node_list.size();
2748 2903

	
2749 2904
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2750 2905
      }
2751 2906
    }
2752 2907

	
2753 2908
    void extractMatching() {
2754 2909
      std::vector<int> blossoms;
2755 2910
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2756 2911
        blossoms.push_back(c);
2757 2912
      }
2758 2913

	
2759 2914
      for (int i = 0; i < int(blossoms.size()); ++i) {
2760 2915

	
2761 2916
        Value offset = (*_blossom_data)[blossoms[i]].offset;
2762 2917
        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2763 2918
        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2764 2919
             n != INVALID; ++n) {
2765 2920
          (*_node_data)[(*_node_index)[n]].pot -= offset;
2766 2921
        }
2767 2922

	
2768 2923
        Arc matching = (*_blossom_data)[blossoms[i]].next;
2769 2924
        Node base = _graph.source(matching);
2770 2925
        extractBlossom(blossoms[i], base, matching);
2771 2926
      }
2772 2927
    }
2773 2928

	
2774 2929
  public:
2775 2930

	
2776 2931
    /// \brief Constructor
2777 2932
    ///
2778 2933
    /// Constructor.
2779 2934
    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2780 2935
      : _graph(graph), _weight(weight), _matching(0),
2781 2936
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
2782 2937
        _node_num(0), _blossom_num(0),
2783 2938

	
2784 2939
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
2785 2940
        _node_index(0), _node_heap_index(0), _node_data(0),
2786 2941
        _tree_set_index(0), _tree_set(0),
2787 2942

	
2788 2943
        _delta2_index(0), _delta2(0),
2789 2944
        _delta3_index(0), _delta3(0),
2790 2945
        _delta4_index(0), _delta4(0),
2791 2946

	
2792
        _delta_sum() {}
2947
        _delta_sum(), _unmatched(0),
2948

	
2949
        _fractional(0)
2950
    {}
2793 2951

	
2794 2952
    ~MaxWeightedPerfectMatching() {
2795 2953
      destroyStructures();
2954
      if (_fractional) {
2955
        delete _fractional;
2956
      }
2796 2957
    }
2797 2958

	
2798 2959
    /// \name Execution Control
2799 2960
    /// The simplest way to execute the algorithm is to use the
2800 2961
    /// \ref run() member function.
2801 2962

	
2802 2963
    ///@{
2803 2964

	
2804 2965
    /// \brief Initialize the algorithm
2805 2966
    ///
2806 2967
    /// This function initializes the algorithm.
2807 2968
    void init() {
2808 2969
      createStructures();
2809 2970

	
2810 2971
      for (ArcIt e(_graph); e != INVALID; ++e) {
2811 2972
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2812 2973
      }
2813 2974
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2814 2975
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
2815 2976
      }
2816 2977
      for (int i = 0; i < _blossom_num; ++i) {
2817 2978
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
2818 2979
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
2819 2980
      }
2820 2981

	
2982
      _unmatched = _node_num;
2983

	
2821 2984
      int index = 0;
2822 2985
      for (NodeIt n(_graph); n != INVALID; ++n) {
2823 2986
        Value max = - std::numeric_limits<Value>::max();
2824 2987
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2825 2988
          if (_graph.target(e) == n) continue;
2826 2989
          if ((dualScale * _weight[e]) / 2 > max) {
2827 2990
            max = (dualScale * _weight[e]) / 2;
2828 2991
          }
2829 2992
        }
2830 2993
        (*_node_index)[n] = index;
2831 2994
        (*_node_data)[index].pot = max;
2832 2995
        int blossom =
2833 2996
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
2834 2997

	
2835 2998
        _tree_set->insert(blossom);
2836 2999

	
2837 3000
        (*_blossom_data)[blossom].status = EVEN;
2838 3001
        (*_blossom_data)[blossom].pred = INVALID;
2839 3002
        (*_blossom_data)[blossom].next = INVALID;
2840 3003
        (*_blossom_data)[blossom].pot = 0;
2841 3004
        (*_blossom_data)[blossom].offset = 0;
2842 3005
        ++index;
2843 3006
      }
2844 3007
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2845 3008
        int si = (*_node_index)[_graph.u(e)];
2846 3009
        int ti = (*_node_index)[_graph.v(e)];
2847 3010
        if (_graph.u(e) != _graph.v(e)) {
2848 3011
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2849 3012
                            dualScale * _weight[e]) / 2);
2850 3013
        }
2851 3014
      }
2852 3015
    }
2853 3016

	
3017
    /// \brief Initialize the algorithm with fractional matching
3018
    ///
3019
    /// This function initializes the algorithm with a fractional
3020
    /// matching. This initialization is also called jumpstart heuristic.
3021
    void fractionalInit() {
3022
      createStructures();
3023
      
3024
      if (_fractional == 0) {
3025
        _fractional = new FractionalMatching(_graph, _weight, false);
3026
      }
3027
      if (!_fractional->run()) {
3028
        _unmatched = -1;
3029
        return;
3030
      }
3031

	
3032
      for (ArcIt e(_graph); e != INVALID; ++e) {
3033
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3034
      }
3035
      for (EdgeIt e(_graph); e != INVALID; ++e) {
3036
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
3037
      }
3038
      for (int i = 0; i < _blossom_num; ++i) {
3039
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
3040
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
3041
      }
3042

	
3043
      _unmatched = 0;
3044

	
3045
      int index = 0;
3046
      for (NodeIt n(_graph); n != INVALID; ++n) {
3047
        Value pot = _fractional->nodeValue(n);
3048
        (*_node_index)[n] = index;
3049
        (*_node_data)[index].pot = pot;
3050
        int blossom =
3051
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
3052

	
3053
        (*_blossom_data)[blossom].status = MATCHED;
3054
        (*_blossom_data)[blossom].pred = INVALID;
3055
        (*_blossom_data)[blossom].next = _fractional->matching(n);
3056
        (*_blossom_data)[blossom].pot = 0;
3057
        (*_blossom_data)[blossom].offset = 0;
3058
        ++index;
3059
      }
3060

	
3061
      typename Graph::template NodeMap<bool> processed(_graph, false);
3062
      for (NodeIt n(_graph); n != INVALID; ++n) {
3063
        if (processed[n]) continue;
3064
        processed[n] = true;
3065
        if (_fractional->matching(n) == INVALID) continue;
3066
        int num = 1;
3067
        Node v = _graph.target(_fractional->matching(n));
3068
        while (n != v) {
3069
          processed[v] = true;
3070
          v = _graph.target(_fractional->matching(v));
3071
          ++num;
3072
        }
3073

	
3074
        if (num % 2 == 1) {
3075
          std::vector<int> subblossoms(num);
3076

	
3077
          subblossoms[--num] = _blossom_set->find(n);
3078
          v = _graph.target(_fractional->matching(n));
3079
          while (n != v) {
3080
            subblossoms[--num] = _blossom_set->find(v);
3081
            v = _graph.target(_fractional->matching(v));            
3082
          }
3083
          
3084
          int surface = 
3085
            _blossom_set->join(subblossoms.begin(), subblossoms.end());
3086
          (*_blossom_data)[surface].status = EVEN;
3087
          (*_blossom_data)[surface].pred = INVALID;
3088
          (*_blossom_data)[surface].next = INVALID;
3089
          (*_blossom_data)[surface].pot = 0;
3090
          (*_blossom_data)[surface].offset = 0;
3091
          
3092
          _tree_set->insert(surface);
3093
          ++_unmatched;
3094
        }
3095
      }
3096

	
3097
      for (EdgeIt e(_graph); e != INVALID; ++e) {
3098
        int si = (*_node_index)[_graph.u(e)];
3099
        int sb = _blossom_set->find(_graph.u(e));
3100
        int ti = (*_node_index)[_graph.v(e)];
3101
        int tb = _blossom_set->find(_graph.v(e));
3102
        if ((*_blossom_data)[sb].status == EVEN &&
3103
            (*_blossom_data)[tb].status == EVEN && sb != tb) {
3104
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3105
                            dualScale * _weight[e]) / 2);
3106
        }
3107
      }
3108

	
3109
      for (NodeIt n(_graph); n != INVALID; ++n) {
3110
        int nb = _blossom_set->find(n);
3111
        if ((*_blossom_data)[nb].status != MATCHED) continue;
3112
        int ni = (*_node_index)[n];
3113

	
3114
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3115
          Node v = _graph.target(e);
3116
          int vb = _blossom_set->find(v);
3117
          int vi = (*_node_index)[v];
3118

	
3119
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3120
            dualScale * _weight[e];
3121

	
3122
          if ((*_blossom_data)[vb].status == EVEN) {
3123

	
3124
            int vt = _tree_set->find(vb);
3125

	
3126
            typename std::map<int, Arc>::iterator it =
3127
              (*_node_data)[ni].heap_index.find(vt);
3128

	
3129
            if (it != (*_node_data)[ni].heap_index.end()) {
3130
              if ((*_node_data)[ni].heap[it->second] > rw) {
3131
                (*_node_data)[ni].heap.replace(it->second, e);
3132
                (*_node_data)[ni].heap.decrease(e, rw);
3133
                it->second = e;
3134
              }
3135
            } else {
3136
              (*_node_data)[ni].heap.push(e, rw);
3137
              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
3138
            }
3139
          }
3140
        }
3141
            
3142
        if (!(*_node_data)[ni].heap.empty()) {
3143
          _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3144
          _delta2->push(nb, _blossom_set->classPrio(nb));
3145
        }
3146
      }
3147
    }
3148

	
2854 3149
    /// \brief Start the algorithm
2855 3150
    ///
2856 3151
    /// This function starts the algorithm.
2857 3152
    ///
2858
    /// \pre \ref init() must be called before using this function.
3153
    /// \pre \ref init() or \ref fractionalInit() must be called before
3154
    /// using this function.
2859 3155
    bool start() {
2860 3156
      enum OpType {
2861 3157
        D2, D3, D4
2862 3158
      };
2863 3159

	
2864
      int unmatched = _node_num;
2865
      while (unmatched > 0) {
3160
      if (_unmatched == -1) return false;
3161

	
3162
      while (_unmatched > 0) {
2866 3163
        Value d2 = !_delta2->empty() ?
2867 3164
          _delta2->prio() : std::numeric_limits<Value>::max();
2868 3165

	
2869 3166
        Value d3 = !_delta3->empty() ?
2870 3167
          _delta3->prio() : std::numeric_limits<Value>::max();
2871 3168

	
2872 3169
        Value d4 = !_delta4->empty() ?
2873 3170
          _delta4->prio() : std::numeric_limits<Value>::max();
2874 3171

	
2875 3172
        _delta_sum = d3; OpType ot = D3;
2876 3173
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
2877 3174
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2878 3175

	
2879 3176
        if (_delta_sum == std::numeric_limits<Value>::max()) {
2880 3177
          return false;
2881 3178
        }
2882 3179

	
2883 3180
        switch (ot) {
2884 3181
        case D2:
2885 3182
          {
2886 3183
            int blossom = _delta2->top();
2887 3184
            Node n = _blossom_set->classTop(blossom);
2888 3185
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
2889 3186
            extendOnArc(e);
2890 3187
          }
2891 3188
          break;
2892 3189
        case D3:
2893 3190
          {
2894 3191
            Edge e = _delta3->top();
2895 3192

	
2896 3193
            int left_blossom = _blossom_set->find(_graph.u(e));
2897 3194
            int right_blossom = _blossom_set->find(_graph.v(e));
2898 3195

	
2899 3196
            if (left_blossom == right_blossom) {
2900 3197
              _delta3->pop();
2901 3198
            } else {
2902 3199
              int left_tree = _tree_set->find(left_blossom);
2903 3200
              int right_tree = _tree_set->find(right_blossom);
2904 3201

	
2905 3202
              if (left_tree == right_tree) {
2906 3203
                shrinkOnEdge(e, left_tree);
2907 3204
              } else {
2908 3205
                augmentOnEdge(e);
2909
                unmatched -= 2;
3206
                _unmatched -= 2;
2910 3207
              }
2911 3208
            }
2912 3209
          } break;
2913 3210
        case D4:
2914 3211
          splitBlossom(_delta4->top());
2915 3212
          break;
2916 3213
        }
2917 3214
      }
2918 3215
      extractMatching();
2919 3216
      return true;
2920 3217
    }
2921 3218

	
2922 3219
    /// \brief Run the algorithm.
2923 3220
    ///
2924 3221
    /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
2925 3222
    ///
2926 3223
    /// \note mwpm.run() is just a shortcut of the following code.
2927 3224
    /// \code
2928
    ///   mwpm.init();
3225
    ///   mwpm.fractionalInit();
2929 3226
    ///   mwpm.start();
2930 3227
    /// \endcode
2931 3228
    bool run() {
2932
      init();
3229
      fractionalInit();
2933 3230
      return start();
2934 3231
    }
2935 3232

	
2936 3233
    /// @}
2937 3234

	
2938 3235
    /// \name Primal Solution
2939 3236
    /// Functions to get the primal solution, i.e. the maximum weighted
2940 3237
    /// perfect matching.\n
2941 3238
    /// Either \ref run() or \ref start() function should be called before
2942 3239
    /// using them.
2943 3240

	
2944 3241
    /// @{
2945 3242

	
2946 3243
    /// \brief Return the weight of the matching.
2947 3244
    ///
2948 3245
    /// This function returns the weight of the found matching.
2949 3246
    ///
2950 3247
    /// \pre Either run() or start() must be called before using this function.
2951 3248
    Value matchingWeight() const {
2952 3249
      Value sum = 0;
2953 3250
      for (NodeIt n(_graph); n != INVALID; ++n) {
2954 3251
        if ((*_matching)[n] != INVALID) {
2955 3252
          sum += _weight[(*_matching)[n]];
2956 3253
        }
2957 3254
      }
2958 3255
      return sum / 2;
2959 3256
    }
2960 3257

	
2961 3258
    /// \brief Return \c true if the given edge is in the matching.
2962 3259
    ///
2963 3260
    /// This function returns \c true if the given edge is in the found
2964 3261
    /// matching.
2965 3262
    ///
2966 3263
    /// \pre Either run() or start() must be called before using this function.
2967 3264
    bool matching(const Edge& edge) const {
2968 3265
      return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
2969 3266
    }
2970 3267

	
2971 3268
    /// \brief Return the matching arc (or edge) incident to the given node.
2972 3269
    ///
2973 3270
    /// This function returns the matching arc (or edge) incident to the
2974 3271
    /// given node in the found matching or \c INVALID if the node is
2975 3272
    /// not covered by the matching.
2976 3273
    ///
2977 3274
    /// \pre Either run() or start() must be called before using this function.
2978 3275
    Arc matching(const Node& node) const {
2979 3276
      return (*_matching)[node];
2980 3277
    }
2981 3278

	
2982 3279
    /// \brief Return a const reference to the matching map.
2983 3280
    ///
2984 3281
    /// This function returns a const reference to a node map that stores
2985 3282
    /// the matching arc (or edge) incident to each node.
2986 3283
    const MatchingMap& matchingMap() const {
2987 3284
      return *_matching;
2988 3285
    }
2989 3286

	
2990 3287
    /// \brief Return the mate of the given node.
2991 3288
    ///
2992 3289
    /// This function returns the mate of the given node in the found
2993 3290
    /// matching or \c INVALID if the node is not covered by the matching.
2994 3291
    ///
2995 3292
    /// \pre Either run() or start() must be called before using this function.
2996 3293
    Node mate(const Node& node) const {
2997 3294
      return _graph.target((*_matching)[node]);
2998 3295
    }
2999 3296

	
3000 3297
    /// @}
3001 3298

	
3002 3299
    /// \name Dual Solution
3003 3300
    /// Functions to get the dual solution.\n
3004 3301
    /// Either \ref run() or \ref start() function should be called before
3005 3302
    /// using them.
3006 3303

	
3007 3304
    /// @{
3008 3305

	
3009 3306
    /// \brief Return the value of the dual solution.
3010 3307
    ///
3011 3308
    /// This function returns the value of the dual solution.
3012 3309
    /// It should be equal to the primal value scaled by \ref dualScale
3013 3310
    /// "dual scale".
3014 3311
    ///
3015 3312
    /// \pre Either run() or start() must be called before using this function.
3016 3313
    Value dualValue() const {
3017 3314
      Value sum = 0;
3018 3315
      for (NodeIt n(_graph); n != INVALID; ++n) {
3019 3316
        sum += nodeValue(n);
3020 3317
      }
3021 3318
      for (int i = 0; i < blossomNum(); ++i) {
3022 3319
        sum += blossomValue(i) * (blossomSize(i) / 2);
3023 3320
      }
3024 3321
      return sum;
3025 3322
    }
3026 3323

	
3027 3324
    /// \brief Return the dual value (potential) of the given node.
3028 3325
    ///
3029 3326
    /// This function returns the dual value (potential) of the given node.
3030 3327
    ///
3031 3328
    /// \pre Either run() or start() must be called before using this function.
3032 3329
    Value nodeValue(const Node& n) const {
3033 3330
      return (*_node_potential)[n];
3034 3331
    }
3035 3332

	
3036 3333
    /// \brief Return the number of the blossoms in the basis.
3037 3334
    ///
3038 3335
    /// This function returns the number of the blossoms in the basis.
3039 3336
    ///
3040 3337
    /// \pre Either run() or start() must be called before using this function.
3041 3338
    /// \see BlossomIt
3042 3339
    int blossomNum() const {
3043 3340
      return _blossom_potential.size();
3044 3341
    }
3045 3342

	
3046 3343
    /// \brief Return the number of the nodes in the given blossom.
3047 3344
    ///
3048 3345
    /// This function returns the number of the nodes in the given blossom.
3049 3346
    ///
3050 3347
    /// \pre Either run() or start() must be called before using this function.
3051 3348
    /// \see BlossomIt
3052 3349
    int blossomSize(int k) const {
3053 3350
      return _blossom_potential[k].end - _blossom_potential[k].begin;
3054 3351
    }
3055 3352

	
3056 3353
    /// \brief Return the dual value (ptential) of the given blossom.
3057 3354
    ///
3058 3355
    /// This function returns the dual value (ptential) of the given blossom.
3059 3356
    ///
3060 3357
    /// \pre Either run() or start() must be called before using this function.
3061 3358
    Value blossomValue(int k) const {
3062 3359
      return _blossom_potential[k].value;
3063 3360
    }
3064 3361

	
3065 3362
    /// \brief Iterator for obtaining the nodes of a blossom.
3066 3363
    ///
3067 3364
    /// This class provides an iterator for obtaining the nodes of the
3068 3365
    /// given blossom. It lists a subset of the nodes.
3069 3366
    /// Before using this iterator, you must allocate a
3070 3367
    /// MaxWeightedPerfectMatching class and execute it.
3071 3368
    class BlossomIt {
3072 3369
    public:
3073 3370

	
3074 3371
      /// \brief Constructor.
3075 3372
      ///
3076 3373
      /// Constructor to get the nodes of the given variable.
3077 3374
      ///
3078 3375
      /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3079 3376
      /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3080 3377
      /// must be called before initializing this iterator.
3081 3378
      BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3082 3379
        : _algorithm(&algorithm)
3083 3380
      {
3084 3381
        _index = _algorithm->_blossom_potential[variable].begin;
3085 3382
        _last = _algorithm->_blossom_potential[variable].end;
3086 3383
      }
3087 3384

	
3088 3385
      /// \brief Conversion to \c Node.
3089 3386
      ///
3090 3387
      /// Conversion to \c Node.
3091 3388
      operator Node() const {
3092 3389
        return _algorithm->_blossom_node_list[_index];
3093 3390
      }
3094 3391

	
3095 3392
      /// \brief Increment operator.
3096 3393
      ///
3097 3394
      /// Increment operator.
3098 3395
      BlossomIt& operator++() {
3099 3396
        ++_index;
3100 3397
        return *this;
3101 3398
      }
3102 3399

	
3103 3400
      /// \brief Validity checking
3104 3401
      ///
3105 3402
      /// This function checks whether the iterator is invalid.
3106 3403
      bool operator==(Invalid) const { return _index == _last; }
3107 3404

	
3108 3405
      /// \brief Validity checking
3109 3406
      ///
3110 3407
      /// This function checks whether the iterator is valid.
3111 3408
      bool operator!=(Invalid) const { return _index != _last; }
3112 3409

	
3113 3410
    private:
3114 3411
      const MaxWeightedPerfectMatching* _algorithm;
3115 3412
      int _last;
3116 3413
      int _index;
3117 3414
    };
3118 3415

	
3119 3416
    /// @}
3120 3417

	
3121 3418
  };
3122 3419

	
3123 3420
} //END OF NAMESPACE LEMON
3124 3421

	
3125 3422
#endif //LEMON_MATCHING_H
Ignore white space 768 line context
... ...
@@ -20,405 +20,429 @@
20 20
#include <sstream>
21 21
#include <vector>
22 22
#include <queue>
23 23
#include <cstdlib>
24 24

	
25 25
#include <lemon/matching.h>
26 26
#include <lemon/smart_graph.h>
27 27
#include <lemon/concepts/graph.h>
28 28
#include <lemon/concepts/maps.h>
29 29
#include <lemon/lgf_reader.h>
30 30
#include <lemon/math.h>
31 31

	
32 32
#include "test_tools.h"
33 33

	
34 34
using namespace std;
35 35
using namespace lemon;
36 36

	
37 37
GRAPH_TYPEDEFS(SmartGraph);
38 38

	
39 39

	
40 40
const int lgfn = 3;
41 41
const std::string lgf[lgfn] = {
42 42
  "@nodes\n"
43 43
  "label\n"
44 44
  "0\n"
45 45
  "1\n"
46 46
  "2\n"
47 47
  "3\n"
48 48
  "4\n"
49 49
  "5\n"
50 50
  "6\n"
51 51
  "7\n"
52 52
  "@edges\n"
53 53
  "     label  weight\n"
54 54
  "7 4  0      984\n"
55 55
  "0 7  1      73\n"
56 56
  "7 1  2      204\n"
57 57
  "2 3  3      583\n"
58 58
  "2 7  4      565\n"
59 59
  "2 1  5      582\n"
60 60
  "0 4  6      551\n"
61 61
  "2 5  7      385\n"
62 62
  "1 5  8      561\n"
63 63
  "5 3  9      484\n"
64 64
  "7 5  10     904\n"
65 65
  "3 6  11     47\n"
66 66
  "7 6  12     888\n"
67 67
  "3 0  13     747\n"
68 68
  "6 1  14     310\n",
69 69

	
70 70
  "@nodes\n"
71 71
  "label\n"
72 72
  "0\n"
73 73
  "1\n"
74 74
  "2\n"
75 75
  "3\n"
76 76
  "4\n"
77 77
  "5\n"
78 78
  "6\n"
79 79
  "7\n"
80 80
  "@edges\n"
81 81
  "     label  weight\n"
82 82
  "2 5  0      710\n"
83 83
  "0 5  1      241\n"
84 84
  "2 4  2      856\n"
85 85
  "2 6  3      762\n"
86 86
  "4 1  4      747\n"
87 87
  "6 1  5      962\n"
88 88
  "4 7  6      723\n"
89 89
  "1 7  7      661\n"
90 90
  "2 3  8      376\n"
91 91
  "1 0  9      416\n"
92 92
  "6 7  10     391\n",
93 93

	
94 94
  "@nodes\n"
95 95
  "label\n"
96 96
  "0\n"
97 97
  "1\n"
98 98
  "2\n"
99 99
  "3\n"
100 100
  "4\n"
101 101
  "5\n"
102 102
  "6\n"
103 103
  "7\n"
104 104
  "@edges\n"
105 105
  "     label  weight\n"
106 106
  "6 2  0      553\n"
107 107
  "0 7  1      653\n"
108 108
  "6 3  2      22\n"
109 109
  "4 7  3      846\n"
110 110
  "7 2  4      981\n"
111 111
  "7 6  5      250\n"
112 112
  "5 2  6      539\n",
113 113
};
114 114

	
115 115
void checkMaxMatchingCompile()
116 116
{
117 117
  typedef concepts::Graph Graph;
118 118
  typedef Graph::Node Node;
119 119
  typedef Graph::Edge Edge;
120 120
  typedef Graph::EdgeMap<bool> MatMap;
121 121

	
122 122
  Graph g;
123 123
  Node n;
124 124
  Edge e;
125 125
  MatMap mat(g);
126 126

	
127 127
  MaxMatching<Graph> mat_test(g);
128 128
  const MaxMatching<Graph>&
129 129
    const_mat_test = mat_test;
130 130

	
131 131
  mat_test.init();
132 132
  mat_test.greedyInit();
133 133
  mat_test.matchingInit(mat);
134 134
  mat_test.startSparse();
135 135
  mat_test.startDense();
136 136
  mat_test.run();
137 137
  
138 138
  const_mat_test.matchingSize();
139 139
  const_mat_test.matching(e);
140 140
  const_mat_test.matching(n);
141 141
  const MaxMatching<Graph>::MatchingMap& mmap =
142 142
    const_mat_test.matchingMap();
143 143
  e = mmap[n];
144 144
  const_mat_test.mate(n);
145 145

	
146 146
  MaxMatching<Graph>::Status stat = 
147 147
    const_mat_test.status(n);
148 148
  const MaxMatching<Graph>::StatusMap& smap =
149 149
    const_mat_test.statusMap();
150 150
  stat = smap[n];
151 151
  const_mat_test.barrier(n);
152 152
}
153 153

	
154 154
void checkMaxWeightedMatchingCompile()
155 155
{
156 156
  typedef concepts::Graph Graph;
157 157
  typedef Graph::Node Node;
158 158
  typedef Graph::Edge Edge;
159 159
  typedef Graph::EdgeMap<int> WeightMap;
160 160

	
161 161
  Graph g;
162 162
  Node n;
163 163
  Edge e;
164 164
  WeightMap w(g);
165 165

	
166 166
  MaxWeightedMatching<Graph> mat_test(g, w);
167 167
  const MaxWeightedMatching<Graph>&
168 168
    const_mat_test = mat_test;
169 169

	
170 170
  mat_test.init();
171 171
  mat_test.start();
172 172
  mat_test.run();
173 173
  
174 174
  const_mat_test.matchingWeight();
175 175
  const_mat_test.matchingSize();
176 176
  const_mat_test.matching(e);
177 177
  const_mat_test.matching(n);
178 178
  const MaxWeightedMatching<Graph>::MatchingMap& mmap =
179 179
    const_mat_test.matchingMap();
180 180
  e = mmap[n];
181 181
  const_mat_test.mate(n);
182 182
  
183 183
  int k = 0;
184 184
  const_mat_test.dualValue();
185 185
  const_mat_test.nodeValue(n);
186 186
  const_mat_test.blossomNum();
187 187
  const_mat_test.blossomSize(k);
188 188
  const_mat_test.blossomValue(k);
189 189
}
190 190

	
191 191
void checkMaxWeightedPerfectMatchingCompile()
192 192
{
193 193
  typedef concepts::Graph Graph;
194 194
  typedef Graph::Node Node;
195 195
  typedef Graph::Edge Edge;
196 196
  typedef Graph::EdgeMap<int> WeightMap;
197 197

	
198 198
  Graph g;
199 199
  Node n;
200 200
  Edge e;
201 201
  WeightMap w(g);
202 202

	
203 203
  MaxWeightedPerfectMatching<Graph> mat_test(g, w);
204 204
  const MaxWeightedPerfectMatching<Graph>&
205 205
    const_mat_test = mat_test;
206 206

	
207 207
  mat_test.init();
208 208
  mat_test.start();
209 209
  mat_test.run();
210 210
  
211 211
  const_mat_test.matchingWeight();
212 212
  const_mat_test.matching(e);
213 213
  const_mat_test.matching(n);
214 214
  const MaxWeightedPerfectMatching<Graph>::MatchingMap& mmap =
215 215
    const_mat_test.matchingMap();
216 216
  e = mmap[n];
217 217
  const_mat_test.mate(n);
218 218
  
219 219
  int k = 0;
220 220
  const_mat_test.dualValue();
221 221
  const_mat_test.nodeValue(n);
222 222
  const_mat_test.blossomNum();
223 223
  const_mat_test.blossomSize(k);
224 224
  const_mat_test.blossomValue(k);
225 225
}
226 226

	
227 227
void checkMatching(const SmartGraph& graph,
228 228
                   const MaxMatching<SmartGraph>& mm) {
229 229
  int num = 0;
230 230

	
231 231
  IntNodeMap comp_index(graph);
232 232
  UnionFind<IntNodeMap> comp(comp_index);
233 233

	
234 234
  int barrier_num = 0;
235 235

	
236 236
  for (NodeIt n(graph); n != INVALID; ++n) {
237 237
    check(mm.status(n) == MaxMatching<SmartGraph>::EVEN ||
238 238
          mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
239 239
    if (mm.status(n) == MaxMatching<SmartGraph>::ODD) {
240 240
      ++barrier_num;
241 241
    } else {
242 242
      comp.insert(n);
243 243
    }
244 244
  }
245 245

	
246 246
  for (EdgeIt e(graph); e != INVALID; ++e) {
247 247
    if (mm.matching(e)) {
248 248
      check(e == mm.matching(graph.u(e)), "Wrong matching");
249 249
      check(e == mm.matching(graph.v(e)), "Wrong matching");
250 250
      ++num;
251 251
    }
252 252
    check(mm.status(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
253 253
          mm.status(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
254 254
          "Wrong Gallai-Edmonds decomposition");
255 255

	
256 256
    check(mm.status(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
257 257
          mm.status(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
258 258
          "Wrong Gallai-Edmonds decomposition");
259 259

	
260 260
    if (mm.status(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
261 261
        mm.status(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
262 262
      comp.join(graph.u(e), graph.v(e));
263 263
    }
264 264
  }
265 265

	
266 266
  std::set<int> comp_root;
267 267
  int odd_comp_num = 0;
268 268
  for (NodeIt n(graph); n != INVALID; ++n) {
269 269
    if (mm.status(n) != MaxMatching<SmartGraph>::ODD) {
270 270
      int root = comp.find(n);
271 271
      if (comp_root.find(root) == comp_root.end()) {
272 272
        comp_root.insert(root);
273 273
        if (comp.size(n) % 2 == 1) {
274 274
          ++odd_comp_num;
275 275
        }
276 276
      }
277 277
    }
278 278
  }
279 279

	
280 280
  check(mm.matchingSize() == num, "Wrong matching");
281 281
  check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
282 282
         "Wrong matching");
283 283
  return;
284 284
}
285 285

	
286 286
void checkWeightedMatching(const SmartGraph& graph,
287 287
                   const SmartGraph::EdgeMap<int>& weight,
288 288
                   const MaxWeightedMatching<SmartGraph>& mwm) {
289 289
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
290 290
    if (graph.u(e) == graph.v(e)) continue;
291 291
    int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
292 292

	
293 293
    for (int i = 0; i < mwm.blossomNum(); ++i) {
294 294
      bool s = false, t = false;
295 295
      for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
296 296
           n != INVALID; ++n) {
297 297
        if (graph.u(e) == n) s = true;
298 298
        if (graph.v(e) == n) t = true;
299 299
      }
300 300
      if (s == true && t == true) {
301 301
        rw += mwm.blossomValue(i);
302 302
      }
303 303
    }
304 304
    rw -= weight[e] * mwm.dualScale;
305 305

	
306 306
    check(rw >= 0, "Negative reduced weight");
307 307
    check(rw == 0 || !mwm.matching(e),
308 308
          "Non-zero reduced weight on matching edge");
309 309
  }
310 310

	
311 311
  int pv = 0;
312 312
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
313 313
    if (mwm.matching(n) != INVALID) {
314 314
      check(mwm.nodeValue(n) >= 0, "Invalid node value");
315 315
      pv += weight[mwm.matching(n)];
316 316
      SmartGraph::Node o = graph.target(mwm.matching(n));
317 317
      check(mwm.mate(n) == o, "Invalid matching");
318 318
      check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
319 319
            "Invalid matching");
320 320
    } else {
321 321
      check(mwm.mate(n) == INVALID, "Invalid matching");
322 322
      check(mwm.nodeValue(n) == 0, "Invalid matching");
323 323
    }
324 324
  }
325 325

	
326 326
  int dv = 0;
327 327
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
328 328
    dv += mwm.nodeValue(n);
329 329
  }
330 330

	
331 331
  for (int i = 0; i < mwm.blossomNum(); ++i) {
332 332
    check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
333 333
    check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
334 334
    dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
335 335
  }
336 336

	
337 337
  check(pv * mwm.dualScale == dv * 2, "Wrong duality");
338 338

	
339 339
  return;
340 340
}
341 341

	
342 342
void checkWeightedPerfectMatching(const SmartGraph& graph,
343 343
                          const SmartGraph::EdgeMap<int>& weight,
344 344
                          const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
345 345
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
346 346
    if (graph.u(e) == graph.v(e)) continue;
347 347
    int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
348 348

	
349 349
    for (int i = 0; i < mwpm.blossomNum(); ++i) {
350 350
      bool s = false, t = false;
351 351
      for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
352 352
           n != INVALID; ++n) {
353 353
        if (graph.u(e) == n) s = true;
354 354
        if (graph.v(e) == n) t = true;
355 355
      }
356 356
      if (s == true && t == true) {
357 357
        rw += mwpm.blossomValue(i);
358 358
      }
359 359
    }
360 360
    rw -= weight[e] * mwpm.dualScale;
361 361

	
362 362
    check(rw >= 0, "Negative reduced weight");
363 363
    check(rw == 0 || !mwpm.matching(e),
364 364
          "Non-zero reduced weight on matching edge");
365 365
  }
366 366

	
367 367
  int pv = 0;
368 368
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
369 369
    check(mwpm.matching(n) != INVALID, "Non perfect");
370 370
    pv += weight[mwpm.matching(n)];
371 371
    SmartGraph::Node o = graph.target(mwpm.matching(n));
372 372
    check(mwpm.mate(n) == o, "Invalid matching");
373 373
    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
374 374
          "Invalid matching");
375 375
  }
376 376

	
377 377
  int dv = 0;
378 378
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
379 379
    dv += mwpm.nodeValue(n);
380 380
  }
381 381

	
382 382
  for (int i = 0; i < mwpm.blossomNum(); ++i) {
383 383
    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
384 384
    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
385 385
    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
386 386
  }
387 387

	
388 388
  check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
389 389

	
390 390
  return;
391 391
}
392 392

	
393 393

	
394 394
int main() {
395 395

	
396 396
  for (int i = 0; i < lgfn; ++i) {
397 397
    SmartGraph graph;
398 398
    SmartGraph::EdgeMap<int> weight(graph);
399 399

	
400 400
    istringstream lgfs(lgf[i]);
401 401
    graphReader(graph, lgfs).
402 402
      edgeMap("weight", weight).run();
403 403

	
404
    MaxMatching<SmartGraph> mm(graph);
405
    mm.run();
406
    checkMatching(graph, mm);
404
    bool perfect;
405
    {
406
      MaxMatching<SmartGraph> mm(graph);
407
      mm.run();
408
      checkMatching(graph, mm);
409
      perfect = 2 * mm.matchingSize() == countNodes(graph);
410
    }
407 411

	
408
    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
409
    mwm.run();
410
    checkWeightedMatching(graph, weight, mwm);
412
    {
413
      MaxWeightedMatching<SmartGraph> mwm(graph, weight);
414
      mwm.run();
415
      checkWeightedMatching(graph, weight, mwm);
416
    }
411 417

	
412
    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
413
    bool perfect = mwpm.run();
418
    {
419
      MaxWeightedMatching<SmartGraph> mwm(graph, weight);
420
      mwm.init();
421
      mwm.start();
422
      checkWeightedMatching(graph, weight, mwm);
423
    }
414 424

	
415
    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
416
          "Perfect matching found");
425
    {
426
      MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
427
      bool result = mwpm.run();
428
      
429
      check(result == perfect, "Perfect matching found");
430
      if (perfect) {
431
        checkWeightedPerfectMatching(graph, weight, mwpm);
432
      }
433
    }
417 434

	
418
    if (perfect) {
419
      checkWeightedPerfectMatching(graph, weight, mwpm);
435
    {
436
      MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
437
      mwpm.init();
438
      bool result = mwpm.start();
439
      
440
      check(result == perfect, "Perfect matching found");
441
      if (perfect) {
442
        checkWeightedPerfectMatching(graph, weight, mwpm);
443
      }
420 444
    }
421 445
  }
422 446

	
423 447
  return 0;
424 448
}
0 comments (0 inline)