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

	
19
#ifndef LEMON_MAX_MATCHING_H
20
#define LEMON_MAX_MATCHING_H
21

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

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

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

	
36
namespace lemon {
37

	
38
  /// \ingroup matching
39
  ///
40
  /// \brief Edmonds' alternating forest maximum matching algorithm.
41
  ///
42
  /// This class implements Edmonds' alternating forest matching
43
  /// algorithm. The algorithm can be started from an arbitrary initial
44
  /// matching (the default is the empty one)
45
  ///
46
  /// The dual solution of the problem is a map of the nodes to
47
  /// MaxMatching::Status, having values \c EVEN/D, \c ODD/A and \c
48
  /// MATCHED/C showing the Gallai-Edmonds decomposition of the
49
  /// graph. The nodes in \c EVEN/D induce a graph with
50
  /// factor-critical components, the nodes in \c ODD/A form the
51
  /// barrier, and the nodes in \c MATCHED/C induce a graph having a
52
  /// perfect matching. The number of the factor-critical components
53
  /// minus the number of barrier nodes is a lower bound on the
54
  /// unmatched nodes, and the matching is optimal if and only if this bound is
55
  /// tight. This decomposition can be attained by calling \c
56
  /// decomposition() after running the algorithm.
57
  ///
58
  /// \param _Graph The graph type the algorithm runs on.
59
  template <typename _Graph>
60
  class MaxMatching {
61
  public:
62

	
63
    typedef _Graph Graph;
64
    typedef typename Graph::template NodeMap<typename Graph::Arc>
65
    MatchingMap;
66

	
67
    ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
68
    ///
69
    ///Indicates the Gallai-Edmonds decomposition of the graph. The
70
    ///nodes with Status \c EVEN/D induce a graph with factor-critical
71
    ///components, the nodes in \c ODD/A form the canonical barrier,
72
    ///and the nodes in \c MATCHED/C induce a graph having a perfect
73
    ///matching.
74
    enum Status {
75
      EVEN = 1, D = 1, MATCHED = 0, C = 0, ODD = -1, A = -1, UNMATCHED = -2
76
    };
77

	
78
    typedef typename Graph::template NodeMap<Status> StatusMap;
79

	
80
  private:
81

	
82
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
83

	
84
    typedef UnionFindEnum<IntNodeMap> BlossomSet;
85
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
86
    typedef RangeMap<Node> NodeIntMap;
87
    typedef MatchingMap EarMap;
88
    typedef std::vector<Node> NodeQueue;
89

	
90
    const Graph& _graph;
91
    MatchingMap* _matching;
92
    StatusMap* _status;
93

	
94
    EarMap* _ear;
95

	
96
    IntNodeMap* _blossom_set_index;
97
    BlossomSet* _blossom_set;
98
    NodeIntMap* _blossom_rep;
99

	
100
    IntNodeMap* _tree_set_index;
101
    TreeSet* _tree_set;
102

	
103
    NodeQueue _node_queue;
104
    int _process, _postpone, _last;
105

	
106
    int _node_num;
107

	
108
  private:
109

	
110
    void createStructures() {
111
      _node_num = countNodes(_graph);
112
      if (!_matching) {
113
        _matching = new MatchingMap(_graph);
114
      }
115
      if (!_status) {
116
        _status = new StatusMap(_graph);
117
      }
118
      if (!_ear) {
119
        _ear = new EarMap(_graph);
120
      }
121
      if (!_blossom_set) {
122
        _blossom_set_index = new IntNodeMap(_graph);
123
        _blossom_set = new BlossomSet(*_blossom_set_index);
124
      }
125
      if (!_blossom_rep) {
126
        _blossom_rep = new NodeIntMap(_node_num);
127
      }
128
      if (!_tree_set) {
129
        _tree_set_index = new IntNodeMap(_graph);
130
        _tree_set = new TreeSet(*_tree_set_index);
131
      }
132
      _node_queue.resize(_node_num);
133
    }
134

	
135
    void destroyStructures() {
136
      if (_matching) {
137
        delete _matching;
138
      }
139
      if (_status) {
140
        delete _status;
141
      }
142
      if (_ear) {
143
        delete _ear;
144
      }
145
      if (_blossom_set) {
146
        delete _blossom_set;
147
        delete _blossom_set_index;
148
      }
149
      if (_blossom_rep) {
150
        delete _blossom_rep;
151
      }
152
      if (_tree_set) {
153
        delete _tree_set_index;
154
        delete _tree_set;
155
      }
156
    }
157

	
158
    void processDense(const Node& n) {
159
      _process = _postpone = _last = 0;
160
      _node_queue[_last++] = n;
161

	
162
      while (_process != _last) {
163
        Node u = _node_queue[_process++];
164
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
165
          Node v = _graph.target(a);
166
          if ((*_status)[v] == MATCHED) {
167
            extendOnArc(a);
168
          } else if ((*_status)[v] == UNMATCHED) {
169
            augmentOnArc(a);
170
            return;
171
          }
172
        }
173
      }
174

	
175
      while (_postpone != _last) {
176
        Node u = _node_queue[_postpone++];
177

	
178
        for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
179
          Node v = _graph.target(a);
180

	
181
          if ((*_status)[v] == EVEN) {
182
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
183
              shrinkOnEdge(a);
184
            }
185
          }
186

	
187
          while (_process != _last) {
188
            Node w = _node_queue[_process++];
189
            for (OutArcIt b(_graph, w); b != INVALID; ++b) {
190
              Node x = _graph.target(b);
191
              if ((*_status)[x] == MATCHED) {
192
                extendOnArc(b);
193
              } else if ((*_status)[x] == UNMATCHED) {
194
                augmentOnArc(b);
195
                return;
196
              }
197
            }
198
          }
199
        }
200
      }
201
    }
202

	
203
    void processSparse(const Node& n) {
204
      _process = _last = 0;
205
      _node_queue[_last++] = n;
206
      while (_process != _last) {
207
        Node u = _node_queue[_process++];
208
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
209
          Node v = _graph.target(a);
210

	
211
          if ((*_status)[v] == EVEN) {
212
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
213
              shrinkOnEdge(a);
214
            }
215
          } else if ((*_status)[v] == MATCHED) {
216
            extendOnArc(a);
217
          } else if ((*_status)[v] == UNMATCHED) {
218
            augmentOnArc(a);
219
            return;
220
          }
221
        }
222
      }
223
    }
224

	
225
    void shrinkOnEdge(const Edge& e) {
226
      Node nca = INVALID;
227

	
228
      {
229
        std::set<Node> left_set, right_set;
230

	
231
        Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
232
        left_set.insert(left);
233

	
234
        Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
235
        right_set.insert(right);
236

	
237
        while (true) {
238
          if ((*_matching)[left] == INVALID) break;
239
          left = _graph.target((*_matching)[left]);
240
          left = (*_blossom_rep)[_blossom_set->
241
                                 find(_graph.target((*_ear)[left]))];
242
          if (right_set.find(left) != right_set.end()) {
243
            nca = left;
244
            break;
245
          }
246
          left_set.insert(left);
247

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

	
259
        if (nca == INVALID) {
260
          if ((*_matching)[left] == INVALID) {
261
            nca = right;
262
            while (left_set.find(nca) == left_set.end()) {
263
              nca = _graph.target((*_matching)[nca]);
264
              nca =(*_blossom_rep)[_blossom_set->
265
                                   find(_graph.target((*_ear)[nca]))];
266
            }
267
          } else {
268
            nca = left;
269
            while (right_set.find(nca) == right_set.end()) {
270
              nca = _graph.target((*_matching)[nca]);
271
              nca = (*_blossom_rep)[_blossom_set->
272
                                   find(_graph.target((*_ear)[nca]))];
273
            }
274
          }
275
        }
276
      }
277

	
278
      {
279

	
280
        Node node = _graph.u(e);
281
        Arc arc = _graph.direct(e, true);
282
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
283

	
284
        while (base != nca) {
285
          _ear->set(node, arc);
286

	
287
          Node n = node;
288
          while (n != base) {
289
            n = _graph.target((*_matching)[n]);
290
            Arc a = (*_ear)[n];
291
            n = _graph.target(a);
292
            _ear->set(n, _graph.oppositeArc(a));
293
          }
294
          node = _graph.target((*_matching)[base]);
295
          _tree_set->erase(base);
296
          _tree_set->erase(node);
297
          _blossom_set->insert(node, _blossom_set->find(base));
298
          _status->set(node, EVEN);
299
          _node_queue[_last++] = node;
300
          arc = _graph.oppositeArc((*_ear)[node]);
301
          node = _graph.target((*_ear)[node]);
302
          base = (*_blossom_rep)[_blossom_set->find(node)];
303
          _blossom_set->join(_graph.target(arc), base);
304
        }
305
      }
306

	
307
      _blossom_rep->set(_blossom_set->find(nca), nca);
308

	
309
      {
310

	
311
        Node node = _graph.v(e);
312
        Arc arc = _graph.direct(e, false);
313
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
314

	
315
        while (base != nca) {
316
          _ear->set(node, arc);
317

	
318
          Node n = node;
319
          while (n != base) {
320
            n = _graph.target((*_matching)[n]);
321
            Arc a = (*_ear)[n];
322
            n = _graph.target(a);
323
            _ear->set(n, _graph.oppositeArc(a));
324
          }
325
          node = _graph.target((*_matching)[base]);
326
          _tree_set->erase(base);
327
          _tree_set->erase(node);
328
          _blossom_set->insert(node, _blossom_set->find(base));
329
          _status->set(node, EVEN);
330
          _node_queue[_last++] = node;
331
          arc = _graph.oppositeArc((*_ear)[node]);
332
          node = _graph.target((*_ear)[node]);
333
          base = (*_blossom_rep)[_blossom_set->find(node)];
334
          _blossom_set->join(_graph.target(arc), base);
335
        }
336
      }
337

	
338
      _blossom_rep->set(_blossom_set->find(nca), nca);
339
    }
340

	
341

	
342

	
343
    void extendOnArc(const Arc& a) {
344
      Node base = _graph.source(a);
345
      Node odd = _graph.target(a);
346

	
347
      _ear->set(odd, _graph.oppositeArc(a));
348
      Node even = _graph.target((*_matching)[odd]);
349
      _blossom_rep->set(_blossom_set->insert(even), even);
350
      _status->set(odd, ODD);
351
      _status->set(even, EVEN);
352
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
353
      _tree_set->insert(odd, tree);
354
      _tree_set->insert(even, tree);
355
      _node_queue[_last++] = even;
356

	
357
    }
358

	
359
    void augmentOnArc(const Arc& a) {
360
      Node even = _graph.source(a);
361
      Node odd = _graph.target(a);
362

	
363
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
364

	
365
      _matching->set(odd, _graph.oppositeArc(a));
366
      _status->set(odd, MATCHED);
367

	
368
      Arc arc = (*_matching)[even];
369
      _matching->set(even, a);
370

	
371
      while (arc != INVALID) {
372
        odd = _graph.target(arc);
373
        arc = (*_ear)[odd];
374
        even = _graph.target(arc);
375
        _matching->set(odd, arc);
376
        arc = (*_matching)[even];
377
        _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
378
      }
379

	
380
      for (typename TreeSet::ItemIt it(*_tree_set, tree);
381
           it != INVALID; ++it) {
382
        if ((*_status)[it] == ODD) {
383
          _status->set(it, MATCHED);
384
        } else {
385
          int blossom = _blossom_set->find(it);
386
          for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
387
               jt != INVALID; ++jt) {
388
            _status->set(jt, MATCHED);
389
          }
390
          _blossom_set->eraseClass(blossom);
391
        }
392
      }
393
      _tree_set->eraseClass(tree);
394

	
395
    }
396

	
397
  public:
398

	
399
    /// \brief Constructor
400
    ///
401
    /// Constructor.
402
    MaxMatching(const Graph& graph)
403
      : _graph(graph), _matching(0), _status(0), _ear(0),
404
        _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
405
        _tree_set_index(0), _tree_set(0) {}
406

	
407
    ~MaxMatching() {
408
      destroyStructures();
409
    }
410

	
411
    /// \name Execution control
412
    /// The simplest way to execute the algorithm is to use the
413
    /// \c run() member function.
414
    /// \n
415

	
416
    /// If you need better control on the execution, you must call
417
    /// \ref init(), \ref greedyInit() or \ref matchingInit()
418
    /// functions first, then you can start the algorithm with the \ref
419
    /// startParse() or startDense() functions.
420

	
421
    ///@{
422

	
423
    /// \brief Sets the actual matching to the empty matching.
424
    ///
425
    /// Sets the actual matching to the empty matching.
426
    ///
427
    void init() {
428
      createStructures();
429
      for(NodeIt n(_graph); n != INVALID; ++n) {
430
        _matching->set(n, INVALID);
431
        _status->set(n, UNMATCHED);
432
      }
433
    }
434

	
435
    ///\brief Finds an initial matching in a greedy way
436
    ///
437
    ///It finds an initial matching in a greedy way.
438
    void greedyInit() {
439
      createStructures();
440
      for (NodeIt n(_graph); n != INVALID; ++n) {
441
        _matching->set(n, INVALID);
442
        _status->set(n, UNMATCHED);
443
      }
444
      for (NodeIt n(_graph); n != INVALID; ++n) {
445
        if ((*_matching)[n] == INVALID) {
446
          for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
447
            Node v = _graph.target(a);
448
            if ((*_matching)[v] == INVALID && v != n) {
449
              _matching->set(n, a);
450
              _status->set(n, MATCHED);
451
              _matching->set(v, _graph.oppositeArc(a));
452
              _status->set(v, MATCHED);
453
              break;
454
            }
455
          }
456
        }
457
      }
