gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge #314
0 6 2
merge default
4 files changed with 3246 insertions and 378 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-2009
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_FRACTIONAL_MATCHING_H
20
#define LEMON_FRACTIONAL_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
#include <lemon/assert.h>
32
#include <lemon/elevator.h>
33

	
34
///\ingroup matching
35
///\file
36
///\brief Fractional matching algorithms in general graphs.
37

	
38
namespace lemon {
39

	
40
  /// \brief Default traits class of MaxFractionalMatching class.
41
  ///
42
  /// Default traits class of MaxFractionalMatching class.
43
  /// \tparam GR Graph type.
44
  template <typename GR>
45
  struct MaxFractionalMatchingDefaultTraits {
46

	
47
    /// \brief The type of the graph the algorithm runs on.
48
    typedef GR Graph;
49

	
50
    /// \brief The type of the map that stores the matching.
51
    ///
52
    /// The type of the map that stores the matching arcs.
53
    /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
54
    typedef typename Graph::template NodeMap<typename GR::Arc> MatchingMap;
55

	
56
    /// \brief Instantiates a MatchingMap.
57
    ///
58
    /// This function instantiates a \ref MatchingMap.
59
    /// \param graph The graph for which we would like to define
60
    /// the matching map.
61
    static MatchingMap* createMatchingMap(const Graph& graph) {
62
      return new MatchingMap(graph);
63
    }
64

	
65
    /// \brief The elevator type used by MaxFractionalMatching algorithm.
66
    ///
67
    /// The elevator type used by MaxFractionalMatching algorithm.
68
    ///
69
    /// \sa Elevator
70
    /// \sa LinkedElevator
71
    typedef LinkedElevator<Graph, typename Graph::Node> Elevator;
72

	
73
    /// \brief Instantiates an Elevator.
74
    ///
75
    /// This function instantiates an \ref Elevator.
76
    /// \param graph The graph for which we would like to define
77
    /// the elevator.
78
    /// \param max_level The maximum level of the elevator.
79
    static Elevator* createElevator(const Graph& graph, int max_level) {
80
      return new Elevator(graph, max_level);
81
    }
82
  };
83

	
84
  /// \ingroup matching
85
  ///
86
  /// \brief Max cardinality fractional matching
87
  ///
88
  /// This class provides an implementation of fractional matching
89
  /// algorithm based on push-relabel principle.
90
  ///
91
  /// The maximum cardinality fractional matching is a relaxation of the
92
  /// maximum cardinality matching problem where the odd set constraints
93
  /// are omitted.
94
  /// It can be formulated with the following linear program.
95
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
96
  /// \f[x_e \ge 0\quad \forall e\in E\f]
97
  /// \f[\max \sum_{e\in E}x_e\f]
98
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
99
  /// \f$X\f$. The result can be represented as the union of a
100
  /// matching with one value edges and a set of odd length cycles
101
  /// with half value edges.
102
  ///
103
  /// The algorithm calculates an optimal fractional matching and a
104
  /// barrier. The number of adjacents of any node set minus the size
105
  /// of node set is a lower bound on the uncovered nodes in the
106
  /// graph. For maximum matching a barrier is computed which
107
  /// maximizes this difference.
108
  ///
109
  /// The algorithm can be executed with the run() function.  After it
110
  /// the matching (the primal solution) and the barrier (the dual
111
  /// solution) can be obtained using the query functions.
112
  ///
113
  /// The primal solution is multiplied by
114
  /// \ref MaxFractionalMatching::primalScale "2".
115
  ///
116
  /// \tparam GR The undirected graph type the algorithm runs on.
117
#ifdef DOXYGEN
118
  template <typename GR, typename TR>
119
#else
120
  template <typename GR,
121
            typename TR = MaxFractionalMatchingDefaultTraits<GR> >
122
#endif
123
  class MaxFractionalMatching {
124
  public:
125

	
126
    /// \brief The \ref MaxFractionalMatchingDefaultTraits "traits
127
    /// class" of the algorithm.
128
    typedef TR Traits;
129
    /// The type of the graph the algorithm runs on.
130
    typedef typename TR::Graph Graph;
131
    /// The type of the matching map.
132
    typedef typename TR::MatchingMap MatchingMap;
133
    /// The type of the elevator.
134
    typedef typename TR::Elevator Elevator;
135

	
136
    /// \brief Scaling factor for primal solution
137
    ///
138
    /// Scaling factor for primal solution.
139
    static const int primalScale = 2;
140

	
141
  private:
142

	
143
    const Graph &_graph;
144
    int _node_num;
145
    bool _allow_loops;
146
    int _empty_level;
147

	
148
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
149

	
150
    bool _local_matching;
151
    MatchingMap *_matching;
152

	
153
    bool _local_level;
154
    Elevator *_level;
155

	
156
    typedef typename Graph::template NodeMap<int> InDegMap;
157
    InDegMap *_indeg;
158

	
159
    void createStructures() {
160
      _node_num = countNodes(_graph);
161

	
162
      if (!_matching) {
163
        _local_matching = true;
164
        _matching = Traits::createMatchingMap(_graph);
165
      }
166
      if (!_level) {
167
        _local_level = true;
168
        _level = Traits::createElevator(_graph, _node_num);
169
      }
170
      if (!_indeg) {
171
        _indeg = new InDegMap(_graph);
172
      }
173
    }
174

	
175
    void destroyStructures() {
176
      if (_local_matching) {
177
        delete _matching;
178
      }
179
      if (_local_level) {
180
        delete _level;
181
      }
182
      if (_indeg) {
183
        delete _indeg;
184
      }
185
    }
186

	
187
    void postprocessing() {
188
      for (NodeIt n(_graph); n != INVALID; ++n) {
189
        if ((*_indeg)[n] != 0) continue;
190
        _indeg->set(n, -1);
191
        Node u = n;
192
        while ((*_matching)[u] != INVALID) {
193
          Node v = _graph.target((*_matching)[u]);
194
          _indeg->set(v, -1);
195
          Arc a = _graph.oppositeArc((*_matching)[u]);
196
          u = _graph.target((*_matching)[v]);
197
          _indeg->set(u, -1);
198
          _matching->set(v, a);
199
        }
200
      }
201

	
202
      for (NodeIt n(_graph); n != INVALID; ++n) {
203
        if ((*_indeg)[n] != 1) continue;
204
        _indeg->set(n, -1);
205

	
206
        int num = 1;
207
        Node u = _graph.target((*_matching)[n]);
208
        while (u != n) {
209
          _indeg->set(u, -1);
210
          u = _graph.target((*_matching)[u]);
211
          ++num;
212
        }
213
        if (num % 2 == 0 && num > 2) {
214
          Arc prev = _graph.oppositeArc((*_matching)[n]);
215
          Node v = _graph.target((*_matching)[n]);
216
          u = _graph.target((*_matching)[v]);
217
          _matching->set(v, prev);
218
          while (u != n) {
219
            prev = _graph.oppositeArc((*_matching)[u]);
220
            v = _graph.target((*_matching)[u]);
221
            u = _graph.target((*_matching)[v]);
222
            _matching->set(v, prev);
223
          }
224
        }
225
      }
226
    }
227

	
228
  public:
229

	
230
    typedef MaxFractionalMatching Create;
231

	
232
    ///\name Named Template Parameters
233

	
234
    ///@{
235

	
236
    template <typename T>
237
    struct SetMatchingMapTraits : public Traits {
238
      typedef T MatchingMap;
239
      static MatchingMap *createMatchingMap(const Graph&) {
240
        LEMON_ASSERT(false, "MatchingMap is not initialized");
241
        return 0; // ignore warnings
242
      }
243
    };
244

	
245
    /// \brief \ref named-templ-param "Named parameter" for setting
246
    /// MatchingMap type
247
    ///
248
    /// \ref named-templ-param "Named parameter" for setting MatchingMap
249
    /// type.
250
    template <typename T>
251
    struct SetMatchingMap
252
      : public MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > {
253
      typedef MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > Create;
254
    };
255

	
256
    template <typename T>
257
    struct SetElevatorTraits : public Traits {
258
      typedef T Elevator;
259
      static Elevator *createElevator(const Graph&, int) {
260
        LEMON_ASSERT(false, "Elevator is not initialized");
261
        return 0; // ignore warnings
262
      }
263
    };
264

	
265
    /// \brief \ref named-templ-param "Named parameter" for setting
266
    /// Elevator type
267
    ///
268
    /// \ref named-templ-param "Named parameter" for setting Elevator
269
    /// type. If this named parameter is used, then an external
270
    /// elevator object must be passed to the algorithm using the
271
    /// \ref elevator(Elevator&) "elevator()" function before calling
272
    /// \ref run() or \ref init().
273
    /// \sa SetStandardElevator
274
    template <typename T>
275
    struct SetElevator
276
      : public MaxFractionalMatching<Graph, SetElevatorTraits<T> > {
277
      typedef MaxFractionalMatching<Graph, SetElevatorTraits<T> > Create;
278
    };
279

	
280
    template <typename T>
281
    struct SetStandardElevatorTraits : public Traits {
282
      typedef T Elevator;
283
      static Elevator *createElevator(const Graph& graph, int max_level) {
284
        return new Elevator(graph, max_level);
285
      }
286
    };
287

	
288
    /// \brief \ref named-templ-param "Named parameter" for setting
289
    /// Elevator type with automatic allocation
290
    ///
291
    /// \ref named-templ-param "Named parameter" for setting Elevator
292
    /// type with automatic allocation.
293
    /// The Elevator should have standard constructor interface to be
294
    /// able to automatically created by the algorithm (i.e. the
295
    /// graph and the maximum level should be passed to it).
296
    /// However an external elevator object could also be passed to the
297
    /// algorithm with the \ref elevator(Elevator&) "elevator()" function
298
    /// before calling \ref run() or \ref init().
299
    /// \sa SetElevator
300
    template <typename T>
301
    struct SetStandardElevator
302
      : public MaxFractionalMatching<Graph, SetStandardElevatorTraits<T> > {
303
      typedef MaxFractionalMatching<Graph,
304
                                    SetStandardElevatorTraits<T> > Create;
305
    };
306

	
307
    /// @}
308

	
309
  protected:
310

	
311
    MaxFractionalMatching() {}
312

	
313
  public:
314

	
315
    /// \brief Constructor
316
    ///
317
    /// Constructor.
318
    ///
319
    MaxFractionalMatching(const Graph &graph, bool allow_loops = true)
320
      : _graph(graph), _allow_loops(allow_loops),
321
        _local_matching(false), _matching(0),
322
        _local_level(false), _level(0),  _indeg(0)
323
    {}
324

	
325
    ~MaxFractionalMatching() {
326
      destroyStructures();
327
    }
328

	
329
    /// \brief Sets the matching map.
330
    ///
331
    /// Sets the matching map.
332
    /// If you don't use this function before calling \ref run() or
333
    /// \ref init(), an instance will be allocated automatically.
334
    /// The destructor deallocates this automatically allocated map,
335
    /// of course.
336
    /// \return <tt>(*this)</tt>
337
    MaxFractionalMatching& matchingMap(MatchingMap& map) {
338
      if (_local_matching) {
339
        delete _matching;
340
        _local_matching = false;
341
      }
342
      _matching = &map;
343
      return *this;
344
    }
345

	
346
    /// \brief Sets the elevator used by algorithm.
347
    ///
348
    /// Sets the elevator used by algorithm.
349
    /// If you don't use this function before calling \ref run() or
350
    /// \ref init(), an instance will be allocated automatically.
351
    /// The destructor deallocates this automatically allocated elevator,
352
    /// of course.
353
    /// \return <tt>(*this)</tt>
354
    MaxFractionalMatching& elevator(Elevator& elevator) {
355
      if (_local_level) {
356
        delete _level;
357
        _local_level = false;
358
      }
359
      _level = &elevator;
360
      return *this;
361
    }
362

	
363
    /// \brief Returns a const reference to the elevator.
364
    ///
365
    /// Returns a const reference to the elevator.
366
    ///
367
    /// \pre Either \ref run() or \ref init() must be called before
368
    /// using this function.
369
    const Elevator& elevator() const {
370
      return *_level;
371
    }
372

	
373
    /// \name Execution control
374
    /// The simplest way to execute the algorithm is to use one of the
375
    /// member functions called \c run(). \n
376
    /// If you need more control on the execution, first
377
    /// you must call \ref init() and then one variant of the start()
378
    /// member.
379

	
380
    /// @{
381

	
382
    /// \brief Initializes the internal data structures.
383
    ///
384
    /// Initializes the internal data structures and sets the initial
385
    /// matching.
386
    void init() {
387
      createStructures();
388

	
389
      _level->initStart();
390
      for (NodeIt n(_graph); n != INVALID; ++n) {
391
        _indeg->set(n, 0);
392
        _matching->set(n, INVALID);
393
        _level->initAddItem(n);
394
      }
395
      _level->initFinish();
396

	
397
      _empty_level = _node_num;
398
      for (NodeIt n(_graph); n != INVALID; ++n) {
399
        for (OutArcIt a(_graph, n); a != INVALID; ++a) {
400
          if (_graph.target(a) == n && !_allow_loops) continue;
401
          _matching->set(n, a);
402
          Node v = _graph.target((*_matching)[n]);
403
          _indeg->set(v, (*_indeg)[v] + 1);
404
          break;
405
        }
406
      }
407

	
408
      for (NodeIt n(_graph); n != INVALID; ++n) {
409
        if ((*_indeg)[n] == 0) {
410
          _level->activate(n);
411
        }
412
      }
413
    }
414

	
415
    /// \brief Starts the algorithm and computes a fractional matching
416
    ///
417
    /// The algorithm computes a maximum fractional matching.
418
    ///
419
    /// \param postprocess The algorithm computes first a matching
420
    /// which is a union of a matching with one value edges, cycles
421
    /// with half value edges and even length paths with half value
422
    /// edges. If the parameter is true, then after the push-relabel
423
    /// algorithm it postprocesses the matching to contain only
424
    /// matching edges and half value odd cycles.
425
    void start(bool postprocess = true) {
426
      Node n;
427
      while ((n = _level->highestActive()) != INVALID) {
428
        int level = _level->highestActiveLevel();
429
        int new_level = _level->maxLevel();
430
        for (InArcIt a(_graph, n); a != INVALID; ++a) {
431
          Node u = _graph.source(a);
432
          if (n == u && !_allow_loops) continue;
433
          Node v = _graph.target((*_matching)[u]);
434
          if ((*_level)[v] < level) {
435
            _indeg->set(v, (*_indeg)[v] - 1);
436
            if ((*_indeg)[v] == 0) {
437
              _level->activate(v);
438
            }
439
            _matching->set(u, a);
440
            _indeg->set(n, (*_indeg)[n] + 1);
441
            _level->deactivate(n);
442
            goto no_more_push;
443
          } else if (new_level > (*_level)[v]) {
444
            new_level = (*_level)[v];
445
          }
446
        }
447

	
448
        if (new_level + 1 < _level->maxLevel()) {
449
          _level->liftHighestActive(new_level + 1);
450
        } else {
451
          _level->liftHighestActiveToTop();
452
        }
453
        if (_level->emptyLevel(level)) {
454
          _level->liftToTop(level);
455
        }
456
      no_more_push:
457
        ;
458
      }
459
      for (NodeIt n(_graph); n != INVALID; ++n) {
460
        if ((*_matching)[n] == INVALID) continue;
461
        Node u = _graph.target((*_matching)[n]);
462
        if ((*_indeg)[u] > 1) {
463
          _indeg->set(u, (*_indeg)[u] - 1);
464
          _matching->set(n, INVALID);
465
        }
466
      }
467
      if (postprocess) {
468
        postprocessing();
469
      }
470
    }
471

	
472
    /// \brief Starts the algorithm and computes a perfect fractional
473
    /// matching
474
    ///
475
    /// The algorithm computes a perfect fractional matching. If it
476
    /// does not exists, then the algorithm returns false and the
477
    /// matching is undefined and the barrier.
478
    ///
479
    /// \param postprocess The algorithm computes first a matching
480
    /// which is a union of a matching with one value edges, cycles
481
    /// with half value edges and even length paths with half value
482
    /// edges. If the parameter is true, then after the push-relabel
483
    /// algorithm it postprocesses the matching to contain only
484
    /// matching edges and half value odd cycles.
485
    bool startPerfect(bool postprocess = true) {
486
      Node n;
487
      while ((n = _level->highestActive()) != INVALID) {
488
        int level = _level->highestActiveLevel();
489
        int new_level = _level->maxLevel();
490
        for (InArcIt a(_graph, n); a != INVALID; ++a) {
491
          Node u = _graph.source(a);
492
          if (n == u && !_allow_loops) continue;
493
          Node v = _graph.target((*_matching)[u]);
494
          if ((*_level)[v] < level) {
495
            _indeg->set(v, (*_indeg)[v] - 1);
496
            if ((*_indeg)[v] == 0) {
497
              _level->activate(v);
498
            }
499
            _matching->set(u, a);
500
            _indeg->set(n, (*_indeg)[n] + 1);
501
            _level->deactivate(n);
502
            goto no_more_push;
503
          } else if (new_level > (*_level)[v]) {
504
            new_level = (*_level)[v];
505
          }
506
        }
507

	
508
        if (new_level + 1 < _level->maxLevel()) {
509
          _level->liftHighestActive(new_level + 1);
510
        } else {
511
          _level->liftHighestActiveToTop();
512
          _empty_level = _level->maxLevel() - 1;
513
          return false;
514
        }
515
        if (_level->emptyLevel(level)) {
516
          _level->liftToTop(level);
517
          _empty_level = level;
518
          return false;
519
        }
520
      no_more_push:
521
        ;
522
      }
523
      if (postprocess) {
524
        postprocessing();
525
      }
526
      return true;
527
    }
528

	
529
    /// \brief Runs the algorithm
530
    ///
531
    /// Just a shortcut for the next code:
532
    ///\code
533
    /// init();
534
    /// start();
535
    ///\endcode
536
    void run(bool postprocess = true) {
537
      init();
538
      start(postprocess);
539
    }
540

	
541
    /// \brief Runs the algorithm to find a perfect fractional matching
542
    ///
543
    /// Just a shortcut for the next code:
544
    ///\code
545
    /// init();
546
    /// startPerfect();
547
    ///\endcode
548
    bool runPerfect(bool postprocess = true) {
549
      init();
550
      return startPerfect(postprocess);
551
    }
552

	
553
    ///@}
554

	
555
    /// \name Query Functions
556
    /// The result of the %Matching algorithm can be obtained using these
557
    /// functions.\n
558
    /// Before the use of these functions,
559
    /// either run() or start() must be called.
560
    ///@{
561

	
562

	
563
    /// \brief Return the number of covered nodes in the matching.
564
    ///
565
    /// This function returns the number of covered nodes in the matching.
566
    ///
567
    /// \pre Either run() or start() must be called before using this function.
568
    int matchingSize() const {
569
      int num = 0;
570
      for (NodeIt n(_graph); n != INVALID; ++n) {
571
        if ((*_matching)[n] != INVALID) {
572
          ++num;
573
        }
574
      }
575
      return num;
576
    }
577

	
578
    /// \brief Returns a const reference to the matching map.
579
    ///
580
    /// Returns a const reference to the node map storing the found
581
    /// fractional matching. This method can be called after
582
    /// running the algorithm.
583
    ///
584
    /// \pre Either \ref run() or \ref init() must be called before
585
    /// using this function.
586
    const MatchingMap& matchingMap() const {
587
      return *_matching;
588
    }
589

	
590
    /// \brief Return \c true if the given edge is in the matching.
591
    ///
592
    /// This function returns \c true if the given edge is in the
593
    /// found matching. The result is scaled by \ref primalScale
594
    /// "primal scale".
595
    ///
596
    /// \pre Either run() or start() must be called before using this function.
597
    int matching(const Edge& edge) const {
598
      return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0) +
599
        (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
600
    }
601

	
602
    /// \brief Return the fractional matching arc (or edge) incident
603
    /// to the given node.
604
    ///
605
    /// This function returns one of the fractional matching arc (or
606
    /// edge) incident to the given node in the found matching or \c
607
    /// INVALID if the node is not covered by the matching or if the
608
    /// node is on an odd length cycle then it is the successor edge
609
    /// on the cycle.
610
    ///
611
    /// \pre Either run() or start() must be called before using this function.
612
    Arc matching(const Node& node) const {
613
      return (*_matching)[node];
614
    }
615

	
616
    /// \brief Returns true if the node is in the barrier
617
    ///
618
    /// The barrier is a subset of the nodes. If the nodes in the
619
    /// barrier have less adjacent nodes than the size of the barrier,
620
    /// then at least as much nodes cannot be covered as the
621
    /// difference of the two subsets.
622
    bool barrier(const Node& node) const {
623
      return (*_level)[node] >= _empty_level;
624
    }
625

	
626
    /// @}
627

	
628
  };
629

	
630
  /// \ingroup matching
631
  ///
632
  /// \brief Weighted fractional matching in general graphs
633
  ///
634
  /// This class provides an efficient implementation of fractional
635
  /// matching algorithm. The implementation uses priority queues and
636
  /// provides \f$O(nm\log n)\f$ time complexity.
637
  ///
638
  /// The maximum weighted fractional matching is a relaxation of the
639
  /// maximum weighted matching problem where the odd set constraints
640
  /// are omitted.
641
  /// It can be formulated with the following linear program.
642
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
643
  /// \f[x_e \ge 0\quad \forall e\in E\f]
644
  /// \f[\max \sum_{e\in E}x_ew_e\f]
645
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
646
  /// \f$X\f$. The result must be the union of a matching with one
647
  /// value edges and a set of odd length cycles with half value edges.
648
  ///
649
  /// The algorithm calculates an optimal fractional matching and a
650
  /// proof of the optimality. The solution of the dual problem can be
651
  /// used to check the result of the algorithm. The dual linear
652
  /// problem is the following.
653
  /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
654
  /// \f[y_u \ge 0 \quad \forall u \in V\f]
655
  /// \f[\min \sum_{u \in V}y_u \f]
656
  ///
657
  /// The algorithm can be executed with the run() function.
658
  /// After it the matching (the primal solution) and the dual solution
659
  /// can be obtained using the query functions.
660
  ///
661
  /// The primal solution is multiplied by
662
  /// \ref MaxWeightedFractionalMatching::primalScale "2".
663
  /// If the value type is integer, then the dual
664
  /// solution is scaled by
665
  /// \ref MaxWeightedFractionalMatching::dualScale "4".
666
  ///
667
  /// \tparam GR The undirected graph type the algorithm runs on.
668
  /// \tparam WM The type edge weight map. The default type is
669
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
670
#ifdef DOXYGEN
671
  template <typename GR, typename WM>
672
#else
673
  template <typename GR,
674
            typename WM = typename GR::template EdgeMap<int> >
675
#endif
676
  class MaxWeightedFractionalMatching {
677
  public:
678

	
679
    /// The graph type of the algorithm
680
    typedef GR Graph;
681
    /// The type of the edge weight map
682
    typedef WM WeightMap;
683
    /// The value type of the edge weights
684
    typedef typename WeightMap::Value Value;
685

	
686
    /// The type of the matching map
687
    typedef typename Graph::template NodeMap<typename Graph::Arc>
688
    MatchingMap;
689

	
690
    /// \brief Scaling factor for primal solution
691
    ///
692
    /// Scaling factor for primal solution.
693
    static const int primalScale = 2;
694

	
695
    /// \brief Scaling factor for dual solution
696
    ///
697
    /// Scaling factor for dual solution. It is equal to 4 or 1
698
    /// according to the value type.
699
    static const int dualScale =
700
      std::numeric_limits<Value>::is_integer ? 4 : 1;
701

	
702
  private:
703

	
704
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
705

	
706
    typedef typename Graph::template NodeMap<Value> NodePotential;
707

	
708
    const Graph& _graph;
709
    const WeightMap& _weight;
710

	
711
    MatchingMap* _matching;
712
    NodePotential* _node_potential;
713

	
714
    int _node_num;
715
    bool _allow_loops;
716

	
717
    enum Status {
718
      EVEN = -1, MATCHED = 0, ODD = 1
719
    };
720

	
721
    typedef typename Graph::template NodeMap<Status> StatusMap;
722
    StatusMap* _status;
723

	
724
    typedef typename Graph::template NodeMap<Arc> PredMap;
725
    PredMap* _pred;
726

	
727
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
728

	
729
    IntNodeMap *_tree_set_index;
730
    TreeSet *_tree_set;
731

	
732
    IntNodeMap *_delta1_index;
733
    BinHeap<Value, IntNodeMap> *_delta1;
734

	
735
    IntNodeMap *_delta2_index;
736
    BinHeap<Value, IntNodeMap> *_delta2;
737

	
738
    IntEdgeMap *_delta3_index;
739
    BinHeap<Value, IntEdgeMap> *_delta3;
740

	
741
    Value _delta_sum;
742

	
743
    void createStructures() {
744
      _node_num = countNodes(_graph);
745

	
746
      if (!_matching) {
747
        _matching = new MatchingMap(_graph);
748
      }
749
      if (!_node_potential) {
750
        _node_potential = new NodePotential(_graph);
751
      }
752
      if (!_status) {
753
        _status = new StatusMap(_graph);
754
      }
755
      if (!_pred) {
756
        _pred = new PredMap(_graph);
757
      }
758
      if (!_tree_set) {
759
        _tree_set_index = new IntNodeMap(_graph);
760
        _tree_set = new TreeSet(*_tree_set_index);
761
      }
762
      if (!_delta1) {
763
        _delta1_index = new IntNodeMap(_graph);
764
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
765
      }
766
      if (!_delta2) {
767
        _delta2_index = new IntNodeMap(_graph);
768
        _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
769
      }
770
      if (!_delta3) {
771
        _delta3_index = new IntEdgeMap(_graph);
772
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
773
      }
774
    }
775

	
776
    void destroyStructures() {
777
      if (_matching) {
778
        delete _matching;
779
      }
780
      if (_node_potential) {
781
        delete _node_potential;
782
      }
783
      if (_status) {
784
        delete _status;
785
      }
786
      if (_pred) {
787
        delete _pred;
788
      }
789
      if (_tree_set) {
790
        delete _tree_set_index;
791
        delete _tree_set;
792
      }
793
      if (_delta1) {
794
        delete _delta1_index;
795
        delete _delta1;
796
      }
797
      if (_delta2) {
798
        delete _delta2_index;
799
        delete _delta2;
800
      }
801
      if (_delta3) {
802
        delete _delta3_index;
803
        delete _delta3;
804
      }
805
    }
806

	
807
    void matchedToEven(Node node, int tree) {
808
      _tree_set->insert(node, tree);
809
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
810
      _delta1->push(node, (*_node_potential)[node]);
811

	
812
      if (_delta2->state(node) == _delta2->IN_HEAP) {
813
        _delta2->erase(node);
814
      }
815

	
816
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
817
        Node v = _graph.source(a);
818
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
819
          dualScale * _weight[a];
820
        if (node == v) {
821
          if (_allow_loops && _graph.direction(a)) {
822
            _delta3->push(a, rw / 2);
823
          }
824
        } else if ((*_status)[v] == EVEN) {
825
          _delta3->push(a, rw / 2);
826
        } else if ((*_status)[v] == MATCHED) {
827
          if (_delta2->state(v) != _delta2->IN_HEAP) {
828
            _pred->set(v, a);
829
            _delta2->push(v, rw);
830
          } else if ((*_delta2)[v] > rw) {
831
            _pred->set(v, a);
832
            _delta2->decrease(v, rw);
833
          }
834
        }
835
      }
836
    }
837

	
838
    void matchedToOdd(Node node, int tree) {
839
      _tree_set->insert(node, tree);
840
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
841

	
842
      if (_delta2->state(node) == _delta2->IN_HEAP) {
843
        _delta2->erase(node);
844
      }
845
    }
846

	
847
    void evenToMatched(Node node, int tree) {
848
      _delta1->erase(node);
849
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
850
      Arc min = INVALID;
851
      Value minrw = std::numeric_limits<Value>::max();
852
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
853
        Node v = _graph.source(a);
854
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
855
          dualScale * _weight[a];
856

	
857
        if (node == v) {
858
          if (_allow_loops && _graph.direction(a)) {
859
            _delta3->erase(a);
860
          }
861
        } else if ((*_status)[v] == EVEN) {
862
          _delta3->erase(a);
863
          if (minrw > rw) {
864
            min = _graph.oppositeArc(a);
865
            minrw = rw;
866
          }
867
        } else if ((*_status)[v]  == MATCHED) {
868
          if ((*_pred)[v] == a) {
869
            Arc mina = INVALID;
870
            Value minrwa = std::numeric_limits<Value>::max();
871
            for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
872
              Node va = _graph.target(aa);
873
              if ((*_status)[va] != EVEN ||
874
                  _tree_set->find(va) == tree) continue;
875
              Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
876
                dualScale * _weight[aa];
877
              if (minrwa > rwa) {
878
                minrwa = rwa;
879
                mina = aa;
880
              }
881
            }
882
            if (mina != INVALID) {
883
              _pred->set(v, mina);
884
              _delta2->increase(v, minrwa);
885
            } else {
886
              _pred->set(v, INVALID);
887
              _delta2->erase(v);
888
            }
889
          }
890
        }
891
      }
