gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Several improvements in maximum matching algorithms - The interface of MaxMatching is changed to be similar to the weighted algorithms - The internal data structure (the queue implementation and the matching map) is changed in the MaxMatching algorithm, which provides better runtime properties - The Blossom iterators are changed slightly in the weighted matching algorithms - Several documentation improvments - The test files are merged
1 4 0
default
5 files changed with 886 insertions and 1017 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -31,76 +31,405 @@
31 31

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

	
36 36
namespace lemon {
37 37

	
38
  ///\ingroup matching
38
  /// \ingroup matching
39 39
  ///
40
  ///\brief Edmonds' alternating forest maximum matching algorithm.
40
  /// \brief Edmonds' alternating forest maximum matching algorithm.
41 41
  ///
42
  ///This class provides Edmonds' alternating forest matching
43
  ///algorithm. The starting matching (if any) can be passed to the
44
  ///algorithm using some of init functions.
42
  /// This class provides Edmonds' alternating forest matching
43
  /// algorithm. The starting matching (if any) can be passed to the
44
  /// algorithm using some of init functions.
45 45
  ///
46
  ///The dual side of a matching is a map of the nodes to
47
  ///MaxMatching::DecompType, having values \c D, \c A and \c C
48
  ///showing the Gallai-Edmonds decomposition of the digraph. The nodes
49
  ///in \c D induce a digraph with factor-critical components, the nodes
50
  ///in \c A form the barrier, and the nodes in \c C induce a digraph
51
  ///having a perfect matching. This decomposition can be attained by
52
  ///calling \c decomposition() after running the algorithm.
46
  /// The dual side of a matching 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 fractor critical components
53
  /// minus the number of barrier nodes is a lower bound on the
54
  /// unmatched nodes, and if the matching is optimal this bound is
55
  /// tight. This decomposition can be attained by calling \c
56
  /// decomposition() after running the algorithm.
53 57
  ///
54
  ///\param Digraph The graph type the algorithm runs on.
55
  template <typename Graph>
58
  /// \param _Graph The graph type the algorithm runs on.
59
  template <typename _Graph>
56 60
  class MaxMatching {
57

	
58
  protected:
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, which
70
    ///shows an upper bound on the size of a maximum matching. The
71
    ///nodes with Status \c EVEN/D induce a graph with factor-critical
72
    ///components, the nodes in \c ODD/A form the canonical barrier,
73
    ///and the nodes in \c MATCHED/C induce a graph having a perfect
74
    ///matching.
75
    enum Status {
76
      EVEN = 1, D = 1, MATCHED = 0, C = 0, ODD = -1, A = -1, UNMATCHED = -2
77
    };
78

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

	
81
  private:
59 82

	
60 83
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
61 84

	
62
    typedef typename Graph::template NodeMap<int> UFECrossRef;
63
    typedef UnionFindEnum<UFECrossRef> UFE;
64
    typedef std::vector<Node> NV;
65

	
66
    typedef typename Graph::template NodeMap<int> EFECrossRef;
67
    typedef ExtendFindEnum<EFECrossRef> EFE;
85
    typedef UnionFindEnum<IntNodeMap> BlossomSet;
86
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
87
    typedef RangeMap<Node> NodeIntMap;
88
    typedef MatchingMap EarMap;
89
    typedef std::vector<Node> NodeQueue;
90

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

	
95
    EarMap* _ear;
96

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

	
101
    IntNodeMap* _tree_set_index;
102
    TreeSet* _tree_set;
103

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

	
107
    int _node_num;
108

	
109
  private:
110

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
279
      {
280

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

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

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

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

	
310
      {
311

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

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

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

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

	
342

	
343

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

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

	
358
    }
359

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

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

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

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

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

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

	
396
    }
68 397

	
69 398
  public:
70 399

	
71
    ///\brief Indicates the Gallai-Edmonds decomposition of the digraph.
400
    /// \brief Constructor
72 401
    ///
73
    ///Indicates the Gallai-Edmonds decomposition of the digraph, which
74
    ///shows an upper bound on the size of a maximum matching. The
75
    ///nodes with DecompType \c D induce a digraph with factor-critical
76
    ///components, the nodes in \c A form the canonical barrier, and the
77
    ///nodes in \c C induce a digraph having a perfect matching.
78
    enum DecompType {
79
      D=0,
80
      A=1,
81
      C=2
82
    };
83

	
84
  protected:
85

	
86
    static const int HEUR_density=2;
87
    const Graph& g;
88
    typename Graph::template NodeMap<Node> _mate;
89
    typename Graph::template NodeMap<DecompType> position;
90

	
91
  public:
92

	
93
    MaxMatching(const Graph& _g)
94
      : g(_g), _mate(_g), position(_g) {}
95

	
96
    ///\brief Sets the actual matching to the empty matching.
402
    /// Constructor.
403
    MaxMatching(const Graph& graph)
404
      : _graph(graph), _matching(0), _status(0), _ear(0),
405
        _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
406
        _tree_set_index(0), _tree_set(0) {}
407

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

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

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

	
422
    ///@{
423

	
424
    /// \brief Sets the actual matching to the empty matching.
97 425
    ///
98
    ///Sets the actual matching to the empty matching.
426
    /// Sets the actual matching to the empty matching.
99 427
    ///
100 428
    void init() {
101
      for(NodeIt v(g); v!=INVALID; ++v) {
102
        _mate.set(v,INVALID);
103
        position.set(v,C);
429
      createStructures();
430
      for(NodeIt n(_graph); n != INVALID; ++n) {
431
        _matching->set(n, INVALID);
432
        _status->set(n, UNMATCHED);
104 433
      }
105 434
    }
106 435

	
... ...
@@ -108,88 +437,96 @@
108 437
    ///
109 438
    ///For initial matchig it finds a maximal greedy matching.
110 439
    void greedyInit() {
111
      for(NodeIt v(g); v!=INVALID; ++v) {
112
        _mate.set(v,INVALID);
113
        position.set(v,C);
440
      createStructures();
441
      for (NodeIt n(_graph); n != INVALID; ++n) {
442
        _matching->set(n, INVALID);
443
        _status->set(n, UNMATCHED);
114 444
      }
115
      for(NodeIt v(g); v!=INVALID; ++v)
116
        if ( _mate[v]==INVALID ) {
117
          for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) {
118
            Node y=g.runningNode(e);
119
            if ( _mate[y]==INVALID && y!=v ) {
120
              _mate.set(v,y);
121
              _mate.set(y,v);
445
      for (NodeIt n(_graph); n != INVALID; ++n) {
446
        if ((*_matching)[n] == INVALID) {
447
          for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
448
            Node v = _graph.target(a);
449
            if ((*_matching)[v] == INVALID && v != n) {
450
              _matching->set(n, a);
451
              _status->set(n, MATCHED);
452
              _matching->set(v, _graph.oppositeArc(a));
453
              _status->set(v, MATCHED);
122 454
              break;
123 455
            }
124 456
          }
125 457
        }
126
    }
127

	
128
    ///\brief Initialize the matching from each nodes' mate.
129
    ///
130
    ///Initialize the matching from a \c Node valued \c Node map. This
131
    ///map must be \e symmetric, i.e. if \c map[u]==v then \c
132
    ///map[v]==u must hold, and \c uv will be an arc of the initial
133
    ///matching.
134
    template <typename MateMap>
135
    void mateMapInit(MateMap& map) {
136
      for(NodeIt v(g); v!=INVALID; ++v) {
137
        _mate.set(v,map[v]);
138
        position.set(v,C);
139 458
      }
140 459
    }
141 460

	
142
    ///\brief Initialize the matching from a node map with the
143
    ///incident matching arcs.
461

	
462
    /// \brief Initialize the matching from the map containing a matching.
144 463
    ///
145
    ///Initialize the matching from an \c Edge valued \c Node map. \c
146
    ///map[v] must be an \c Edge incident to \c v. This map must have
147
    ///the property that if \c g.oppositeNode(u,map[u])==v then \c \c
148
    ///g.oppositeNode(v,map[v])==u holds, and now some arc joining \c
149
    ///u to \c v will be an arc of the matching.
150
    template<typename MatchingMap>
151
    void matchingMapInit(MatchingMap& map) {
152
      for(NodeIt v(g); v!=INVALID; ++v) {
153
        position.set(v,C);
154
        Edge e=map[v];
155
        if ( e!=INVALID )
156
          _mate.set(v,g.oppositeNode(v,e));
157
        else
158
          _mate.set(v,INVALID);
464
    /// Initialize the matching from a \c bool valued \c Edge map. This
465
    /// map must have the property that there are no two incident edges
466
    /// with true value, ie. it contains a matching.
467
    /// \return %True if the map contains a matching.
468
    template <typename MatchingMap>
469
    bool matchingInit(const MatchingMap& matching) {
470
      createStructures();
471

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

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

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

	
162
    ///\brief Initialize the matching from the map containing the
163
    ///undirected matching arcs.
493
    /// \brief Starts Edmonds' algorithm
164 494
    ///
165
    ///Initialize the matching from a \c bool valued \c Edge map. This
166
    ///map must have the property that there are no two incident arcs
167
    ///\c e, \c f with \c map[e]==map[f]==true. The arcs \c e with \c
168
    ///map[e]==true form the matching.
169
    template <typename MatchingMap>
170
    void matchingInit(MatchingMap& map) {
171
      for(NodeIt v(g); v!=INVALID; ++v) {
172
        _mate.set(v,INVALID);
173
        position.set(v,C);
174
      }
175
      for(EdgeIt e(g); e!=INVALID; ++e) {
176
        if ( map[e] ) {
177
          Node u=g.u(e);
178
          Node v=g.v(e);
179
          _mate.set(u,v);
180
          _mate.set(v,u);
495
    /// If runs the original Edmonds' algorithm.
496
    void startSparse() {
497
      for(NodeIt n(_graph); n != INVALID; ++n) {
498
        if ((*_status)[n] == UNMATCHED) {
499
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
500
          _tree_set->insert(n);
501
          _status->set(n, EVEN);
502
          processSparse(n);
181 503
        }
182 504
      }
183 505
    }
184 506

	
185

	
186
    ///\brief Runs Edmonds' algorithm.
507
    /// \brief Starts Edmonds' algorithm.
187 508
    ///
188
    ///Runs Edmonds' algorithm for sparse digraphs (number of arcs <
189
    ///2*number of nodes), and a heuristical Edmonds' algorithm with a
190
    ///heuristic of postponing shrinks for dense digraphs.
509
    /// It runs Edmonds' algorithm with a heuristic of postponing
510
    /// shrinks, giving a faster algorithm for dense graphs.
511
    void startDense() {
512
      for(NodeIt n(_graph); n != INVALID; ++n) {
513
        if ((*_status)[n] == UNMATCHED) {
514
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
515
          _tree_set->insert(n);
516
          _status->set(n, EVEN);
517
          processDense(n);
518
        }
519
      }
520
    }
521

	
522

	
523
    /// \brief Runs Edmonds' algorithm
524
    ///
525
    /// Runs Edmonds' algorithm for sparse graphs (<tt>m<2*n</tt>)
526
    /// or Edmonds' algorithm with a heuristic of
527
    /// postponing shrinks for dense graphs.
191 528
    void run() {
192
      if (countEdges(g) < HEUR_density * countNodes(g)) {
529
      if (countEdges(_graph) < 2 * countNodes(_graph)) {
193 530
        greedyInit();
194 531
        startSparse();
195 532
      } else {
... ...
@@ -198,422 +535,75 @@
198 535
      }
199 536
    }
200 537

	
201

	
202
    ///\brief Starts Edmonds' algorithm.
203
    ///
204
    ///If runs the original Edmonds' algorithm.
205
    void startSparse() {
206

	
207
      typename Graph::template NodeMap<Node> ear(g,INVALID);
208
      //undefined for the base nodes of the blossoms (i.e. for the
209
      //representative elements of UFE blossom) and for the nodes in C
210

	
211
      UFECrossRef blossom_base(g);
212
      UFE blossom(blossom_base);
213
      NV rep(countNodes(g));
214

	
215
      EFECrossRef tree_base(g);
216
      EFE tree(tree_base);
217

	
218
      //If these UFE's would be members of the class then also
219
      //blossom_base and tree_base should be a member.
220

	
221
      //We build only one tree and the other vertices uncovered by the
222
      //matching belong to C. (They can be considered as singleton
223
      //trees.) If this tree can be augmented or no more
224
      //grow/augmentation/shrink is possible then we return to this
225
      //"for" cycle.
226
      for(NodeIt v(g); v!=INVALID; ++v) {
227
        if (position[v]==C && _mate[v]==INVALID) {
228
          rep[blossom.insert(v)] = v;
229
          tree.insert(v);
230
          position.set(v,D);
231
          normShrink(v, ear, blossom, rep, tree);
232
        }
233
      }
234
    }
235

	
236
    ///\brief Starts Edmonds' algorithm.
237
    ///
238
    ///It runs Edmonds' algorithm with a heuristic of postponing
239
    ///shrinks, giving a faster algorithm for dense digraphs.
240
    void startDense() {
241

	
242
      typename Graph::template NodeMap<Node> ear(g,INVALID);
243
      //undefined for the base nodes of the blossoms (i.e. for the
244
      //representative elements of UFE blossom) and for the nodes in C
245

	
246
      UFECrossRef blossom_base(g);
247
      UFE blossom(blossom_base);
248
      NV rep(countNodes(g));
249

	
250
      EFECrossRef tree_base(g);
251
      EFE tree(tree_base);
252

	
253
      //If these UFE's would be members of the class then also
254
      //blossom_base and tree_base should be a member.
255

	
256
      //We build only one tree and the other vertices uncovered by the
257
      //matching belong to C. (They can be considered as singleton
258
      //trees.) If this tree can be augmented or no more
259
      //grow/augmentation/shrink is possible then we return to this
260
      //"for" cycle.
261
      for(NodeIt v(g); v!=INVALID; ++v) {
262
        if ( position[v]==C && _mate[v]==INVALID ) {
263
          rep[blossom.insert(v)] = v;
264
          tree.insert(v);
265
          position.set(v,D);
266
          lateShrink(v, ear, blossom, rep, tree);
267
        }
268
      }
269
    }
270

	
271

	
538
    /// @}
539

	
540
    /// \name Primal solution
541
    /// Functions for get the primal solution, ie. the matching.
542

	
543
    /// @{
272 544

	
273 545
    ///\brief Returns the size of the actual matching stored.
274 546
    ///
275 547
    ///Returns the size of the actual matching stored. After \ref
276
    ///run() it returns the size of a maximum matching in the digraph.
277
    int size() const {
278
      int s=0;
279
      for(NodeIt v(g); v!=INVALID; ++v) {
280
        if ( _mate[v]!=INVALID ) {
281
          ++s;
548
    ///run() it returns the size of the maximum matching in the graph.
549
    int matchingSize() const {
550
      int size = 0;
551
      for (NodeIt n(_graph); n != INVALID; ++n) {
552
        if ((*_matching)[n] != INVALID) {
553
          ++size;
282 554
        }
283 555
      }
284
      return s/2;
556
      return size / 2;
285 557
    }
286 558

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

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

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

	
296
    ///\brief Returns the matching arc incident to the given node.
297
    ///
298
    ///Returns the matching arc of a \c node in the actual matching.
299
    ///Returns INVALID if the \c node is not covered by the actual matching.
300
    Edge matchingArc(const Node& node) const {
301
      if (_mate[node] == INVALID) return INVALID;
302
      Node n = node < _mate[node] ? node : _mate[node];
303
      for (IncEdgeIt e(g, n); e != INVALID; ++e) {
304
        if (g.oppositeNode(n, e) == _mate[n]) {
305
          return e;
306
        }
307
      }
308
      return INVALID;
309
    }
583
    /// @}
584

	
585
    /// \name Dual solution
586
    /// Functions for get the dual solution, ie. the decomposition.
587

	
588
    /// @{
310 589

	
311 590
    /// \brief Returns the class of the node in the Edmonds-Gallai
312 591
    /// decomposition.
313 592
    ///
314 593
    /// Returns the class of the node in the Edmonds-Gallai
315 594
    /// decomposition.
316
    DecompType decomposition(const Node& n) {
317
      return position[n] == A;
595
    Status decomposition(const Node& n) const {
596
      return (*_status)[n];
318 597
    }
319 598

	
320 599
    /// \brief Returns true when the node is in the barrier.
321 600
    ///
322 601
    /// Returns true when the node is in the barrier.
323
    bool barrier(const Node& n) {
324
      return position[n] == A;
602
    bool barrier(const Node& n) const {
603
      return (*_status)[n] == ODD;
325 604
    }
326 605

	
327
    ///\brief Gives back the matching in a \c Node of mates.
328
    ///
329
    ///Writes the stored matching to a \c Node valued \c Node map. The
330
    ///resulting map will be \e symmetric, i.e. if \c map[u]==v then \c
331
    ///map[v]==u will hold, and now \c uv is an arc of the matching.
332
    template <typename MateMap>
333
    void mateMap(MateMap& map) const {
334
      for(NodeIt v(g); v!=INVALID; ++v) {
335
        map.set(v,_mate[v]);
336
      }
337
    }
338

	
339
    ///\brief Gives back the matching in an \c Edge valued \c Node
340
    ///map.
341
    ///
342
    ///Writes the stored matching to an \c Edge valued \c Node
343
    ///map. \c map[v] will be an \c Edge incident to \c v. This
344
    ///map will have the property that if \c g.oppositeNode(u,map[u])
345
    ///== v then \c map[u]==map[v] holds, and now this arc is an arc
346
    ///of the matching.
347
    template <typename MatchingMap>
348
    void matchingMap(MatchingMap& map)  const {
349
      typename Graph::template NodeMap<bool> todo(g,true);
350
      for(NodeIt v(g); v!=INVALID; ++v) {
351
        if (_mate[v]!=INVALID && v < _mate[v]) {
352
          Node u=_mate[v];
353
          for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
354
            if ( g.runningNode(e) == u ) {
355
              map.set(u,e);
356
              map.set(v,e);
357
              todo.set(u,false);
358
              todo.set(v,false);
359
              break;
360
            }
361
          }
362
        }
363
      }
364
    }
365

	
366

	
367
    ///\brief Gives back the matching in a \c bool valued \c Edge
368
    ///map.
369
    ///
370
    ///Writes the matching stored to a \c bool valued \c Arc
371
    ///map. This map will have the property that there are no two
372
    ///incident arcs \c e, \c f with \c map[e]==map[f]==true. The
373
    ///arcs \c e with \c map[e]==true form the matching.
374
    template<typename MatchingMap>
375
    void matching(MatchingMap& map) const {
376
      for(EdgeIt e(g); e!=INVALID; ++e) map.set(e,false);
377

	
378
      typename Graph::template NodeMap<bool> todo(g,true);
379
      for(NodeIt v(g); v!=INVALID; ++v) {
380
        if ( todo[v] && _mate[v]!=INVALID ) {
381
          Node u=_mate[v];
382
          for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
383
            if ( g.runningNode(e) == u ) {
384
              map.set(e,true);
385
              todo.set(u,false);
386
              todo.set(v,false);
387
              break;
388
            }
389
          }
390
        }
391
      }
392
    }
393

	
394

	
395
    ///\brief Returns the canonical decomposition of the digraph after running
396
    ///the algorithm.
397
    ///
398
    ///After calling any run methods of the class, it writes the
399
    ///Gallai-Edmonds canonical decomposition of the digraph. \c map
400
    ///must be a node map of \ref DecompType 's.
401
    template <typename DecompositionMap>
402
    void decomposition(DecompositionMap& map) const {
403
      for(NodeIt v(g); v!=INVALID; ++v) map.set(v,position[v]);
404
    }
405

	
406
    ///\brief Returns a barrier on the nodes.
407
    ///
408
    ///After calling any run methods of the class, it writes a
409
    ///canonical barrier on the nodes. The odd component number of the
410
    ///remaining digraph minus the barrier size is a lower bound for the
411
    ///uncovered nodes in the digraph. The \c map must be a node map of
412
    ///bools.
413
    template <typename BarrierMap>
414
    void barrier(BarrierMap& barrier) {
415
      for(NodeIt v(g); v!=INVALID; ++v) barrier.set(v,position[v] == A);
416
    }
417

	
418
  private:
419

	
420

	
421
    void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,
422
                    UFE& blossom, NV& rep, EFE& tree) {
423
      //We have one tree which we grow, and also shrink but only if it
424
      //cannot be postponed. If we augment then we return to the "for"
425
      //cycle of runEdmonds().
426

	
427
      std::queue<Node> Q;   //queue of the totally unscanned nodes
428
      Q.push(v);
429
      std::queue<Node> R;
430
      //queue of the nodes which must be scanned for a possible shrink
431

	
432
      while ( !Q.empty() ) {
433
        Node x=Q.front();
434
        Q.pop();
435
        for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
436
          Node y=g.runningNode(e);
437
          //growOrAugment grows if y is covered by the matching and
438
          //augments if not. In this latter case it returns 1.
439
          if (position[y]==C &&
440
              growOrAugment(y, x, ear, blossom, rep, tree, Q)) return;
441
        }
442
        R.push(x);
443
      }
444

	
445
      while ( !R.empty() ) {
446
        Node x=R.front();
447
        R.pop();
448

	
449
        for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
450
          Node y=g.runningNode(e);
451

	
452
          if ( position[y] == D && blossom.find(x) != blossom.find(y) )
453
            //Recall that we have only one tree.
454
            shrink( x, y, ear, blossom, rep, tree, Q);
455

	
456
          while ( !Q.empty() ) {
457
            Node z=Q.front();
458
            Q.pop();
459
            for( IncEdgeIt f(g,z); f!= INVALID; ++f ) {
460
              Node w=g.runningNode(f);
461
              //growOrAugment grows if y is covered by the matching and
462
              //augments if not. In this latter case it returns 1.
463
              if (position[w]==C &&
464
                  growOrAugment(w, z, ear, blossom, rep, tree, Q)) return;
465
            }
466
            R.push(z);
467
          }
468
        } //for e
469
      } // while ( !R.empty() )
470
    }
471

	
472
    void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,
473
                    UFE& blossom, NV& rep, EFE& tree) {
474
      //We have one tree, which we grow and shrink. If we augment then we
475
      //return to the "for" cycle of runEdmonds().
476

	
477
      std::queue<Node> Q;   //queue of the unscanned nodes
478
      Q.push(v);
479
      while ( !Q.empty() ) {
480

	
481
        Node x=Q.front();
482
        Q.pop();
483

	
484
        for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
485
          Node y=g.runningNode(e);
486

	
487
          switch ( position[y] ) {
488
          case D:          //x and y must be in the same tree
489
            if ( blossom.find(x) != blossom.find(y))
490
              //x and y are in the same tree
491
              shrink(x, y, ear, blossom, rep, tree, Q);
492
            break;
493
          case C:
494
            //growOrAugment grows if y is covered by the matching and
495
            //augments if not. In this latter case it returns 1.
496
            if (growOrAugment(y, x, ear, blossom, rep, tree, Q)) return;
497
            break;
498
          default: break;
499
          }
500
        }
501
      }
502
    }
503

	
504
    void shrink(Node x,Node y, typename Graph::template NodeMap<Node>& ear,
505
                UFE& blossom, NV& rep, EFE& tree,std::queue<Node>& Q) {
506
      //x and y are the two adjacent vertices in two blossoms.
507

	
508
      typename Graph::template NodeMap<bool> path(g,false);
509

	
510
      Node b=rep[blossom.find(x)];
511
      path.set(b,true);
512
      b=_mate[b];
513
      while ( b!=INVALID ) {
514
        b=rep[blossom.find(ear[b])];
515
        path.set(b,true);
516
        b=_mate[b];
517
      } //we go until the root through bases of blossoms and odd vertices
518

	
519
      Node top=y;
520
      Node middle=rep[blossom.find(top)];
521
      Node bottom=x;
522
      while ( !path[middle] )
523
        shrinkStep(top, middle, bottom, ear, blossom, rep, tree, Q);
524
      //Until we arrive to a node on the path, we update blossom, tree
525
      //and the positions of the odd nodes.
526

	
527
      Node base=middle;
528
      top=x;
529
      middle=rep[blossom.find(top)];
530
      bottom=y;
531
      Node blossom_base=rep[blossom.find(base)];
532
      while ( middle!=blossom_base )
533
        shrinkStep(top, middle, bottom, ear, blossom, rep, tree, Q);
534
      //Until we arrive to a node on the path, we update blossom, tree
535
      //and the positions of the odd nodes.
536

	
537
      rep[blossom.find(base)] = base;
538
    }
539

	
540
    void shrinkStep(Node& top, Node& middle, Node& bottom,
541
                    typename Graph::template NodeMap<Node>& ear,
542
                    UFE& blossom, NV& rep, EFE& tree, std::queue<Node>& Q) {
543
      //We traverse a blossom and update everything.
544

	
545
      ear.set(top,bottom);
546
      Node t=top;
547
      while ( t!=middle ) {
548
        Node u=_mate[t];
549
        t=ear[u];
550
        ear.set(t,u);
551
      }
552
      bottom=_mate[middle];
553
      position.set(bottom,D);
554
      Q.push(bottom);
555
      top=ear[bottom];
556
      Node oldmiddle=middle;
557
      middle=rep[blossom.find(top)];
558
      tree.erase(bottom);
559
      tree.erase(oldmiddle);
560
      blossom.insert(bottom);
561
      blossom.join(bottom, oldmiddle);
562
      blossom.join(top, oldmiddle);
563
    }
564

	
565

	
566

	
567
    bool growOrAugment(Node& y, Node& x, typename Graph::template
568
                       NodeMap<Node>& ear, UFE& blossom, NV& rep, EFE& tree,
569
                       std::queue<Node>& Q) {
570
      //x is in a blossom in the tree, y is outside. If y is covered by
571
      //the matching we grow, otherwise we augment. In this case we
572
      //return 1.
573

	
574
      if ( _mate[y]!=INVALID ) {       //grow
575
        ear.set(y,x);
576
        Node w=_mate[y];
577
        rep[blossom.insert(w)] = w;
578
        position.set(y,A);
579
        position.set(w,D);
580
        int t = tree.find(rep[blossom.find(x)]);
581
        tree.insert(y,t);
582
        tree.insert(w,t);
583
        Q.push(w);
584
      } else {                      //augment
585
        augment(x, ear, blossom, rep, tree);
586
        _mate.set(x,y);
587
        _mate.set(y,x);
588
        return true;
589
      }
590
      return false;
591
    }
592

	
593
    void augment(Node x, typename Graph::template NodeMap<Node>& ear,
594
                 UFE& blossom, NV& rep, EFE& tree) {
595
      Node v=_mate[x];
596
      while ( v!=INVALID ) {
597

	
598
        Node u=ear[v];
599
        _mate.set(v,u);
600
        Node tmp=v;
601
        v=_mate[u];
602
        _mate.set(u,tmp);
603
      }
604
      int y = tree.find(rep[blossom.find(x)]);
605
      for (typename EFE::ItemIt tit(tree, y); tit != INVALID; ++tit) {
606
        if ( position[tit] == D ) {
607
          int b = blossom.find(tit);
608
          for (typename UFE::ItemIt bit(blossom, b); bit != INVALID; ++bit) {
609
            position.set(bit, C);
610
          }
611
          blossom.eraseClass(b);
612
        } else position.set(tit, C);
613
      }
614
      tree.eraseClass(y);
615

	
616
    }
606
    /// @}
617 607

	
618 608
  };
619 609

	
... ...
@@ -627,25 +617,28 @@
627 617
  /// \f$O(nm\log(n))\f$ time complexity.
628 618
  ///
629 619
  /// The maximum weighted matching problem is to find undirected
630
  /// arcs in the digraph with maximum overall weight and no two of
631
  /// them shares their endpoints. The problem can be formulated with
632
  /// the next linear program:
620
  /// edges in the graph with maximum overall weight and no two of
621
  /// them shares their ends. The problem can be formulated with the
622
  /// following linear program.
633 623
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
634
  ///\f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2} \quad \forall B\in\mathcal{O}\f]
624
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
625
      \quad \forall B\in\mathcal{O}\f] */
635 626
  /// \f[x_e \ge 0\quad \forall e\in E\f]
636 627
  /// \f[\max \sum_{e\in E}x_ew_e\f]
637
  /// where \f$\delta(X)\f$ is the set of arcs incident to a node in
638
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of arcs with both endpoints in
639
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality subsets of
640
  /// the nodes.
628
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
629
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
630
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
631
  /// subsets of the nodes.
641 632
  ///
642 633
  /// The algorithm calculates an optimal matching and a proof of the
643 634
  /// optimality. The solution of the dual problem can be used to check
644
  /// the result of the algorithm. The dual linear problem is the next:
645
  /// \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge w_{uv} \quad \forall uv\in E\f]
635
  /// the result of the algorithm. The dual linear problem is the
636
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
637
      z_B \ge w_{uv} \quad \forall uv\in E\f] */
646 638
  /// \f[y_u \ge 0 \quad \forall u \in V\f]
647 639
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
648
  /// \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}\frac{\vert B \vert - 1}{2}z_B\f]
640
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
641
      \frac{\vert B \vert - 1}{2}z_B\f] */
649 642
  ///
650 643
  /// The algorithm can be executed with \c run() or the \c init() and
651 644
  /// then the \c start() member functions. After it the matching can
... ...
@@ -705,16 +698,13 @@
705 698
    int _node_num;
706 699
    int _blossom_num;
707 700

	
708
    typedef typename Graph::template NodeMap<int> NodeIntMap;
709
    typedef typename Graph::template ArcMap<int> ArcIntMap;
710
    typedef typename Graph::template EdgeMap<int> EdgeIntMap;
711 701
    typedef RangeMap<int> IntIntMap;
712 702

	
713 703
    enum Status {
714 704
      EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
715 705
    };
716 706

	
717
    typedef HeapUnionFind<Value, NodeIntMap> BlossomSet;
707
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
718 708
    struct BlossomData {
719 709
      int tree;
720 710
      Status status;
... ...
@@ -723,21 +713,21 @@
723 713
      Node base;
724 714
    };
725 715

	
726
    NodeIntMap *_blossom_index;
716
    IntNodeMap *_blossom_index;
727 717
    BlossomSet *_blossom_set;
728 718
    RangeMap<BlossomData>* _blossom_data;
729 719

	
730
    NodeIntMap *_node_index;
731
    ArcIntMap *_node_heap_index;
720
    IntNodeMap *_node_index;
721
    IntArcMap *_node_heap_index;
732 722

	
733 723
    struct NodeData {
734 724

	
735
      NodeData(ArcIntMap& node_heap_index)
725
      NodeData(IntArcMap& node_heap_index)
736 726
        : heap(node_heap_index) {}
737 727

	
738 728
      int blossom;
739 729
      Value pot;
740
      BinHeap<Value, ArcIntMap> heap;
730
      BinHeap<Value, IntArcMap> heap;
741 731
      std::map<int, Arc> heap_index;
742 732

	
743 733
      int tree;
... ...
@@ -750,14 +740,14 @@
750 740
    IntIntMap *_tree_set_index;
751 741
    TreeSet *_tree_set;
752 742

	
753
    NodeIntMap *_delta1_index;
754
    BinHeap<Value, NodeIntMap> *_delta1;
743
    IntNodeMap *_delta1_index;
744
    BinHeap<Value, IntNodeMap> *_delta1;
755 745

	
756 746
    IntIntMap *_delta2_index;
757 747
    BinHeap<Value, IntIntMap> *_delta2;
758 748

	
759
    EdgeIntMap *_delta3_index;
760
    BinHeap<Value, EdgeIntMap> *_delta3;
749
    IntEdgeMap *_delta3_index;
750
    BinHeap<Value, IntEdgeMap> *_delta3;
761 751

	
762 752
    IntIntMap *_delta4_index;
763 753
    BinHeap<Value, IntIntMap> *_delta4;
... ...
@@ -775,14 +765,14 @@
775 765
        _node_potential = new NodePotential(_graph);
776 766
      }
777 767
      if (!_blossom_set) {
778
        _blossom_index = new NodeIntMap(_graph);
768
        _blossom_index = new IntNodeMap(_graph);
779 769
        _blossom_set = new BlossomSet(*_blossom_index);
780 770
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
781 771
      }
782 772

	
783 773
      if (!_node_index) {
784
        _node_index = new NodeIntMap(_graph);
785
        _node_heap_index = new ArcIntMap(_graph);
774
        _node_index = new IntNodeMap(_graph);
775
        _node_heap_index = new IntArcMap(_graph);
786 776
        _node_data = new RangeMap<NodeData>(_node_num,
787 777
                                              NodeData(*_node_heap_index));
788 778
      }
... ...
@@ -792,16 +782,16 @@
792 782
        _tree_set = new TreeSet(*_tree_set_index);
793 783
      }
794 784
      if (!_delta1) {
795
        _delta1_index = new NodeIntMap(_graph);
796
        _delta1 = new BinHeap<Value, NodeIntMap>(*_delta1_index);
785
        _delta1_index = new IntNodeMap(_graph);
786
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
797 787
      }
798 788
      if (!_delta2) {
799 789
        _delta2_index = new IntIntMap(_blossom_num);
800 790
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
801 791
      }
802 792
      if (!_delta3) {
803
        _delta3_index = new EdgeIntMap(_graph);
804
        _delta3 = new BinHeap<Value, EdgeIntMap>(*_delta3_index);
793
        _delta3_index = new IntEdgeMap(_graph);
794
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
805 795
      }
806 796
      if (!_delta4) {
807 797
        _delta4_index = new IntIntMap(_blossom_num);
... ...
@@ -1266,10 +1256,10 @@
1266 1256
    }
1267 1257

	
1268 1258

	
1269
    void augmentOnArc(const Edge& arc) {
1270

	
1271
      int left = _blossom_set->find(_graph.u(arc));
1272
      int right = _blossom_set->find(_graph.v(arc));
1259
    void augmentOnEdge(const Edge& edge) {
1260

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

	
1274 1264
      if ((*_blossom_data)[left].status == EVEN) {
1275 1265
        int left_tree = _tree_set->find(left);
... ...
@@ -1289,8 +1279,8 @@
1289 1279
        unmatchedToMatched(right);
1290 1280
      }
1291 1281

	
1292
      (*_blossom_data)[left].next = _graph.direct(arc, true);
1293
      (*_blossom_data)[right].next = _graph.direct(arc, false);
1282
      (*_blossom_data)[left].next = _graph.direct(edge, true);
1283
      (*_blossom_data)[right].next = _graph.direct(edge, false);
1294 1284
    }
1295 1285

	
1296 1286
    void extendOnArc(const Arc& arc) {
... ...
@@ -1310,7 +1300,7 @@
1310 1300
      matchedToEven(even, tree);
1311 1301
    }
1312 1302

	
1313
    void shrinkOnArc(const Edge& edge, int tree) {
1303
    void shrinkOnEdge(const Edge& edge, int tree) {
1314 1304
      int nca = -1;
1315 1305
      std::vector<int> left_path, right_path;
1316 1306

	
... ...
@@ -1652,7 +1642,7 @@
1652 1642
      createStructures();
1653 1643

	
1654 1644
      for (ArcIt e(_graph); e != INVALID; ++e) {
1655
        _node_heap_index->set(e, BinHeap<Value, ArcIntMap>::PRE_HEAP);
1645
        _node_heap_index->set(e, BinHeap<Value, IntArcMap>::PRE_HEAP);
1656 1646
      }
1657 1647
      for (NodeIt n(_graph); n != INVALID; ++n) {
1658 1648
        _delta1_index->set(n, _delta1->PRE_HEAP);
... ...
@@ -1769,9 +1759,9 @@
1769 1759
              }
1770 1760

	
1771 1761
              if (left_tree == right_tree) {
1772
                shrinkOnArc(e, left_tree);
1762
                shrinkOnEdge(e, left_tree);
1773 1763
              } else {
1774
                augmentOnArc(e);
1764
                augmentOnEdge(e);
1775 1765
                unmatched -= 2;
1776 1766
              }
1777 1767
            }
... ...
@@ -1818,11 +1808,24 @@
1818 1808
      return sum /= 2;
1819 1809
    }
1820 1810

	
1821
    /// \brief Returns true when the arc is in the matching.
1811
    /// \brief Returns the cardinality of the matching.
1822 1812
    ///
1823
    /// Returns true when the arc is in the matching.
1824
    bool matching(const Edge& arc) const {
1825
      return (*_matching)[_graph.u(arc)] == _graph.direct(arc, true);
1813
    /// Returns the cardinality of the matching.
1814
    int matchingSize() const {
1815
      int num = 0;
1816
      for (NodeIt n(_graph); n != INVALID; ++n) {
1817
        if ((*_matching)[n] != INVALID) {
1818
          ++num;
1819
        }
1820
      }
1821
      return num /= 2;
1822
    }
1823

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

	
1828 1831
    /// \brief Returns the incident matching arc.
... ...
@@ -1913,16 +1916,11 @@
1913 1916
        _last = _algorithm->_blossom_potential[variable].end;
1914 1917
      }
1915 1918

	
1916
      /// \brief Invalid constructor.
1917
      ///
1918
      /// Invalid constructor.
1919
      BlossomIt(Invalid) : _index(-1) {}
1920

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

	
1928 1926
      /// \brief Increment operator.
... ...
@@ -1930,18 +1928,18 @@
1930 1928
      /// Increment operator.
1931 1929
      BlossomIt& operator++() {
1932 1930
        ++_index;
1933
        if (_index == _last) {
1934
          _index = -1;
1935
        }
1936 1931
        return *this;
1937 1932
      }
1938 1933

	
1939
      bool operator==(const BlossomIt& it) const {
1940
        return _index == it._index;
1941
      }
1942
      bool operator!=(const BlossomIt& it) const {
1943
        return _index != it._index;
1944
      }
1934
      /// \brief Validity checking
1935
      ///
1936
      /// Checks whether the iterator is invalid.
1937
      bool operator==(Invalid) const { return _index == _last; }
1938

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

	
1946 1944
    private:
1947 1945
      const MaxWeightedMatching* _algorithm;
... ...
@@ -1958,29 +1956,32 @@
1958 1956
  /// \brief Weighted perfect matching in general graphs
1959 1957
  ///
1960 1958
  /// This class provides an efficient implementation of Edmond's
1961
  /// maximum weighted perfecr matching algorithm. The implementation
1959
  /// maximum weighted perfect matching algorithm. The implementation
1962 1960
  /// is based on extensive use of priority queues and provides
1963 1961
  /// \f$O(nm\log(n))\f$ time complexity.
1964 1962
  ///
1965 1963
  /// The maximum weighted matching problem is to find undirected
1966
  /// arcs in the digraph with maximum overall weight and no two of
1967
  /// them shares their endpoints and covers all nodes. The problem
1968
  /// can be formulated with the next linear program:
1964
  /// edges in the graph with maximum overall weight and no two of
1965
  /// them shares their ends and covers all nodes. The problem can be
1966
  /// formulated with the following linear program.
1969 1967
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1970
  ///\f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2} \quad \forall B\in\mathcal{O}\f]
1968
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
1969
      \quad \forall B\in\mathcal{O}\f] */
1971 1970
  /// \f[x_e \ge 0\quad \forall e\in E\f]
1972 1971
  /// \f[\max \sum_{e\in E}x_ew_e\f]
1973
  /// where \f$\delta(X)\f$ is the set of arcs incident to a node in
1974
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of arcs with both endpoints in
1975
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality subsets of
1976
  /// the nodes.
1972
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1973
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
1974
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
1975
  /// subsets of the nodes.
1977 1976
  ///
1978 1977
  /// The algorithm calculates an optimal matching and a proof of the
1979 1978
  /// optimality. The solution of the dual problem can be used to check
1980
  /// the result of the algorithm. The dual linear problem is the next:
1981
  /// \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge w_{uv} \quad \forall uv\in E\f]
1979
  /// the result of the algorithm. The dual linear problem is the
1980
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
1981
      w_{uv} \quad \forall uv\in E\f] */
1982 1982
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
1983
  /// \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}\frac{\vert B \vert - 1}{2}z_B\f]
1983
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
1984
      \frac{\vert B \vert - 1}{2}z_B\f] */
1984 1985
  ///
1985 1986
  /// The algorithm can be executed with \c run() or the \c init() and
1986 1987
  /// then the \c start() member functions. After it the matching can
... ...
@@ -2040,16 +2041,13 @@
2040 2041
    int _node_num;
2041 2042
    int _blossom_num;
2042 2043

	
2043
    typedef typename Graph::template NodeMap<int> NodeIntMap;
2044
    typedef typename Graph::template ArcMap<int> ArcIntMap;
2045
    typedef typename Graph::template EdgeMap<int> EdgeIntMap;
2046 2044
    typedef RangeMap<int> IntIntMap;
2047 2045

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

	
2052
    typedef HeapUnionFind<Value, NodeIntMap> BlossomSet;
2050
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2053 2051
    struct BlossomData {
2054 2052
      int tree;
2055 2053
      Status status;
... ...
@@ -2057,21 +2055,21 @@
2057 2055
      Value pot, offset;
2058 2056
    };
2059 2057

	
2060
    NodeIntMap *_blossom_index;
2058
    IntNodeMap *_blossom_index;
2061 2059
    BlossomSet *_blossom_set;
2062 2060
    RangeMap<BlossomData>* _blossom_data;
2063 2061

	
2064
    NodeIntMap *_node_index;
2065
    ArcIntMap *_node_heap_index;
2062
    IntNodeMap *_node_index;
2063
    IntArcMap *_node_heap_index;
2066 2064

	
2067 2065
    struct NodeData {
2068 2066

	
2069
      NodeData(ArcIntMap& node_heap_index)
2067
      NodeData(IntArcMap& node_heap_index)
2070 2068
        : heap(node_heap_index) {}
2071 2069

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

	
2077 2075
      int tree;
... ...
@@ -2087,8 +2085,8 @@
2087 2085
    IntIntMap *_delta2_index;
2088 2086
    BinHeap<Value, IntIntMap> *_delta2;
2089 2087

	
2090
    EdgeIntMap *_delta3_index;
2091
    BinHeap<Value, EdgeIntMap> *_delta3;
2088
    IntEdgeMap *_delta3_index;
2089
    BinHeap<Value, IntEdgeMap> *_delta3;
2092 2090

	
2093 2091
    IntIntMap *_delta4_index;
2094 2092
    BinHeap<Value, IntIntMap> *_delta4;
... ...
@@ -2106,16 +2104,16 @@
2106 2104
        _node_potential = new NodePotential(_graph);
2107 2105
      }
2108 2106
      if (!_blossom_set) {
2109
        _blossom_index = new NodeIntMap(_graph);
2107
        _blossom_index = new IntNodeMap(_graph);
2110 2108
        _blossom_set = new BlossomSet(*_blossom_index);
2111 2109
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2112 2110
      }
2113 2111

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

	
2121 2119
      if (!_tree_set) {
... ...
@@ -2127,8 +2125,8 @@
2127 2125
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2128 2126
      }
2129 2127
      if (!_delta3) {
2130
        _delta3_index = new EdgeIntMap(_graph);
2131
        _delta3 = new BinHeap<Value, EdgeIntMap>(*_delta3_index);
2128
        _delta3_index = new IntEdgeMap(_graph);
2129
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2132 2130
      }
2133 2131
      if (!_delta4) {
2134 2132
        _delta4_index = new IntIntMap(_blossom_num);
... ...
@@ -2461,10 +2459,10 @@
2461 2459
      _tree_set->eraseClass(tree);
2462 2460
    }
2463 2461

	
2464
    void augmentOnArc(const Edge& arc) {
2465

	
2466
      int left = _blossom_set->find(_graph.u(arc));
2467
      int right = _blossom_set->find(_graph.v(arc));
2462
    void augmentOnEdge(const Edge& edge) {
2463

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

	
2469 2467
      int left_tree = _tree_set->find(left);
2470 2468
      alternatePath(left, left_tree);
... ...
@@ -2474,8 +2472,8 @@
2474 2472
      alternatePath(right, right_tree);
2475 2473
      destroyTree(right_tree);
2476 2474

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

	
2481 2479
    void extendOnArc(const Arc& arc) {
... ...
@@ -2495,7 +2493,7 @@
2495 2493
      matchedToEven(even, tree);
2496 2494
    }
2497 2495

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

	
... ...
@@ -2831,7 +2829,7 @@
2831 2829
      createStructures();
2832 2830

	
2833 2831
      for (ArcIt e(_graph); e != INVALID; ++e) {
2834
        _node_heap_index->set(e, BinHeap<Value, ArcIntMap>::PRE_HEAP);
2832
        _node_heap_index->set(e, BinHeap<Value, IntArcMap>::PRE_HEAP);
2835 2833
      }
2836 2834
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2837 2835
        _delta3_index->set(e, _delta3->PRE_HEAP);
... ...
@@ -2924,9 +2922,9 @@
2924 2922
              int right_tree = _tree_set->find(right_blossom);
2925 2923

	
2926 2924
              if (left_tree == right_tree) {
2927
                shrinkOnArc(e, left_tree);
2925
                shrinkOnEdge(e, left_tree);
2928 2926
              } else {
2929
                augmentOnArc(e);
2927
                augmentOnEdge(e);
2930 2928
                unmatched -= 2;
2931 2929
              }
2932 2930
            }
... ...
@@ -2974,16 +2972,16 @@
2974 2972
      return sum /= 2;
2975 2973
    }
2976 2974

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

	
2984
    /// \brief Returns the incident matching arc.
2982
    /// \brief Returns the incident matching edge.
2985 2983
    ///
2986
    /// Returns the incident matching arc from given node.
2984
    /// Returns the incident matching arc from given edge.
2987 2985
    Arc matching(const Node& node) const {
2988 2986
      return (*_matching)[node];
2989 2987
    }
... ...
@@ -3066,16 +3064,11 @@
3066 3064
        _last = _algorithm->_blossom_potential[variable].end;
3067 3065
      }
3068 3066

	
3069
      /// \brief Invalid constructor.
3070
      ///
3071
      /// Invalid constructor.
3072
      BlossomIt(Invalid) : _index(-1) {}
3073

	
3074 3067
      /// \brief Conversion to node.
3075 3068
      ///
3076 3069
      /// Conversion to node.
3077 3070
      operator Node() const {
3078
        return _algorithm ? _algorithm->_blossom_node_list[_index] : INVALID;
3071
        return _algorithm->_blossom_node_list[_index];
3079 3072
      }
3080 3073

	
3081 3074
      /// \brief Increment operator.
... ...
@@ -3083,18 +3076,18 @@
3083 3076
      /// Increment operator.
3084 3077
      BlossomIt& operator++() {
3085 3078
        ++_index;
3086
        if (_index == _last) {
3087
          _index = -1;
3088
        }
3089 3079
        return *this;
3090 3080
      }
3091 3081

	
3092
      bool operator==(const BlossomIt& it) const {
3093
        return _index == it._index;
3094
      }
3095
      bool operator!=(const BlossomIt& it) const {
3096
        return _index != it._index;
3097
      }
3082
      /// \brief Validity checking
3083
      ///
3084
      /// Checks whether the iterator is invalid.
3085
      bool operator==(Invalid) const { return _index == _last; }
3086

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

	
3099 3092
    private:
3100 3093
      const MaxWeightedPerfectMatching* _algorithm;
Ignore white space 6 line context
... ...
@@ -17,7 +17,6 @@
17 17
  kruskal_test
18 18
  maps_test
19 19
  max_matching_test
20
  max_weighted_matching_test
21 20
  random_test
22 21
  path_test
23 22
  time_measure_test
Ignore white space 6 line context
... ...
@@ -20,7 +20,6 @@
20 20
	test/kruskal_test \
21 21
        test/maps_test \
22 22
	test/max_matching_test \
23
	test/max_weighted_matching_test \
24 23
        test/random_test \
25 24
        test/path_test \
26 25
        test/test_tools_fail \
... ...
@@ -45,7 +44,6 @@
45 44
test_kruskal_test_SOURCES = test/kruskal_test.cc
46 45
test_maps_test_SOURCES = test/maps_test.cc
47 46
test_max_matching_test_SOURCES = test/max_matching_test.cc
48
test_max_weighted_matching_test_SOURCES = test/max_weighted_matching_test.cc
49 47
test_path_test_SOURCES = test/path_test.cc
50 48
test_random_test_SOURCES = test/random_test.cc
51 49
test_test_tools_fail_SOURCES = test/test_tools_fail.cc
Ignore white space 6 line context
... ...
@@ -17,165 +17,294 @@
17 17
 */
18 18

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

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

	
25 30
#include "test_tools.h"
26
#include <lemon/list_graph.h>
27
#include <lemon/max_matching.h>
28 31

	
29 32
using namespace std;
30 33
using namespace lemon;
31 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

	
32 280
int main() {
33 281

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

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

	
38
  Graph g;
39
  g.clear();
290
    MaxMatching<SmartGraph> mm(graph);
291
    mm.run();
292
    checkMatching(graph, mm);
40 293

	
41
  std::vector<Graph::Node> nodes;
42
  for (int i=0; i<13; ++i)
43
      nodes.push_back(g.addNode());
294
    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
295
    mwm.run();
296
    checkWeightedMatching(graph, weight, mwm);
44 297

	
45
  g.addEdge(nodes[0], nodes[0]);
46
  g.addEdge(nodes[6], nodes[10]);
47
  g.addEdge(nodes[5], nodes[10]);
48
  g.addEdge(nodes[4], nodes[10]);
49
  g.addEdge(nodes[3], nodes[11]);
50
  g.addEdge(nodes[1], nodes[6]);
51
  g.addEdge(nodes[4], nodes[7]);
52
  g.addEdge(nodes[1], nodes[8]);
53
  g.addEdge(nodes[0], nodes[8]);
54
  g.addEdge(nodes[3], nodes[12]);
55
  g.addEdge(nodes[6], nodes[9]);
56
  g.addEdge(nodes[9], nodes[11]);
57
  g.addEdge(nodes[2], nodes[10]);
58
  g.addEdge(nodes[10], nodes[8]);
59
  g.addEdge(nodes[5], nodes[8]);
60
  g.addEdge(nodes[6], nodes[3]);
61
  g.addEdge(nodes[0], nodes[5]);
62
  g.addEdge(nodes[6], nodes[12]);
298
    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
299
    bool perfect = mwpm.run();
63 300

	
64
  MaxMatching<Graph> max_matching(g);
65
  max_matching.init();
66
  max_matching.startDense();
301
    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
302
          "Perfect matching found");
67 303

	
68
  int s=0;
69
  Graph::NodeMap<Node> mate(g,INVALID);
70
  max_matching.mateMap(mate);
71
  for(NodeIt v(g); v!=INVALID; ++v) {
72
    if ( mate[v]!=INVALID ) ++s;
73
  }
74
  int size=int(s/2);  //size will be used as the size of a maxmatching
75

	
76
  for(NodeIt v(g); v!=INVALID; ++v) {
77
    max_matching.mate(v);
78
  }
79

	
80
  check ( size == max_matching.size(), "mate() returns a different size matching than max_matching.size()" );
81

	
82
  Graph::NodeMap<MaxMatching<Graph>::DecompType> pos0(g);
83
  max_matching.decomposition(pos0);
84

	
85
  max_matching.init();
86
  max_matching.startSparse();
87
  s=0;
88
  max_matching.mateMap(mate);
89
  for(NodeIt v(g); v!=INVALID; ++v) {
90
    if ( mate[v]!=INVALID ) ++s;
91
  }
92
  check ( int(s/2) == size, "The size does not equal!" );
93

	
94
  Graph::NodeMap<MaxMatching<Graph>::DecompType> pos1(g);
95
  max_matching.decomposition(pos1);
96

	
97
  max_matching.run();
98
  s=0;
99
  max_matching.mateMap(mate);
100
  for(NodeIt v(g); v!=INVALID; ++v) {
101
    if ( mate[v]!=INVALID ) ++s;
102
  }
103
  check ( int(s/2) == size, "The size does not equal!" );
104

	
105
  Graph::NodeMap<MaxMatching<Graph>::DecompType> pos2(g);
106
  max_matching.decomposition(pos2);
107

	
108
  max_matching.run();
109
  s=0;
110
  max_matching.mateMap(mate);
111
  for(NodeIt v(g); v!=INVALID; ++v) {
112
    if ( mate[v]!=INVALID ) ++s;
113
  }
114
  check ( int(s/2) == size, "The size does not equal!" );
115

	
116
  Graph::NodeMap<MaxMatching<Graph>::DecompType> pos(g);
117
  max_matching.decomposition(pos);
118

	
119
  bool ismatching=true;
120
  for(NodeIt v(g); v!=INVALID; ++v) {
121
    if ( mate[v]!=INVALID ) {
122
      Node u=mate[v];
123
      if (mate[u]!=v) ismatching=false;
304
    if (perfect) {
305
      checkWeightedPerfectMatching(graph, weight, mwpm);
124 306
    }
125 307
  }
126
  check ( ismatching, "It is not a matching!" );
127

	
128
  bool coincide=true;
129
  for(NodeIt v(g); v!=INVALID; ++v) {
130
   if ( pos0[v] != pos1[v] || pos1[v]!=pos2[v] || pos2[v]!=pos[v] ) {
131
     coincide=false;
132
    }
133
  }
134
  check ( coincide, "The decompositions do not coincide! " );
135

	
136
  bool noarc=true;
137
  for(EdgeIt e(g); e!=INVALID; ++e) {
138
   if ( (pos[g.v(e)]==max_matching.C &&
139
         pos[g.u(e)]==max_matching.D) ||
140
         (pos[g.v(e)]==max_matching.D &&
141
          pos[g.u(e)]==max_matching.C) )
142
      noarc=false;
143
  }
144
  check ( noarc, "There are arcs between D and C!" );
145

	
146
  bool oddcomp=true;
147
  Graph::NodeMap<bool> todo(g,true);
148
  int num_comp=0;
149
  for(NodeIt v(g); v!=INVALID; ++v) {
150
   if ( pos[v]==max_matching.D && todo[v] ) {
151
      int comp_size=1;
152
      ++num_comp;
153
      std::queue<Node> Q;
154
      Q.push(v);
155
      todo.set(v,false);
156
      while (!Q.empty()) {
157
        Node w=Q.front();
158
        Q.pop();
159
        for(IncEdgeIt e(g,w); e!=INVALID; ++e) {
160
          Node u=g.runningNode(e);
161
          if ( pos[u]==max_matching.D && todo[u] ) {
162
            ++comp_size;
163
            Q.push(u);
164
            todo.set(u,false);
165
          }
166
        }
167
      }
168
      if ( !(comp_size % 2) ) oddcomp=false;
169
    }
170
  }
171
  check ( oddcomp, "A component of g[D] is not odd." );
172

	
173
  int barrier=0;
174
  for(NodeIt v(g); v!=INVALID; ++v) {
175
    if ( pos[v]==max_matching.A ) ++barrier;
176
  }
177
  int expected_size=int( countNodes(g)-num_comp+barrier)/2;
178
  check ( size==expected_size, "The size of the matching is wrong." );
179 308

	
180 309
  return 0;
181 310
}
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 "test_tools.h"
27
#include <lemon/smart_graph.h>
28
#include <lemon/max_matching.h>
29
#include <lemon/lgf_reader.h>
30

	
31
using namespace std;
32
using namespace lemon;
33

	
34
GRAPH_TYPEDEFS(SmartGraph);
35

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

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

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

	
111
void checkMatching(const SmartGraph& graph,
112
                   const SmartGraph::EdgeMap<int>& weight,
113
                   const MaxWeightedMatching<SmartGraph>& mwm) {
114
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
115
    if (graph.u(e) == graph.v(e)) continue;
116
    int rw =
117
      mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
118

	
119
    for (int i = 0; i < mwm.blossomNum(); ++i) {
120
      bool s = false, t = false;
121
      for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
122
           n != INVALID; ++n) {
123
        if (graph.u(e) == n) s = true;
124
        if (graph.v(e) == n) t = true;
125
      }
126
      if (s == true && t == true) {
127
        rw += mwm.blossomValue(i);
128
      }
129
    }
130
    rw -= weight[e] * mwm.dualScale;
131

	
132
    check(rw >= 0, "Negative reduced weight");
133
    check(rw == 0 || !mwm.matching(e),
134
          "Non-zero reduced weight on matching arc");
135
  }
136

	
137
  int pv = 0;
138
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
139
    if (mwm.matching(n) != INVALID) {
140
      check(mwm.nodeValue(n) >= 0, "Invalid node value");
141
      pv += weight[mwm.matching(n)];
142
      SmartGraph::Node o = graph.target(mwm.matching(n));
143
      check(mwm.mate(n) == o, "Invalid matching");
144
      check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
145
            "Invalid matching");
146
    } else {
147
      check(mwm.mate(n) == INVALID, "Invalid matching");
148
      check(mwm.nodeValue(n) == 0, "Invalid matching");
149
    }
150
  }