458
    }
459

	
460

	
461
    /// \brief Initialize the matching from a map containing.
462
    ///
463
    /// Initialize the matching from a \c bool valued \c Edge map. This
464
    /// map must have the property that there are no two incident edges
465
    /// with true value, ie. it contains a matching.
466
    /// \return %True if the map contains a matching.
467
    template <typename MatchingMap>
468
    bool matchingInit(const MatchingMap& matching) {
469
      createStructures();
470

	
471
      for (NodeIt n(_graph); n != INVALID; ++n) {
472
        _matching->set(n, INVALID);
473
        _status->set(n, UNMATCHED);
474
      }
475
      for(EdgeIt e(_graph); e!=INVALID; ++e) {
476
        if (matching[e]) {
477

	
478
          Node u = _graph.u(e);
479
          if ((*_matching)[u] != INVALID) return false;
480
          _matching->set(u, _graph.direct(e, true));
481
          _status->set(u, MATCHED);
482

	
483
          Node v = _graph.v(e);
484
          if ((*_matching)[v] != INVALID) return false;
485
          _matching->set(v, _graph.direct(e, false));
486
          _status->set(v, MATCHED);
487
        }
488
      }
489
      return true;
490
    }
491

	
492
    /// \brief Starts Edmonds' algorithm
493
    ///
494
    /// If runs the original Edmonds' algorithm.
495
    void startSparse() {
496
      for(NodeIt n(_graph); n != INVALID; ++n) {
497
        if ((*_status)[n] == UNMATCHED) {
498
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
499
          _tree_set->insert(n);
500
          _status->set(n, EVEN);
501
          processSparse(n);
502
        }
503
      }
504
    }
505

	
506
    /// \brief Starts Edmonds' algorithm.
507
    ///
508
    /// It runs Edmonds' algorithm with a heuristic of postponing
509
    /// shrinks, therefore resulting in a faster algorithm for dense graphs.
510
    void startDense() {
511
      for(NodeIt n(_graph); n != INVALID; ++n) {
512
        if ((*_status)[n] == UNMATCHED) {
513
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
514
          _tree_set->insert(n);
515
          _status->set(n, EVEN);
516
          processDense(n);
517
        }
518
      }
519
    }
520

	
521

	
522
    /// \brief Runs Edmonds' algorithm
523
    ///
524
    /// Runs Edmonds' algorithm for sparse graphs (<tt>m<2*n</tt>)
525
    /// or Edmonds' algorithm with a heuristic of
526
    /// postponing shrinks for dense graphs.
527
    void run() {
528
      if (countEdges(_graph) < 2 * countNodes(_graph)) {
529
        greedyInit();
530
        startSparse();
531
      } else {
532
        init();
533
        startDense();
534
      }
535
    }
536

	
537
    /// @}
538

	
539
    /// \name Primal solution
540
    /// Functions to get the primal solution, ie. the matching.
541

	
542
    /// @{
543

	
544
    ///\brief Returns the size of the current matching.
545
    ///
546
    ///Returns the size of the current matching. After \ref
547
    ///run() it returns the size of the maximum matching in the graph.
548
    int matchingSize() const {
549
      int size = 0;
550
      for (NodeIt n(_graph); n != INVALID; ++n) {
551
        if ((*_matching)[n] != INVALID) {
552
          ++size;
553
        }
554
      }
555
      return size / 2;
556
    }
557

	
558
    /// \brief Returns true when the edge is in the matching.
559
    ///
560
    /// Returns true when the edge is in the matching.
561
    bool matching(const Edge& edge) const {
562
      return edge == (*_matching)[_graph.u(edge)];
563
    }
564

	
565
    /// \brief Returns the matching edge incident to the given node.
566
    ///
567
    /// Returns the matching edge of a \c node in the actual matching or
568
    /// INVALID if the \c node is not covered by the actual matching.
569
    Arc matching(const Node& n) const {
570
      return (*_matching)[n];
571
    }
572

	
573
    ///\brief Returns the mate of a node in the actual matching.
574
    ///
575
    ///Returns the mate of a \c node in the actual matching or
576
    ///INVALID if the \c node is not covered by the actual matching.
577
    Node mate(const Node& n) const {
578
      return (*_matching)[n] != INVALID ?
579
        _graph.target((*_matching)[n]) : INVALID;
580
    }
581

	
582
    /// @}
583

	
584
    /// \name Dual solution
585
    /// Functions to get the dual solution, ie. the decomposition.
586

	
587
    /// @{
588

	
589
    /// \brief Returns the class of the node in the Edmonds-Gallai
590
    /// decomposition.
591
    ///
592
    /// Returns the class of the node in the Edmonds-Gallai
593
    /// decomposition.
594
    Status decomposition(const Node& n) const {
595
      return (*_status)[n];
596
    }
597

	
598
    /// \brief Returns true when the node is in the barrier.
599
    ///
600
    /// Returns true when the node is in the barrier.
601
    bool barrier(const Node& n) const {
602
      return (*_status)[n] == ODD;
603
    }
604

	
605
    /// @}
606

	
607
  };
608

	
609
  /// \ingroup matching
610
  ///
611
  /// \brief Weighted matching in general graphs
612
  ///
613
  /// This class provides an efficient implementation of Edmond's
614
  /// maximum weighted matching algorithm. The implementation is based
615
  /// on extensive use of priority queues and provides
616
  /// \f$O(nm\log(n))\f$ time complexity.
617
  ///
618
  /// The maximum weighted matching problem is to find undirected
619
  /// edges in the graph with maximum overall weight and no two of
620
  /// them shares their ends. The problem can be formulated with the
621
  /// following linear program.
622
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
623
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
624
      \quad \forall B\in\mathcal{O}\f] */
625
  /// \f[x_e \ge 0\quad \forall e\in E\f]
626
  /// \f[\max \sum_{e\in E}x_ew_e\f]
627
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
628
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
629
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
630
  /// subsets of the nodes.
631
  ///
632
  /// The algorithm calculates an optimal matching and a proof of the
633
  /// optimality. The solution of the dual problem can be used to check
634
  /// the result of the algorithm. The dual linear problem is the
635
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
636
      z_B \ge w_{uv} \quad \forall uv\in E\f] */
637
  /// \f[y_u \ge 0 \quad \forall u \in V\f]
638
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
639
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
640
      \frac{\vert B \vert - 1}{2}z_B\f] */
641
  ///
642
  /// The algorithm can be executed with \c run() or the \c init() and
643
  /// then the \c start() member functions. After it the matching can
644
  /// be asked with \c matching() or mate() functions. The dual
645
  /// solution can be get with \c nodeValue(), \c blossomNum() and \c
646
  /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
647
  /// "BlossomIt" nested class, which is able to iterate on the nodes
648
  /// of a blossom. If the value type is integral then the dual
649
  /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
650
  template <typename _Graph,
651
            typename _WeightMap = typename _Graph::template EdgeMap<int> >
652
  class MaxWeightedMatching {
653
  public:
654

	
655
    typedef _Graph Graph;
656
    typedef _WeightMap WeightMap;
657
    typedef typename WeightMap::Value Value;
658

	
659
    /// \brief Scaling factor for dual solution
660
    ///
661
    /// Scaling factor for dual solution, it is equal to 4 or 1
662
    /// according to the value type.
663
    static const int dualScale =
664
      std::numeric_limits<Value>::is_integer ? 4 : 1;
665

	
666
    typedef typename Graph::template NodeMap<typename Graph::Arc>
667
    MatchingMap;
668

	
669
  private:
670

	
671
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
672

	
673
    typedef typename Graph::template NodeMap<Value> NodePotential;
674
    typedef std::vector<Node> BlossomNodeList;
675

	
676
    struct BlossomVariable {
677
      int begin, end;
678
      Value value;
679

	
680
      BlossomVariable(int _begin, int _end, Value _value)
681
        : begin(_begin), end(_end), value(_value) {}
682

	
683
    };
684

	
685
    typedef std::vector<BlossomVariable> BlossomPotential;
686

	
687
    const Graph& _graph;
688
    const WeightMap& _weight;
689

	
690
    MatchingMap* _matching;
691

	
692
    NodePotential* _node_potential;
693

	
694
    BlossomPotential _blossom_potential;
695
    BlossomNodeList _blossom_node_list;
696

	
697
    int _node_num;
698
    int _blossom_num;
699

	
700
    typedef RangeMap<int> IntIntMap;
701

	
702
    enum Status {
703
      EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
704
    };
705

	
706
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
707
    struct BlossomData {
708
      int tree;
709
      Status status;
710
      Arc pred, next;
711
      Value pot, offset;
712
      Node base;
713
    };
714

	
715
    IntNodeMap *_blossom_index;
716
    BlossomSet *_blossom_set;
717
    RangeMap<BlossomData>* _blossom_data;
718

	
719
    IntNodeMap *_node_index;
720
    IntArcMap *_node_heap_index;
721

	
722
    struct NodeData {
723

	
724
      NodeData(IntArcMap& node_heap_index)
725
        : heap(node_heap_index) {}
726

	
727
      int blossom;
728
      Value pot;
729
      BinHeap<Value, IntArcMap> heap;
730
      std::map<int, Arc> heap_index;
731

	
732
      int tree;
733
    };
734

	
735
    RangeMap<NodeData>* _node_data;
736

	
737
    typedef ExtendFindEnum<IntIntMap> TreeSet;
738

	
739
    IntIntMap *_tree_set_index;
740
    TreeSet *_tree_set;
741

	
742
    IntNodeMap *_delta1_index;
743
    BinHeap<Value, IntNodeMap> *_delta1;
744

	
745
    IntIntMap *_delta2_index;
746
    BinHeap<Value, IntIntMap> *_delta2;
747

	
748
    IntEdgeMap *_delta3_index;
749
    BinHeap<Value, IntEdgeMap> *_delta3;
750

	
751
    IntIntMap *_delta4_index;
752
    BinHeap<Value, IntIntMap> *_delta4;
753

	
754
    Value _delta_sum;
755

	
756
    void createStructures() {
757
      _node_num = countNodes(_graph);
758
      _blossom_num = _node_num * 3 / 2;
759

	
760
      if (!_matching) {
761
        _matching = new MatchingMap(_graph);
762
      }
763
      if (!_node_potential) {
764
        _node_potential = new NodePotential(_graph);
765
      }
766
      if (!_blossom_set) {
767
        _blossom_index = new IntNodeMap(_graph);
768
        _blossom_set = new BlossomSet(*_blossom_index);
769
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
770
      }
771

	
772
      if (!_node_index) {
773
        _node_index = new IntNodeMap(_graph);
774
        _node_heap_index = new IntArcMap(_graph);
775
        _node_data = new RangeMap<NodeData>(_node_num,
776
                                              NodeData(*_node_heap_index));
777
      }
778

	
779
      if (!_tree_set) {
780
        _tree_set_index = new IntIntMap(_blossom_num);
781
        _tree_set = new TreeSet(*_tree_set_index);
782
      }
783
      if (!_delta1) {
784
        _delta1_index = new IntNodeMap(_graph);
785
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
786
      }
787
      if (!_delta2) {
788
        _delta2_index = new IntIntMap(_blossom_num);
789
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
790
      }
791
      if (!_delta3) {
792
        _delta3_index = new IntEdgeMap(_graph);
793
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
794
      }
795
      if (!_delta4) {
796
        _delta4_index = new IntIntMap(_blossom_num);
797
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
798
      }
799
    }
800

	
801
    void destroyStructures() {
802
      _node_num = countNodes(_graph);
803
      _blossom_num = _node_num * 3 / 2;
804

	
805
      if (_matching) {
806
        delete _matching;
807
      }
808
      if (_node_potential) {
809
        delete _node_potential;
810
      }
811
      if (_blossom_set) {
812
        delete _blossom_index;
813
        delete _blossom_set;
814
        delete _blossom_data;
815
      }
816

	
817
      if (_node_index) {
818
        delete _node_index;
819
        delete _node_heap_index;
820
        delete _node_data;
821
      }
822

	
823
      if (_tree_set) {
824
        delete _tree_set_index;
825
        delete _tree_set;
826
      }
827
      if (_delta1) {
828
        delete _delta1_index;
829
        delete _delta1;
830
      }
831
      if (_delta2) {
832
        delete _delta2_index;
833
        delete _delta2;
834
      }
835
      if (_delta3) {
836
        delete _delta3_index;
837
        delete _delta3;
838
      }
839
      if (_delta4) {
840
        delete _delta4_index;
841
        delete _delta4;
842
      }
843
    }
844

	
845
    void matchedToEven(int blossom, int tree) {
846
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
847
        _delta2->erase(blossom);
848
      }
849

	
850
      if (!_blossom_set->trivial(blossom)) {
851
        (*_blossom_data)[blossom].pot -=
852
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
853
      }
854

	
855
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
856
           n != INVALID; ++n) {
857

	
858
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
859
        int ni = (*_node_index)[n];
860

	
861
        (*_node_data)[ni].heap.clear();
862
        (*_node_data)[ni].heap_index.clear();
863

	
864
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
865

	
866
        _delta1->push(n, (*_node_data)[ni].pot);
867

	
868
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
869
          Node v = _graph.source(e);
870
          int vb = _blossom_set->find(v);
871
          int vi = (*_node_index)[v];
872

	
873
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
874
            dualScale * _weight[e];
875

	
876
          if ((*_blossom_data)[vb].status == EVEN) {
877
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
878
              _delta3->push(e, rw / 2);
879
            }
880
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
881
            if (_delta3->state(e) != _delta3->IN_HEAP) {
882
              _delta3->push(e, rw);
883
            }
884
          } else {
885
            typename std::map<int, Arc>::iterator it =
886
              (*_node_data)[vi].heap_index.find(tree);
887

	
888
            if (it != (*_node_data)[vi].heap_index.end()) {
889
              if ((*_node_data)[vi].heap[it->second] > rw) {
890
                (*_node_data)[vi].heap.replace(it->second, e);
891
                (*_node_data)[vi].heap.decrease(e, rw);
892
                it->second = e;
893
              }
894
            } else {
895
              (*_node_data)[vi].heap.push(e, rw);
896
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
897
            }
898

	
899
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
900
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
901

	
902
              if ((*_blossom_data)[vb].status == MATCHED) {
903
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
904
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
905
                               (*_blossom_data)[vb].offset);
906
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
907
                           (*_blossom_data)[vb].offset){
908
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
909
                                   (*_blossom_data)[vb].offset);