892
      if (min != INVALID) {
893
        _pred->set(node, min);
894
        _delta2->push(node, minrw);
895
      } else {
896
        _pred->set(node, INVALID);
897
      }
898
    }
899

	
900
    void oddToMatched(Node node) {
901
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
902
      Arc min = INVALID;
903
      Value minrw = std::numeric_limits<Value>::max();
904
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
905
        Node v = _graph.source(a);
906
        if ((*_status)[v] != EVEN) continue;
907
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
908
          dualScale * _weight[a];
909

	
910
        if (minrw > rw) {
911
          min = _graph.oppositeArc(a);
912
          minrw = rw;
913
        }
914
      }
915
      if (min != INVALID) {
916
        _pred->set(node, min);
917
        _delta2->push(node, minrw);
918
      } else {
919
        _pred->set(node, INVALID);
920
      }
921
    }
922

	
923
    void alternatePath(Node even, int tree) {
924
      Node odd;
925

	
926
      _status->set(even, MATCHED);
927
      evenToMatched(even, tree);
928

	
929
      Arc prev = (*_matching)[even];
930
      while (prev != INVALID) {
931
        odd = _graph.target(prev);
932
        even = _graph.target((*_pred)[odd]);
933
        _matching->set(odd, (*_pred)[odd]);
934
        _status->set(odd, MATCHED);
935
        oddToMatched(odd);
936

	
937
        prev = (*_matching)[even];
938
        _status->set(even, MATCHED);
939
        _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
940
        evenToMatched(even, tree);
941
      }
942
    }