151

	
152
  int dv = 0;
153
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
154
    dv += mwm.nodeValue(n);
155
  }
156

	
157
  for (int i = 0; i < mwm.blossomNum(); ++i) {
158
    check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
159
    check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
160
    dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
161
  }
162

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

	
165
  return;
166
}
167

	
168
void checkPerfectMatching(const SmartGraph& graph,
169
                          const SmartGraph::EdgeMap<int>& weight,
170
                          const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
171
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
172
    if (graph.u(e) == graph.v(e)) continue;
173
    int rw =
174
      mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
175

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

	
189
    check(rw >= 0, "Negative reduced weight");
190
    check(rw == 0 || !mwpm.matching(e),
191
          "Non-zero reduced weight on matching arc");
192
  }
193

	
194
  int pv = 0;
195
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
196
    check(mwpm.matching(n) != INVALID, "Non perfect");
197
    pv += weight[mwpm.matching(n)];
198
    SmartGraph::Node o = graph.target(mwpm.matching(n));
199
    check(mwpm.mate(n) == o, "Invalid matching");
200
    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
201
          "Invalid matching");
202
  }
203

	
204
  int dv = 0;
205
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
206
    dv += mwpm.nodeValue(n);
207
  }
208

	
209
  for (int i = 0; i < mwpm.blossomNum(); ++i) {
210
    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
211
    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
212
    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
213
  }
214

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

	
217
  return;
218
}
219

	
220

	
221
int main() {
222

	
223
  for (int i = 0; i < lgfn; ++i) {
224
    SmartGraph graph;
225
    SmartGraph::EdgeMap<int> weight(graph);
226

	
227
    istringstream lgfs(lgf[i]);
228
    graphReader(graph, lgfs).
229
      edgeMap("weight", weight).run();
230

	
231
    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
232
    mwm.run();
233
    checkMatching(graph, weight, mwm);
234

	
235
    MaxMatching<SmartGraph> mm(graph);
236
    mm.run();
237

	
238
    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
239
    bool perfect = mwpm.run();
240

	
241
    check(perfect == (mm.size() * 2 == countNodes(graph)),
242
          "Perfect matching found");
243

	
244
    if (perfect) {
245
      checkPerfectMatching(graph, weight, mwpm);
246
    }
247
  }
248

	
249
  return 0;
250
}
0 comments (0 inline)