910
                }
911
              }
912
            }
913
          }
914
        }
915
      }
916
      (*_blossom_data)[blossom].offset = 0;
917
    }
918

	
919
    void matchedToOdd(int blossom) {
920
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
921
        _delta2->erase(blossom);
922
      }
923
      (*_blossom_data)[blossom].offset += _delta_sum;
924
      if (!_blossom_set->trivial(blossom)) {
925
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
926
                     (*_blossom_data)[blossom].offset);
927
      }
928
    }
929

	
930
    void evenToMatched(int blossom, int tree) {
931
      if (!_blossom_set->trivial(blossom)) {
932
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
933
      }
934

	
935
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
936
           n != INVALID; ++n) {
937
        int ni = (*_node_index)[n];
938
        (*_node_data)[ni].pot -= _delta_sum;
939

	
940
        _delta1->erase(n);
941

	
942
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
943
          Node v = _graph.source(e);
944
          int vb = _blossom_set->find(v);
945
          int vi = (*_node_index)[v];
946

	
947
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
948
            dualScale * _weight[e];
949

	
950
          if (vb == blossom) {
951
            if (_delta3->state(e) == _delta3->IN_HEAP) {
952
              _delta3->erase(e);
953
            }
954
          } else if ((*_blossom_data)[vb].status == EVEN) {
955

	
956
            if (_delta3->state(e) == _delta3->IN_HEAP) {
957
              _delta3->erase(e);
958
            }
959

	
960
            int vt = _tree_set->find(vb);
961

	
962
            if (vt != tree) {
963

	
964
              Arc r = _graph.oppositeArc(e);
965

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

	
969
              if (it != (*_node_data)[ni].heap_index.end()) {
970
                if ((*_node_data)[ni].heap[it->second] > rw) {
971
                  (*_node_data)[ni].heap.replace(it->second, r);
972
                  (*_node_data)[ni].heap.decrease(r, rw);
973
                  it->second = r;
974
                }
975
              } else {
976
                (*_node_data)[ni].heap.push(r, rw);
977
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
978
              }
979

	
980
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
981
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
982

	
983
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
984
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
985
                               (*_blossom_data)[blossom].offset);
986
                } else if ((*_delta2)[blossom] >
987
                           _blossom_set->classPrio(blossom) -
988
                           (*_blossom_data)[blossom].offset){
989
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
990
                                   (*_blossom_data)[blossom].offset);
991
                }
992
              }
993
            }
994

	
995
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
996
            if (_delta3->state(e) == _delta3->IN_HEAP) {
997
              _delta3->erase(e);
998
            }
999
          } else {
1000

	
1001
            typename std::map<int, Arc>::iterator it =
1002
              (*_node_data)[vi].heap_index.find(tree);
1003

	
1004
            if (it != (*_node_data)[vi].heap_index.end()) {
1005
              (*_node_data)[vi].heap.erase(it->second);
1006
              (*_node_data)[vi].heap_index.erase(it);
1007
              if ((*_node_data)[vi].heap.empty()) {
1008
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
1009
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1010
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1011
              }
1012

	
1013
              if ((*_blossom_data)[vb].status == MATCHED) {
1014
                if (_blossom_set->classPrio(vb) ==
1015
                    std::numeric_limits<Value>::max()) {
1016
                  _delta2->erase(vb);
1017
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1018
                           (*_blossom_data)[vb].offset) {
1019
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
1020
                                   (*_blossom_data)[vb].offset);
1021
                }
1022
              }
1023
            }
1024
          }
1025
        }
1026
      }
1027
    }
1028

	
1029
    void oddToMatched(int blossom) {
1030
      (*_blossom_data)[blossom].offset -= _delta_sum;
1031

	
1032
      if (_blossom_set->classPrio(blossom) !=
1033
          std::numeric_limits<Value>::max()) {
1034
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1035
                       (*_blossom_data)[blossom].offset);
1036
      }
1037

	
1038
      if (!_blossom_set->trivial(blossom)) {
1039
        _delta4->erase(blossom);
1040
      }
1041
    }
1042

	
1043
    void oddToEven(int blossom, int tree) {
1044
      if (!_blossom_set->trivial(blossom)) {
1045
        _delta4->erase(blossom);
1046
        (*_blossom_data)[blossom].pot -=
1047
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1048
      }
1049

	
1050
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1051
           n != INVALID; ++n) {
1052
        int ni = (*_node_index)[n];
1053

	
1054
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1055

	
1056
        (*_node_data)[ni].heap.clear();
1057
        (*_node_data)[ni].heap_index.clear();
1058
        (*_node_data)[ni].pot +=
1059
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
1060

	
1061
        _delta1->push(n, (*_node_data)[ni].pot);
1062

	
1063
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1064
          Node v = _graph.source(e);
1065
          int vb = _blossom_set->find(v);
1066
          int vi = (*_node_index)[v];
1067

	
1068
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1069
            dualScale * _weight[e];
1070

	
1071
          if ((*_blossom_data)[vb].status == EVEN) {
1072
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1073
              _delta3->push(e, rw / 2);
1074
            }
1075
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1076
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1077
              _delta3->push(e, rw);
1078
            }
1079
          } else {
1080

	
1081
            typename std::map<int, Arc>::iterator it =
1082
              (*_node_data)[vi].heap_index.find(tree);
1083

	
1084
            if (it != (*_node_data)[vi].heap_index.end()) {
1085
              if ((*_node_data)[vi].heap[it->second] > rw) {
1086
                (*_node_data)[vi].heap.replace(it->second, e);
1087
                (*_node_data)[vi].heap.decrease(e, rw);
1088
                it->second = e;
1089
              }
1090
            } else {
1091
              (*_node_data)[vi].heap.push(e, rw);
1092
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1093
            }
1094

	
1095
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1096
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1097

	
1098
              if ((*_blossom_data)[vb].status == MATCHED) {
1099
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
1100
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
1101
                               (*_blossom_data)[vb].offset);
1102
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1103
                           (*_blossom_data)[vb].offset) {
1104
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1105
                                   (*_blossom_data)[vb].offset);
1106
                }
1107
              }
1108
            }
1109
          }
1110
        }
1111
      }
1112
      (*_blossom_data)[blossom].offset = 0;
1113
    }
1114

	
1115

	
1116
    void matchedToUnmatched(int blossom) {
1117
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1118
        _delta2->erase(blossom);
1119
      }
1120

	
1121
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1122
           n != INVALID; ++n) {
1123
        int ni = (*_node_index)[n];
1124

	
1125
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1126

	
1127
        (*_node_data)[ni].heap.clear();
1128
        (*_node_data)[ni].heap_index.clear();
1129

	
1130
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1131
          Node v = _graph.target(e);
1132
          int vb = _blossom_set->find(v);
1133
          int vi = (*_node_index)[v];
1134

	
1135
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1136
            dualScale * _weight[e];
1137

	
1138
          if ((*_blossom_data)[vb].status == EVEN) {
1139
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1140
              _delta3->push(e, rw);
1141
            }
1142
          }
1143
        }
1144
      }
1145
    }
1146

	
1147
    void unmatchedToMatched(int blossom) {
1148
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1149
           n != INVALID; ++n) {
1150
        int ni = (*_node_index)[n];
1151

	
1152
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1153
          Node v = _graph.source(e);
1154
          int vb = _blossom_set->find(v);
1155
          int vi = (*_node_index)[v];
1156

	
1157
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1158
            dualScale * _weight[e];
1159

	
1160
          if (vb == blossom) {
1161
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1162
              _delta3->erase(e);
1163
            }
1164
          } else if ((*_blossom_data)[vb].status == EVEN) {
1165

	
1166
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1167
              _delta3->erase(e);
1168
            }
1169

	
1170
            int vt = _tree_set->find(vb);
1171

	
1172
            Arc r = _graph.oppositeArc(e);
1173

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

	
1177
            if (it != (*_node_data)[ni].heap_index.end()) {
1178
              if ((*_node_data)[ni].heap[it->second] > rw) {
1179
                (*_node_data)[ni].heap.replace(it->second, r);
1180
                (*_node_data)[ni].heap.decrease(r, rw);
1181
                it->second = r;
1182
              }
1183
            } else {
1184
              (*_node_data)[ni].heap.push(r, rw);
1185
              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1186
            }
1187

	
1188
            if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1189
              _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1190

	
1191
              if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1192
                _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1193
                             (*_blossom_data)[blossom].offset);
1194
              } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
1195
                         (*_blossom_data)[blossom].offset){
1196
                _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1197
                                 (*_blossom_data)[blossom].offset);
1198
              }
1199
            }
1200

	
1201
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1202
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1203
              _delta3->erase(e);
1204
            }
1205
          }
1206
        }
1207
      }
1208
    }
1209

	
1210
    void alternatePath(int even, int tree) {
1211
      int odd;
1212

	
1213
      evenToMatched(even, tree);
1214
      (*_blossom_data)[even].status = MATCHED;
1215

	
1216
      while ((*_blossom_data)[even].pred != INVALID) {
1217
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1218
        (*_blossom_data)[odd].status = MATCHED;
1219
        oddToMatched(odd);
1220
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1221

	
1222
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1223
        (*_blossom_data)[even].status = MATCHED;
1224
        evenToMatched(even, tree);
1225
        (*_blossom_data)[even].next =
1226
          _graph.oppositeArc((*_blossom_data)[odd].pred);
1227
      }
1228

	
1229
    }
1230

	
1231
    void destroyTree(int tree) {
1232
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1233
        if ((*_blossom_data)[b].status == EVEN) {
1234
          (*_blossom_data)[b].status = MATCHED;
1235
          evenToMatched(b, tree);
1236
        } else if ((*_blossom_data)[b].status == ODD) {
1237
          (*_blossom_data)[b].status = MATCHED;
1238
          oddToMatched(b);
1239
        }
1240
      }
1241
      _tree_set->eraseClass(tree);
1242
    }
1243

	
1244

	
1245
    void unmatchNode(const Node& node) {
1246
      int blossom = _blossom_set->find(node);
1247
      int tree = _tree_set->find(blossom);
1248

	
1249
      alternatePath(blossom, tree);
1250
      destroyTree(tree);
1251

	
1252
      (*_blossom_data)[blossom].status = UNMATCHED;
1253
      (*_blossom_data)[blossom].base = node;
1254
      matchedToUnmatched(blossom);
1255
    }
1256

	
1257

	
1258
    void augmentOnEdge(const Edge& edge) {
1259

	
1260
      int left = _blossom_set->find(_graph.u(edge));
1261
      int right = _blossom_set->find(_graph.v(edge));
1262

	
1263
      if ((*_blossom_data)[left].status == EVEN) {
1264
        int left_tree = _tree_set->find(left);
1265
        alternatePath(left, left_tree);
1266
        destroyTree(left_tree);
1267
      } else {
1268
        (*_blossom_data)[left].status = MATCHED;
1269
        unmatchedToMatched(left);
1270
      }
1271

	
1272
      if ((*_blossom_data)[right].status == EVEN) {
1273
        int right_tree = _tree_set->find(right);
1274
        alternatePath(right, right_tree);
1275
        destroyTree(right_tree);
1276
      } else {
1277
        (*_blossom_data)[right].status = MATCHED;
1278
        unmatchedToMatched(right);
1279
      }
1280

	
1281
      (*_blossom_data)[left].next = _graph.direct(edge, true);
1282
      (*_blossom_data)[right].next = _graph.direct(edge, false);
1283
    }
1284

	
1285
    void extendOnArc(const Arc& arc) {
1286
      int base = _blossom_set->find(_graph.target(arc));
1287
      int tree = _tree_set->find(base);
1288

	
1289
      int odd = _blossom_set->find(_graph.source(arc));
1290
      _tree_set->insert(odd, tree);
1291
      (*_blossom_data)[odd].status = ODD;
1292
      matchedToOdd(odd);
1293
      (*_blossom_data)[odd].pred = arc;
1294

	
1295
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1296
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1297
      _tree_set->insert(even, tree);
1298
      (*_blossom_data)[even].status = EVEN;
1299
      matchedToEven(even, tree);
1300
    }
