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
}
Ignore white space 6 line context
... ...
@@ -386,7 +386,7 @@
386 386
also provide functions to query the minimum cut, which is the dual
387 387
problem of maximum flow.
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,
391 391
but it is strongly related to maximum flow.
392 392
For more information, see \ref Circulation.
... ...
@@ -522,6 +522,13 @@
522 522
- \ref MaxWeightedPerfectMatching
523 523
  Edmond's blossom shrinking algorithm for calculating maximum weighted
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

	
526 533
\image html matching.png
527 534
\image latex matching.eps "Min Cost Perfect Matching" width=\textwidth
Ignore white space 6 line context
... ...
@@ -84,6 +84,7 @@
84 84
	lemon/error.h \
85 85
	lemon/euler.h \
86 86
	lemon/fib_heap.h \
87
	lemon/fractional_matching.h \
87 88
	lemon/full_graph.h \
88 89
	lemon/glpk.h \
89 90
	lemon/gomory_hu.h \
Ignore white space 6 line context
... ...
@@ -16,8 +16,8 @@
16 16
 *
17 17
 */
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

	
22 22
#include <vector>
23 23
#include <queue>
... ...
@@ -28,6 +28,7 @@
28 28
#include <lemon/unionfind.h>
29 29
#include <lemon/bin_heap.h>
30 30
#include <lemon/maps.h>
31
#include <lemon/fractional_matching.h>
31 32

	
32 33
///\ingroup matching
33 34
///\file
... ...
@@ -41,7 +42,7 @@
41 42
  ///
42 43
  /// This class implements Edmonds' alternating forest matching algorithm
43 44
  /// for finding a maximum cardinality matching in a general undirected graph.
44
  /// 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).
46 47
  ///
47 48
  /// The dual solution of the problem is a map of the nodes to
... ...
@@ -69,11 +70,11 @@
69 70

	
70 71
    ///\brief Status constants for Gallai-Edmonds decomposition.
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)
74 75
    ///induce a subgraph with factor-critical components, the nodes with
75 76
    ///status \c ODD (or \c A) form the canonical barrier, and the nodes
76
    ///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.
78 79
    enum Status {
79 80
      EVEN = 1,       ///< = 1. (\c D is an alias for \c EVEN.)
... ...
@@ -512,7 +513,7 @@
512 513
      }
513 514
    }
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
517 518
    ///
518 519
    /// This function runs Edmonds' algorithm with a heuristic of postponing