943

	
944
    void destroyTree(int tree) {
945
      for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
946
        if ((*_status)[n] == EVEN) {
947
          _status->set(n, MATCHED);
948
          evenToMatched(n, tree);
949
        } else if ((*_status)[n] == ODD) {
950
          _status->set(n, MATCHED);
951
          oddToMatched(n);
952
        }
953
      }
954
      _tree_set->eraseClass(tree);
955
    }
956

	
957

	
958
    void unmatchNode(const Node& node) {
959
      int tree = _tree_set->find(node);
960

	
961
      alternatePath(node, tree);
962
      destroyTree(tree);
963

	
964
      _matching->set(node, INVALID);
965
    }
966

	
967

	
968
    void augmentOnEdge(const Edge& edge) {
969
      Node left = _graph.u(edge);
970
      int left_tree = _tree_set->find(left);
971

	
972
      alternatePath(left, left_tree);
973
      destroyTree(left_tree);
974
      _matching->set(left, _graph.direct(edge, true));
975

	
976
      Node right = _graph.v(edge);
977
      int right_tree = _tree_set->find(right);
978

	
979
      alternatePath(right, right_tree);
980
      destroyTree(right_tree);
981
      _matching->set(right, _graph.direct(edge, false));
982
    }
983

	
984
    void augmentOnArc(const Arc& arc) {
985
      Node left = _graph.source(arc);
986
      _status->set(left, MATCHED);
987
      _matching->set(left, arc);
988
      _pred->set(left, arc);
989

	
990
      Node right = _graph.target(arc);
991
      int right_tree = _tree_set->find(right);
992

	
993
      alternatePath(right, right_tree);
994
      destroyTree(right_tree);
995
      _matching->set(right, _graph.oppositeArc(arc));
996
    }
997

	
998
    void extendOnArc(const Arc& arc) {
999
      Node base = _graph.target(arc);
1000
      int tree = _tree_set->find(base);
1001

	
1002
      Node odd = _graph.source(arc);
1003
      _tree_set->insert(odd, tree);
1004
      _status->set(odd, ODD);
1005
      matchedToOdd(odd, tree);
1006
      _pred->set(odd, arc);
1007

	
1008
      Node even = _graph.target((*_matching)[odd]);
1009
      _tree_set->insert(even, tree);
1010
      _status->set(even, EVEN);
1011
      matchedToEven(even, tree);
1012
    }
1013

	
1014
    void cycleOnEdge(const Edge& edge, int tree) {
1015
      Node nca = INVALID;
1016
      std::vector<Node> left_path, right_path;
1017

	
1018
      {
1019
        std::set<Node> left_set, right_set;
1020
        Node left = _graph.u(edge);
1021
        left_path.push_back(left);
1022
        left_set.insert(left);
1023

	
1024
        Node right = _graph.v(edge);
1025
        right_path.push_back(right);
1026
        right_set.insert(right);
1027

	
1028
        while (true) {
1029

	
1030
          if (left_set.find(right) != left_set.end()) {
1031
            nca = right;
1032
            break;
1033
          }
1034

	
1035
          if ((*_matching)[left] == INVALID) break;
1036

	
1037
          left = _graph.target((*_matching)[left]);
1038
          left_path.push_back(left);
1039
          left = _graph.target((*_pred)[left]);
1040
          left_path.push_back(left);
1041

	
1042
          left_set.insert(left);
1043

	
1044
          if (right_set.find(left) != right_set.end()) {
1045
            nca = left;
1046
            break;
1047
          }
1048

	
1049
          if ((*_matching)[right] == INVALID) break;
1050

	
1051
          right = _graph.target((*_matching)[right]);
1052
          right_path.push_back(right);
1053
          right = _graph.target((*_pred)[right]);
1054
          right_path.push_back(right);
1055

	
1056
          right_set.insert(right);
1057

	
1058
        }
1059

	
1060
        if (nca == INVALID) {
1061
          if ((*_matching)[left] == INVALID) {
1062
            nca = right;
1063
            while (left_set.find(nca) == left_set.end()) {
1064
              nca = _graph.target((*_matching)[nca]);
1065
              right_path.push_back(nca);
1066
              nca = _graph.target((*_pred)[nca]);
1067
              right_path.push_back(nca);
1068
            }
1069
          } else {
1070
            nca = left;
1071
            while (right_set.find(nca) == right_set.end()) {
1072
              nca = _graph.target((*_matching)[nca]);
1073
              left_path.push_back(nca);
1074
              nca = _graph.target((*_pred)[nca]);
1075
              left_path.push_back(nca);
1076
            }
1077
          }
1078
        }
1079
      }
1080

	
1081
      alternatePath(nca, tree);
1082
      Arc prev;
1083

	
1084
      prev = _graph.direct(edge, true);
1085
      for (int i = 0; left_path[i] != nca; i += 2) {
1086
        _matching->set(left_path[i], prev);
1087
        _status->set(left_path[i], MATCHED);
1088
        evenToMatched(left_path[i], tree);
1089

	
1090
        prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1091
        _status->set(left_path[i + 1], MATCHED);
1092
        oddToMatched(left_path[i + 1]);
1093
      }
1094
      _matching->set(nca, prev);
1095

	
1096
      for (int i = 0; right_path[i] != nca; i += 2) {
1097
        _status->set(right_path[i], MATCHED);
1098
        evenToMatched(right_path[i], tree);
1099

	
1100
        _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
1101
        _status->set(right_path[i + 1], MATCHED);
1102
        oddToMatched(right_path[i + 1]);
1103
      }
1104

	
1105
      destroyTree(tree);
1106
    }
1107

	
1108
    void extractCycle(const Arc &arc) {
1109
      Node left = _graph.source(arc);
1110
      Node odd = _graph.target((*_matching)[left]);
1111
      Arc prev;
1112
      while (odd != left) {
1113
        Node even = _graph.target((*_matching)[odd]);
1114
        prev = (*_matching)[odd];
1115
        odd = _graph.target((*_matching)[even]);
1116
        _matching->set(even, _graph.oppositeArc(prev));
1117
      }
1118
      _matching->set(left, arc);
1119

	
1120
      Node right = _graph.target(arc);
1121
      int right_tree = _tree_set->find(right);
1122
      alternatePath(right, right_tree);
1123
      destroyTree(right_tree);
1124
      _matching->set(right, _graph.oppositeArc(arc));
1125
    }
1126

	
1127
  public:
1128

	
1129
    /// \brief Constructor
1130
    ///
1131
    /// Constructor.
1132
    MaxWeightedFractionalMatching(const Graph& graph, const WeightMap& weight,
1133
                                  bool allow_loops = true)
1134
      : _graph(graph), _weight(weight), _matching(0),
1135
      _node_potential(0), _node_num(0), _allow_loops(allow_loops),
1136
      _status(0),  _pred(0),
1137
      _tree_set_index(0), _tree_set(0),
1138

	
1139
      _delta1_index(0), _delta1(0),
1140
      _delta2_index(0), _delta2(0),
1141
      _delta3_index(0), _delta3(0),
1142

	
1143
      _delta_sum() {}
1144

	
1145
    ~MaxWeightedFractionalMatching() {
1146
      destroyStructures();
1147
    }
1148

	
1149
    /// \name Execution Control
1150
    /// The simplest way to execute the algorithm is to use the
1151
    /// \ref run() member function.
1152

	
1153
    ///@{
1154

	
1155
    /// \brief Initialize the algorithm
1156
    ///
1157
    /// This function initializes the algorithm.
1158
    void init() {
1159
      createStructures();
1160

	
1161
      for (NodeIt n(_graph); n != INVALID; ++n) {
1162
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1163
        (*_delta2_index)[n] = _delta2->PRE_HEAP;
1164
      }
1165
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1166
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1167
      }
1168

	
1169
      for (NodeIt n(_graph); n != INVALID; ++n) {
1170
        Value max = 0;
1171
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1172
          if (_graph.target(e) == n && !_allow_loops) continue;
1173
          if ((dualScale * _weight[e]) / 2 > max) {
1174
            max = (dualScale * _weight[e]) / 2;
1175
          }
1176
        }
1177
        _node_potential->set(n, max);
1178
        _delta1->push(n, max);
1179

	
1180
        _tree_set->insert(n);
1181

	
1182
        _matching->set(n, INVALID);
1183
        _status->set(n, EVEN);
1184
      }
1185

	
1186
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1187
        Node left = _graph.u(e);
1188
        Node right = _graph.v(e);
1189
        if (left == right && !_allow_loops) continue;
1190
        _delta3->push(e, ((*_node_potential)[left] +
1191
                          (*_node_potential)[right] -
1192
                          dualScale * _weight[e]) / 2);
1193
      }
1194
    }
1195

	
1196
    /// \brief Start the algorithm
1197
    ///
1198
    /// This function starts the algorithm.
1199
    ///
1200
    /// \pre \ref init() must be called before using this function.
1201
    void start() {
1202
      enum OpType {
1203
        D1, D2, D3
1204
      };
1205

	
1206
      int unmatched = _node_num;
1207
      while (unmatched > 0) {
1208
        Value d1 = !_delta1->empty() ?
1209
          _delta1->prio() : std::numeric_limits<Value>::max();
1210

	
1211
        Value d2 = !_delta2->empty() ?
1212
          _delta2->prio() : std::numeric_limits<Value>::max();
1213

	
1214
        Value d3 = !_delta3->empty() ?
1215
          _delta3->prio() : std::numeric_limits<Value>::max();
1216

	
1217
        _delta_sum = d3; OpType ot = D3;
1218
        if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1219
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1220

	
1221
        switch (ot) {
1222
        case D1:
1223
          {
1224
            Node n = _delta1->top();
1225
            unmatchNode(n);
1226
            --unmatched;
1227
          }
1228
          break;
1229
        case D2:
1230
          {
1231
            Node n = _delta2->top();
1232
            Arc a = (*_pred)[n];
1233
            if ((*_matching)[n] == INVALID) {
1234
              augmentOnArc(a);
1235
              --unmatched;
1236
            } else {
1237
              Node v = _graph.target((*_matching)[n]);
1238
              if ((*_matching)[n] !=
1239
                  _graph.oppositeArc((*_matching)[v])) {
1240
                extractCycle(a);
1241
                --unmatched;
1242
              } else {
1243
                extendOnArc(a);
1244
              }
1245
            }
1246
          } break;
1247
        case D3:
1248
          {
1249
            Edge e = _delta3->top();
1250

	
1251
            Node left = _graph.u(e);
1252
            Node right = _graph.v(e);
1253

	
1254
            int left_tree = _tree_set->find(left);
1255
            int right_tree = _tree_set->find(right);
1256

	
1257
            if (left_tree == right_tree) {
1258
              cycleOnEdge(e, left_tree);
1259
              --unmatched;
1260
            } else {
1261
              augmentOnEdge(e);
1262
              unmatched -= 2;
1263
            }
1264
          } break;
1265
        }
1266
      }
1267
    }
1268

	
1269
    /// \brief Run the algorithm.
1270
    ///
1271
    /// This method runs the \c %MaxWeightedFractionalMatching algorithm.
1272
    ///
1273
    /// \note mwfm.run() is just a shortcut of the following code.
1274
    /// \code
1275
    ///   mwfm.init();
1276
    ///   mwfm.start();
1277
    /// \endcode
1278
    void run() {
1279
      init();
1280
      start();
1281
    }
1282

	
1283
    /// @}
1284

	
1285
    /// \name Primal Solution
1286
    /// Functions to get the primal solution, i.e. the maximum weighted
1287
    /// matching.\n
1288
    /// Either \ref run() or \ref start() function should be called before
1289
    /// using them.
1290

	
1291
    /// @{
1292

	
1293
    /// \brief Return the weight of the matching.
1294
    ///
1295
    /// This function returns the weight of the found matching. This
1296
    /// value is scaled by \ref primalScale "primal scale".
1297
    ///
1298
    /// \pre Either run() or start() must be called before using this function.
1299
    Value matchingWeight() const {
1300
      Value sum = 0;
1301
      for (NodeIt n(_graph); n != INVALID; ++n) {
1302
        if ((*_matching)[n] != INVALID) {
1303
          sum += _weight[(*_matching)[n]];
1304
        }
1305
      }
1306
      return sum * primalScale / 2;
1307
    }
1308

	
1309
    /// \brief Return the number of covered nodes in the matching.
1310
    ///
1311
    /// This function returns the number of covered nodes in the matching.
1312
    ///
1313
    /// \pre Either run() or start() must be called before using this function.