1301

	
1302
    void shrinkOnEdge(const Edge& edge, int tree) {
1303
      int nca = -1;
1304
      std::vector<int> left_path, right_path;
1305

	
1306
      {
1307
        std::set<int> left_set, right_set;
1308
        int left = _blossom_set->find(_graph.u(edge));
1309
        left_path.push_back(left);
1310
        left_set.insert(left);
1311

	
1312
        int right = _blossom_set->find(_graph.v(edge));
1313
        right_path.push_back(right);
1314
        right_set.insert(right);
1315

	
1316
        while (true) {
1317

	
1318
          if ((*_blossom_data)[left].pred == INVALID) break;
1319

	
1320
          left =
1321
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1322
          left_path.push_back(left);
1323
          left =
1324
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1325
          left_path.push_back(left);
1326

	
1327
          left_set.insert(left);
1328

	
1329
          if (right_set.find(left) != right_set.end()) {
1330
            nca = left;
1331
            break;
1332
          }
1333

	
1334
          if ((*_blossom_data)[right].pred == INVALID) break;
1335

	
1336
          right =
1337
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1338
          right_path.push_back(right);
1339
          right =
1340
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1341
          right_path.push_back(right);
1342

	
1343
          right_set.insert(right);
1344

	
1345
          if (left_set.find(right) != left_set.end()) {
1346
            nca = right;
1347
            break;
1348
          }
1349

	
1350
        }
1351

	
1352
        if (nca == -1) {
1353
          if ((*_blossom_data)[left].pred == INVALID) {
1354
            nca = right;
1355
            while (left_set.find(nca) == left_set.end()) {
1356
              nca =
1357
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1358
              right_path.push_back(nca);
1359
              nca =
1360
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1361
              right_path.push_back(nca);
1362
            }
1363
          } else {
1364
            nca = left;
1365
            while (right_set.find(nca) == right_set.end()) {
1366
              nca =
1367
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1368
              left_path.push_back(nca);
1369
              nca =
1370
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1371
              left_path.push_back(nca);
1372
            }
1373
          }
1374
        }
1375
      }
1376

	
1377
      std::vector<int> subblossoms;
1378
      Arc prev;
1379

	
1380
      prev = _graph.direct(edge, true);
1381
      for (int i = 0; left_path[i] != nca; i += 2) {
1382
        subblossoms.push_back(left_path[i]);
1383
        (*_blossom_data)[left_path[i]].next = prev;
1384
        _tree_set->erase(left_path[i]);
1385

	
1386
        subblossoms.push_back(left_path[i + 1]);
1387
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
1388
        oddToEven(left_path[i + 1], tree);
1389
        _tree_set->erase(left_path[i + 1]);
1390
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1391
      }
1392

	
1393
      int k = 0;
1394
      while (right_path[k] != nca) ++k;
1395

	
1396
      subblossoms.push_back(nca);
1397
      (*_blossom_data)[nca].next = prev;
1398

	
1399
      for (int i = k - 2; i >= 0; i -= 2) {
1400
        subblossoms.push_back(right_path[i + 1]);
1401
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
1402
        oddToEven(right_path[i + 1], tree);
1403
        _tree_set->erase(right_path[i + 1]);
1404

	
1405
        (*_blossom_data)[right_path[i + 1]].next =
1406
          (*_blossom_data)[right_path[i + 1]].pred;
1407

	
1408
        subblossoms.push_back(right_path[i]);
1409
        _tree_set->erase(right_path[i]);
1410
      }
1411

	
1412
      int surface =
1413
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
1414

	
1415
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1416
        if (!_blossom_set->trivial(subblossoms[i])) {
1417
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1418
        }
1419
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
1420
      }
1421

	
1422
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
1423
      (*_blossom_data)[surface].offset = 0;
1424
      (*_blossom_data)[surface].status = EVEN;
1425
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1426
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1427

	
1428
      _tree_set->insert(surface, tree);
1429
      _tree_set->erase(nca);
1430
    }
1431

	
1432
    void splitBlossom(int blossom) {
1433
      Arc next = (*_blossom_data)[blossom].next;
1434
      Arc pred = (*_blossom_data)[blossom].pred;
1435

	
1436
      int tree = _tree_set->find(blossom);
1437

	
1438
      (*_blossom_data)[blossom].status = MATCHED;
1439
      oddToMatched(blossom);
1440
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1441
        _delta2->erase(blossom);
1442
      }
1443

	
1444
      std::vector<int> subblossoms;
1445
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
1446

	
1447
      Value offset = (*_blossom_data)[blossom].offset;
1448
      int b = _blossom_set->find(_graph.source(pred));
1449
      int d = _blossom_set->find(_graph.source(next));
1450

	
1451
      int ib = -1, id = -1;
1452
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1453
        if (subblossoms[i] == b) ib = i;
1454
        if (subblossoms[i] == d) id = i;
1455

	
1456
        (*_blossom_data)[subblossoms[i]].offset = offset;
1457
        if (!_blossom_set->trivial(subblossoms[i])) {
1458
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1459
        }
1460
        if (_blossom_set->classPrio(subblossoms[i]) !=
1461
            std::numeric_limits<Value>::max()) {
1462
          _delta2->push(subblossoms[i],
1463
                        _blossom_set->classPrio(subblossoms[i]) -
1464
                        (*_blossom_data)[subblossoms[i]].offset);
1465
        }
1466
      }
1467

	
1468
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1469
        for (int i = (id + 1) % subblossoms.size();
1470
             i != ib; i = (i + 2) % subblossoms.size()) {
1471
          int sb = subblossoms[i];
1472
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1473
          (*_blossom_data)[sb].next =
1474
            _graph.oppositeArc((*_blossom_data)[tb].next);
1475
        }
1476

	
1477
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1478
          int sb = subblossoms[i];
1479
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1480
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1481

	
1482
          (*_blossom_data)[sb].status = ODD;
1483
          matchedToOdd(sb);
1484
          _tree_set->insert(sb, tree);
1485
          (*_blossom_data)[sb].pred = pred;
1486
          (*_blossom_data)[sb].next =
1487
                           _graph.oppositeArc((*_blossom_data)[tb].next);
1488

	
1489
          pred = (*_blossom_data)[ub].next;
1490

	
1491
          (*_blossom_data)[tb].status = EVEN;
1492
          matchedToEven(tb, tree);
1493
          _tree_set->insert(tb, tree);
1494
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1495
        }
1496

	
1497
        (*_blossom_data)[subblossoms[id]].status = ODD;
1498
        matchedToOdd(subblossoms[id]);
1499
        _tree_set->insert(subblossoms[id], tree);
1500
        (*_blossom_data)[subblossoms[id]].next = next;
1501
        (*_blossom_data)[subblossoms[id]].pred = pred;
1502

	
1503
      } else {
1504

	
1505
        for (int i = (ib + 1) % subblossoms.size();
1506
             i != id; i = (i + 2) % subblossoms.size()) {
1507
          int sb = subblossoms[i];
1508
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1509
          (*_blossom_data)[sb].next =
1510
            _graph.oppositeArc((*_blossom_data)[tb].next);
1511
        }
1512

	
1513
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1514
          int sb = subblossoms[i];
1515
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1516
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1517

	
1518
          (*_blossom_data)[sb].status = ODD;
1519
          matchedToOdd(sb);
1520
          _tree_set->insert(sb, tree);
1521
          (*_blossom_data)[sb].next = next;
1522
          (*_blossom_data)[sb].pred =
1523
            _graph.oppositeArc((*_blossom_data)[tb].next);
1524

	
1525
          (*_blossom_data)[tb].status = EVEN;
1526
          matchedToEven(tb, tree);
1527
          _tree_set->insert(tb, tree);
1528
          (*_blossom_data)[tb].pred =
1529
            (*_blossom_data)[tb].next =
1530
            _graph.oppositeArc((*_blossom_data)[ub].next);
1531
          next = (*_blossom_data)[ub].next;
1532
        }
1533

	
1534
        (*_blossom_data)[subblossoms[ib]].status = ODD;
1535
        matchedToOdd(subblossoms[ib]);
1536
        _tree_set->insert(subblossoms[ib], tree);
1537
        (*_blossom_data)[subblossoms[ib]].next = next;
1538
        (*_blossom_data)[subblossoms[ib]].pred = pred;
1539
      }
1540
      _tree_set->erase(blossom);
1541
    }
1542

	
1543
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1544
      if (_blossom_set->trivial(blossom)) {
1545
        int bi = (*_node_index)[base];
1546
        Value pot = (*_node_data)[bi].pot;
1547

	
1548
        _matching->set(base, matching);
1549
        _blossom_node_list.push_back(base);
1550
        _node_potential->set(base, pot);
1551
      } else {
1552

	
1553
        Value pot = (*_blossom_data)[blossom].pot;
1554
        int bn = _blossom_node_list.size();
1555

	
1556
        std::vector<int> subblossoms;
1557
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
1558
        int b = _blossom_set->find(base);
1559
        int ib = -1;
1560
        for (int i = 0; i < int(subblossoms.size()); ++i) {
1561
          if (subblossoms[i] == b) { ib = i; break; }
1562
        }
1563

	
1564
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
1565
          int sb = subblossoms[(ib + i) % subblossoms.size()];
1566
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1567

	
1568
          Arc m = (*_blossom_data)[tb].next;
1569
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1570
          extractBlossom(tb, _graph.source(m), m);
1571
        }
1572
        extractBlossom(subblossoms[ib], base, matching);
1573

	
1574
        int en = _blossom_node_list.size();
1575

	
1576
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1577
      }
1578
    }
1579

	
1580
    void extractMatching() {
1581
      std::vector<int> blossoms;
1582
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1583
        blossoms.push_back(c);
1584
      }
1585

	
1586
      for (int i = 0; i < int(blossoms.size()); ++i) {
1587
        if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
1588

	
1589
          Value offset = (*_blossom_data)[blossoms[i]].offset;
1590
          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1591
          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1592
               n != INVALID; ++n) {
1593
            (*_node_data)[(*_node_index)[n]].pot -= offset;
1594
          }
1595

	
1596
          Arc matching = (*_blossom_data)[blossoms[i]].next;
1597
          Node base = _graph.source(matching);
1598
          extractBlossom(blossoms[i], base, matching);
1599
        } else {
1600
          Node base = (*_blossom_data)[blossoms[i]].base;
1601
          extractBlossom(blossoms[i], base, INVALID);
1602
        }
1603
      }
1604
    }
1605

	
1606
  public:
1607

	
1608
    /// \brief Constructor
1609
    ///
1610
    /// Constructor.
1611
    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1612
      : _graph(graph), _weight(weight), _matching(0),
1613
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
1614
        _node_num(0), _blossom_num(0),
1615

	
1616
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
1617
        _node_index(0), _node_heap_index(0), _node_data(0),
1618
        _tree_set_index(0), _tree_set(0),
1619

	
1620
        _delta1_index(0), _delta1(0),
1621
        _delta2_index(0), _delta2(0),
1622
        _delta3_index(0), _delta3(0),
1623
        _delta4_index(0), _delta4(0),
1624

	
1625
        _delta_sum() {}
1626

	
1627
    ~MaxWeightedMatching() {
1628
      destroyStructures();
1629
    }
1630

	
1631
    /// \name Execution control
1632
    /// The simplest way to execute the algorithm is to use the
1633
    /// \c run() member function.
1634

	
1635
    ///@{
1636

	
1637
    /// \brief Initialize the algorithm
1638
    ///
1639
    /// Initialize the algorithm
1640
    void init() {
1641
      createStructures();
1642

	
1643
      for (ArcIt e(_graph); e != INVALID; ++e) {
1644
        _node_heap_index->set(e, BinHeap<Value, IntArcMap>::PRE_HEAP);
1645
      }
1646
      for (NodeIt n(_graph); n != INVALID; ++n) {
1647
        _delta1_index->set(n, _delta1->PRE_HEAP);
1648
      }
1649
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1650
        _delta3_index->set(e, _delta3->PRE_HEAP);
1651
      }
1652
      for (int i = 0; i < _blossom_num; ++i) {
1653
        _delta2_index->set(i, _delta2->PRE_HEAP);
1654
        _delta4_index->set(i, _delta4->PRE_HEAP);
1655
      }
1656

	
1657
      int index = 0;
1658
      for (NodeIt n(_graph); n != INVALID; ++n) {
1659
        Value max = 0;
1660
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1661
          if (_graph.target(e) == n) continue;
1662
          if ((dualScale * _weight[e]) / 2 > max) {
1663
            max = (dualScale * _weight[e]) / 2;
1664
          }
1665
        }
1666
        _node_index->set(n, index);
1667
        (*_node_data)[index].pot = max;
1668
        _delta1->push(n, max);
1669
        int blossom =
1670
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1671

	
1672
        _tree_set->insert(blossom);
1673

	
1674
        (*_blossom_data)[blossom].status = EVEN;
1675
        (*_blossom_data)[blossom].pred = INVALID;
1676
        (*_blossom_data)[blossom].next = INVALID;
1677
        (*_blossom_data)[blossom].pot = 0;
1678
        (*_blossom_data)[blossom].offset = 0;
1679
        ++index;
1680
      }
1681
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1682
        int si = (*_node_index)[_graph.u(e)];
1683
        int ti = (*_node_index)[_graph.v(e)];
1684
        if (_graph.u(e) != _graph.v(e)) {
1685
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1686
                            dualScale * _weight[e]) / 2);
1687
        }
1688
      }
1689
    }
1690

	
1691
    /// \brief Starts the algorithm
1692
    ///
1693
    /// Starts the algorithm