... ...
@@ -534,8 +535,8 @@
534 535

	
535 536
    /// \brief Run Edmonds' algorithm
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).
540 541
    void run() {
541 542
      if (countEdges(_graph) < 2 * countNodes(_graph)) {
... ...
@@ -556,7 +557,7 @@
556 557

	
557 558
    /// \brief Return the size (cardinality) of the matching.
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.
561 562
    int matchingSize() const {
562 563
      int size = 0;
... ...
@@ -570,7 +571,7 @@
570 571

	
571 572
    /// \brief Return \c true if the given edge is in the matching.
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.
575 576
    bool matching(const Edge& edge) const {
576 577
      return edge == (*_matching)[_graph.u(edge)];
... ...
@@ -579,7 +580,7 @@
579 580
    /// \brief Return the matching arc (or edge) incident to the given node.
580 581
    ///
581 582
    /// This function returns the matching arc (or edge) incident to the
582
    /// 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.
584 585
    Arc matching(const Node& n) const {
585 586
      return (*_matching)[n];
... ...
@@ -595,7 +596,7 @@
595 596

	
596 597
    /// \brief Return the mate of the given node.
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.
600 601
    Node mate(const Node& n) const {
601 602
      return (*_matching)[n] != INVALID ?
... ...
@@ -605,7 +606,7 @@
605 606
    /// @}
606 607

	
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.
610 611

	
611 612
    /// @{
... ...
@@ -648,8 +649,8 @@
648 649
  /// on extensive use of priority queues and provides
649 650
  /// \f$O(nm\log n)\f$ time complexity.
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.
654 655
  /// It can be formulated with the following linear program.
655 656
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
... ...
@@ -673,16 +674,16 @@
673 674
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
674 675
      \frac{\vert B \vert - 1}{2}z_B\f] */
675 676
  ///
676
  /// 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
682 683
  /// by \ref MaxWeightedMatching::dualScale "4".
683 684
  ///
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>".
687 688
#ifdef DOXYGEN
688 689
  template <typename GR, typename WM>
... ...
@@ -745,7 +746,7 @@
745 746
    typedef RangeMap<int> IntIntMap;
746 747

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

	
751 752
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
... ...
@@ -797,6 +798,10 @@
797 798
    BinHeap<Value, IntIntMap> *_delta4;
798 799

	
799 800
    Value _delta_sum;
801
    int _unmatched;
802

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

	
801 806
    void createStructures() {
802 807
      _node_num = countNodes(_graph);
... ...
@@ -844,9 +849,6 @@
844 849
    }
845 850

	
846 851
    void destroyStructures() {
847
      _node_num = countNodes(_graph);
848
      _blossom_num = _node_num * 3 / 2;
849

	
850 852
      if (_matching) {
851 853
        delete _matching;
852 854
      }
... ...
@@ -922,10 +924,6 @@
922 924
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
923 925
              _delta3->push(e, rw / 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 {
930 928
            typename std::map<int, Arc>::iterator it =
931 929
              (*_node_data)[vi].heap_index.find(tree);
... ...
@@ -949,202 +947,6 @@
949 947
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
950 948
                               (*_blossom_data)[vb].offset);
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) {
1149 951
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1150 952
                                   (*_blossom_data)[vb].offset);
... ...
@@ -1157,43 +959,145 @@
1157 959
      (*_blossom_data)[blossom].offset = 0;
1158 960
    }
1159 961

	
1160

	
1161
    void matchedToUnmatched(int blossom) {
962
    void matchedToOdd(int blossom) {
1162 963
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1163 964
        _delta2->erase(blossom);
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

	
1166 978
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1167 979
           n != INVALID; ++n) {
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);
1178 988
          int vi = (*_node_index)[v];
1179 989

	
1180 990
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1181 991
            dualScale * _weight[e];
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
            }
1187 1062
          }
1188 1063
        }
1189 1064
      }
1190 1065
    }
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);
1194 1089
           n != INVALID; ++n) {
1195 1090
        int ni = (*_node_index)[n];
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) {
1198 1102
          Node v = _graph.source(e);
1199 1103
          int vb = _blossom_set->find(v);
... ...
@@ -1202,54 +1106,44 @@
1202 1106
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1203 1107
            dualScale * _weight[e];
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
          }
1251 1144
        }
1252 1145
      }
1146
      (*_blossom_data)[blossom].offset = 0;
1253 1147
    }
1254 1148

	
1255 1149
    void alternatePath(int even, int tree) {
... ...
@@ -1294,39 +1188,42 @@
1294 1188
      alternatePath(blossom, tree);
1295 1189
      destroyTree(tree);
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) {
1304 1196

	
1305 1197
      int left = _blossom_set->find(_graph.u(edge));
1306 1198
      int right = _blossom_set->find(_graph.v(edge));
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

	
1326 1208
      (*_blossom_data)[left].next = _graph.direct(edge, true);
1327 1209
      (*_blossom_data)[right].next = _graph.direct(edge, false);
1328 1210
    }
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) {
1331 1228
      int base = _blossom_set->find(_graph.target(arc));
1332 1229
      int tree = _tree_set->find(base);
... ...
@@ -1529,7 +1426,7 @@
1529 1426
          _tree_set->insert(sb, tree);
1530 1427
          (*_blossom_data)[sb].pred = pred;
1531 1428
          (*_blossom_data)[sb].next =
1532
                           _graph.oppositeArc((*_blossom_data)[tb].next);
1429
            _graph.oppositeArc((*_blossom_data)[tb].next);
1533 1430

	
1534 1431
          pred = (*_blossom_data)[ub].next;
1535 1432

	
... ...
@@ -1629,7 +1526,7 @@
1629 1526
      }