1314
    int matchingSize() const {
1315
      int num = 0;
1316
      for (NodeIt n(_graph); n != INVALID; ++n) {
1317
        if ((*_matching)[n] != INVALID) {
1318
          ++num;
1319
        }
1320
      }
1321
      return num;
1322
    }
1323

	
1324
    /// \brief Return \c true if the given edge is in the matching.
1325
    ///
1326
    /// This function returns \c true if the given edge is in the
1327
    /// found matching. The result is scaled by \ref primalScale
1328
    /// "primal scale".
1329
    ///
1330
    /// \pre Either run() or start() must be called before using this function.
1331
    int matching(const Edge& edge) const {
1332
      return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
1333
        + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
1334
    }
1335

	
1336
    /// \brief Return the fractional matching arc (or edge) incident
1337
    /// to the given node.
1338
    ///
1339
    /// This function returns one of the fractional matching arc (or
1340
    /// edge) incident to the given node in the found matching or \c
1341
    /// INVALID if the node is not covered by the matching or if the
1342
    /// node is on an odd length cycle then it is the successor edge
1343
    /// on the cycle.
1344
    ///
1345
    /// \pre Either run() or start() must be called before using this function.
1346
    Arc matching(const Node& node) const {
1347
      return (*_matching)[node];
1348
    }
1349

	
1350
    /// \brief Return a const reference to the matching map.
1351
    ///
1352
    /// This function returns a const reference to a node map that stores
1353
    /// the matching arc (or edge) incident to each node.
1354
    const MatchingMap& matchingMap() const {
1355
      return *_matching;
1356
    }
1357

	
1358
    /// @}
1359

	
1360
    /// \name Dual Solution
1361
    /// Functions to get the dual solution.\n
1362
    /// Either \ref run() or \ref start() function should be called before
1363
    /// using them.
1364

	
1365
    /// @{
1366

	
1367
    /// \brief Return the value of the dual solution.
1368
    ///
1369
    /// This function returns the value of the dual solution.
1370
    /// It should be equal to the primal value scaled by \ref dualScale
1371
    /// "dual scale".
1372
    ///
1373
    /// \pre Either run() or start() must be called before using this function.
1374
    Value dualValue() const {
1375
      Value sum = 0;
1376
      for (NodeIt n(_graph); n != INVALID; ++n) {
1377
        sum += nodeValue(n);
1378
      }
1379
      return sum;
1380
    }
1381

	
1382
    /// \brief Return the dual value (potential) of the given node.
1383
    ///
1384
    /// This function returns the dual value (potential) of the given node.
1385
    ///
1386
    /// \pre Either run() or start() must be called before using this function.
1387
    Value nodeValue(const Node& n) const {
1388
      return (*_node_potential)[n];
1389
    }
1390

	
1391
    /// @}
1392

	
1393
  };
1394

	
1395
  /// \ingroup matching
1396
  ///
1397
  /// \brief Weighted fractional perfect matching in general graphs
1398
  ///
1399
  /// This class provides an efficient implementation of fractional
1400
  /// matching algorithm. The implementation uses priority queues and
1401
  /// provides \f$O(nm\log n)\f$ time complexity.
1402
  ///
1403
  /// The maximum weighted fractional perfect matching is a relaxation
1404
  /// of the maximum weighted perfect matching problem where the odd
1405
  /// set constraints are omitted.
1406
  /// It can be formulated with the following linear program.
1407
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1408
  /// \f[x_e \ge 0\quad \forall e\in E\f]
1409
  /// \f[\max \sum_{e\in E}x_ew_e\f]
1410
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1411
  /// \f$X\f$. The result must be the union of a matching with one
1412
  /// value edges and a set of odd length cycles with half value edges.
1413
  ///
1414
  /// The algorithm calculates an optimal fractional matching and a
1415
  /// proof of the optimality. The solution of the dual problem can be
1416
  /// used to check the result of the algorithm. The dual linear
1417
  /// problem is the following.
1418
  /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
1419
  /// \f[\min \sum_{u \in V}y_u \f]
1420
  ///
1421
  /// The algorithm can be executed with the run() function.
1422
  /// After it the matching (the primal solution) and the dual solution
1423
  /// can be obtained using the query functions.
1424
  ///
1425
  /// The primal solution is multiplied by
1426
  /// \ref MaxWeightedPerfectFractionalMatching::primalScale "2".
1427
  /// If the value type is integer, then the dual
1428
  /// solution is scaled by
1429
  /// \ref MaxWeightedPerfectFractionalMatching::dualScale "4".
1430
  ///
1431
  /// \tparam GR The undirected graph type the algorithm runs on.
1432
  /// \tparam WM The type edge weight map. The default type is
1433
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
1434
#ifdef DOXYGEN
1435
  template <typename GR, typename WM>
1436
#else
1437
  template <typename GR,
1438
            typename WM = typename GR::template EdgeMap<int> >
1439
#endif
1440
  class MaxWeightedPerfectFractionalMatching {
1441
  public:
1442

	
1443
    /// The graph type of the algorithm
1444
    typedef GR Graph;
1445
    /// The type of the edge weight map
1446
    typedef WM WeightMap;
1447
    /// The value type of the edge weights
1448
    typedef typename WeightMap::Value Value;
1449

	
1450
    /// The type of the matching map
1451
    typedef typename Graph::template NodeMap<typename Graph::Arc>
1452
    MatchingMap;
1453

	
1454
    /// \brief Scaling factor for primal solution
1455
    ///
1456
    /// Scaling factor for primal solution.
1457
    static const int primalScale = 2;
1458

	
1459
    /// \brief Scaling factor for dual solution
1460
    ///
1461
    /// Scaling factor for dual solution. It is equal to 4 or 1
1462
    /// according to the value type.
1463
    static const int dualScale =
1464
      std::numeric_limits<Value>::is_integer ? 4 : 1;
1465

	
1466
  private:
1467

	
1468
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1469

	
1470
    typedef typename Graph::template NodeMap<Value> NodePotential;
1471

	
1472
    const Graph& _graph;
1473
    const WeightMap& _weight;
1474

	
1475
    MatchingMap* _matching;
1476
    NodePotential* _node_potential;
1477

	
1478
    int _node_num;
1479
    bool _allow_loops;
1480

	
1481
    enum Status {
1482
      EVEN = -1, MATCHED = 0, ODD = 1
1483
    };
1484

	
1485
    typedef typename Graph::template NodeMap<Status> StatusMap;
1486
    StatusMap* _status;
1487

	
1488
    typedef typename Graph::template NodeMap<Arc> PredMap;
1489
    PredMap* _pred;
1490

	
1491
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
1492

	
1493
    IntNodeMap *_tree_set_index;
1494
    TreeSet *_tree_set;
1495

	
1496
    IntNodeMap *_delta2_index;
1497
    BinHeap<Value, IntNodeMap> *_delta2;
1498

	
1499
    IntEdgeMap *_delta3_index;
1500
    BinHeap<Value, IntEdgeMap> *_delta3;
1501

	
1502
    Value _delta_sum;
1503

	
1504
    void createStructures() {
1505
      _node_num = countNodes(_graph);
1506

	
1507
      if (!_matching) {
1508
        _matching = new MatchingMap(_graph);
1509
      }
1510
      if (!_node_potential) {
1511
        _node_potential = new NodePotential(_graph);
1512
      }
1513
      if (!_status) {
1514
        _status = new StatusMap(_graph);
1515
      }
1516
      if (!_pred) {
1517
        _pred = new PredMap(_graph);
1518
      }
1519
      if (!_tree_set) {
1520
        _tree_set_index = new IntNodeMap(_graph);
1521
        _tree_set = new TreeSet(*_tree_set_index);
1522
      }
1523
      if (!_delta2) {
1524
        _delta2_index = new IntNodeMap(_graph);
1525
        _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
1526
      }
1527
      if (!_delta3) {
1528
        _delta3_index = new IntEdgeMap(_graph);
1529
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
1530
      }
1531
    }
1532

	
1533
    void destroyStructures() {
1534
      if (_matching) {
1535
        delete _matching;
1536
      }
1537
      if (_node_potential) {
1538
        delete _node_potential;
1539
      }
1540
      if (_status) {
1541
        delete _status;
1542
      }
1543
      if (_pred) {
1544
        delete _pred;
1545
      }
1546
      if (_tree_set) {
1547
        delete _tree_set_index;
1548
        delete _tree_set;
1549
      }
1550
      if (_delta2) {
1551
        delete _delta2_index;
1552
        delete _delta2;
1553
      }
1554
      if (_delta3) {
1555
        delete _delta3_index;
1556
        delete _delta3;
1557
      }
1558
    }
1559

	
1560
    void matchedToEven(Node node, int tree) {
1561
      _tree_set->insert(node, tree);
1562
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
1563

	
1564
      if (_delta2->state(node) == _delta2->IN_HEAP) {
1565
        _delta2->erase(node);
1566
      }
1567

	
1568
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
1569
        Node v = _graph.source(a);
1570
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1571
          dualScale * _weight[a];
1572
        if (node == v) {
1573
          if (_allow_loops && _graph.direction(a)) {
1574
            _delta3->push(a, rw / 2);
1575
          }
1576
        } else if ((*_status)[v] == EVEN) {
1577
          _delta3->push(a, rw / 2);
1578
        } else if ((*_status)[v] == MATCHED) {
1579
          if (_delta2->state(v) != _delta2->IN_HEAP) {
1580
            _pred->set(v, a);
1581
            _delta2->push(v, rw);
1582
          } else if ((*_delta2)[v] > rw) {
1583
            _pred->set(v, a);
1584
            _delta2->decrease(v, rw);
1585
          }
1586
        }
1587
      }
1588
    }
1589

	
1590
    void matchedToOdd(Node node, int tree) {
1591
      _tree_set->insert(node, tree);
1592
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
1593

	
1594
      if (_delta2->state(node) == _delta2->IN_HEAP) {
1595
        _delta2->erase(node);
1596
      }
1597
    }
1598

	
1599
    void evenToMatched(Node node, int tree) {
1600
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
1601
      Arc min = INVALID;
1602
      Value minrw = std::numeric_limits<Value>::max();
1603
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
1604
        Node v = _graph.source(a);
1605
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1606
          dualScale * _weight[a];
1607

	
1608
        if (node == v) {
1609
          if (_allow_loops && _graph.direction(a)) {
1610
            _delta3->erase(a);
1611
          }
1612
        } else if ((*_status)[v] == EVEN) {
1613
          _delta3->erase(a);
1614
          if (minrw > rw) {
1615
            min = _graph.oppositeArc(a);
1616
            minrw = rw;
1617
          }
1618
        } else if ((*_status)[v]  == MATCHED) {
1619
          if ((*_pred)[v] == a) {
1620
            Arc mina = INVALID;
1621
            Value minrwa = std::numeric_limits<Value>::max();
1622
            for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
1623
              Node va = _graph.target(aa);
1624
              if ((*_status)[va] != EVEN ||
1625
                  _tree_set->find(va) == tree) continue;
1626
              Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
1627
                dualScale * _weight[aa];
1628
              if (minrwa > rwa) {
1629
                minrwa = rwa;
1630
                mina = aa;
1631
              }
1632
            }
1633
            if (mina != INVALID) {
1634
              _pred->set(v, mina);
1635
              _delta2->increase(v, minrwa);
1636
            } else {
1637
              _pred->set(v, INVALID);
1638
              _delta2->erase(v);
1639
            }
1640
          }
1641
        }
1642
      }
1643
      if (min != INVALID) {
1644
        _pred->set(node, min);
1645
        _delta2->push(node, minrw);
1646
      } else {
1647
        _pred->set(node, INVALID);
1648
      }
1649
    }
1650

	
1651
    void oddToMatched(Node node) {
1652
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
1653
      Arc min = INVALID;
1654
      Value minrw = std::numeric_limits<Value>::max();
1655
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
1656
        Node v = _graph.source(a);
1657
        if ((*_status)[v] != EVEN) continue;
1658
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1659
          dualScale * _weight[a];
1660

	
1661
        if (minrw > rw) {
1662
          min = _graph.oppositeArc(a);
1663
          minrw = rw;
1664
        }
1665
      }
1666
      if (min != INVALID) {
1667
        _pred->set(node, min);
1668
        _delta2->push(node, minrw);
1669
      } else {
1670
        _pred->set(node, INVALID);
1671
      }
1672
    }
1673

	
1674
    void alternatePath(Node even, int tree) {
1675
      Node odd;
1676

	
1677
      _status->set(even, MATCHED);
1678
      evenToMatched(even, tree);
1679

	
1680
      Arc prev = (*_matching)[even];
1681
      while (prev != INVALID) {
1682
        odd = _graph.target(prev);
1683
        even = _graph.target((*_pred)[odd]);
1684
        _matching->set(odd, (*_pred)[odd]);
1685
        _status->set(odd, MATCHED);
1686
        oddToMatched(odd);
1687

	
1688
        prev = (*_matching)[even];
1689
        _status->set(even, MATCHED);
1690
        _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
1691
        evenToMatched(even, tree);
1692
      }
1693
    }
1694

	
1695
    void destroyTree(int tree) {
1696
      for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
1697
        if ((*_status)[n] == EVEN) {
1698
          _status->set(n, MATCHED);
1699
          evenToMatched(n, tree);
1700
        } else if ((*_status)[n] == ODD) {
1701
          _status->set(n, MATCHED);
1702
          oddToMatched(n);
1703
        }
1704
      }
1705
      _tree_set->eraseClass(tree);
1706
    }
1707

	
1708
    void augmentOnEdge(const Edge& edge) {
1709
      Node left = _graph.u(edge);
1710
      int left_tree = _tree_set->find(left);
1711

	
1712
      alternatePath(left, left_tree);
1713
      destroyTree(left_tree);
1714
      _matching->set(left, _graph.direct(edge, true));
1715

	
1716
      Node right = _graph.v(edge);
1717
      int right_tree = _tree_set->find(right);
1718

	
1719
      alternatePath(right, right_tree);
1720
      destroyTree(right_tree);
1721
      _matching->set(right, _graph.direct(edge, false));
1722
    }
1723

	
1724
    void augmentOnArc(const Arc& arc) {
1725
      Node left = _graph.source(arc);
1726
      _status->set(left, MATCHED);
1727
      _matching->set(left, arc);
1728
      _pred->set(left, arc);
1729

	
1730
      Node right = _graph.target(arc);
1731
      int right_tree = _tree_set->find(right);
1732

	
1733
      alternatePath(right, right_tree);
1734
      destroyTree(right_tree);
1735
      _matching->set(right, _graph.oppositeArc(arc));
1736
    }