1694
    void start() {
1695
      enum OpType {
1696
        D1, D2, D3, D4
1697
      };
1698

	
1699
      int unmatched = _node_num;
1700
      while (unmatched > 0) {
1701
        Value d1 = !_delta1->empty() ?
1702
          _delta1->prio() : std::numeric_limits<Value>::max();
1703

	
1704
        Value d2 = !_delta2->empty() ?
1705
          _delta2->prio() : std::numeric_limits<Value>::max();
1706

	
1707
        Value d3 = !_delta3->empty() ?
1708
          _delta3->prio() : std::numeric_limits<Value>::max();
1709

	
1710
        Value d4 = !_delta4->empty() ?
1711
          _delta4->prio() : std::numeric_limits<Value>::max();
1712

	
1713
        _delta_sum = d1; OpType ot = D1;
1714
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1715
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1716
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1717

	
1718

	
1719
        switch (ot) {
1720
        case D1:
1721
          {
1722
            Node n = _delta1->top();
1723
            unmatchNode(n);
1724
            --unmatched;
1725
          }
1726
          break;
1727
        case D2:
1728
          {
1729
            int blossom = _delta2->top();
1730
            Node n = _blossom_set->classTop(blossom);
1731
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1732
            extendOnArc(e);
1733
          }
1734
          break;
1735
        case D3:
1736
          {
1737
            Edge e = _delta3->top();
1738

	
1739
            int left_blossom = _blossom_set->find(_graph.u(e));
1740
            int right_blossom = _blossom_set->find(_graph.v(e));
1741

	
1742
            if (left_blossom == right_blossom) {
1743
              _delta3->pop();
1744
            } else {
1745
              int left_tree;
1746
              if ((*_blossom_data)[left_blossom].status == EVEN) {
1747
                left_tree = _tree_set->find(left_blossom);
1748
              } else {
1749
                left_tree = -1;
1750
                ++unmatched;
1751
              }
1752
              int right_tree;
1753
              if ((*_blossom_data)[right_blossom].status == EVEN) {
1754
                right_tree = _tree_set->find(right_blossom);
1755
              } else {
1756
                right_tree = -1;
1757
                ++unmatched;
1758
              }
1759

	
1760
              if (left_tree == right_tree) {
1761
                shrinkOnEdge(e, left_tree);
1762
              } else {
1763
                augmentOnEdge(e);
1764
                unmatched -= 2;
1765
              }
1766
            }
1767
          } break;
1768
        case D4:
1769
          splitBlossom(_delta4->top());
1770
          break;
1771
        }
1772
      }
1773
      extractMatching();
1774
    }
1775

	
1776
    /// \brief Runs %MaxWeightedMatching algorithm.
1777
    ///
1778
    /// This method runs the %MaxWeightedMatching algorithm.
1779
    ///
1780
    /// \note mwm.run() is just a shortcut of the following code.
1781
    /// \code
1782
    ///   mwm.init();
1783
    ///   mwm.start();
1784
    /// \endcode
1785
    void run() {
1786
      init();
1787
      start();
1788
    }
1789

	
1790
    /// @}
1791

	
1792
    /// \name Primal solution
1793
    /// Functions to get the primal solution, ie. the matching.
1794

	
1795
    /// @{
1796

	
1797
    /// \brief Returns the weight of the matching.
1798
    ///
1799
    /// Returns the weight of the matching.
1800
    Value matchingValue() const {
1801
      Value sum = 0;
1802
      for (NodeIt n(_graph); n != INVALID; ++n) {
1803
        if ((*_matching)[n] != INVALID) {
1804
          sum += _weight[(*_matching)[n]];
1805
        }
1806
      }
1807
      return sum /= 2;
1808
    }
1809

	
1810
    /// \brief Returns the cardinality of the matching.
1811
    ///
1812
    /// Returns the cardinality of the matching.
1813
    int matchingSize() const {
1814
      int num = 0;
1815
      for (NodeIt n(_graph); n != INVALID; ++n) {
1816
        if ((*_matching)[n] != INVALID) {
1817
          ++num;
1818
        }
1819
      }
1820
      return num /= 2;
1821
    }
1822

	
1823
    /// \brief Returns true when the edge is in the matching.
1824
    ///
1825
    /// Returns true when the edge is in the matching.
1826
    bool matching(const Edge& edge) const {
1827
      return edge == (*_matching)[_graph.u(edge)];
1828
    }
1829

	
1830
    /// \brief Returns the incident matching arc.
1831
    ///
1832
    /// Returns the incident matching arc from given node. If the
1833
    /// node is not matched then it gives back \c INVALID.
1834
    Arc matching(const Node& node) const {
1835
      return (*_matching)[node];
1836
    }
1837

	
1838
    /// \brief Returns the mate of the node.
1839
    ///
1840
    /// Returns the adjancent node in a mathcing arc. If the node is
1841
    /// not matched then it gives back \c INVALID.
1842
    Node mate(const Node& node) const {
1843
      return (*_matching)[node] != INVALID ?
1844
        _graph.target((*_matching)[node]) : INVALID;
1845
    }
1846

	
1847
    /// @}
1848

	
1849
    /// \name Dual solution
1850
    /// Functions to get the dual solution.
1851

	
1852
    /// @{
1853

	
1854
    /// \brief Returns the value of the dual solution.
1855
    ///
1856
    /// Returns the value of the dual solution. It should be equal to
1857
    /// the primal value scaled by \ref dualScale "dual scale".
1858
    Value dualValue() const {
1859
      Value sum = 0;
1860
      for (NodeIt n(_graph); n != INVALID; ++n) {
1861
        sum += nodeValue(n);
1862
      }
1863
      for (int i = 0; i < blossomNum(); ++i) {
1864
        sum += blossomValue(i) * (blossomSize(i) / 2);
1865
      }
1866
      return sum;
1867
    }
1868

	
1869
    /// \brief Returns the value of the node.
1870
    ///
1871
    /// Returns the the value of the node.
1872
    Value nodeValue(const Node& n) const {
1873
      return (*_node_potential)[n];
1874
    }
1875

	
1876
    /// \brief Returns the number of the blossoms in the basis.
1877
    ///
1878
    /// Returns the number of the blossoms in the basis.
1879
    /// \see BlossomIt
1880
    int blossomNum() const {
1881
      return _blossom_potential.size();
1882
    }
1883

	
1884

	
1885
    /// \brief Returns the number of the nodes in the blossom.
1886
    ///
1887
    /// Returns the number of the nodes in the blossom.
1888
    int blossomSize(int k) const {
1889
      return _blossom_potential[k].end - _blossom_potential[k].begin;
1890
    }
1891

	
1892
    /// \brief Returns the value of the blossom.
1893
    ///
1894
    /// Returns the the value of the blossom.
1895
    /// \see BlossomIt
1896
    Value blossomValue(int k) const {
1897
      return _blossom_potential[k].value;
1898
    }
1899

	
1900
    /// \brief Iterator for obtaining the nodes of the blossom.
1901
    ///
1902
    /// Iterator for obtaining the nodes of the blossom. This class
1903
    /// provides a common lemon style iterator for listing a
1904
    /// subset of the nodes.
1905
    class BlossomIt {
1906
    public:
1907

	
1908
      /// \brief Constructor.
1909
      ///
1910
      /// Constructor to get the nodes of the variable.
1911
      BlossomIt(const MaxWeightedMatching& algorithm, int variable)
1912
        : _algorithm(&algorithm)
1913
      {
1914
        _index = _algorithm->_blossom_potential[variable].begin;
1915
        _last = _algorithm->_blossom_potential[variable].end;
1916
      }
1917

	
1918
      /// \brief Conversion to node.
1919
      ///
1920
      /// Conversion to node.
1921
      operator Node() const {
1922
        return _algorithm->_blossom_node_list[_index];
1923
      }
1924

	
1925
      /// \brief Increment operator.
1926
      ///
1927
      /// Increment operator.
1928
      BlossomIt& operator++() {
1929
        ++_index;
1930
        return *this;
1931
      }
1932

	
1933
      /// \brief Validity checking
1934
      ///
1935
      /// Checks whether the iterator is invalid.
1936
      bool operator==(Invalid) const { return _index == _last; }
1937

	
1938
      /// \brief Validity checking
1939
      ///
1940
      /// Checks whether the iterator is valid.
1941
      bool operator!=(Invalid) const { return _index != _last; }
1942

	
1943
    private:
1944
      const MaxWeightedMatching* _algorithm;
1945
      int _last;
1946
      int _index;
1947
    };
1948

	
1949
    /// @}
1950

	
1951
  };
1952

	
1953
  /// \ingroup matching
1954
  ///
1955
  /// \brief Weighted perfect matching in general graphs
1956
  ///
1957
  /// This class provides an efficient implementation of Edmond's
1958
  /// maximum weighted perfect matching algorithm. The implementation
1959
  /// is based on extensive use of priority queues and provides
1960
  /// \f$O(nm\log(n))\f$ time complexity.
1961
  ///
1962
  /// The maximum weighted matching problem is to find undirected
1963
  /// edges in the graph with maximum overall weight and no two of
1964
  /// them shares their ends and covers all nodes. The problem can be
1965
  /// formulated with the following linear program.
1966
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1967
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
1968
      \quad \forall B\in\mathcal{O}\f] */
1969
  /// \f[x_e \ge 0\quad \forall e\in E\f]
1970
  /// \f[\max \sum_{e\in E}x_ew_e\f]
1971
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1972
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
1973
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
1974
  /// subsets of the nodes.
1975
  ///
1976
  /// The algorithm calculates an optimal matching and a proof of the
1977
  /// optimality. The solution of the dual problem can be used to check
1978
  /// the result of the algorithm. The dual linear problem is the
1979
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
1980
      w_{uv} \quad \forall uv\in E\f] */
1981
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
1982
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
1983
      \frac{\vert B \vert - 1}{2}z_B\f] */
1984
  ///
1985
  /// The algorithm can be executed with \c run() or the \c init() and
1986
  /// then the \c start() member functions. After it the matching can
1987
  /// be asked with \c matching() or mate() functions. The dual
1988
  /// solution can be get with \c nodeValue(), \c blossomNum() and \c
1989
  /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
1990
  /// "BlossomIt" nested class which is able to iterate on the nodes
1991
  /// of a blossom. If the value type is integral then the dual
1992
  /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
1993
  template <typename _Graph,
1994
            typename _WeightMap = typename _Graph::template EdgeMap<int> >
1995
  class MaxWeightedPerfectMatching {
1996
  public:
1997

	
1998
    typedef _Graph Graph;
1999
    typedef _WeightMap WeightMap;
2000
    typedef typename WeightMap::Value Value;
2001

	
2002
    /// \brief Scaling factor for dual solution
2003
    ///
2004
    /// Scaling factor for dual solution, it is equal to 4 or 1
2005
    /// according to the value type.
2006
    static const int dualScale =
2007
      std::numeric_limits<Value>::is_integer ? 4 : 1;
2008

	
2009
    typedef typename Graph::template NodeMap<typename Graph::Arc>
2010
    MatchingMap;
2011

	
2012
  private:
2013

	
2014
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
2015

	
2016
    typedef typename Graph::template NodeMap<Value> NodePotential;
2017
    typedef std::vector<Node> BlossomNodeList;
2018

	
2019
    struct BlossomVariable {
2020
      int begin, end;
2021
      Value value;
2022

	
2023
      BlossomVariable(int _begin, int _end, Value _value)
2024
        : begin(_begin), end(_end), value(_value) {}
2025

	
2026
    };
2027

	
2028
    typedef std::vector<BlossomVariable> BlossomPotential;
2029

	
2030
    const Graph& _graph;
2031
    const WeightMap& _weight;
2032

	
2033
    MatchingMap* _matching;
2034

	
2035
    NodePotential* _node_potential;
2036

	
2037
    BlossomPotential _blossom_potential;
2038
    BlossomNodeList _blossom_node_list;
2039

	
2040
    int _node_num;
2041
    int _blossom_num;
2042

	
2043
    typedef RangeMap<int> IntIntMap;
2044

	
2045
    enum Status {
2046
      EVEN = -1, MATCHED = 0, ODD = 1
2047
    };
2048

	
2049
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2050
    struct BlossomData {
2051
      int tree;
2052
      Status status;
2053
      Arc pred, next;
2054
      Value pot, offset;
2055
    };
2056

	
2057
    IntNodeMap *_blossom_index;
2058
    BlossomSet *_blossom_set;
2059
    RangeMap<BlossomData>* _blossom_data;
2060

	
2061
    IntNodeMap *_node_index;
2062
    IntArcMap *_node_heap_index;
2063

	
2064
    struct NodeData {
2065

	
2066
      NodeData(IntArcMap& node_heap_index)
2067
        : heap(node_heap_index) {}
2068

	
2069
      int blossom;
2070
      Value pot;
2071
      BinHeap<Value, IntArcMap> heap;
2072
      std::map<int, Arc> heap_index;
2073

	
2074
      int tree;
2075
    };
2076

	
2077
    RangeMap<NodeData>* _node_data;
2078

	
2079
    typedef ExtendFindEnum<IntIntMap> TreeSet;
2080

	
2081
    IntIntMap *_tree_set_index;
2082
    TreeSet *_tree_set;
2083

	
2084
    IntIntMap *_delta2_index;
2085
    BinHeap<Value, IntIntMap> *_delta2;
2086

	
2087
    IntEdgeMap *_delta3_index;
2088
    BinHeap<Value, IntEdgeMap> *_delta3;
2089

	
2090
    IntIntMap *_delta4_index;
2091
    BinHeap<Value, IntIntMap> *_delta4;
2092

	
2093
    Value _delta_sum;
2094

	
2095
    void createStructures() {
2096
      _node_num = countNodes(_graph);
2097
      _blossom_num = _node_num * 3 / 2;
2098

	
2099
      if (!_matching) {
2100
        _matching = new MatchingMap(_graph);
2101
      }
2102
      if (!_node_potential) {
2103
        _node_potential = new NodePotential(_graph);
2104
      }
2105
      if (!_blossom_set) {
2106
        _blossom_index = new IntNodeMap(_graph);
2107
        _blossom_set = new BlossomSet(*_blossom_index);
2108
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2109
      }
2110

	
2111
      if (!_node_index) {
2112
        _node_index = new IntNodeMap(_graph);
2113
        _node_heap_index = new IntArcMap(_graph);
2114
        _node_data = new RangeMap<NodeData>(_node_num,
2115
                                            NodeData(*_node_heap_index));
2116
      }
2117

	
2118
      if (!_tree_set) {
2119
        _tree_set_index = new IntIntMap(_blossom_num);
2120
        _tree_set = new TreeSet(*_tree_set_index);
2121
      }
2122
      if (!_delta2) {
2123
        _delta2_index = new IntIntMap(_blossom_num);
2124
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2125
      }
2126
      if (!_delta3) {
2127
        _delta3_index = new IntEdgeMap(_graph);
2128
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2129
      }
2130
      if (!_delta4) {
2131
        _delta4_index = new IntIntMap(_blossom_num);
2132
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2133
      }
2134
    }
2135

	
2136
    void destroyStructures() {
2137
      _node_num = countNodes(_graph);
2138
      _blossom_num = _node_num * 3 / 2;
2139

	
2140
      if (_matching) {
2141
        delete _matching;
2142
      }
2143
      if (_node_potential) {
2144
        delete _node_potential;
2145
      }
2146
      if (_blossom_set) {
2147
        delete _blossom_index;
2148
        delete _blossom_set;
2149
        delete _blossom_data;
2150
      }
2151

	
2152
      if (_node_index) {
2153
        delete _node_index;
2154
        delete _node_heap_index;
2155
        delete _node_data;
2156
      }
2157

	
2158
      if (_tree_set) {
2159
        delete _tree_set_index;
2160
        delete _tree_set;
2161
      }
2162
      if (_delta2) {
2163
        delete _delta2_index;
2164
        delete _delta2;
2165
      }
2166
      if (_delta3) {
2167
        delete _delta3_index;
2168
        delete _delta3;
2169
      }
2170
      if (_delta4) {
2171
        delete _delta4_index;
2172
        delete _delta4;
2173
      }
2174
    }
2175

	
2176
    void matchedToEven(int blossom, int tree) {
2177
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2178
        _delta2->erase(blossom);
2179
      }
2180

	
2181
      if (!_blossom_set->trivial(blossom)) {
2182
        (*_blossom_data)[blossom].pot -=
2183
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2184
      }
2185

	
2186
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2187
           n != INVALID; ++n) {
2188

	
2189
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2190
        int ni = (*_node_index)[n];
2191

	
2192
        (*_node_data)[ni].heap.clear();
2193
        (*_node_data)[ni].heap_index.clear();
2194

	
2195
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2196

	
2197
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2198
          Node v = _graph.source(e);
2199
          int vb = _blossom_set->find(v);
2200
          int vi = (*_node_index)[v];
2201

	
2202
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2203
            dualScale * _weight[e];
2204

	
2205
          if ((*_blossom_data)[vb].status == EVEN) {
2206
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2207
              _delta3->push(e, rw / 2);
2208
            }
2209
          } else {
2210
            typename std::map<int, Arc>::iterator it =
2211
              (*_node_data)[vi].heap_index.find(tree);
2212

	
2213
            if (it != (*_node_data)[vi].heap_index.end()) {
2214
              if ((*_node_data)[vi].heap[it->second] > rw) {
2215
                (*_node_data)[vi].heap.replace(it->second, e);
2216
                (*_node_data)[vi].heap.decrease(e, rw);
2217
                it->second = e;
2218
              }
2219
            } else {
2220
              (*_node_data)[vi].heap.push(e, rw);
2221
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2222
            }
2223

	
2224
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2225
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2226

	
2227
              if ((*_blossom_data)[vb].status == MATCHED) {
2228
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2229
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2230
                               (*_blossom_data)[vb].offset);
2231
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2232
                           (*_blossom_data)[vb].offset){
2233
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2234
                                   (*_blossom_data)[vb].offset);