1630 1527

	
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

	
1634 1531
          Value offset = (*_blossom_data)[blossoms[i]].offset;
1635 1532
          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
... ...
@@ -1667,10 +1564,16 @@
1667 1564
        _delta3_index(0), _delta3(0),
1668 1565
        _delta4_index(0), _delta4(0),
1669 1566

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

	
1569
        _fractional(0)
1570
    {}
1671 1571

	
1672 1572
    ~MaxWeightedMatching() {
1673 1573
      destroyStructures();
1574
      if (_fractional) {
1575
        delete _fractional;
1576
      }
1674 1577
    }
1675 1578

	
1676 1579
    /// \name Execution Control
... ...
@@ -1699,6 +1602,8 @@
1699 1602
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1700 1603
      }
1701 1604

	
1605
      _unmatched = _node_num;
1606

	
1702 1607
      int index = 0;
1703 1608
      for (NodeIt n(_graph); n != INVALID; ++n) {
1704 1609
        Value max = 0;
... ...
@@ -1733,18 +1638,155 @@
1733 1638
      }
1734 1639
    }
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
1737 1779
    ///
1738 1780
    /// This function starts the algorithm.
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() {
1742 1785
      enum OpType {
1743 1786
        D1, D2, D3, D4
1744 1787
      };
1745 1788

	
1746
      int unmatched = _node_num;
1747
      while (unmatched > 0) {
1789
      while (_unmatched > 0) {
1748 1790
        Value d1 = !_delta1->empty() ?
1749 1791
          _delta1->prio() : std::numeric_limits<Value>::max();
1750 1792

	
... ...
@@ -1757,26 +1799,30 @@
1757 1799
        Value d4 = !_delta4->empty() ?
1758 1800
          _delta4->prio() : std::numeric_limits<Value>::max();
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) {
1767 1808
        case D1:
1768 1809
          {
1769 1810
            Node n = _delta1->top();
1770 1811
            unmatchNode(n);
1771
            --unmatched;
1812
            --_unmatched;
1772 1813
          }
1773 1814
          break;
1774 1815
        case D2:
1775 1816
          {
1776 1817
            int blossom = _delta2->top();
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
          }
1781 1827
          break;
1782 1828
        case D3:
... ...
@@ -1789,26 +1835,14 @@
1789 1835
            if (left_blossom == right_blossom) {
1790 1836
              _delta3->pop();
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

	
1807 1841
              if (left_tree == right_tree) {
1808 1842
                shrinkOnEdge(e, left_tree);
1809 1843
              } else {
1810 1844
                augmentOnEdge(e);
1811
                unmatched -= 2;
1845
                _unmatched -= 2;
1812 1846
              }
1813 1847
            }
1814 1848
          } break;
... ...
@@ -1826,18 +1860,18 @@
1826 1860
    ///
1827 1861
    /// \note mwm.run() is just a shortcut of the following code.
1828 1862
    /// \code
1829
    ///   mwm.init();
1863
    ///   mwm.fractionalInit();
1830 1864
    ///   mwm.start();
1831 1865
    /// \endcode
1832 1866
    void run() {
1833
      init();
1867
      fractionalInit();
1834 1868
      start();
1835 1869
    }
1836 1870

	
1837 1871
    /// @}
1838 1872

	
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
1842 1876
    /// Either \ref run() or \ref start() function should be called before
1843 1877
    /// using them.
... ...
@@ -1856,7 +1890,7 @@
1856 1890
          sum += _weight[(*_matching)[n]];
1857 1891
        }
1858 1892
      }
1859
      return sum /= 2;
1893
      return sum / 2;
1860 1894
    }
1861 1895

	
1862 1896
    /// \brief Return the size (cardinality) of the matching.
... ...
@@ -1876,7 +1910,7 @@
1876 1910

	
1877 1911
    /// \brief Return \c true if the given edge is in the matching.
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.
1881 1915
    ///