1737

	
1738
    void extendOnArc(const Arc& arc) {
1739
      Node base = _graph.target(arc);
1740
      int tree = _tree_set->find(base);
1741

	
1742
      Node odd = _graph.source(arc);
1743
      _tree_set->insert(odd, tree);
1744
      _status->set(odd, ODD);
1745
      matchedToOdd(odd, tree);
1746
      _pred->set(odd, arc);
1747

	
1748
      Node even = _graph.target((*_matching)[odd]);
1749
      _tree_set->insert(even, tree);
1750
      _status->set(even, EVEN);
1751
      matchedToEven(even, tree);
1752
    }
1753

	
1754
    void cycleOnEdge(const Edge& edge, int tree) {
1755
      Node nca = INVALID;
1756
      std::vector<Node> left_path, right_path;
1757

	
1758
      {
1759
        std::set<Node> left_set, right_set;
1760
        Node left = _graph.u(edge);
1761
        left_path.push_back(left);
1762
        left_set.insert(left);
1763

	
1764
        Node right = _graph.v(edge);
1765
        right_path.push_back(right);
1766
        right_set.insert(right);
1767

	
1768
        while (true) {
1769

	
1770
          if (left_set.find(right) != left_set.end()) {
1771
            nca = right;
1772
            break;
1773
          }
1774

	
1775
          if ((*_matching)[left] == INVALID) break;
1776

	
1777
          left = _graph.target((*_matching)[left]);
1778
          left_path.push_back(left);
1779
          left = _graph.target((*_pred)[left]);
1780
          left_path.push_back(left);
1781

	
1782
          left_set.insert(left);
1783

	
1784
          if (right_set.find(left) != right_set.end()) {
1785
            nca = left;
1786
            break;
1787
          }
1788

	
1789
          if ((*_matching)[right] == INVALID) break;
1790

	
1791
          right = _graph.target((*_matching)[right]);
1792
          right_path.push_back(right);
1793
          right = _graph.target((*_pred)[right]);
1794
          right_path.push_back(right);
1795

	
1796
          right_set.insert(right);
1797

	
1798
        }
1799

	
1800
        if (nca == INVALID) {
1801
          if ((*_matching)[left] == INVALID) {
1802
            nca = right;
1803
            while (left_set.find(nca) == left_set.end()) {
1804
              nca = _graph.target((*_matching)[nca]);
1805
              right_path.push_back(nca);
1806
              nca = _graph.target((*_pred)[nca]);
1807
              right_path.push_back(nca);
1808
            }
1809
          } else {
1810
            nca = left;
1811
            while (right_set.find(nca) == right_set.end()) {
1812
              nca = _graph.target((*_matching)[nca]);
1813
              left_path.push_back(nca);
1814
              nca = _graph.target((*_pred)[nca]);
1815
              left_path.push_back(nca);
1816
            }
1817
          }
1818
        }
1819
      }
1820

	
1821
      alternatePath(nca, tree);
1822
      Arc prev;
1823

	
1824
      prev = _graph.direct(edge, true);
1825
      for (int i = 0; left_path[i] != nca; i += 2) {
1826
        _matching->set(left_path[i], prev);
1827
        _status->set(left_path[i], MATCHED);
1828
        evenToMatched(left_path[i], tree);
1829

	
1830
        prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1831
        _status->set(left_path[i + 1], MATCHED);
1832
        oddToMatched(left_path[i + 1]);
1833
      }
1834
      _matching->set(nca, prev);
1835

	
1836
      for (int i = 0; right_path[i] != nca; i += 2) {
1837
        _status->set(right_path[i], MATCHED);
1838
        evenToMatched(right_path[i], tree);
1839

	
1840
        _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
1841
        _status->set(right_path[i + 1], MATCHED);
1842
        oddToMatched(right_path[i + 1]);
1843
      }
1844

	
1845
      destroyTree(tree);
1846
    }
1847

	
1848
    void extractCycle(const Arc &arc) {
1849
      Node left = _graph.source(arc);
1850
      Node odd = _graph.target((*_matching)[left]);
1851
      Arc prev;
1852
      while (odd != left) {
1853
        Node even = _graph.target((*_matching)[odd]);
1854
        prev = (*_matching)[odd];
1855
        odd = _graph.target((*_matching)[even]);
1856
        _matching->set(even, _graph.oppositeArc(prev));
1857
      }
1858
      _matching->set(left, arc);
1859

	
1860
      Node right = _graph.target(arc);
1861
      int right_tree = _tree_set->find(right);
1862
      alternatePath(right, right_tree);
1863
      destroyTree(right_tree);
1864
      _matching->set(right, _graph.oppositeArc(arc));
1865
    }
1866

	
1867
  public:
1868

	
1869
    /// \brief Constructor
1870
    ///
1871
    /// Constructor.
1872
    MaxWeightedPerfectFractionalMatching(const Graph& graph,
1873
                                         const WeightMap& weight,
1874
                                         bool allow_loops = true)
1875
      : _graph(graph), _weight(weight), _matching(0),
1876
      _node_potential(0), _node_num(0), _allow_loops(allow_loops),
1877
      _status(0),  _pred(0),
1878
      _tree_set_index(0), _tree_set(0),
1879

	
1880
      _delta2_index(0), _delta2(0),
1881
      _delta3_index(0), _delta3(0),
1882

	
1883
      _delta_sum() {}
1884

	
1885
    ~MaxWeightedPerfectFractionalMatching() {
1886
      destroyStructures();
1887
    }
1888

	
1889
    /// \name Execution Control
1890
    /// The simplest way to execute the algorithm is to use the
1891
    /// \ref run() member function.
1892

	
1893
    ///@{
1894

	
1895
    /// \brief Initialize the algorithm
1896
    ///
1897
    /// This function initializes the algorithm.
1898
    void init() {
1899
      createStructures();
1900

	
1901
      for (NodeIt n(_graph); n != INVALID; ++n) {
1902
        (*_delta2_index)[n] = _delta2->PRE_HEAP;
1903
      }
1904
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1905
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1906
      }
1907

	
1908
      for (NodeIt n(_graph); n != INVALID; ++n) {
1909
        Value max = - std::numeric_limits<Value>::max();
1910
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1911
          if (_graph.target(e) == n && !_allow_loops) continue;
1912
          if ((dualScale * _weight[e]) / 2 > max) {
1913
            max = (dualScale * _weight[e]) / 2;
1914
          }
1915
        }
1916
        _node_potential->set(n, max);
1917

	
1918
        _tree_set->insert(n);
1919

	
1920
        _matching->set(n, INVALID);
1921
        _status->set(n, EVEN);
1922
      }
1923

	
1924
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1925
        Node left = _graph.u(e);
1926
        Node right = _graph.v(e);
1927
        if (left == right && !_allow_loops) continue;
1928
        _delta3->push(e, ((*_node_potential)[left] +
1929
                          (*_node_potential)[right] -
1930
                          dualScale * _weight[e]) / 2);
1931
      }
1932
    }
1933

	
1934
    /// \brief Start the algorithm
1935
    ///
1936
    /// This function starts the algorithm.
1937
    ///
1938
    /// \pre \ref init() must be called before using this function.
1939
    bool start() {
1940
      enum OpType {
1941
        D2, D3
1942
      };
1943

	
1944
      int unmatched = _node_num;
1945
      while (unmatched > 0) {
1946
        Value d2 = !_delta2->empty() ?
1947
          _delta2->prio() : std::numeric_limits<Value>::max();
1948

	
1949
        Value d3 = !_delta3->empty() ?
1950
          _delta3->prio() : std::numeric_limits<Value>::max();
1951

	
1952
        _delta_sum = d3; OpType ot = D3;
1953
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1954

	
1955
        if (_delta_sum == std::numeric_limits<Value>::max()) {
1956
          return false;
1957
        }
1958

	
1959
        switch (ot) {
1960
        case D2:
1961
          {
1962
            Node n = _delta2->top();
1963
            Arc a = (*_pred)[n];
1964
            if ((*_matching)[n] == INVALID) {
1965
              augmentOnArc(a);
1966
              --unmatched;
1967
            } else {
1968
              Node v = _graph.target((*_matching)[n]);
1969
              if ((*_matching)[n] !=
1970
                  _graph.oppositeArc((*_matching)[v])) {
1971
                extractCycle(a);
1972
                --unmatched;
1973
              } else {
1974
                extendOnArc(a);
1975
              }
1976
            }
1977
          } break;
1978
        case D3:
1979
          {
1980
            Edge e = _delta3->top();
1981

	
1982
            Node left = _graph.u(e);
1983
            Node right = _graph.v(e);
1984

	
1985
            int left_tree = _tree_set->find(left);
1986
            int right_tree = _tree_set->find(right);
1987

	
1988
            if (left_tree == right_tree) {
1989
              cycleOnEdge(e, left_tree);
1990
              --unmatched;
1991
            } else {
1992
              augmentOnEdge(e);
1993
              unmatched -= 2;
1994
            }
1995
          } break;
1996
        }
1997
      }
1998
      return true;
1999
    }
2000

	
2001
    /// \brief Run the algorithm.
2002
    ///
2003
    /// This method runs the \c %MaxWeightedPerfectFractionalMatching 
2004
    /// algorithm.
2005
    ///
2006
    /// \note mwfm.run() is just a shortcut of the following code.
2007
    /// \code
2008
    ///   mwpfm.init();
2009
    ///   mwpfm.start();
2010
    /// \endcode
2011
    bool run() {
2012
      init();
2013
      return start();
2014
    }
2015

	
2016
    /// @}
2017

	
2018
    /// \name Primal Solution
2019
    /// Functions to get the primal solution, i.e. the maximum weighted
2020
    /// matching.\n
2021
    /// Either \ref run() or \ref start() function should be called before
2022
    /// using them.
2023

	
2024
    /// @{
2025

	
2026
    /// \brief Return the weight of the matching.
2027
    ///
2028
    /// This function returns the weight of the found matching. This
2029
    /// value is scaled by \ref primalScale "primal scale".
2030
    ///
2031
    /// \pre Either run() or start() must be called before using this function.
2032
    Value matchingWeight() const {
2033
      Value sum = 0;
2034
      for (NodeIt n(_graph); n != INVALID; ++n) {
2035
        if ((*_matching)[n] != INVALID) {
2036
          sum += _weight[(*_matching)[n]];
2037
        }
2038
      }
2039
      return sum * primalScale / 2;
2040
    }
2041

	
2042
    /// \brief Return the number of covered nodes in the matching.
2043
    ///
2044
    /// This function returns the number of covered nodes in the matching.
2045
    ///
2046
    /// \pre Either run() or start() must be called before using this function.
2047
    int matchingSize() const {
2048
      int num = 0;
2049
      for (NodeIt n(_graph); n != INVALID; ++n) {
2050
        if ((*_matching)[n] != INVALID) {
2051
          ++num;
2052
        }
2053
      }
2054
      return num;
2055
    }
2056

	
2057
    /// \brief Return \c true if the given edge is in the matching.
2058
    ///
2059
    /// This function returns \c true if the given edge is in the
2060
    /// found matching. The result is scaled by \ref primalScale
2061
    /// "primal scale".
2062
    ///
2063
    /// \pre Either run() or start() must be called before using this function.
2064
    int matching(const Edge& edge) const {
2065
      return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
2066
        + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
2067
    }
2068

	
2069
    /// \brief Return the fractional matching arc (or edge) incident
2070
    /// to the given node.
2071
    ///
2072
    /// This function returns one of the fractional matching arc (or
2073
    /// edge) incident to the given node in the found matching or \c
2074
    /// INVALID if the node is not covered by the matching or if the
2075
    /// node is on an odd length cycle then it is the successor edge
2076
    /// on the cycle.
2077
    ///
2078
    /// \pre Either run() or start() must be called before using this function.
2079
    Arc matching(const Node& node) const {
2080
      return (*_matching)[node];
2081
    }
2082

	
2083
    /// \brief Return a const reference to the matching map.
2084
    ///
2085
    /// This function returns a const reference to a node map that stores
2086
    /// the matching arc (or edge) incident to each node.
2087
    const MatchingMap& matchingMap() const {
2088
      return *_matching;
2089
    }
2090

	
2091
    /// @}
2092

	
2093
    /// \name Dual Solution
2094
    /// Functions to get the dual solution.\n
2095
    /// Either \ref run() or \ref start() function should be called before
2096
    /// using them.
2097

	
2098
    /// @{
2099

	
2100
    /// \brief Return the value of the dual solution.
2101
    ///
2102
    /// This function returns the value of the dual solution.
2103
    /// It should be equal to the primal value scaled by \ref dualScale
2104
    /// "dual scale".
2105
    ///
2106
    /// \pre Either run() or start() must be called before using this function.
2107
    Value dualValue() const {
2108
      Value sum = 0;
2109
      for (NodeIt n(_graph); n != INVALID; ++n) {
2110
        sum += nodeValue(n);
2111
      }
2112
      return sum;
2113
    }
2114

	
2115
    /// \brief Return the dual value (potential) of the given node.
2116
    ///
2117
    /// This function returns the dual value (potential) of the given node.
2118
    ///
2119
    /// \pre Either run() or start() must be called before using this function.
2120
    Value nodeValue(const Node& n) const {
2121
      return (*_node_potential)[n];
2122
    }
2123

	
2124
    /// @}
2125

	
2126
  };
2127

	
2128
} //END OF NAMESPACE LEMON
2129

	
2130
#endif //LEMON_FRACTIONAL_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-2009
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 <cstdlib>
24

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

	
32
#include "test_tools.h"
33

	
34
using namespace std;
35
using namespace lemon;
36

	
37
GRAPH_TYPEDEFS(SmartGraph);
38

	
39

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

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

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

	
114
  "@nodes\n"
115
  "label\n"
116
  "0\n"
117
  "@edges\n"
118
  "     label  weight\n"
119
  "0 0  0      100\n"