2235
                }
2236
              }
2237
            }
2238
          }
2239
        }
2240
      }
2241
      (*_blossom_data)[blossom].offset = 0;
2242
    }
2243

	
2244
    void matchedToOdd(int blossom) {
2245
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2246
        _delta2->erase(blossom);
2247
      }
2248
      (*_blossom_data)[blossom].offset += _delta_sum;
2249
      if (!_blossom_set->trivial(blossom)) {
2250
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2251
                     (*_blossom_data)[blossom].offset);
2252
      }
2253
    }
2254

	
2255
    void evenToMatched(int blossom, int tree) {
2256
      if (!_blossom_set->trivial(blossom)) {
2257
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2258
      }
2259

	
2260
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2261
           n != INVALID; ++n) {
2262
        int ni = (*_node_index)[n];
2263
        (*_node_data)[ni].pot -= _delta_sum;
2264

	
2265
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2266
          Node v = _graph.source(e);
2267
          int vb = _blossom_set->find(v);
2268
          int vi = (*_node_index)[v];
2269

	
2270
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2271
            dualScale * _weight[e];
2272

	
2273
          if (vb == blossom) {
2274
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2275
              _delta3->erase(e);
2276
            }
2277
          } else if ((*_blossom_data)[vb].status == EVEN) {
2278

	
2279
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2280
              _delta3->erase(e);
2281
            }
2282

	
2283
            int vt = _tree_set->find(vb);
2284

	
2285
            if (vt != tree) {
2286

	
2287
              Arc r = _graph.oppositeArc(e);
2288

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

	
2292
              if (it != (*_node_data)[ni].heap_index.end()) {
2293
                if ((*_node_data)[ni].heap[it->second] > rw) {
2294
                  (*_node_data)[ni].heap.replace(it->second, r);
2295
                  (*_node_data)[ni].heap.decrease(r, rw);
2296
                  it->second = r;
2297
                }
2298
              } else {
2299
                (*_node_data)[ni].heap.push(r, rw);
2300
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2301
              }
2302

	
2303
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2304
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2305

	
2306
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2307
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2308
                               (*_blossom_data)[blossom].offset);
2309
                } else if ((*_delta2)[blossom] >
2310
                           _blossom_set->classPrio(blossom) -
2311
                           (*_blossom_data)[blossom].offset){
2312
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2313
                                   (*_blossom_data)[blossom].offset);
2314
                }
2315
              }
2316
            }
2317
          } else {
2318

	
2319
            typename std::map<int, Arc>::iterator it =
2320
              (*_node_data)[vi].heap_index.find(tree);
2321

	
2322
            if (it != (*_node_data)[vi].heap_index.end()) {
2323
              (*_node_data)[vi].heap.erase(it->second);
2324
              (*_node_data)[vi].heap_index.erase(it);
2325
              if ((*_node_data)[vi].heap.empty()) {
2326
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
2327
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2328
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2329
              }
2330

	
2331
              if ((*_blossom_data)[vb].status == MATCHED) {
2332
                if (_blossom_set->classPrio(vb) ==
2333
                    std::numeric_limits<Value>::max()) {
2334
                  _delta2->erase(vb);
2335
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2336
                           (*_blossom_data)[vb].offset) {
2337
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
2338
                                   (*_blossom_data)[vb].offset);
2339
                }
2340
              }
2341
            }
2342
          }
2343
        }
2344
      }
2345
    }
2346

	
2347
    void oddToMatched(int blossom) {
2348
      (*_blossom_data)[blossom].offset -= _delta_sum;
2349

	
2350
      if (_blossom_set->classPrio(blossom) !=
2351
          std::numeric_limits<Value>::max()) {
2352
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2353
                       (*_blossom_data)[blossom].offset);
2354
      }
2355

	
2356
      if (!_blossom_set->trivial(blossom)) {
2357
        _delta4->erase(blossom);
2358
      }
2359
    }
2360

	
2361
    void oddToEven(int blossom, int tree) {
2362
      if (!_blossom_set->trivial(blossom)) {
2363
        _delta4->erase(blossom);
2364
        (*_blossom_data)[blossom].pot -=
2365
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2366
      }
2367

	
2368
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2369
           n != INVALID; ++n) {
2370
        int ni = (*_node_index)[n];
2371

	
2372
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2373

	
2374
        (*_node_data)[ni].heap.clear();
2375
        (*_node_data)[ni].heap_index.clear();
2376
        (*_node_data)[ni].pot +=
2377
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
2378

	
2379
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2380
          Node v = _graph.source(e);
2381
          int vb = _blossom_set->find(v);
2382
          int vi = (*_node_index)[v];
2383

	
2384
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2385
            dualScale * _weight[e];
2386

	
2387
          if ((*_blossom_data)[vb].status == EVEN) {
2388
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2389
              _delta3->push(e, rw / 2);
2390
            }
2391
          } else {
2392

	
2393
            typename std::map<int, Arc>::iterator it =
2394
              (*_node_data)[vi].heap_index.find(tree);
2395

	
2396
            if (it != (*_node_data)[vi].heap_index.end()) {
2397
              if ((*_node_data)[vi].heap[it->second] > rw) {
2398
                (*_node_data)[vi].heap.replace(it->second, e);
2399
                (*_node_data)[vi].heap.decrease(e, rw);
2400
                it->second = e;
2401
              }
2402
            } else {
2403
              (*_node_data)[vi].heap.push(e, rw);
2404
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2405
            }
2406

	
2407
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2408
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2409

	
2410
              if ((*_blossom_data)[vb].status == MATCHED) {
2411
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2412
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2413
                               (*_blossom_data)[vb].offset);
2414
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2415
                           (*_blossom_data)[vb].offset) {
2416
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2417
                                   (*_blossom_data)[vb].offset);
2418
                }
2419
              }
2420
            }
2421
          }
2422
        }
2423
      }
2424
      (*_blossom_data)[blossom].offset = 0;
2425
    }
2426

	
2427
    void alternatePath(int even, int tree) {
2428
      int odd;
2429

	
2430
      evenToMatched(even, tree);
2431
      (*_blossom_data)[even].status = MATCHED;
2432

	
2433
      while ((*_blossom_data)[even].pred != INVALID) {
2434
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2435
        (*_blossom_data)[odd].status = MATCHED;
2436
        oddToMatched(odd);
2437
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2438

	
2439
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2440
        (*_blossom_data)[even].status = MATCHED;
2441
        evenToMatched(even, tree);
2442
        (*_blossom_data)[even].next =
2443
          _graph.oppositeArc((*_blossom_data)[odd].pred);
2444
      }
2445

	
2446
    }
2447

	
2448
    void destroyTree(int tree) {
2449
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2450
        if ((*_blossom_data)[b].status == EVEN) {
2451
          (*_blossom_data)[b].status = MATCHED;
2452
          evenToMatched(b, tree);
2453
        } else if ((*_blossom_data)[b].status == ODD) {
2454
          (*_blossom_data)[b].status = MATCHED;
2455
          oddToMatched(b);
2456
        }
2457
      }
2458
      _tree_set->eraseClass(tree);
2459
    }
2460

	
2461
    void augmentOnEdge(const Edge& edge) {
2462

	
2463
      int left = _blossom_set->find(_graph.u(edge));
2464
      int right = _blossom_set->find(_graph.v(edge));
2465

	
2466
      int left_tree = _tree_set->find(left);
2467
      alternatePath(left, left_tree);
2468
      destroyTree(left_tree);
2469

	
2470
      int right_tree = _tree_set->find(right);
2471
      alternatePath(right, right_tree);
2472
      destroyTree(right_tree);
2473

	
2474
      (*_blossom_data)[left].next = _graph.direct(edge, true);
2475
      (*_blossom_data)[right].next = _graph.direct(edge, false);
2476
    }
2477

	
2478
    void extendOnArc(const Arc& arc) {
2479
      int base = _blossom_set->find(_graph.target(arc));
2480
      int tree = _tree_set->find(base);
2481

	
2482
      int odd = _blossom_set->find(_graph.source(arc));
2483
      _tree_set->insert(odd, tree);
2484
      (*_blossom_data)[odd].status = ODD;
2485
      matchedToOdd(odd);
2486
      (*_blossom_data)[odd].pred = arc;
2487

	
2488
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2489
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2490
      _tree_set->insert(even, tree);
2491
      (*_blossom_data)[even].status = EVEN;
2492
      matchedToEven(even, tree);
2493
    }