1882 1916
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -1887,7 +1921,7 @@
1887 1921
    /// \brief Return the matching arc (or edge) incident to the given node.
1888 1922
    ///
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.
1892 1926
    ///
1893 1927
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -1905,7 +1939,7 @@
1905 1939

	
1906 1940
    /// \brief Return the mate of the given node.
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.
1910 1944
    ///
1911 1945
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -1925,8 +1959,8 @@
1925 1959

	
1926 1960
    /// \brief Return the value of the dual solution.
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".
1931 1965
    ///
1932 1966
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -1981,9 +2015,9 @@
1981 2015

	
1982 2016
    /// \brief Iterator for obtaining the nodes of a blossom.
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.
1988 2022
    class BlossomIt {
1989 2023
    public:
... ...
@@ -1992,8 +2026,8 @@
1992 2026
      ///
1993 2027
      /// Constructor to get the nodes of the given variable.
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.
1998 2032
      BlossomIt(const MaxWeightedMatching& algorithm, int variable)
1999 2033
        : _algorithm(&algorithm)
... ...
@@ -2046,8 +2080,8 @@
2046 2080
  /// is based on extensive use of priority queues and provides
2047 2081
  /// \f$O(nm\log n)\f$ time complexity.
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.
2052 2086
  /// It can be formulated with the following linear program.
2053 2087
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
... ...
@@ -2070,16 +2104,16 @@
2070 2104
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2071 2105
      \frac{\vert B \vert - 1}{2}z_B\f] */
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
2079 2113
  /// by \ref MaxWeightedMatching::dualScale "4".
2080 2114
  ///
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>".
2084 2118
#ifdef DOXYGEN
2085 2119
  template <typename GR, typename WM>
... ...
@@ -2190,6 +2224,11 @@
2190 2224
    BinHeap<Value, IntIntMap> *_delta4;
2191 2225

	
2192 2226
    Value _delta_sum;
2227
    int _unmatched;
2228

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

	
2194 2233
    void createStructures() {
2195 2234
      _node_num = countNodes(_graph);
... ...
@@ -2233,9 +2272,6 @@
2233 2272
    }
2234 2273

	
2235 2274
    void destroyStructures() {
2236
      _node_num = countNodes(_graph);
2237
      _blossom_num = _node_num * 3 / 2;
2238

	
2239 2275
      if (_matching) {
2240 2276
        delete _matching;
2241 2277
      }
... ...
@@ -2908,10 +2944,16 @@
2908 2944
        _delta3_index(0), _delta3(0),
2909 2945
        _delta4_index(0), _delta4(0),
2910 2946

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

	
2949
        _fractional(0)
2950
    {}
2912 2951

	
2913 2952
    ~MaxWeightedPerfectMatching() {
2914 2953
      destroyStructures();
2954
      if (_fractional) {
2955
        delete _fractional;
2956
      }
2915 2957
    }
2916 2958

	
2917 2959
    /// \name Execution Control
... ...
@@ -2937,6 +2979,8 @@
2937 2979
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
2938 2980
      }
2939 2981

	
2982
      _unmatched = _node_num;
2983

	
2940 2984
      int index = 0;
2941 2985
      for (NodeIt n(_graph); n != INVALID; ++n) {
2942 2986
        Value max = - std::numeric_limits<Value>::max();
... ...
@@ -2970,18 +3014,152 @@
2970 3014
      }
2971 3015
    }
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
2974 3150
    ///
2975 3151
    /// This function starts the algorithm.
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() {
2979 3156
      enum OpType {
2980 3157
        D2, D3, D4
2981 3158
      };
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() ?
2986 3164
          _delta2->prio() : std::numeric_limits<Value>::max();
2987 3165

	
... ...
@@ -2991,8 +3169,8 @@
2991 3169
        Value d4 = !_delta4->empty() ?
2992 3170
          _delta4->prio() : std::numeric_limits<Value>::max();
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; }
2997 3175

	
2998 3176
        if (_delta_sum == std::numeric_limits<Value>::max()) {
... ...
@@ -3025,7 +3203,7 @@
3025 3203
                shrinkOnEdge(e, left_tree);
3026 3204
              } else {
3027 3205
                augmentOnEdge(e);
3028
                unmatched -= 2;
3206
                _unmatched -= 2;
3029 3207
              }