120
};
121

	
122
void checkMaxFractionalMatchingCompile()
123
{
124
  typedef concepts::Graph Graph;
125
  typedef Graph::Node Node;
126
  typedef Graph::Edge Edge;
127

	
128
  Graph g;
129
  Node n;
130
  Edge e;
131

	
132
  MaxFractionalMatching<Graph> mat_test(g);
133
  const MaxFractionalMatching<Graph>&
134
    const_mat_test = mat_test;
135

	
136
  mat_test.init();
137
  mat_test.start();
138
  mat_test.start(true);
139
  mat_test.startPerfect();
140
  mat_test.startPerfect(true);
141
  mat_test.run();
142
  mat_test.run(true);
143
  mat_test.runPerfect();
144
  mat_test.runPerfect(true);
145

	
146
  const_mat_test.matchingSize();
147
  const_mat_test.matching(e);
148
  const_mat_test.matching(n);
149
  const MaxFractionalMatching<Graph>::MatchingMap& mmap =
150
    const_mat_test.matchingMap();
151
  e = mmap[n];
152

	
153
  const_mat_test.barrier(n);
154
}
155

	
156
void checkMaxWeightedFractionalMatchingCompile()
157
{
158
  typedef concepts::Graph Graph;
159
  typedef Graph::Node Node;
160
  typedef Graph::Edge Edge;
161
  typedef Graph::EdgeMap<int> WeightMap;
162

	
163
  Graph g;
164
  Node n;
165
  Edge e;
166
  WeightMap w(g);
167

	
168
  MaxWeightedFractionalMatching<Graph> mat_test(g, w);
169
  const MaxWeightedFractionalMatching<Graph>&
170
    const_mat_test = mat_test;
171

	
172
  mat_test.init();
173
  mat_test.start();
174
  mat_test.run();
175

	
176
  const_mat_test.matchingWeight();
177
  const_mat_test.matchingSize();
178
  const_mat_test.matching(e);
179
  const_mat_test.matching(n);
180
  const MaxWeightedFractionalMatching<Graph>::MatchingMap& mmap =
181
    const_mat_test.matchingMap();
182
  e = mmap[n];
183

	
184
  const_mat_test.dualValue();
185
  const_mat_test.nodeValue(n);
186
}
187

	
188
void checkMaxWeightedPerfectFractionalMatchingCompile()
189
{
190
  typedef concepts::Graph Graph;
191
  typedef Graph::Node Node;
192
  typedef Graph::Edge Edge;
193
  typedef Graph::EdgeMap<int> WeightMap;
194

	
195
  Graph g;
196
  Node n;
197
  Edge e;
198
  WeightMap w(g);
199

	
200
  MaxWeightedPerfectFractionalMatching<Graph> mat_test(g, w);
201
  const MaxWeightedPerfectFractionalMatching<Graph>&
202
    const_mat_test = mat_test;
203

	
204
  mat_test.init();
205
  mat_test.start();
206
  mat_test.run();
207

	
208
  const_mat_test.matchingWeight();
209
  const_mat_test.matching(e);
210
  const_mat_test.matching(n);
211
  const MaxWeightedPerfectFractionalMatching<Graph>::MatchingMap& mmap =
212
    const_mat_test.matchingMap();
213
  e = mmap[n];
214

	
215
  const_mat_test.dualValue();
216
  const_mat_test.nodeValue(n);
217
}
218

	
219
void checkFractionalMatching(const SmartGraph& graph,
220
                             const MaxFractionalMatching<SmartGraph>& mfm,
221
                             bool allow_loops = true) {
222
  int pv = 0;
223
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
224
    int indeg = 0;
225
    for (InArcIt a(graph, n); a != INVALID; ++a) {
226
      if (mfm.matching(graph.source(a)) == a) {
227
        ++indeg;
228
      }
229
    }
230
    if (mfm.matching(n) != INVALID) {
231
      check(indeg == 1, "Invalid matching");
232
      ++pv;
233
    } else {
234
      check(indeg == 0, "Invalid matching");
235
    }
236
  }
237
  check(pv == mfm.matchingSize(), "Wrong matching size");
238

	
239
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
240
    check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
241
          (e == mfm.matching(graph.v(e)) ? 1 : 0) == 
242
          mfm.matching(e), "Invalid matching");
243
  }
244

	
245
  SmartGraph::NodeMap<bool> processed(graph, false);
246
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
247
    if (processed[n]) continue;
248
    processed[n] = true;
249
    if (mfm.matching(n) == INVALID) continue;
250
    int num = 1;
251
    Node v = graph.target(mfm.matching(n));
252
    while (v != n) {
253
      processed[v] = true;
254
      ++num;
255
      v = graph.target(mfm.matching(v));
256
    }
257
    check(num == 2 || num % 2 == 1, "Wrong cycle size");
258
    check(allow_loops || num != 1, "Wrong cycle size");
259
  }
260

	
261
  int anum = 0, bnum = 0;
262
  SmartGraph::NodeMap<bool> neighbours(graph, false);
263
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
264
    if (!mfm.barrier(n)) continue;
265
    ++anum;
266
    for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
267
      Node u = graph.source(a);
268
      if (!allow_loops && u == n) continue;
269
      if (!neighbours[u]) {
270
        neighbours[u] = true;
271
        ++bnum;
272
      }
273
    }
274
  }
275
  check(anum - bnum + mfm.matchingSize() == countNodes(graph),
276
        "Wrong barrier");
277
}
278

	
279
void checkPerfectFractionalMatching(const SmartGraph& graph,
280
                             const MaxFractionalMatching<SmartGraph>& mfm,
281
                             bool perfect, bool allow_loops = true) {
282
  if (perfect) {
283
    for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
284
      int indeg = 0;
285
      for (InArcIt a(graph, n); a != INVALID; ++a) {
286
        if (mfm.matching(graph.source(a)) == a) {
287
          ++indeg;
288
        }
289
      }
290
      check(mfm.matching(n) != INVALID, "Invalid matching");
291
      check(indeg == 1, "Invalid matching");
292
    }
293
    for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
294
      check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
295
            (e == mfm.matching(graph.v(e)) ? 1 : 0) == 
296
            mfm.matching(e), "Invalid matching");
297
    }
298
  } else {
299
    int anum = 0, bnum = 0;
300
    SmartGraph::NodeMap<bool> neighbours(graph, false);
301
    for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
302
      if (!mfm.barrier(n)) continue;
303
      ++anum;
304
      for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
305
        Node u = graph.source(a);
306
        if (!allow_loops && u == n) continue;
307
        if (!neighbours[u]) {
308
          neighbours[u] = true;
309
          ++bnum;
310
        }
311
      }
312
    }
313
    check(anum - bnum > 0, "Wrong barrier");
314
  }
315
}
316

	
317
void checkWeightedFractionalMatching(const SmartGraph& graph,
318
                   const SmartGraph::EdgeMap<int>& weight,
319
                   const MaxWeightedFractionalMatching<SmartGraph>& mwfm,
320
                   bool allow_loops = true) {
321
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
322
    if (graph.u(e) == graph.v(e) && !allow_loops) continue;
323
    int rw = mwfm.nodeValue(graph.u(e)) + mwfm.nodeValue(graph.v(e))
324
      - weight[e] * mwfm.dualScale;
325

	
326
    check(rw >= 0, "Negative reduced weight");
327
    check(rw == 0 || !mwfm.matching(e),
328
          "Non-zero reduced weight on matching edge");
329
  }
330

	
331
  int pv = 0;
332
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
333
    int indeg = 0;
334
    for (InArcIt a(graph, n); a != INVALID; ++a) {
335
      if (mwfm.matching(graph.source(a)) == a) {
336
        ++indeg;
337
      }
338
    }
339
    check(indeg <= 1, "Invalid matching");
340
    if (mwfm.matching(n) != INVALID) {
341
      check(mwfm.nodeValue(n) >= 0, "Invalid node value");
342
      check(indeg == 1, "Invalid matching");
343
      pv += weight[mwfm.matching(n)];
344
      SmartGraph::Node o = graph.target(mwfm.matching(n));
345
    } else {
346
      check(mwfm.nodeValue(n) == 0, "Invalid matching");
347
      check(indeg == 0, "Invalid matching");
348
    }
349
  }
350

	
351
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
352
    check((e == mwfm.matching(graph.u(e)) ? 1 : 0) +
353
          (e == mwfm.matching(graph.v(e)) ? 1 : 0) == 
354
          mwfm.matching(e), "Invalid matching");
355
  }
356

	
357
  int dv = 0;
358
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
359
    dv += mwfm.nodeValue(n);
360
  }
361

	
362
  check(pv * mwfm.dualScale == dv * 2, "Wrong duality");
363

	
364
  SmartGraph::NodeMap<bool> processed(graph, false);
365
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
366
    if (processed[n]) continue;
367
    processed[n] = true;
368
    if (mwfm.matching(n) == INVALID) continue;
369
    int num = 1;
370
    Node v = graph.target(mwfm.matching(n));
371
    while (v != n) {
372
      processed[v] = true;
373
      ++num;
374
      v = graph.target(mwfm.matching(v));
375
    }
376
    check(num == 2 || num % 2 == 1, "Wrong cycle size");
377
    check(allow_loops || num != 1, "Wrong cycle size");
378
  }
379

	
380
  return;
381
}
382

	
383
void checkWeightedPerfectFractionalMatching(const SmartGraph& graph,
384
                const SmartGraph::EdgeMap<int>& weight,
385
                const MaxWeightedPerfectFractionalMatching<SmartGraph>& mwpfm,
386
                bool allow_loops = true) {
387
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
388
    if (graph.u(e) == graph.v(e) && !allow_loops) continue;
389
    int rw = mwpfm.nodeValue(graph.u(e)) + mwpfm.nodeValue(graph.v(e))
390
      - weight[e] * mwpfm.dualScale;
391

	
392
    check(rw >= 0, "Negative reduced weight");
393
    check(rw == 0 || !mwpfm.matching(e),
394
          "Non-zero reduced weight on matching edge");
395
  }
396

	
397
  int pv = 0;
398
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
399
    int indeg = 0;
400
    for (InArcIt a(graph, n); a != INVALID; ++a) {
401
      if (mwpfm.matching(graph.source(a)) == a) {
402
        ++indeg;
403
      }
404
    }
405
    check(mwpfm.matching(n) != INVALID, "Invalid perfect matching");
406
    check(indeg == 1, "Invalid perfect matching");
407
    pv += weight[mwpfm.matching(n)];
408
    SmartGraph::Node o = graph.target(mwpfm.matching(n));
409
  }
410

	
411
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
412
    check((e == mwpfm.matching(graph.u(e)) ? 1 : 0) +
413
          (e == mwpfm.matching(graph.v(e)) ? 1 : 0) == 
414
          mwpfm.matching(e), "Invalid matching");
415
  }
416

	
417
  int dv = 0;
418
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
419
    dv += mwpfm.nodeValue(n);
420
  }
421

	
422
  check(pv * mwpfm.dualScale == dv * 2, "Wrong duality");
423

	
424
  SmartGraph::NodeMap<bool> processed(graph, false);
425
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
426
    if (processed[n]) continue;
427
    processed[n] = true;
428
    if (mwpfm.matching(n) == INVALID) continue;
429
    int num = 1;
430
    Node v = graph.target(mwpfm.matching(n));
431
    while (v != n) {
432
      processed[v] = true;
433
      ++num;
434
      v = graph.target(mwpfm.matching(v));
435
    }
436
    check(num == 2 || num % 2 == 1, "Wrong cycle size");
437
    check(allow_loops || num != 1, "Wrong cycle size");
438
  }
439

	
440
  return;
441
}
442

	
443

	
444
int main() {
445

	
446
  for (int i = 0; i < lgfn; ++i) {
447
    SmartGraph graph;
448
    SmartGraph::EdgeMap<int> weight(graph);
449

	
450
    istringstream lgfs(lgf[i]);
451
    graphReader(graph, lgfs).
452
      edgeMap("weight", weight).run();
453

	
454
    bool perfect_with_loops;
455
    {
456
      MaxFractionalMatching<SmartGraph> mfm(graph, true);
457
      mfm.run();
458
      checkFractionalMatching(graph, mfm, true);
459
      perfect_with_loops = mfm.matchingSize() == countNodes(graph);
460
    }
461

	
462
    bool perfect_without_loops;
463
    {
464
      MaxFractionalMatching<SmartGraph> mfm(graph, false);
465
      mfm.run();
466
      checkFractionalMatching(graph, mfm, false);
467
      perfect_without_loops = mfm.matchingSize() == countNodes(graph);
468
    }
469

	
470
    {
471
      MaxFractionalMatching<SmartGraph> mfm(graph, true);
472
      bool result = mfm.runPerfect();
473
      checkPerfectFractionalMatching(graph, mfm, result, true);
474
      check(result == perfect_with_loops, "Wrong perfect matching");
475
    }
476

	
477
    {
478
      MaxFractionalMatching<SmartGraph> mfm(graph, false);
479
      bool result = mfm.runPerfect();
480
      checkPerfectFractionalMatching(graph, mfm, result, false);
481
      check(result == perfect_without_loops, "Wrong perfect matching");
482
    }
483

	
484
    {
485
      MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, true);
486
      mwfm.run();
487
      checkWeightedFractionalMatching(graph, weight, mwfm, true);
488
    }
489

	
490
    {
491
      MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, false);
492
      mwfm.run();
493
      checkWeightedFractionalMatching(graph, weight, mwfm, false);
494
    }
495

	
496
    {
497
      MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
498
                                                             true);
499
      bool perfect = mwpfm.run();
500
      check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
501
            "Perfect matching found");
502
      check(perfect == perfect_with_loops, "Wrong perfect matching");
503

	
504
      if (perfect) {
505
        checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, true);
506
      }
507
    }
508

	
509
    {
510
      MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
511
                                                             false);
512
      bool perfect = mwpfm.run();
513
      check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
514
            "Perfect matching found");
515
      check(perfect == perfect_without_loops, "Wrong perfect matching");
516

	
517
      if (perfect) {
518
        checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, false);
519
      }
520
    }
521

	
522
  }
523

	
524
  return 0;
525
}
Show white space 6 line context
... ...
@@ -388,3 +388,3 @@
388 388

	
389
\ref Circulation is a preflow push-relabel algorithm implemented directly 
389
\ref Circulation is a preflow push-relabel algorithm implemented directly
390 390
for finding feasible circulations, which is a somewhat different problem,
... ...
@@ -524,2 +524,9 @@
524 524
  perfect matching in general graphs.
525
- \ref MaxFractionalMatching Push-relabel algorithm for calculating
526
  maximum cardinality fractional matching in general graphs.
527
- \ref MaxWeightedFractionalMatching Augmenting path algorithm for calculating
528
  maximum weighted fractional matching in general graphs.
529
- \ref MaxWeightedPerfectFractionalMatching
530
  Augmenting path algorithm for calculating maximum weighted
531
  perfect fractional matching in general graphs.
525 532

	
Ignore white space 6 line context
... ...
@@ -86,2 +86,3 @@
86 86
	lemon/fib_heap.h \