2494

	
2495
    void shrinkOnEdge(const Edge& edge, int tree) {
2496
      int nca = -1;
2497
      std::vector<int> left_path, right_path;
2498

	
2499
      {
2500
        std::set<int> left_set, right_set;
2501
        int left = _blossom_set->find(_graph.u(edge));
2502
        left_path.push_back(left);
2503
        left_set.insert(left);
2504

	
2505
        int right = _blossom_set->find(_graph.v(edge));
2506
        right_path.push_back(right);
2507
        right_set.insert(right);
2508

	
2509
        while (true) {
2510

	
2511
          if ((*_blossom_data)[left].pred == INVALID) break;
2512

	
2513
          left =
2514
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2515
          left_path.push_back(left);
2516
          left =
2517
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2518
          left_path.push_back(left);
2519

	
2520
          left_set.insert(left);
2521

	
2522
          if (right_set.find(left) != right_set.end()) {
2523
            nca = left;
2524
            break;
2525
          }
2526

	
2527
          if ((*_blossom_data)[right].pred == INVALID) break;
2528

	
2529
          right =
2530
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2531
          right_path.push_back(right);
2532
          right =
2533
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2534
          right_path.push_back(right);
2535

	
2536
          right_set.insert(right);
2537

	
2538
          if (left_set.find(right) != left_set.end()) {
2539
            nca = right;
2540
            break;
2541
          }
2542

	
2543
        }
2544

	
2545
        if (nca == -1) {
2546
          if ((*_blossom_data)[left].pred == INVALID) {
2547
            nca = right;
2548
            while (left_set.find(nca) == left_set.end()) {
2549
              nca =
2550
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2551
              right_path.push_back(nca);
2552
              nca =
2553
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2554
              right_path.push_back(nca);
2555
            }
2556
          } else {
2557
            nca = left;
2558
            while (right_set.find(nca) == right_set.end()) {
2559
              nca =
2560
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2561
              left_path.push_back(nca);
2562
              nca =
2563
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2564
              left_path.push_back(nca);
2565
            }
2566
          }
2567
        }
2568
      }
2569

	
2570
      std::vector<int> subblossoms;
2571
      Arc prev;
2572

	
2573
      prev = _graph.direct(edge, true);
2574
      for (int i = 0; left_path[i] != nca; i += 2) {
2575
        subblossoms.push_back(left_path[i]);
2576
        (*_blossom_data)[left_path[i]].next = prev;
2577
        _tree_set->erase(left_path[i]);
2578

	
2579
        subblossoms.push_back(left_path[i + 1]);
2580
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
2581
        oddToEven(left_path[i + 1], tree);
2582
        _tree_set->erase(left_path[i + 1]);
2583
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2584
      }
2585

	
2586
      int k = 0;
2587
      while (right_path[k] != nca) ++k;
2588

	
2589
      subblossoms.push_back(nca);
2590
      (*_blossom_data)[nca].next = prev;
2591

	
2592
      for (int i = k - 2; i >= 0; i -= 2) {
2593
        subblossoms.push_back(right_path[i + 1]);
2594
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
2595
        oddToEven(right_path[i + 1], tree);
2596
        _tree_set->erase(right_path[i + 1]);
2597

	
2598
        (*_blossom_data)[right_path[i + 1]].next =
2599
          (*_blossom_data)[right_path[i + 1]].pred;
2600

	
2601
        subblossoms.push_back(right_path[i]);
2602
        _tree_set->erase(right_path[i]);
2603
      }
2604

	
2605
      int surface =
2606
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
2607

	
2608
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2609
        if (!_blossom_set->trivial(subblossoms[i])) {
2610
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2611
        }
2612
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
2613
      }
2614

	
2615
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
2616
      (*_blossom_data)[surface].offset = 0;
2617
      (*_blossom_data)[surface].status = EVEN;
2618
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2619
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2620

	
2621
      _tree_set->insert(surface, tree);
2622
      _tree_set->erase(nca);
2623
    }
2624

	
2625
    void splitBlossom(int blossom) {
2626
      Arc next = (*_blossom_data)[blossom].next;
2627
      Arc pred = (*_blossom_data)[blossom].pred;
2628

	
2629
      int tree = _tree_set->find(blossom);
2630

	
2631
      (*_blossom_data)[blossom].status = MATCHED;
2632
      oddToMatched(blossom);
2633
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2634
        _delta2->erase(blossom);
2635
      }
2636

	
2637
      std::vector<int> subblossoms;
2638
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
2639

	
2640
      Value offset = (*_blossom_data)[blossom].offset;
2641
      int b = _blossom_set->find(_graph.source(pred));
2642
      int d = _blossom_set->find(_graph.source(next));
2643

	
2644
      int ib = -1, id = -1;
2645
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2646
        if (subblossoms[i] == b) ib = i;
2647
        if (subblossoms[i] == d) id = i;
2648

	
2649
        (*_blossom_data)[subblossoms[i]].offset = offset;
2650
        if (!_blossom_set->trivial(subblossoms[i])) {
2651
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2652
        }
2653
        if (_blossom_set->classPrio(subblossoms[i]) !=
2654
            std::numeric_limits<Value>::max()) {
2655
          _delta2->push(subblossoms[i],
2656
                        _blossom_set->classPrio(subblossoms[i]) -
2657
                        (*_blossom_data)[subblossoms[i]].offset);
2658
        }
2659
      }
2660

	
2661
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2662
        for (int i = (id + 1) % subblossoms.size();
2663
             i != ib; i = (i + 2) % subblossoms.size()) {
2664
          int sb = subblossoms[i];
2665
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2666
          (*_blossom_data)[sb].next =
2667
            _graph.oppositeArc((*_blossom_data)[tb].next);
2668
        }
2669

	
2670
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2671
          int sb = subblossoms[i];
2672
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2673
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2674

	
2675
          (*_blossom_data)[sb].status = ODD;
2676
          matchedToOdd(sb);
2677
          _tree_set->insert(sb, tree);
2678
          (*_blossom_data)[sb].pred = pred;
2679
          (*_blossom_data)[sb].next =
2680
                           _graph.oppositeArc((*_blossom_data)[tb].next);
2681

	
2682
          pred = (*_blossom_data)[ub].next;
2683

	
2684
          (*_blossom_data)[tb].status = EVEN;
2685
          matchedToEven(tb, tree);
2686
          _tree_set->insert(tb, tree);
2687
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2688
        }
2689

	
2690
        (*_blossom_data)[subblossoms[id]].status = ODD;
2691
        matchedToOdd(subblossoms[id]);
2692
        _tree_set->insert(subblossoms[id], tree);
2693
        (*_blossom_data)[subblossoms[id]].next = next;
2694
        (*_blossom_data)[subblossoms[id]].pred = pred;
2695

	
2696
      } else {
2697

	
2698
        for (int i = (ib + 1) % subblossoms.size();
2699
             i != id; i = (i + 2) % subblossoms.size()) {
2700
          int sb = subblossoms[i];
2701
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2702
          (*_blossom_data)[sb].next =
2703
            _graph.oppositeArc((*_blossom_data)[tb].next);
2704
        }
2705

	
2706
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2707
          int sb = subblossoms[i];
2708
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2709
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2710

	
2711
          (*_blossom_data)[sb].status = ODD;
2712
          matchedToOdd(sb);
2713
          _tree_set->insert(sb, tree);
2714
          (*_blossom_data)[sb].next = next;
2715
          (*_blossom_data)[sb].pred =
2716
            _graph.oppositeArc((*_blossom_data)[tb].next);
2717

	
2718
          (*_blossom_data)[tb].status = EVEN;
2719
          matchedToEven(tb, tree);
2720
          _tree_set->insert(tb, tree);
2721
          (*_blossom_data)[tb].pred =
2722
            (*_blossom_data)[tb].next =
2723
            _graph.oppositeArc((*_blossom_data)[ub].next);
2724
          next = (*_blossom_data)[ub].next;
2725
        }
2726

	
2727
        (*_blossom_data)[subblossoms[ib]].status = ODD;
2728
        matchedToOdd(subblossoms[ib]);
2729
        _tree_set->insert(subblossoms[ib], tree);
2730
        (*_blossom_data)[subblossoms[ib]].next = next;
2731
        (*_blossom_data)[subblossoms[ib]].pred = pred;
2732
      }
2733
      _tree_set->erase(blossom);
2734
    }
2735

	
2736
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2737
      if (_blossom_set->trivial(blossom)) {
2738
        int bi = (*_node_index)[base];
2739
        Value pot = (*_node_data)[bi].pot;
2740

	
2741
        _matching->set(base, matching);
2742
        _blossom_node_list.push_back(base);
2743
        _node_potential->set(base, pot);
2744
      } else {
2745

	
2746
        Value pot = (*_blossom_data)[blossom].pot;
2747
        int bn = _blossom_node_list.size();
2748

	
2749
        std::vector<int> subblossoms;
2750
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
2751
        int b = _blossom_set->find(base);
2752
        int ib = -1;
2753
        for (int i = 0; i < int(subblossoms.size()); ++i) {
2754
          if (subblossoms[i] == b) { ib = i; break; }
2755
        }
2756

	
2757
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
2758
          int sb = subblossoms[(ib + i) % subblossoms.size()];
2759
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2760

	
2761
          Arc m = (*_blossom_data)[tb].next;
2762
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2763
          extractBlossom(tb, _graph.source(m), m);
2764
        }
2765
        extractBlossom(subblossoms[ib], base, matching);
2766

	
2767
        int en = _blossom_node_list.size();
2768

	
2769
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2770
      }
2771
    }
2772

	
2773
    void extractMatching() {
2774
      std::vector<int> blossoms;
2775
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2776
        blossoms.push_back(c);
2777
      }
2778

	
2779
      for (int i = 0; i < int(blossoms.size()); ++i) {
2780

	
2781
        Value offset = (*_blossom_data)[blossoms[i]].offset;
2782
        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2783
        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2784
             n != INVALID; ++n) {
2785
          (*_node_data)[(*_node_index)[n]].pot -= offset;
2786
        }
2787

	
2788
        Arc matching = (*_blossom_data)[blossoms[i]].next;
2789
        Node base = _graph.source(matching);
2790
        extractBlossom(blossoms[i], base, matching);
2791
      }
2792
    }
2793

	
2794
  public:
2795

	
2796
    /// \brief Constructor
2797
    ///
2798
    /// Constructor.
2799
    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2800
      : _graph(graph), _weight(weight), _matching(0),
2801
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
2802
        _node_num(0), _blossom_num(0),
2803

	
2804
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
2805
        _node_index(0), _node_heap_index(0), _node_data(0),
2806
        _tree_set_index(0), _tree_set(0),
2807

	
2808
        _delta2_index(0), _delta2(0),
2809
        _delta3_index(0), _delta3(0),
2810
        _delta4_index(0), _delta4(0),
2811

	
2812
        _delta_sum() {}
2813

	
2814
    ~MaxWeightedPerfectMatching() {
2815
      destroyStructures();
2816
    }
2817

	
2818
    /// \name Execution control
2819
    /// The simplest way to execute the algorithm is to use the
2820
    /// \c run() member function.
2821

	
2822
    ///@{
2823

	
2824
    /// \brief Initialize the algorithm
2825
    ///
2826
    /// Initialize the algorithm
2827
    void init() {
2828
      createStructures();
2829

	
2830
      for (ArcIt e(_graph); e != INVALID; ++e) {
2831
        _node_heap_index->set(e, BinHeap<Value, IntArcMap>::PRE_HEAP);
2832
      }
2833
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2834
        _delta3_index->set(e, _delta3->PRE_HEAP);
2835
      }
2836
      for (int i = 0; i < _blossom_num; ++i) {
2837
        _delta2_index->set(i, _delta2->PRE_HEAP);
2838
        _delta4_index->set(i, _delta4->PRE_HEAP);
2839
      }
2840

	
2841
      int index = 0;
2842
      for (NodeIt n(_graph); n != INVALID; ++n) {
2843
        Value max = - std::numeric_limits<Value>::max();
2844
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2845
          if (_graph.target(e) == n) continue;
2846
          if ((dualScale * _weight[e]) / 2 > max) {
2847
            max = (dualScale * _weight[e]) / 2;
2848
          }
2849
        }
2850
        _node_index->set(n, index);
2851
        (*_node_data)[index].pot = max;
2852
        int blossom =
2853
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
2854

	
2855
        _tree_set->insert(blossom);
2856

	
2857
        (*_blossom_data)[blossom].status = EVEN;
2858
        (*_blossom_data)[blossom].pred = INVALID;
2859
        (*_blossom_data)[blossom].next = INVALID;
2860
        (*_blossom_data)[blossom].pot = 0;
2861
        (*_blossom_data)[blossom].offset = 0;
2862
        ++index;
2863
      }
2864
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2865
        int si = (*_node_index)[_graph.u(e)];
2866
        int ti = (*_node_index)[_graph.v(e)];
2867
        if (_graph.u(e) != _graph.v(e)) {
2868
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2869
                            dualScale * _weight[e]) / 2);
2870
        }
2871
      }
2872
    }
2873

	
2874
    /// \brief Starts the algorithm
2875
    ///
2876
    /// Starts the algorithm
2877
    bool start() {
2878
      enum OpType {
2879
        D2, D3, D4
2880
      };
2881

	
2882
      int unmatched = _node_num;
2883
      while (unmatched > 0) {
2884
        Value d2 = !_delta2->empty() ?
2885
          _delta2->prio() : std::numeric_limits<Value>::max();
2886

	
2887
        Value d3 = !_delta3->empty() ?
2888
          _delta3->prio() : std::numeric_limits<Value>::max();
2889

	
2890
        Value d4 = !_delta4->empty() ?
2891
          _delta4->prio() : std::numeric_limits<Value>::max();
2892

	
2893
        _delta_sum = d2; OpType ot = D2;
2894
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
2895
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2896

	
2897
        if (_delta_sum == std::numeric_limits<Value>::max()) {
2898
          return false;
2899
        }
2900

	
2901
        switch (ot) {
2902
        case D2:
2903
          {
2904
            int blossom = _delta2->top();
2905
            Node n = _blossom_set->classTop(blossom);
2906
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
2907
            extendOnArc(e);
2908
          }
2909
          break;
2910
        case D3:
2911
          {
2912
            Edge e = _delta3->top();
2913

	
2914
            int left_blossom = _blossom_set->find(_graph.u(e));
2915
            int right_blossom = _blossom_set->find(_graph.v(e));
2916

	
2917
            if (left_blossom == right_blossom) {
2918
              _delta3->pop();
2919
            } else {
2920
              int left_tree = _tree_set->find(left_blossom);
2921
              int right_tree = _tree_set->find(right_blossom);
2922

	
2923
              if (left_tree == right_tree) {
2924
                shrinkOnEdge(e, left_tree);
2925
              } else {
2926
                augmentOnEdge(e);
2927
                unmatched -= 2;
2928
              }
2929
            }
2930
          } break;
2931
        case D4:
2932
          splitBlossom(_delta4->top());
2933
          break;
2934
        }
2935
      }
2936
      extractMatching();
2937
      return true;
2938
    }