3030 3208
            }
3031 3209
          } break;
... ...
@@ -3044,18 +3222,18 @@
3044 3222
    ///
3045 3223
    /// \note mwpm.run() is just a shortcut of the following code.
3046 3224
    /// \code
3047
    ///   mwpm.init();
3225
    ///   mwpm.fractionalInit();
3048 3226
    ///   mwpm.start();
3049 3227
    /// \endcode
3050 3228
    bool run() {
3051
      init();
3229
      fractionalInit();
3052 3230
      return start();
3053 3231
    }
3054 3232

	
3055 3233
    /// @}
3056 3234

	
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
3060 3238
    /// Either \ref run() or \ref start() function should be called before
3061 3239
    /// using them.
... ...
@@ -3074,12 +3252,12 @@
3074 3252
          sum += _weight[(*_matching)[n]];
3075 3253
        }
3076 3254
      }
3077
      return sum /= 2;
3255
      return sum / 2;
3078 3256
    }
3079 3257

	
3080 3258
    /// \brief Return \c true if the given edge is in the matching.
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.
3084 3262
    ///
3085 3263
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -3090,7 +3268,7 @@
3090 3268
    /// \brief Return the matching arc (or edge) incident to the given node.
3091 3269
    ///
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.
3095 3273
    ///
3096 3274
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -3108,7 +3286,7 @@
3108 3286

	
3109 3287
    /// \brief Return the mate of the given node.
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.
3113 3291
    ///
3114 3292
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -3127,8 +3305,8 @@
3127 3305

	
3128 3306
    /// \brief Return the value of the dual solution.
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".
3133 3311
    ///
3134 3312
    /// \pre Either run() or start() must be called before using this function.
... ...
@@ -3183,9 +3361,9 @@
3183 3361

	
3184 3362
    /// \brief Iterator for obtaining the nodes of a blossom.
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.
3190 3368
    class BlossomIt {
3191 3369
    public:
... ...
@@ -3194,8 +3372,8 @@
3194 3372
      ///
3195 3373
      /// Constructor to get the nodes of the given variable.
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.
3200 3378
      BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3201 3379
        : _algorithm(&algorithm)
... ...
@@ -3241,4 +3419,4 @@
3241 3419

	
3242 3420
} //END OF NAMESPACE LEMON
3243 3421

	
3244
#endif //LEMON_MAX_MATCHING_H
3422
#endif //LEMON_MATCHING_H
Ignore white space 6 line context
... ...
@@ -21,6 +21,7 @@
21 21
  edge_set_test
22 22
  error_test
23 23
  euler_test
24
  fractional_matching_test
24 25
  gomory_hu_test
25 26
  graph_copy_test
26 27
  graph_test
Ignore white space 6 line context
... ...
@@ -23,6 +23,7 @@
23 23
	test/edge_set_test \
24 24
	test/error_test \
25 25
	test/euler_test \
26
	test/fractional_matching_test \
26 27
	test/gomory_hu_test \
27 28
	test/graph_copy_test \
28 29
	test/graph_test \
... ...
@@ -71,6 +72,7 @@
71 72
test_edge_set_test_SOURCES = test/edge_set_test.cc
72 73
test_error_test_SOURCES = test/error_test.cc
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
75 77
test_graph_copy_test_SOURCES = test/graph_copy_test.cc
76 78
test_graph_test_SOURCES = test/graph_test.cc
Ignore white space 6 line context
... ...
@@ -401,22 +401,46 @@
401 401
    graphReader(graph, lgfs).
402 402
      edgeMap("weight", weight).run();
403 403

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

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

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

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

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

	
0 comments (0 inline)