87
	lemon/fractional_matching.h \
87 88
	lemon/full_graph.h \
Ignore white space 6 line context
... ...
@@ -18,4 +18,4 @@
18 18

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

	
... ...
@@ -30,2 +30,3 @@
30 30
#include <lemon/maps.h>
31
#include <lemon/fractional_matching.h>
31 32

	
... ...
@@ -43,3 +44,3 @@
43 44
  /// for finding a maximum cardinality matching in a general undirected graph.
44
  /// It can be started from an arbitrary initial matching 
45
  /// It can be started from an arbitrary initial matching
45 46
  /// (the default is the empty one).
... ...
@@ -71,3 +72,3 @@
71 72
    ///
72
    ///These constants are used for indicating the Gallai-Edmonds 
73
    ///These constants are used for indicating the Gallai-Edmonds
73 74
    ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
... ...
@@ -75,3 +76,3 @@
75 76
    ///status \c ODD (or \c A) form the canonical barrier, and the nodes
76
    ///with status \c MATCHED (or \c C) induce a subgraph having a 
77
    ///with status \c MATCHED (or \c C) induce a subgraph having a
77 78
    ///perfect matching.
... ...
@@ -514,3 +515,3 @@
514 515

	
515
    /// \brief Start Edmonds' algorithm with a heuristic improvement 
516
    /// \brief Start Edmonds' algorithm with a heuristic improvement
516 517
    /// for dense graphs
... ...
@@ -536,4 +537,4 @@
536 537
    ///
537
    /// This function runs Edmonds' algorithm. An additional heuristic of 
538
    /// postponing shrinks is used for relatively dense graphs 
538
    /// This function runs Edmonds' algorithm. An additional heuristic of
539
    /// postponing shrinks is used for relatively dense graphs
539 540
    /// (for which <tt>m>=2*n</tt> holds).
... ...
@@ -558,3 +559,3 @@
558 559
    ///
559
    /// This function returns the size (cardinality) of the current matching. 
560
    /// This function returns the size (cardinality) of the current matching.
560 561
    /// After run() it returns the size of the maximum matching in the graph.
... ...
@@ -572,3 +573,3 @@
572 573
    ///
573
    /// This function returns \c true if the given edge is in the current 
574
    /// This function returns \c true if the given edge is in the current
574 575
    /// matching.
... ...
@@ -581,3 +582,3 @@
581 582
    /// This function returns the matching arc (or edge) incident to the
582
    /// given node in the current matching or \c INVALID if the node is 
583
    /// given node in the current matching or \c INVALID if the node is
583 584
    /// not covered by the matching.
... ...
@@ -597,3 +598,3 @@
597 598
    ///
598
    /// This function returns the mate of the given node in the current 
599
    /// This function returns the mate of the given node in the current
599 600
    /// matching or \c INVALID if the node is not covered by the matching.
... ...
@@ -607,3 +608,3 @@
607 608
    /// \name Dual Solution
608
    /// Functions to get the dual solution, i.e. the Gallai-Edmonds 
609
    /// Functions to get the dual solution, i.e. the Gallai-Edmonds
609 610
    /// decomposition.
... ...
@@ -650,4 +651,4 @@
650 651
  ///
651
  /// The maximum weighted matching problem is to find a subset of the 
652
  /// edges in an undirected graph with maximum overall weight for which 
652
  /// The maximum weighted matching problem is to find a subset of the
653
  /// edges in an undirected graph with maximum overall weight for which
653 654
  /// each node has at most one incident edge.
... ...
@@ -675,7 +676,7 @@
675 676
  ///
676
  /// The algorithm can be executed with the run() function. 
677
  /// The algorithm can be executed with the run() function.
677 678
  /// After it the matching (the primal solution) and the dual solution
678
  /// can be obtained using the query functions and the 
679
  /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class, 
680
  /// which is able to iterate on the nodes of a blossom. 
679
  /// can be obtained using the query functions and the
680
  /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
681
  /// which is able to iterate on the nodes of a blossom.
681 682
  /// If the value type is integer, then the dual solution is multiplied
... ...
@@ -684,3 +685,3 @@
684 685
  /// \tparam GR The undirected graph type the algorithm runs on.
685
  /// \tparam WM The type edge weight map. The default type is 
686
  /// \tparam WM The type edge weight map. The default type is
686 687
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
... ...
@@ -747,3 +748,3 @@
747 748
    enum Status {
748
      EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
749
      EVEN = -1, MATCHED = 0, ODD = 1
749 750
    };
... ...
@@ -799,2 +800,6 @@
799 800
    Value _delta_sum;
801
    int _unmatched;
802

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

	
... ...
@@ -846,5 +851,2 @@
846 851
    void destroyStructures() {
847
      _node_num = countNodes(_graph);
848
      _blossom_num = _node_num * 3 / 2;
849

	
850 852
      if (_matching) {
... ...
@@ -924,6 +926,2 @@
924 926
            }
925
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
926
            if (_delta3->state(e) != _delta3->IN_HEAP) {
927
              _delta3->push(e, rw);
928
            }
929 927
          } else {
... ...
@@ -951,198 +949,2 @@
951 949
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
952
                           (*_blossom_data)[vb].offset){
953
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
954
                                   (*_blossom_data)[vb].offset);
955
                }
956
              }
957
            }
958
          }
959
        }
960
      }
961
      (*_blossom_data)[blossom].offset = 0;
962
    }
963

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

	
975
    void evenToMatched(int blossom, int tree) {
976
      if (!_blossom_set->trivial(blossom)) {
977
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
978
      }
979

	
980
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
981
           n != INVALID; ++n) {
982
        int ni = (*_node_index)[n];
983
        (*_node_data)[ni].pot -= _delta_sum;
984

	
985
        _delta1->erase(n);
986

	
987
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
988
          Node v = _graph.source(e);
989
          int vb = _blossom_set->find(v);
990
          int vi = (*_node_index)[v];
991

	
992
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
993
            dualScale * _weight[e];
994

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

	
1001
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1002
              _delta3->erase(e);
1003
            }
1004

	
1005
            int vt = _tree_set->find(vb);
1006

	
1007
            if (vt != tree) {
1008

	
1009
              Arc r = _graph.oppositeArc(e);
1010

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

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

	
1025
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1026
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1027

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

	
1040
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1041
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1042
              _delta3->erase(e);
1043
            }
1044
          } else {
1045

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

	
1049
            if (it != (*_node_data)[vi].heap_index.end()) {
1050
              (*_node_data)[vi].heap.erase(it->second);
1051
              (*_node_data)[vi].heap_index.erase(it);
1052
              if ((*_node_data)[vi].heap.empty()) {
1053
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
1054
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1055
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1056
              }
1057

	
1058
              if ((*_blossom_data)[vb].status == MATCHED) {
1059
                if (_blossom_set->classPrio(vb) ==
1060
                    std::numeric_limits<Value>::max()) {
1061
                  _delta2->erase(vb);
1062
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1063
                           (*_blossom_data)[vb].offset) {
1064
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
1065
                                   (*_blossom_data)[vb].offset);
1066
                }
1067
              }
1068
            }
1069
          }
1070
        }
1071
      }
1072
    }
1073

	
1074
    void oddToMatched(int blossom) {
1075
      (*_blossom_data)[blossom].offset -= _delta_sum;
1076

	
1077
      if (_blossom_set->classPrio(blossom) !=
1078
          std::numeric_limits<Value>::max()) {
1079
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1080
                       (*_blossom_data)[blossom].offset);
1081
      }
1082

	
1083
      if (!_blossom_set->trivial(blossom)) {
1084
        _delta4->erase(blossom);
1085
      }
1086
    }
1087

	
1088
    void oddToEven(int blossom, int tree) {
1089
      if (!_blossom_set->trivial(blossom)) {
1090
        _delta4->erase(blossom);
1091
        (*_blossom_data)[blossom].pot -=
1092
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1093
      }
1094

	
1095
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1096
           n != INVALID; ++n) {
1097
        int ni = (*_node_index)[n];
1098

	
1099
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1100

	
1101
        (*_node_data)[ni].heap.clear();
1102
        (*_node_data)[ni].heap_index.clear();
1103
        (*_node_data)[ni].pot +=
1104
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
1105

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

	
1108
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1109
          Node v = _graph.source(e);
1110
          int vb = _blossom_set->find(v);
1111
          int vi = (*_node_index)[v];
1112

	
1113
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1114
            dualScale * _weight[e];
1115

	
1116
          if ((*_blossom_data)[vb].status == EVEN) {
1117
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1118
              _delta3->push(e, rw / 2);
1119
            }
1120
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1121
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1122
              _delta3->push(e, rw);
1123
            }
1124
          } else {
1125

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

	
1129
            if (it != (*_node_data)[vi].heap_index.end()) {
1130
              if ((*_node_data)[vi].heap[it->second] > rw) {
1131
                (*_node_data)[vi].heap.replace(it->second, e);
1132
                (*_node_data)[vi].heap.decrease(e, rw);
1133
                it->second = e;
1134
              }
1135
            } else {
1136
              (*_node_data)[vi].heap.push(e, rw);
1137
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1138
            }
1139

	
1140
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1141
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1142

	
1143
              if ((*_blossom_data)[vb].status == MATCHED) {
1144
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
1145
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
1146
                               (*_blossom_data)[vb].offset);
1147
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1148 950
                           (*_blossom_data)[vb].offset) {
... ...
@@ -1159,4 +961,3 @@
1159 961

	
1160

	
1161
    void matchedToUnmatched(int blossom) {
962
    void matchedToOdd(int blossom) {
1162 963
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
... ...
@@ -1164,2 +965,13 @@
1164 965
      }
966
      (*_blossom_data)[blossom].offset += _delta_sum;
967
      if (!_blossom_set->trivial(blossom)) {
968
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
969
                      (*_blossom_data)[blossom].offset);
970
      }
971
    }
972

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

	
... ...
@@ -1168,10 +980,8 @@
1168 980
        int ni = (*_node_index)[n];
1169

	
1170
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1171

	
1172
        (*_node_data)[ni].heap.clear();
1173
        (*_node_data)[ni].heap_index.clear();
1174

	
1175
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1176
          Node v = _graph.target(e);
981
        (*_node_data)[ni].pot -= _delta_sum;
982

	
983
        _delta1->erase(n);
984

	
985
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
986
          Node v = _graph.source(e);
1177 987
          int vb = _blossom_set->find(v);
... ...
@@ -1182,5 +992,70 @@
1182 992

	
1183
          if ((*_blossom_data)[vb].status == EVEN) {
1184
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1185
              _delta3->push(e, rw);
993
          if (vb == blossom) {
994
            if (_delta3->state(e) == _delta3->IN_HEAP) {
995
              _delta3->erase(e);
996
            }
997
          } else if ((*_blossom_data)[vb].status == EVEN) {
998

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

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

	
1005
            if (vt != tree) {
1006

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

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

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

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

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

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

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

	
1051
              if ((*_blossom_data)[vb].status == MATCHED) {
1052
                if (_blossom_set->classPrio(vb) ==
1053
                    std::numeric_limits<Value>::max()) {
1054
                  _delta2->erase(vb);
1055
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1056
                           (*_blossom_data)[vb].offset) {
1057
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
1058
                                   (*_blossom_data)[vb].offset);
1059
                }
1060
              }
1186 1061
            }
... ...
@@ -1191,3 +1066,23 @@
1191 1066

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

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

	
1076
      if (!_blossom_set->trivial(blossom)) {
1077
        _delta4->erase(blossom);
1078
      }
1079
    }
1080

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

	
1193 1088
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
... ...
@@ -1196,2 +1091,11 @@
1196 1091

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

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

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

	
1197 1101
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
... ...
@@ -1204,47 +1108,36 @@
1204 1108

	
1205
          if (vb == blossom) {
1206
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1207
              _delta3->erase(e);
1109
          if ((*_blossom_data)[vb].status == EVEN) {
1110
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1111
              _delta3->push(e, rw / 2);
1208 1112
            }
1209
          } else if ((*_blossom_data)[vb].status == EVEN) {
1210

	
1211
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1212
              _delta3->erase(e);
1213
            }
1214

	
1215
            int vt = _tree_set->find(vb);
1216

	
1217
            Arc r = _graph.oppositeArc(e);
1113
          } else {
1218 1114

	
1219 1115
            typename std::map<int, Arc>::iterator it =
1220
              (*_node_data)[ni].heap_index.find(vt);
1221

	
1222
            if (it != (*_node_data)[ni].heap_index.end()) {
1223
              if ((*_node_data)[ni].heap[it->second] > rw) {
1224
                (*_node_data)[ni].heap.replace(it->second, r);
1225
                (*_node_data)[ni].heap.decrease(r, rw);
1226
                it->second = r;
1116
              (*_node_data)[vi].heap_index.find(tree);
1117

	
1118
            if (it != (*_node_data)[vi].heap_index.end()) {
1119
              if ((*_node_data)[vi].heap[it->second] > rw) {
1120
                (*_node_data)[vi].heap.replace(it->second, e);
1121
                (*_node_data)[vi].heap.decrease(e, rw);
1122
                it->second = e;
1227 1123
              }
1228 1124
            } else {
1229
              (*_node_data)[ni].heap.push(r, rw);
1230
              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1125
              (*_node_data)[vi].heap.push(e, rw);
1126
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1231 1127
            }
1232 1128

	
1233
            if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1234
              _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1235

	
1236
              if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1237
                _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1238
                             (*_blossom_data)[blossom].offset);
1239
              } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
1240
                         (*_blossom_data)[blossom].offset){
1241
                _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1242
                                 (*_blossom_data)[blossom].offset);
1129
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1130
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1131

	
1132
              if ((*_blossom_data)[vb].status == MATCHED) {
1133
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
1134
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
1135
                               (*_blossom_data)[vb].offset);
1136
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1137
                           (*_blossom_data)[vb].offset) {
1138
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1139
                                   (*_blossom_data)[vb].offset);
1140
                }
1243 1141
              }
1244 1142
            }
1245

	
1246
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1247
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1248
              _delta3->erase(e);
1249
            }
1250 1143
          }
... ...
@@ -1252,2 +1145,3 @@
1252 1145
      }
1146
      (*_blossom_data)[blossom].offset = 0;
1253 1147
    }
... ...
@@ -1296,8 +1190,6 @@
1296 1190

	
1297
      (*_blossom_data)[blossom].status = UNMATCHED;
1298 1191
      (*_blossom_data)[blossom].base = node;
1299
      matchedToUnmatched(blossom);