2939

	
2940
    /// \brief Runs %MaxWeightedPerfectMatching algorithm.
2941
    ///
2942
    /// This method runs the %MaxWeightedPerfectMatching algorithm.
2943
    ///
2944
    /// \note mwm.run() is just a shortcut of the following code.
2945
    /// \code
2946
    ///   mwm.init();
2947
    ///   mwm.start();
2948
    /// \endcode
2949
    bool run() {
2950
      init();
2951
      return start();
2952
    }
2953

	
2954
    /// @}
2955

	
2956
    /// \name Primal solution
2957
    /// Functions to get the primal solution, ie. the matching.
2958

	
2959
    /// @{
2960

	
2961
    /// \brief Returns the matching value.
2962
    ///
2963
    /// Returns the matching value.
2964
    Value matchingValue() const {
2965
      Value sum = 0;
2966
      for (NodeIt n(_graph); n != INVALID; ++n) {
2967
        if ((*_matching)[n] != INVALID) {
2968
          sum += _weight[(*_matching)[n]];
2969
        }
2970
      }
2971
      return sum /= 2;
2972
    }
2973

	
2974
    /// \brief Returns true when the edge is in the matching.
2975
    ///
2976
    /// Returns true when the edge is in the matching.
2977
    bool matching(const Edge& edge) const {
2978
      return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
2979
    }
2980

	
2981
    /// \brief Returns the incident matching edge.
2982
    ///
2983
    /// Returns the incident matching arc from given edge.
2984
    Arc matching(const Node& node) const {
2985
      return (*_matching)[node];
2986
    }
2987

	
2988
    /// \brief Returns the mate of the node.
2989
    ///
2990
    /// Returns the adjancent node in a mathcing arc.
2991
    Node mate(const Node& node) const {
2992
      return _graph.target((*_matching)[node]);
2993
    }
2994

	
2995
    /// @}
2996

	
2997
    /// \name Dual solution
2998
    /// Functions to get the dual solution.
2999

	
3000
    /// @{
3001

	
3002
    /// \brief Returns the value of the dual solution.
3003
    ///
3004
    /// Returns the value of the dual solution. It should be equal to
3005
    /// the primal value scaled by \ref dualScale "dual scale".
3006
    Value dualValue() const {
3007
      Value sum = 0;
3008
      for (NodeIt n(_graph); n != INVALID; ++n) {
3009
        sum += nodeValue(n);
3010
      }
3011
      for (int i = 0; i < blossomNum(); ++i) {
3012
        sum += blossomValue(i) * (blossomSize(i) / 2);
3013
      }
3014
      return sum;
3015
    }
3016

	
3017
    /// \brief Returns the value of the node.
3018
    ///
3019
    /// Returns the the value of the node.
3020
    Value nodeValue(const Node& n) const {
3021
      return (*_node_potential)[n];
3022
    }
3023

	
3024
    /// \brief Returns the number of the blossoms in the basis.
3025
    ///
3026
    /// Returns the number of the blossoms in the basis.
3027
    /// \see BlossomIt
3028
    int blossomNum() const {
3029
      return _blossom_potential.size();
3030
    }
3031

	
3032

	
3033
    /// \brief Returns the number of the nodes in the blossom.
3034
    ///
3035
    /// Returns the number of the nodes in the blossom.
3036
    int blossomSize(int k) const {
3037
      return _blossom_potential[k].end - _blossom_potential[k].begin;
3038
    }
3039

	
3040
    /// \brief Returns the value of the blossom.
3041
    ///
3042
    /// Returns the the value of the blossom.
3043
    /// \see BlossomIt
3044
    Value blossomValue(int k) const {
3045
      return _blossom_potential[k].value;
3046
    }
3047

	
3048
    /// \brief Iterator for obtaining the nodes of the blossom.
3049
    ///
3050
    /// Iterator for obtaining the nodes of the blossom. This class
3051
    /// provides a common lemon style iterator for listing a
3052
    /// subset of the nodes.
3053
    class BlossomIt {
3054
    public:
3055

	
3056
      /// \brief Constructor.
3057
      ///
3058
      /// Constructor to get the nodes of the variable.
3059
      BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3060
        : _algorithm(&algorithm)
3061
      {
3062
        _index = _algorithm->_blossom_potential[variable].begin;
3063
        _last = _algorithm->_blossom_potential[variable].end;
3064
      }
3065

	
3066
      /// \brief Conversion to node.
3067
      ///
3068
      /// Conversion to node.
3069
      operator Node() const {
3070
        return _algorithm->_blossom_node_list[_index];
3071
      }
3072

	
3073
      /// \brief Increment operator.
3074
      ///
3075
      /// Increment operator.
3076
      BlossomIt& operator++() {
3077
        ++_index;
3078
        return *this;
3079
      }
3080

	
3081
      /// \brief Validity checking
3082
      ///
3083
      /// Checks whether the iterator is invalid.
3084
      bool operator==(Invalid) const { return _index == _last; }
3085

	
3086
      /// \brief Validity checking
3087
      ///
3088
      /// Checks whether the iterator is valid.
3089
      bool operator!=(Invalid) const { return _index != _last; }
3090

	
3091
    private:
3092
      const MaxWeightedPerfectMatching* _algorithm;
3093
      int _last;
3094
      int _index;
3095
    };
3096

	
3097
    /// @}
3098

	
3099
  };
3100

	
3101

	
3102
} //END OF NAMESPACE LEMON
3103

	
3104
#endif //LEMON_MAX_MATCHING_H
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#include <iostream>
20
#include <sstream>
21
#include <vector>
22
#include <queue>
23
#include <lemon/math.h>
24
#include <cstdlib>
25

	
26
#include <lemon/max_matching.h>
27
#include <lemon/smart_graph.h>
28
#include <lemon/lgf_reader.h>
29

	
30
#include "test_tools.h"
31

	
32
using namespace std;
33
using namespace lemon;
34

	
35
GRAPH_TYPEDEFS(SmartGraph);
36

	
37

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

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

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

	
113
void checkMatching(const SmartGraph& graph,
114
                   const MaxMatching<SmartGraph>& mm) {
115
  int num = 0;
116

	
117
  IntNodeMap comp_index(graph);
118
  UnionFind<IntNodeMap> comp(comp_index);
119

	
120
  int barrier_num = 0;
121

	
122
  for (NodeIt n(graph); n != INVALID; ++n) {
123
    check(mm.decomposition(n) == MaxMatching<SmartGraph>::EVEN ||
124
          mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
125
    if (mm.decomposition(n) == MaxMatching<SmartGraph>::ODD) {
126
      ++barrier_num;
127
    } else {
128
      comp.insert(n);
129
    }
130
  }
131

	
132
  for (EdgeIt e(graph); e != INVALID; ++e) {
133
    if (mm.matching(e)) {
134
      check(e == mm.matching(graph.u(e)), "Wrong matching");
135
      check(e == mm.matching(graph.v(e)), "Wrong matching");
136
      ++num;
137
    }
138
    check(mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
139
          mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
140
          "Wrong Gallai-Edmonds decomposition");
141

	
142
    check(mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
143
          mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
144
          "Wrong Gallai-Edmonds decomposition");
145

	
146
    if (mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
147
        mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
148
      comp.join(graph.u(e), graph.v(e));
149
    }
150
  }
151

	
152
  std::set<int> comp_root;
153
  int odd_comp_num = 0;
154
  for (NodeIt n(graph); n != INVALID; ++n) {
155
    if (mm.decomposition(n) != MaxMatching<SmartGraph>::ODD) {
156
      int root = comp.find(n);
157
      if (comp_root.find(root) == comp_root.end()) {
158
        comp_root.insert(root);
159
        if (comp.size(n) % 2 == 1) {
160
          ++odd_comp_num;
161
        }
162
      }
163
    }
164
  }
165

	
166
  check(mm.matchingSize() == num, "Wrong matching");
167
  check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
168
         "Wrong matching");
169
  return;
170
}
171

	
172
void checkWeightedMatching(const SmartGraph& graph,
173
                   const SmartGraph::EdgeMap<int>& weight,
174
                   const MaxWeightedMatching<SmartGraph>& mwm) {
175
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
176
    if (graph.u(e) == graph.v(e)) continue;
177
    int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
178

	
179
    for (int i = 0; i < mwm.blossomNum(); ++i) {
180
      bool s = false, t = false;
181
      for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
182
           n != INVALID; ++n) {
183
        if (graph.u(e) == n) s = true;
184
        if (graph.v(e) == n) t = true;
185
      }
186
      if (s == true && t == true) {
187
        rw += mwm.blossomValue(i);
188
      }
189
    }
190
    rw -= weight[e] * mwm.dualScale;
191

	
192
    check(rw >= 0, "Negative reduced weight");
193
    check(rw == 0 || !mwm.matching(e),
194
          "Non-zero reduced weight on matching edge");
195
  }
196

	
197
  int pv = 0;
198
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
199
    if (mwm.matching(n) != INVALID) {
200
      check(mwm.nodeValue(n) >= 0, "Invalid node value");
201
      pv += weight[mwm.matching(n)];
202
      SmartGraph::Node o = graph.target(mwm.matching(n));
203
      check(mwm.mate(n) == o, "Invalid matching");
204
      check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
205
            "Invalid matching");
206
    } else {
207
      check(mwm.mate(n) == INVALID, "Invalid matching");
208
      check(mwm.nodeValue(n) == 0, "Invalid matching");
209
    }
210
  }
211

	
212
  int dv = 0;
213
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
214
    dv += mwm.nodeValue(n);
215
  }
216

	
217
  for (int i = 0; i < mwm.blossomNum(); ++i) {
218
    check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
219
    check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
220
    dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
221
  }
222

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

	
225
  return;
226
}
227

	
228
void checkWeightedPerfectMatching(const SmartGraph& graph,
229
                          const SmartGraph::EdgeMap<int>& weight,
230
                          const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
231
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
232
    if (graph.u(e) == graph.v(e)) continue;
233
    int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
234

	
235
    for (int i = 0; i < mwpm.blossomNum(); ++i) {
236
      bool s = false, t = false;
237
      for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
238
           n != INVALID; ++n) {
239
        if (graph.u(e) == n) s = true;
240
        if (graph.v(e) == n) t = true;
241
      }
242
      if (s == true && t == true) {
243
        rw += mwpm.blossomValue(i);
244
      }
245
    }
246
    rw -= weight[e] * mwpm.dualScale;
247

	
248
    check(rw >= 0, "Negative reduced weight");
249
    check(rw == 0 || !mwpm.matching(e),
250
          "Non-zero reduced weight on matching edge");
251
  }
252

	
253
  int pv = 0;
254
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
255
    check(mwpm.matching(n) != INVALID, "Non perfect");
256
    pv += weight[mwpm.matching(n)];
257
    SmartGraph::Node o = graph.target(mwpm.matching(n));
258
    check(mwpm.mate(n) == o, "Invalid matching");
259
    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
260
          "Invalid matching");
261
  }
262

	
263
  int dv = 0;
264
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
265
    dv += mwpm.nodeValue(n);
266
  }
267

	
268
  for (int i = 0; i < mwpm.blossomNum(); ++i) {
269
    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
270
    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
271
    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
272
  }
273

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

	
276
  return;
277
}
278

	
279

	
280
int main() {
281

	
282
  for (int i = 0; i < lgfn; ++i) {
283
    SmartGraph graph;
284
    SmartGraph::EdgeMap<int> weight(graph);
285

	
286
    istringstream lgfs(lgf[i]);
287
    graphReader(graph, lgfs).
288
      edgeMap("weight", weight).run();
289

	
290
    MaxMatching<SmartGraph> mm(graph);
291
    mm.run();
292
    checkMatching(graph, mm);
293

	
294
    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
295
    mwm.run();
296
    checkWeightedMatching(graph, weight, mwm);
297

	
298
    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
299
    bool perfect = mwpm.run();
300

	
301
    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
302
          "Perfect matching found");
303

	
304
    if (perfect) {
305
      checkWeightedPerfectMatching(graph, weight, mwpm);
306
    }
307
  }
308

	
309
  return 0;
310
}
Ignore white space 6 line context
... ...
@@ -35,6 +35,7 @@
35 35
	lemon/list_graph.h \
36 36
	lemon/maps.h \
37 37
	lemon/math.h \
38
	lemon/max_matching.h \
38 39
	lemon/path.h \
39 40
        lemon/random.h \
40 41
	lemon/smart_graph.h \
Ignore white space 6 line context
... ...
@@ -16,6 +16,7 @@
16 16
  heap_test
17 17
  kruskal_test
18 18
  maps_test
19
  max_matching_test
19 20
  random_test
20 21
  path_test
21 22
  time_measure_test
Ignore white space 6 line context
... ...
@@ -19,6 +19,7 @@
19 19
	test/heap_test \
20 20
	test/kruskal_test \
21 21
        test/maps_test \
22
	test/max_matching_test \
22 23
        test/random_test \
23 24
        test/path_test \
24 25
        test/test_tools_fail \
... ...
@@ -42,6 +43,7 @@
42 43
test_heap_test_SOURCES = test/heap_test.cc
43 44
test_kruskal_test_SOURCES = test/kruskal_test.cc
44 45
test_maps_test_SOURCES = test/maps_test.cc
46
test_max_matching_test_SOURCES = test/max_matching_test.cc
45 47
test_path_test_SOURCES = test/path_test.cc
46 48
test_random_test_SOURCES = test/random_test.cc
47 49
test_test_tools_fail_SOURCES = test/test_tools_fail.cc
0 comments (0 inline)