1192
      (*_blossom_data)[blossom].next = INVALID;
1300 1193
    }
1301 1194

	
1302

	
1303 1195
    void augmentOnEdge(const Edge& edge) {
... ...
@@ -1307,19 +1199,9 @@
1307 1199

	
1308
      if ((*_blossom_data)[left].status == EVEN) {
1309
        int left_tree = _tree_set->find(left);
1310
        alternatePath(left, left_tree);
1311
        destroyTree(left_tree);
1312
      } else {
1313
        (*_blossom_data)[left].status = MATCHED;
1314
        unmatchedToMatched(left);
1315
      }
1316

	
1317
      if ((*_blossom_data)[right].status == EVEN) {
1318
        int right_tree = _tree_set->find(right);
1319
        alternatePath(right, right_tree);
1320
        destroyTree(right_tree);
1321
      } else {
1322
        (*_blossom_data)[right].status = MATCHED;
1323
        unmatchedToMatched(right);
1324
      }
1200
      int left_tree = _tree_set->find(left);
1201
      alternatePath(left, left_tree);
1202
      destroyTree(left_tree);
1203

	
1204
      int right_tree = _tree_set->find(right);
1205
      alternatePath(right, right_tree);
1206
      destroyTree(right_tree);
1325 1207

	
... ...
@@ -1329,2 +1211,17 @@
1329 1211

	
1212
    void augmentOnArc(const Arc& arc) {
1213

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

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

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

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

	
1330 1227
    void extendOnArc(const Arc& arc) {
... ...
@@ -1531,3 +1428,3 @@
1531 1428
          (*_blossom_data)[sb].next =
1532
                           _graph.oppositeArc((*_blossom_data)[tb].next);
1429
            _graph.oppositeArc((*_blossom_data)[tb].next);
1533 1430

	
... ...
@@ -1631,3 +1528,3 @@
1631 1528
      for (int i = 0; i < int(blossoms.size()); ++i) {
1632
        if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
1529
        if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1633 1530

	
... ...
@@ -1669,3 +1566,6 @@
1669 1566

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

	
1569
        _fractional(0)
1570
    {}
1671 1571

	
... ...
@@ -1673,2 +1573,5 @@
1673 1573
      destroyStructures();
1574
      if (_fractional) {
1575
        delete _fractional;
1576
      }
1674 1577
    }
... ...
@@ -1701,2 +1604,4 @@
1701 1604

	
1605
      _unmatched = _node_num;
1606

	
1702 1607
      int index = 0;
... ...
@@ -1735,2 +1640,139 @@
1735 1640

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

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

	
1667
      _unmatched = 0;
1668

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

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

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

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

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

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

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

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

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

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

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

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

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

	
1736 1778
    /// \brief Start the algorithm
... ...
@@ -1739,3 +1781,4 @@
1739 1781
    ///
1740
    /// \pre \ref init() must be called before using this function.
1782
    /// \pre \ref init() or \ref fractionalInit() must be called
1783
    /// before using this function.
1741 1784
    void start() {
... ...
@@ -1745,4 +1788,3 @@
1745 1788

	
1746
      int unmatched = _node_num;
1747
      while (unmatched > 0) {
1789
      while (_unmatched > 0) {
1748 1790
        Value d1 = !_delta1->empty() ?
... ...
@@ -1759,8 +1801,7 @@
1759 1801

	
1760
        _delta_sum = d1; OpType ot = D1;
1802
        _delta_sum = d3; OpType ot = D3;
1803
        if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1761 1804
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1762
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1763 1805
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1764 1806

	
1765

	
1766 1807
        switch (ot) {
... ...
@@ -1770,3 +1811,3 @@
1770 1811
            unmatchNode(n);
1771
            --unmatched;
1812
            --_unmatched;
1772 1813
          }
... ...
@@ -1777,4 +1818,9 @@
1777 1818
            Node n = _blossom_set->classTop(blossom);
1778
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1779
            extendOnArc(e);
1819
            Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
1820
            if ((*_blossom_data)[blossom].next == INVALID) {
1821
              augmentOnArc(a);
1822
              --_unmatched;
1823
            } else {
1824
              extendOnArc(a);
1825
            }
1780 1826
          }
... ...
@@ -1791,16 +1837,4 @@
1791 1837
            } else {
1792
              int left_tree;
1793
              if ((*_blossom_data)[left_blossom].status == EVEN) {
1794
                left_tree = _tree_set->find(left_blossom);
1795
              } else {
1796
                left_tree = -1;
1797
                ++unmatched;
1798
              }
1799
              int right_tree;
1800
              if ((*_blossom_data)[right_blossom].status == EVEN) {
1801
                right_tree = _tree_set->find(right_blossom);
1802
              } else {
1803
                right_tree = -1;
1804
                ++unmatched;
1805
              }
1838
              int left_tree = _tree_set->find(left_blossom);
1839
              int right_tree = _tree_set->find(right_blossom);
1806 1840

	
... ...
@@ -1810,3 +1844,3 @@
1810 1844
                augmentOnEdge(e);
1811
                unmatched -= 2;
1845
                _unmatched -= 2;
1812 1846
              }
... ...
@@ -1828,3 +1862,3 @@
1828 1862
    /// \code
1829
    ///   mwm.init();
1863
    ///   mwm.fractionalInit();
1830 1864
    ///   mwm.start();
... ...
@@ -1832,3 +1866,3 @@
1832 1866
    void run() {
1833
      init();
1867
      fractionalInit();
1834 1868
      start();
... ...
@@ -1839,3 +1873,3 @@
1839 1873
    /// \name Primal Solution
1840
    /// Functions to get the primal solution, i.e. the maximum weighted 
1874
    /// Functions to get the primal solution, i.e. the maximum weighted
1841 1875
    /// matching.\n
... ...
@@ -1858,3 +1892,3 @@
1858 1892
      }
1859
      return sum /= 2;
1893
      return sum / 2;
1860 1894
    }
... ...
@@ -1878,3 +1912,3 @@
1878 1912
    ///
1879
    /// This function returns \c true if the given edge is in the found 
1913
    /// This function returns \c true if the given edge is in the found
1880 1914
    /// matching.
... ...
@@ -1889,3 +1923,3 @@
1889 1923
    /// This function returns the matching arc (or edge) incident to the
1890
    /// given node in the found matching or \c INVALID if the node is 
1924
    /// given node in the found matching or \c INVALID if the node is
1891 1925
    /// not covered by the matching.
... ...
@@ -1907,3 +1941,3 @@
1907 1941
    ///
1908
    /// This function returns the mate of the given node in the found 
1942
    /// This function returns the mate of the given node in the found
1909 1943
    /// matching or \c INVALID if the node is not covered by the matching.
... ...
@@ -1927,4 +1961,4 @@
1927 1961
    ///
1928
    /// This function returns the value of the dual solution. 
1929
    /// It should be equal to the primal value scaled by \ref dualScale 
1962
    /// This function returns the value of the dual solution.
1963
    /// It should be equal to the primal value scaled by \ref dualScale
1930 1964
    /// "dual scale".
... ...
@@ -1983,5 +2017,5 @@
1983 2017
    ///
1984
    /// This class provides an iterator for obtaining the nodes of the 
2018
    /// This class provides an iterator for obtaining the nodes of the
1985 2019
    /// given blossom. It lists a subset of the nodes.
1986
    /// Before using this iterator, you must allocate a 
2020
    /// Before using this iterator, you must allocate a
1987 2021
    /// MaxWeightedMatching class and execute it.
... ...
@@ -1994,4 +2028,4 @@
1994 2028
      ///
1995
      /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or 
1996
      /// \ref MaxWeightedMatching::start() "algorithm.start()" must be 
2029
      /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
2030
      /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
1997 2031
      /// called before initializing this iterator.
... ...
@@ -2048,4 +2082,4 @@
2048 2082
  ///
2049
  /// The maximum weighted perfect matching problem is to find a subset of 
2050
  /// the edges in an undirected graph with maximum overall weight for which 
2083
  /// The maximum weighted perfect matching problem is to find a subset of
2084
  /// the edges in an undirected graph with maximum overall weight for which
2051 2085
  /// each node has exactly one incident edge.
... ...
@@ -2072,7 +2106,7 @@
2072 2106
  ///
2073
  /// The algorithm can be executed with the run() function. 
2107
  /// The algorithm can be executed with the run() function.
2074 2108
  /// After it the matching (the primal solution) and the dual solution
2075
  /// can be obtained using the query functions and the 
2076
  /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class, 
2077
  /// which is able to iterate on the nodes of a blossom. 
2109
  /// can be obtained using the query functions and the
2110
  /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2111
  /// which is able to iterate on the nodes of a blossom.
2078 2112
  /// If the value type is integer, then the dual solution is multiplied
... ...
@@ -2081,3 +2115,3 @@
2081 2115
  /// \tparam GR The undirected graph type the algorithm runs on.
2082
  /// \tparam WM The type edge weight map. The default type is 
2116
  /// \tparam WM The type edge weight map. The default type is
2083 2117
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
... ...
@@ -2192,2 +2226,7 @@
2192 2226
    Value _delta_sum;
2227
    int _unmatched;
2228

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

	
... ...
@@ -2235,5 +2274,2 @@
2235 2274
    void destroyStructures() {
2236
      _node_num = countNodes(_graph);
2237
      _blossom_num = _node_num * 3 / 2;
2238

	
2239 2275
      if (_matching) {
... ...
@@ -2910,3 +2946,6 @@
2910 2946

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

	
2949
        _fractional(0)
2950
    {}
2912 2951

	
... ...
@@ -2914,2 +2953,5 @@
2914 2953
      destroyStructures();
2954
      if (_fractional) {
2955
        delete _fractional;
2956
      }
2915 2957
    }
... ...
@@ -2939,2 +2981,4 @@
2939 2981

	
2982
      _unmatched = _node_num;
2983

	
2940 2984
      int index = 0;
... ...
@@ -2972,2 +3016,134 @@
2972 3016

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

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

	
3043
      _unmatched = 0;
3044

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

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

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

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

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

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

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

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

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

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

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

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

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

	
2973 3149
    /// \brief Start the algorithm
... ...
@@ -2976,3 +3152,4 @@
2976 3152
    ///
2977
    /// \pre \ref init() must be called before using this function.
3153
    /// \pre \ref init() or \ref fractionalInit() must be called before
3154
    /// using this function.
2978 3155
    bool start() {
... ...
@@ -2982,4 +3159,5 @@
2982 3159

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

	
3162
      while (_unmatched > 0) {
2985 3163
        Value d2 = !_delta2->empty() ?
... ...
@@ -2993,4 +3171,4 @@
2993 3171

	
2994
        _delta_sum = d2; OpType ot = D2;
2995
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
3172
        _delta_sum = d3; OpType ot = D3;
3173
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
2996 3174
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
... ...
@@ -3027,3 +3205,3 @@
3027 3205
                augmentOnEdge(e);
3028
                unmatched -= 2;
3206
                _unmatched -= 2;
3029 3207
              }
... ...
@@ -3046,3 +3224,3 @@
3046 3224
    /// \code
3047
    ///   mwpm.init();
3225
    ///   mwpm.fractionalInit();
3048 3226
    ///   mwpm.start();
... ...
@@ -3050,3 +3228,3 @@
3050 3228
    bool run() {
3051
      init();
3229
      fractionalInit();
3052 3230
      return start();
... ...
@@ -3057,3 +3235,3 @@
3057 3235
    /// \name Primal Solution
3058
    /// Functions to get the primal solution, i.e. the maximum weighted 
3236
    /// Functions to get the primal solution, i.e. the maximum weighted
3059 3237
    /// perfect matching.\n
... ...
@@ -3076,3 +3254,3 @@
3076 3254
      }
3077
      return sum /= 2;
3255
      return sum / 2;
3078 3256
    }
... ...
@@ -3081,3 +3259,3 @@
3081 3259
    ///
3082
    /// This function returns \c true if the given edge is in the found 
3260
    /// This function returns \c true if the given edge is in the found
3083 3261
    /// matching.
... ...
@@ -3092,3 +3270,3 @@
3092 3270
    /// This function returns the matching arc (or edge) incident to the
3093
    /// given node in the found matching or \c INVALID if the node is 
3271
    /// given node in the found matching or \c INVALID if the node is
3094 3272
    /// not covered by the matching.
... ...
@@ -3110,3 +3288,3 @@
3110 3288
    ///
3111
    /// This function returns the mate of the given node in the found 
3289
    /// This function returns the mate of the given node in the found
3112 3290
    /// matching or \c INVALID if the node is not covered by the matching.
... ...
@@ -3129,4 +3307,4 @@
3129 3307
    ///
3130
    /// This function returns the value of the dual solution. 
3131
    /// It should be equal to the primal value scaled by \ref dualScale 
3308
    /// This function returns the value of the dual solution.
3309
    /// It should be equal to the primal value scaled by \ref dualScale
3132 3310
    /// "dual scale".
... ...
@@ -3185,5 +3363,5 @@
3185 3363
    ///
3186
    /// This class provides an iterator for obtaining the nodes of the 
3364
    /// This class provides an iterator for obtaining the nodes of the
3187 3365
    /// given blossom. It lists a subset of the nodes.
3188
    /// Before using this iterator, you must allocate a 
3366
    /// Before using this iterator, you must allocate a
3189 3367
    /// MaxWeightedPerfectMatching class and execute it.
... ...
@@ -3196,4 +3374,4 @@
3196 3374
      ///
3197
      /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()" 
3198
      /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()" 
3375
      /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3376
      /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3199 3377
      /// must be called before initializing this iterator.
... ...
@@ -3243,2 +3421,2 @@
3243 3421

	
3244
#endif //LEMON_MAX_MATCHING_H
3422
#endif //LEMON_MATCHING_H
Ignore white space 6 line context
... ...
@@ -23,2 +23,3 @@
23 23
  euler_test
24
  fractional_matching_test
24 25
  gomory_hu_test
Ignore white space 6 line context
... ...
@@ -25,2 +25,3 @@
25 25
	test/euler_test \
26
	test/fractional_matching_test \
26 27
	test/gomory_hu_test \
... ...
@@ -73,2 +74,3 @@
73 74
test_euler_test_SOURCES = test/euler_test.cc
75
test_fractional_matching_test_SOURCES = test/fractional_matching_test.cc
74 76
test_gomory_hu_test_SOURCES = test/gomory_hu_test.cc
Ignore white space 6 line context
... ...
@@ -403,18 +403,42 @@
403 403

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

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

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

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

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