lemon/fractional_matching.h
changeset 870 61120524af27
child 871 86613aa28a0c
equal deleted inserted replaced
-1:000000000000 0:1ec5754fa4c3
       
     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 MaxWeightedMatching::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 is based on extensive use
       
   636   /// of priority queues and provides \f$O(nm\log n)\f$ time
       
   637   /// complexity.
       
   638   ///
       
   639   /// The maximum weighted fractional matching is a relaxation of the
       
   640   /// maximum weighted matching problem where the odd set constraints
       
   641   /// are omitted.
       
   642   /// It can be formulated with the following linear program.
       
   643   /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
       
   644   /// \f[x_e \ge 0\quad \forall e\in E\f]
       
   645   /// \f[\max \sum_{e\in E}x_ew_e\f]
       
   646   /// where \f$\delta(X)\f$ is the set of edges incident to a node in
       
   647   /// \f$X\f$. The result must be the union of a matching with one
       
   648   /// value edges and a set of odd length cycles with half value edges.
       
   649   ///
       
   650   /// The algorithm calculates an optimal fractional matching and a
       
   651   /// proof of the optimality. The solution of the dual problem can be
       
   652   /// used to check the result of the algorithm. The dual linear
       
   653   /// problem is the following.
       
   654   /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
       
   655   /// \f[y_u \ge 0 \quad \forall u \in V\f]
       
   656   /// \f[\min \sum_{u \in V}y_u \f] ///
       
   657   ///
       
   658   /// The algorithm can be executed with the run() function.
       
   659   /// After it the matching (the primal solution) and the dual solution
       
   660   /// can be obtained using the query functions.
       
   661   ///
       
   662   /// If the value type is integer, then the primal and the dual
       
   663   /// solutions are multiplied by
       
   664   /// \ref MaxWeightedMatching::primalScale "2" and
       
   665   /// \ref MaxWeightedMatching::dualScale "4" respectively.
       
   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. It is equal to 2 or 1
       
   693     /// according to the value type.
       
   694     static const int primalScale =
       
   695       std::numeric_limits<Value>::is_integer ? 2 : 1;
       
   696 
       
   697     /// \brief Scaling factor for dual solution
       
   698     ///
       
   699     /// Scaling factor for dual solution. It is equal to 4 or 1
       
   700     /// according to the value type.
       
   701     static const int dualScale =
       
   702       std::numeric_limits<Value>::is_integer ? 4 : 1;
       
   703 
       
   704   private:
       
   705 
       
   706     TEMPLATE_GRAPH_TYPEDEFS(Graph);
       
   707 
       
   708     typedef typename Graph::template NodeMap<Value> NodePotential;
       
   709 
       
   710     const Graph& _graph;
       
   711     const WeightMap& _weight;
       
   712 
       
   713     MatchingMap* _matching;
       
   714     NodePotential* _node_potential;
       
   715 
       
   716     int _node_num;
       
   717     bool _allow_loops;
       
   718 
       
   719     enum Status {
       
   720       EVEN = -1, MATCHED = 0, ODD = 1
       
   721     };
       
   722 
       
   723     typedef typename Graph::template NodeMap<Status> StatusMap;
       
   724     StatusMap* _status;
       
   725 
       
   726     typedef typename Graph::template NodeMap<Arc> PredMap;
       
   727     PredMap* _pred;
       
   728 
       
   729     typedef ExtendFindEnum<IntNodeMap> TreeSet;
       
   730 
       
   731     IntNodeMap *_tree_set_index;
       
   732     TreeSet *_tree_set;
       
   733 
       
   734     IntNodeMap *_delta1_index;
       
   735     BinHeap<Value, IntNodeMap> *_delta1;
       
   736 
       
   737     IntNodeMap *_delta2_index;
       
   738     BinHeap<Value, IntNodeMap> *_delta2;
       
   739 
       
   740     IntEdgeMap *_delta3_index;
       
   741     BinHeap<Value, IntEdgeMap> *_delta3;
       
   742 
       
   743     Value _delta_sum;
       
   744 
       
   745     void createStructures() {
       
   746       _node_num = countNodes(_graph);
       
   747 
       
   748       if (!_matching) {
       
   749         _matching = new MatchingMap(_graph);
       
   750       }
       
   751       if (!_node_potential) {
       
   752         _node_potential = new NodePotential(_graph);
       
   753       }
       
   754       if (!_status) {
       
   755         _status = new StatusMap(_graph);
       
   756       }
       
   757       if (!_pred) {
       
   758         _pred = new PredMap(_graph);
       
   759       }
       
   760       if (!_tree_set) {
       
   761         _tree_set_index = new IntNodeMap(_graph);
       
   762         _tree_set = new TreeSet(*_tree_set_index);
       
   763       }
       
   764       if (!_delta1) {
       
   765         _delta1_index = new IntNodeMap(_graph);
       
   766         _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
       
   767       }
       
   768       if (!_delta2) {
       
   769         _delta2_index = new IntNodeMap(_graph);
       
   770         _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
       
   771       }
       
   772       if (!_delta3) {
       
   773         _delta3_index = new IntEdgeMap(_graph);
       
   774         _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
       
   775       }
       
   776     }
       
   777 
       
   778     void destroyStructures() {
       
   779       if (_matching) {
       
   780         delete _matching;
       
   781       }
       
   782       if (_node_potential) {
       
   783         delete _node_potential;
       
   784       }
       
   785       if (_status) {
       
   786         delete _status;
       
   787       }
       
   788       if (_pred) {
       
   789         delete _pred;
       
   790       }
       
   791       if (_tree_set) {
       
   792         delete _tree_set_index;
       
   793         delete _tree_set;
       
   794       }
       
   795       if (_delta1) {
       
   796         delete _delta1_index;
       
   797         delete _delta1;
       
   798       }
       
   799       if (_delta2) {
       
   800         delete _delta2_index;
       
   801         delete _delta2;
       
   802       }
       
   803       if (_delta3) {
       
   804         delete _delta3_index;
       
   805         delete _delta3;
       
   806       }
       
   807     }
       
   808 
       
   809     void matchedToEven(Node node, int tree) {
       
   810       _tree_set->insert(node, tree);
       
   811       _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
       
   812       _delta1->push(node, (*_node_potential)[node]);
       
   813 
       
   814       if (_delta2->state(node) == _delta2->IN_HEAP) {
       
   815         _delta2->erase(node);
       
   816       }
       
   817 
       
   818       for (InArcIt a(_graph, node); a != INVALID; ++a) {
       
   819         Node v = _graph.source(a);
       
   820         Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
       
   821           dualScale * _weight[a];
       
   822         if (node == v) {
       
   823           if (_allow_loops && _graph.direction(a)) {
       
   824             _delta3->push(a, rw / 2);
       
   825           }
       
   826         } else if ((*_status)[v] == EVEN) {
       
   827           _delta3->push(a, rw / 2);
       
   828         } else if ((*_status)[v] == MATCHED) {
       
   829           if (_delta2->state(v) != _delta2->IN_HEAP) {
       
   830             _pred->set(v, a);
       
   831             _delta2->push(v, rw);
       
   832           } else if ((*_delta2)[v] > rw) {
       
   833             _pred->set(v, a);
       
   834             _delta2->decrease(v, rw);
       
   835           }
       
   836         }
       
   837       }
       
   838     }
       
   839 
       
   840     void matchedToOdd(Node node, int tree) {
       
   841       _tree_set->insert(node, tree);
       
   842       _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
       
   843 
       
   844       if (_delta2->state(node) == _delta2->IN_HEAP) {
       
   845         _delta2->erase(node);
       
   846       }
       
   847     }
       
   848 
       
   849     void evenToMatched(Node node, int tree) {
       
   850       _delta1->erase(node);
       
   851       _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
       
   852       Arc min = INVALID;
       
   853       Value minrw = std::numeric_limits<Value>::max();
       
   854       for (InArcIt a(_graph, node); a != INVALID; ++a) {
       
   855         Node v = _graph.source(a);
       
   856         Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
       
   857           dualScale * _weight[a];
       
   858 
       
   859         if (node == v) {
       
   860           if (_allow_loops && _graph.direction(a)) {
       
   861             _delta3->erase(a);
       
   862           }
       
   863         } else if ((*_status)[v] == EVEN) {
       
   864           _delta3->erase(a);
       
   865           if (minrw > rw) {
       
   866             min = _graph.oppositeArc(a);
       
   867             minrw = rw;
       
   868           }
       
   869         } else if ((*_status)[v]  == MATCHED) {
       
   870           if ((*_pred)[v] == a) {
       
   871             Arc mina = INVALID;
       
   872             Value minrwa = std::numeric_limits<Value>::max();
       
   873             for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
       
   874               Node va = _graph.target(aa);
       
   875               if ((*_status)[va] != EVEN ||
       
   876                   _tree_set->find(va) == tree) continue;
       
   877               Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
       
   878                 dualScale * _weight[aa];
       
   879               if (minrwa > rwa) {
       
   880                 minrwa = rwa;
       
   881                 mina = aa;
       
   882               }
       
   883             }
       
   884             if (mina != INVALID) {
       
   885               _pred->set(v, mina);
       
   886               _delta2->increase(v, minrwa);
       
   887             } else {
       
   888               _pred->set(v, INVALID);
       
   889               _delta2->erase(v);
       
   890             }
       
   891           }
       
   892         }
       
   893       }
       
   894       if (min != INVALID) {
       
   895         _pred->set(node, min);
       
   896         _delta2->push(node, minrw);
       
   897       } else {
       
   898         _pred->set(node, INVALID);
       
   899       }
       
   900     }
       
   901 
       
   902     void oddToMatched(Node node) {
       
   903       _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
       
   904       Arc min = INVALID;
       
   905       Value minrw = std::numeric_limits<Value>::max();
       
   906       for (InArcIt a(_graph, node); a != INVALID; ++a) {
       
   907         Node v = _graph.source(a);
       
   908         if ((*_status)[v] != EVEN) continue;
       
   909         Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
       
   910           dualScale * _weight[a];
       
   911 
       
   912         if (minrw > rw) {
       
   913           min = _graph.oppositeArc(a);
       
   914           minrw = rw;
       
   915         }
       
   916       }
       
   917       if (min != INVALID) {
       
   918         _pred->set(node, min);
       
   919         _delta2->push(node, minrw);
       
   920       } else {
       
   921         _pred->set(node, INVALID);
       
   922       }
       
   923     }
       
   924 
       
   925     void alternatePath(Node even, int tree) {
       
   926       Node odd;
       
   927 
       
   928       _status->set(even, MATCHED);
       
   929       evenToMatched(even, tree);
       
   930 
       
   931       Arc prev = (*_matching)[even];
       
   932       while (prev != INVALID) {
       
   933         odd = _graph.target(prev);
       
   934         even = _graph.target((*_pred)[odd]);
       
   935         _matching->set(odd, (*_pred)[odd]);
       
   936         _status->set(odd, MATCHED);
       
   937         oddToMatched(odd);
       
   938 
       
   939         prev = (*_matching)[even];
       
   940         _status->set(even, MATCHED);
       
   941         _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
       
   942         evenToMatched(even, tree);
       
   943       }
       
   944     }
       
   945 
       
   946     void destroyTree(int tree) {
       
   947       for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
       
   948         if ((*_status)[n] == EVEN) {
       
   949           _status->set(n, MATCHED);
       
   950           evenToMatched(n, tree);
       
   951         } else if ((*_status)[n] == ODD) {
       
   952           _status->set(n, MATCHED);
       
   953           oddToMatched(n);
       
   954         }
       
   955       }
       
   956       _tree_set->eraseClass(tree);
       
   957     }
       
   958 
       
   959 
       
   960     void unmatchNode(const Node& node) {
       
   961       int tree = _tree_set->find(node);
       
   962 
       
   963       alternatePath(node, tree);
       
   964       destroyTree(tree);
       
   965 
       
   966       _matching->set(node, INVALID);
       
   967     }
       
   968 
       
   969 
       
   970     void augmentOnEdge(const Edge& edge) {
       
   971       Node left = _graph.u(edge);
       
   972       int left_tree = _tree_set->find(left);
       
   973 
       
   974       alternatePath(left, left_tree);
       
   975       destroyTree(left_tree);
       
   976       _matching->set(left, _graph.direct(edge, true));
       
   977 
       
   978       Node right = _graph.v(edge);
       
   979       int right_tree = _tree_set->find(right);
       
   980 
       
   981       alternatePath(right, right_tree);
       
   982       destroyTree(right_tree);
       
   983       _matching->set(right, _graph.direct(edge, false));
       
   984     }
       
   985 
       
   986     void augmentOnArc(const Arc& arc) {
       
   987       Node left = _graph.source(arc);
       
   988       _status->set(left, MATCHED);
       
   989       _matching->set(left, arc);
       
   990       _pred->set(left, arc);
       
   991 
       
   992       Node right = _graph.target(arc);
       
   993       int right_tree = _tree_set->find(right);
       
   994 
       
   995       alternatePath(right, right_tree);
       
   996       destroyTree(right_tree);
       
   997       _matching->set(right, _graph.oppositeArc(arc));
       
   998     }
       
   999 
       
  1000     void extendOnArc(const Arc& arc) {
       
  1001       Node base = _graph.target(arc);
       
  1002       int tree = _tree_set->find(base);
       
  1003 
       
  1004       Node odd = _graph.source(arc);
       
  1005       _tree_set->insert(odd, tree);
       
  1006       _status->set(odd, ODD);
       
  1007       matchedToOdd(odd, tree);
       
  1008       _pred->set(odd, arc);
       
  1009 
       
  1010       Node even = _graph.target((*_matching)[odd]);
       
  1011       _tree_set->insert(even, tree);
       
  1012       _status->set(even, EVEN);
       
  1013       matchedToEven(even, tree);
       
  1014     }
       
  1015 
       
  1016     void cycleOnEdge(const Edge& edge, int tree) {
       
  1017       Node nca = INVALID;
       
  1018       std::vector<Node> left_path, right_path;
       
  1019 
       
  1020       {
       
  1021         std::set<Node> left_set, right_set;
       
  1022         Node left = _graph.u(edge);
       
  1023         left_path.push_back(left);
       
  1024         left_set.insert(left);
       
  1025 
       
  1026         Node right = _graph.v(edge);
       
  1027         right_path.push_back(right);
       
  1028         right_set.insert(right);
       
  1029 
       
  1030         while (true) {
       
  1031 
       
  1032           if (left_set.find(right) != left_set.end()) {
       
  1033             nca = right;
       
  1034             break;
       
  1035           }
       
  1036 
       
  1037           if ((*_matching)[left] == INVALID) break;
       
  1038 
       
  1039           left = _graph.target((*_matching)[left]);
       
  1040           left_path.push_back(left);
       
  1041           left = _graph.target((*_pred)[left]);
       
  1042           left_path.push_back(left);
       
  1043 
       
  1044           left_set.insert(left);
       
  1045 
       
  1046           if (right_set.find(left) != right_set.end()) {
       
  1047             nca = left;
       
  1048             break;
       
  1049           }
       
  1050 
       
  1051           if ((*_matching)[right] == INVALID) break;
       
  1052 
       
  1053           right = _graph.target((*_matching)[right]);
       
  1054           right_path.push_back(right);
       
  1055           right = _graph.target((*_pred)[right]);
       
  1056           right_path.push_back(right);
       
  1057 
       
  1058           right_set.insert(right);
       
  1059 
       
  1060         }
       
  1061 
       
  1062         if (nca == INVALID) {
       
  1063           if ((*_matching)[left] == INVALID) {
       
  1064             nca = right;
       
  1065             while (left_set.find(nca) == left_set.end()) {
       
  1066               nca = _graph.target((*_matching)[nca]);
       
  1067               right_path.push_back(nca);
       
  1068               nca = _graph.target((*_pred)[nca]);
       
  1069               right_path.push_back(nca);
       
  1070             }
       
  1071           } else {
       
  1072             nca = left;
       
  1073             while (right_set.find(nca) == right_set.end()) {
       
  1074               nca = _graph.target((*_matching)[nca]);
       
  1075               left_path.push_back(nca);
       
  1076               nca = _graph.target((*_pred)[nca]);
       
  1077               left_path.push_back(nca);
       
  1078             }
       
  1079           }
       
  1080         }
       
  1081       }
       
  1082 
       
  1083       alternatePath(nca, tree);
       
  1084       Arc prev;
       
  1085 
       
  1086       prev = _graph.direct(edge, true);
       
  1087       for (int i = 0; left_path[i] != nca; i += 2) {
       
  1088         _matching->set(left_path[i], prev);
       
  1089         _status->set(left_path[i], MATCHED);
       
  1090         evenToMatched(left_path[i], tree);
       
  1091 
       
  1092         prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
       
  1093         _status->set(left_path[i + 1], MATCHED);
       
  1094         oddToMatched(left_path[i + 1]);
       
  1095       }
       
  1096       _matching->set(nca, prev);
       
  1097 
       
  1098       for (int i = 0; right_path[i] != nca; i += 2) {
       
  1099         _status->set(right_path[i], MATCHED);
       
  1100         evenToMatched(right_path[i], tree);
       
  1101 
       
  1102         _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
       
  1103         _status->set(right_path[i + 1], MATCHED);
       
  1104         oddToMatched(right_path[i + 1]);
       
  1105       }
       
  1106 
       
  1107       destroyTree(tree);
       
  1108     }
       
  1109 
       
  1110     void extractCycle(const Arc &arc) {
       
  1111       Node left = _graph.source(arc);
       
  1112       Node odd = _graph.target((*_matching)[left]);
       
  1113       Arc prev;
       
  1114       while (odd != left) {
       
  1115         Node even = _graph.target((*_matching)[odd]);
       
  1116         prev = (*_matching)[odd];
       
  1117         odd = _graph.target((*_matching)[even]);
       
  1118         _matching->set(even, _graph.oppositeArc(prev));
       
  1119       }
       
  1120       _matching->set(left, arc);
       
  1121 
       
  1122       Node right = _graph.target(arc);
       
  1123       int right_tree = _tree_set->find(right);
       
  1124       alternatePath(right, right_tree);
       
  1125       destroyTree(right_tree);
       
  1126       _matching->set(right, _graph.oppositeArc(arc));
       
  1127     }
       
  1128 
       
  1129   public:
       
  1130 
       
  1131     /// \brief Constructor
       
  1132     ///
       
  1133     /// Constructor.
       
  1134     MaxWeightedFractionalMatching(const Graph& graph, const WeightMap& weight,
       
  1135                                   bool allow_loops = true)
       
  1136       : _graph(graph), _weight(weight), _matching(0),
       
  1137       _node_potential(0), _node_num(0), _allow_loops(allow_loops),
       
  1138       _status(0),  _pred(0),
       
  1139       _tree_set_index(0), _tree_set(0),
       
  1140 
       
  1141       _delta1_index(0), _delta1(0),
       
  1142       _delta2_index(0), _delta2(0),
       
  1143       _delta3_index(0), _delta3(0),
       
  1144 
       
  1145       _delta_sum() {}
       
  1146 
       
  1147     ~MaxWeightedFractionalMatching() {
       
  1148       destroyStructures();
       
  1149     }
       
  1150 
       
  1151     /// \name Execution Control
       
  1152     /// The simplest way to execute the algorithm is to use the
       
  1153     /// \ref run() member function.
       
  1154 
       
  1155     ///@{
       
  1156 
       
  1157     /// \brief Initialize the algorithm
       
  1158     ///
       
  1159     /// This function initializes the algorithm.
       
  1160     void init() {
       
  1161       createStructures();
       
  1162 
       
  1163       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1164         (*_delta1_index)[n] = _delta1->PRE_HEAP;
       
  1165         (*_delta2_index)[n] = _delta2->PRE_HEAP;
       
  1166       }
       
  1167       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  1168         (*_delta3_index)[e] = _delta3->PRE_HEAP;
       
  1169       }
       
  1170 
       
  1171       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1172         Value max = 0;
       
  1173         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
       
  1174           if (_graph.target(e) == n && !_allow_loops) continue;
       
  1175           if ((dualScale * _weight[e]) / 2 > max) {
       
  1176             max = (dualScale * _weight[e]) / 2;
       
  1177           }
       
  1178         }
       
  1179         _node_potential->set(n, max);
       
  1180         _delta1->push(n, max);
       
  1181 
       
  1182         _tree_set->insert(n);
       
  1183 
       
  1184         _matching->set(n, INVALID);
       
  1185         _status->set(n, EVEN);
       
  1186       }
       
  1187 
       
  1188       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  1189         Node left = _graph.u(e);
       
  1190         Node right = _graph.v(e);
       
  1191         if (left == right && !_allow_loops) continue;
       
  1192         _delta3->push(e, ((*_node_potential)[left] +
       
  1193                           (*_node_potential)[right] -
       
  1194                           dualScale * _weight[e]) / 2);
       
  1195       }
       
  1196     }
       
  1197 
       
  1198     /// \brief Start the algorithm
       
  1199     ///
       
  1200     /// This function starts the algorithm.
       
  1201     ///
       
  1202     /// \pre \ref init() must be called before using this function.
       
  1203     void start() {
       
  1204       enum OpType {
       
  1205         D1, D2, D3
       
  1206       };
       
  1207 
       
  1208       int unmatched = _node_num;
       
  1209       while (unmatched > 0) {
       
  1210         Value d1 = !_delta1->empty() ?
       
  1211           _delta1->prio() : std::numeric_limits<Value>::max();
       
  1212 
       
  1213         Value d2 = !_delta2->empty() ?
       
  1214           _delta2->prio() : std::numeric_limits<Value>::max();
       
  1215 
       
  1216         Value d3 = !_delta3->empty() ?
       
  1217           _delta3->prio() : std::numeric_limits<Value>::max();
       
  1218 
       
  1219         _delta_sum = d3; OpType ot = D3;
       
  1220         if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
       
  1221         if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
       
  1222 
       
  1223         switch (ot) {
       
  1224         case D1:
       
  1225           {
       
  1226             Node n = _delta1->top();
       
  1227             unmatchNode(n);
       
  1228             --unmatched;
       
  1229           }
       
  1230           break;
       
  1231         case D2:
       
  1232           {
       
  1233             Node n = _delta2->top();
       
  1234             Arc a = (*_pred)[n];
       
  1235             if ((*_matching)[n] == INVALID) {
       
  1236               augmentOnArc(a);
       
  1237               --unmatched;
       
  1238             } else {
       
  1239               Node v = _graph.target((*_matching)[n]);
       
  1240               if ((*_matching)[n] !=
       
  1241                   _graph.oppositeArc((*_matching)[v])) {
       
  1242                 extractCycle(a);
       
  1243                 --unmatched;
       
  1244               } else {
       
  1245                 extendOnArc(a);
       
  1246               }
       
  1247             }
       
  1248           } break;
       
  1249         case D3:
       
  1250           {
       
  1251             Edge e = _delta3->top();
       
  1252 
       
  1253             Node left = _graph.u(e);
       
  1254             Node right = _graph.v(e);
       
  1255 
       
  1256             int left_tree = _tree_set->find(left);
       
  1257             int right_tree = _tree_set->find(right);
       
  1258 
       
  1259             if (left_tree == right_tree) {
       
  1260               cycleOnEdge(e, left_tree);
       
  1261               --unmatched;
       
  1262             } else {
       
  1263               augmentOnEdge(e);
       
  1264               unmatched -= 2;
       
  1265             }
       
  1266           } break;
       
  1267         }
       
  1268       }
       
  1269     }
       
  1270 
       
  1271     /// \brief Run the algorithm.
       
  1272     ///
       
  1273     /// This method runs the \c %MaxWeightedMatching algorithm.
       
  1274     ///
       
  1275     /// \note mwfm.run() is just a shortcut of the following code.
       
  1276     /// \code
       
  1277     ///   mwfm.init();
       
  1278     ///   mwfm.start();
       
  1279     /// \endcode
       
  1280     void run() {
       
  1281       init();
       
  1282       start();
       
  1283     }
       
  1284 
       
  1285     /// @}
       
  1286 
       
  1287     /// \name Primal Solution
       
  1288     /// Functions to get the primal solution, i.e. the maximum weighted
       
  1289     /// matching.\n
       
  1290     /// Either \ref run() or \ref start() function should be called before
       
  1291     /// using them.
       
  1292 
       
  1293     /// @{
       
  1294 
       
  1295     /// \brief Return the weight of the matching.
       
  1296     ///
       
  1297     /// This function returns the weight of the found matching. This
       
  1298     /// value is scaled by \ref primalScale "primal scale".
       
  1299     ///
       
  1300     /// \pre Either run() or start() must be called before using this function.
       
  1301     Value matchingWeight() const {
       
  1302       Value sum = 0;
       
  1303       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1304         if ((*_matching)[n] != INVALID) {
       
  1305           sum += _weight[(*_matching)[n]];
       
  1306         }
       
  1307       }
       
  1308       return sum * primalScale / 2;
       
  1309     }
       
  1310 
       
  1311     /// \brief Return the number of covered nodes in the matching.
       
  1312     ///
       
  1313     /// This function returns the number of covered nodes in the matching.
       
  1314     ///
       
  1315     /// \pre Either run() or start() must be called before using this function.
       
  1316     int matchingSize() const {
       
  1317       int num = 0;
       
  1318       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1319         if ((*_matching)[n] != INVALID) {
       
  1320           ++num;
       
  1321         }
       
  1322       }
       
  1323       return num;
       
  1324     }
       
  1325 
       
  1326     /// \brief Return \c true if the given edge is in the matching.
       
  1327     ///
       
  1328     /// This function returns \c true if the given edge is in the
       
  1329     /// found matching. The result is scaled by \ref primalScale
       
  1330     /// "primal scale".
       
  1331     ///
       
  1332     /// \pre Either run() or start() must be called before using this function.
       
  1333     Value matching(const Edge& edge) const {
       
  1334       return Value(edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
       
  1335         * primalScale / 2 + Value(edge == (*_matching)[_graph.v(edge)] ? 1 : 0)
       
  1336         * primalScale / 2;
       
  1337     }
       
  1338 
       
  1339     /// \brief Return the fractional matching arc (or edge) incident
       
  1340     /// to the given node.
       
  1341     ///
       
  1342     /// This function returns one of the fractional matching arc (or
       
  1343     /// edge) incident to the given node in the found matching or \c
       
  1344     /// INVALID if the node is not covered by the matching or if the
       
  1345     /// node is on an odd length cycle then it is the successor edge
       
  1346     /// on the cycle.
       
  1347     ///
       
  1348     /// \pre Either run() or start() must be called before using this function.
       
  1349     Arc matching(const Node& node) const {
       
  1350       return (*_matching)[node];
       
  1351     }
       
  1352 
       
  1353     /// \brief Return a const reference to the matching map.
       
  1354     ///
       
  1355     /// This function returns a const reference to a node map that stores
       
  1356     /// the matching arc (or edge) incident to each node.
       
  1357     const MatchingMap& matchingMap() const {
       
  1358       return *_matching;
       
  1359     }
       
  1360 
       
  1361     /// @}
       
  1362 
       
  1363     /// \name Dual Solution
       
  1364     /// Functions to get the dual solution.\n
       
  1365     /// Either \ref run() or \ref start() function should be called before
       
  1366     /// using them.
       
  1367 
       
  1368     /// @{
       
  1369 
       
  1370     /// \brief Return the value of the dual solution.
       
  1371     ///
       
  1372     /// This function returns the value of the dual solution.
       
  1373     /// It should be equal to the primal value scaled by \ref dualScale
       
  1374     /// "dual scale".
       
  1375     ///
       
  1376     /// \pre Either run() or start() must be called before using this function.
       
  1377     Value dualValue() const {
       
  1378       Value sum = 0;
       
  1379       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1380         sum += nodeValue(n);
       
  1381       }
       
  1382       return sum;
       
  1383     }
       
  1384 
       
  1385     /// \brief Return the dual value (potential) of the given node.
       
  1386     ///
       
  1387     /// This function returns the dual value (potential) of the given node.
       
  1388     ///
       
  1389     /// \pre Either run() or start() must be called before using this function.
       
  1390     Value nodeValue(const Node& n) const {
       
  1391       return (*_node_potential)[n];
       
  1392     }
       
  1393 
       
  1394     /// @}
       
  1395 
       
  1396   };
       
  1397 
       
  1398   /// \ingroup matching
       
  1399   ///
       
  1400   /// \brief Weighted fractional perfect matching in general graphs
       
  1401   ///
       
  1402   /// This class provides an efficient implementation of fractional
       
  1403   /// matching algorithm. The implementation is based on extensive use
       
  1404   /// of priority queues and provides \f$O(nm\log n)\f$ time
       
  1405   /// complexity.
       
  1406   ///
       
  1407   /// The maximum weighted fractional perfect matching is a relaxation
       
  1408   /// of the maximum weighted perfect matching problem where the odd
       
  1409   /// set constraints are omitted.
       
  1410   /// It can be formulated with the following linear program.
       
  1411   /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
       
  1412   /// \f[x_e \ge 0\quad \forall e\in E\f]
       
  1413   /// \f[\max \sum_{e\in E}x_ew_e\f]
       
  1414   /// where \f$\delta(X)\f$ is the set of edges incident to a node in
       
  1415   /// \f$X\f$. The result must be the union of a matching with one
       
  1416   /// value edges and a set of odd length cycles with half value edges.
       
  1417   ///
       
  1418   /// The algorithm calculates an optimal fractional matching and a
       
  1419   /// proof of the optimality. The solution of the dual problem can be
       
  1420   /// used to check the result of the algorithm. The dual linear
       
  1421   /// problem is the following.
       
  1422   /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
       
  1423   /// \f[\min \sum_{u \in V}y_u \f] ///
       
  1424   ///
       
  1425   /// The algorithm can be executed with the run() function.
       
  1426   /// After it the matching (the primal solution) and the dual solution
       
  1427   /// can be obtained using the query functions.
       
  1428 
       
  1429   /// If the value type is integer, then the primal and the dual
       
  1430   /// solutions are multiplied by
       
  1431   /// \ref MaxWeightedMatching::primalScale "2" and
       
  1432   /// \ref MaxWeightedMatching::dualScale "4" respectively.
       
  1433   ///
       
  1434   /// \tparam GR The undirected graph type the algorithm runs on.
       
  1435   /// \tparam WM The type edge weight map. The default type is
       
  1436   /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
       
  1437 #ifdef DOXYGEN
       
  1438   template <typename GR, typename WM>
       
  1439 #else
       
  1440   template <typename GR,
       
  1441             typename WM = typename GR::template EdgeMap<int> >
       
  1442 #endif
       
  1443   class MaxWeightedPerfectFractionalMatching {
       
  1444   public:
       
  1445 
       
  1446     /// The graph type of the algorithm
       
  1447     typedef GR Graph;
       
  1448     /// The type of the edge weight map
       
  1449     typedef WM WeightMap;
       
  1450     /// The value type of the edge weights
       
  1451     typedef typename WeightMap::Value Value;
       
  1452 
       
  1453     /// The type of the matching map
       
  1454     typedef typename Graph::template NodeMap<typename Graph::Arc>
       
  1455     MatchingMap;
       
  1456 
       
  1457     /// \brief Scaling factor for primal solution
       
  1458     ///
       
  1459     /// Scaling factor for primal solution. It is equal to 2 or 1
       
  1460     /// according to the value type.
       
  1461     static const int primalScale =
       
  1462       std::numeric_limits<Value>::is_integer ? 2 : 1;
       
  1463 
       
  1464     /// \brief Scaling factor for dual solution
       
  1465     ///
       
  1466     /// Scaling factor for dual solution. It is equal to 4 or 1
       
  1467     /// according to the value type.
       
  1468     static const int dualScale =
       
  1469       std::numeric_limits<Value>::is_integer ? 4 : 1;
       
  1470 
       
  1471   private:
       
  1472 
       
  1473     TEMPLATE_GRAPH_TYPEDEFS(Graph);
       
  1474 
       
  1475     typedef typename Graph::template NodeMap<Value> NodePotential;
       
  1476 
       
  1477     const Graph& _graph;
       
  1478     const WeightMap& _weight;
       
  1479 
       
  1480     MatchingMap* _matching;
       
  1481     NodePotential* _node_potential;
       
  1482 
       
  1483     int _node_num;
       
  1484     bool _allow_loops;
       
  1485 
       
  1486     enum Status {
       
  1487       EVEN = -1, MATCHED = 0, ODD = 1
       
  1488     };
       
  1489 
       
  1490     typedef typename Graph::template NodeMap<Status> StatusMap;
       
  1491     StatusMap* _status;
       
  1492 
       
  1493     typedef typename Graph::template NodeMap<Arc> PredMap;
       
  1494     PredMap* _pred;
       
  1495 
       
  1496     typedef ExtendFindEnum<IntNodeMap> TreeSet;
       
  1497 
       
  1498     IntNodeMap *_tree_set_index;
       
  1499     TreeSet *_tree_set;
       
  1500 
       
  1501     IntNodeMap *_delta2_index;
       
  1502     BinHeap<Value, IntNodeMap> *_delta2;
       
  1503 
       
  1504     IntEdgeMap *_delta3_index;
       
  1505     BinHeap<Value, IntEdgeMap> *_delta3;
       
  1506 
       
  1507     Value _delta_sum;
       
  1508 
       
  1509     void createStructures() {
       
  1510       _node_num = countNodes(_graph);
       
  1511 
       
  1512       if (!_matching) {
       
  1513         _matching = new MatchingMap(_graph);
       
  1514       }
       
  1515       if (!_node_potential) {
       
  1516         _node_potential = new NodePotential(_graph);
       
  1517       }
       
  1518       if (!_status) {
       
  1519         _status = new StatusMap(_graph);
       
  1520       }
       
  1521       if (!_pred) {
       
  1522         _pred = new PredMap(_graph);
       
  1523       }
       
  1524       if (!_tree_set) {
       
  1525         _tree_set_index = new IntNodeMap(_graph);
       
  1526         _tree_set = new TreeSet(*_tree_set_index);
       
  1527       }
       
  1528       if (!_delta2) {
       
  1529         _delta2_index = new IntNodeMap(_graph);
       
  1530         _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
       
  1531       }
       
  1532       if (!_delta3) {
       
  1533         _delta3_index = new IntEdgeMap(_graph);
       
  1534         _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
       
  1535       }
       
  1536     }
       
  1537 
       
  1538     void destroyStructures() {
       
  1539       if (_matching) {
       
  1540         delete _matching;
       
  1541       }
       
  1542       if (_node_potential) {
       
  1543         delete _node_potential;
       
  1544       }
       
  1545       if (_status) {
       
  1546         delete _status;
       
  1547       }
       
  1548       if (_pred) {
       
  1549         delete _pred;
       
  1550       }
       
  1551       if (_tree_set) {
       
  1552         delete _tree_set_index;
       
  1553         delete _tree_set;
       
  1554       }
       
  1555       if (_delta2) {
       
  1556         delete _delta2_index;
       
  1557         delete _delta2;
       
  1558       }
       
  1559       if (_delta3) {
       
  1560         delete _delta3_index;
       
  1561         delete _delta3;
       
  1562       }
       
  1563     }
       
  1564 
       
  1565     void matchedToEven(Node node, int tree) {
       
  1566       _tree_set->insert(node, tree);
       
  1567       _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
       
  1568 
       
  1569       if (_delta2->state(node) == _delta2->IN_HEAP) {
       
  1570         _delta2->erase(node);
       
  1571       }
       
  1572 
       
  1573       for (InArcIt a(_graph, node); a != INVALID; ++a) {
       
  1574         Node v = _graph.source(a);
       
  1575         Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
       
  1576           dualScale * _weight[a];
       
  1577         if (node == v) {
       
  1578           if (_allow_loops && _graph.direction(a)) {
       
  1579             _delta3->push(a, rw / 2);
       
  1580           }
       
  1581         } else if ((*_status)[v] == EVEN) {
       
  1582           _delta3->push(a, rw / 2);
       
  1583         } else if ((*_status)[v] == MATCHED) {
       
  1584           if (_delta2->state(v) != _delta2->IN_HEAP) {
       
  1585             _pred->set(v, a);
       
  1586             _delta2->push(v, rw);
       
  1587           } else if ((*_delta2)[v] > rw) {
       
  1588             _pred->set(v, a);
       
  1589             _delta2->decrease(v, rw);
       
  1590           }
       
  1591         }
       
  1592       }
       
  1593     }
       
  1594 
       
  1595     void matchedToOdd(Node node, int tree) {
       
  1596       _tree_set->insert(node, tree);
       
  1597       _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
       
  1598 
       
  1599       if (_delta2->state(node) == _delta2->IN_HEAP) {
       
  1600         _delta2->erase(node);
       
  1601       }
       
  1602     }
       
  1603 
       
  1604     void evenToMatched(Node node, int tree) {
       
  1605       _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
       
  1606       Arc min = INVALID;
       
  1607       Value minrw = std::numeric_limits<Value>::max();
       
  1608       for (InArcIt a(_graph, node); a != INVALID; ++a) {
       
  1609         Node v = _graph.source(a);
       
  1610         Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
       
  1611           dualScale * _weight[a];
       
  1612 
       
  1613         if (node == v) {
       
  1614           if (_allow_loops && _graph.direction(a)) {
       
  1615             _delta3->erase(a);
       
  1616           }
       
  1617         } else if ((*_status)[v] == EVEN) {
       
  1618           _delta3->erase(a);
       
  1619           if (minrw > rw) {
       
  1620             min = _graph.oppositeArc(a);
       
  1621             minrw = rw;
       
  1622           }
       
  1623         } else if ((*_status)[v]  == MATCHED) {
       
  1624           if ((*_pred)[v] == a) {
       
  1625             Arc mina = INVALID;
       
  1626             Value minrwa = std::numeric_limits<Value>::max();
       
  1627             for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
       
  1628               Node va = _graph.target(aa);
       
  1629               if ((*_status)[va] != EVEN ||
       
  1630                   _tree_set->find(va) == tree) continue;
       
  1631               Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
       
  1632                 dualScale * _weight[aa];
       
  1633               if (minrwa > rwa) {
       
  1634                 minrwa = rwa;
       
  1635                 mina = aa;
       
  1636               }
       
  1637             }
       
  1638             if (mina != INVALID) {
       
  1639               _pred->set(v, mina);
       
  1640               _delta2->increase(v, minrwa);
       
  1641             } else {
       
  1642               _pred->set(v, INVALID);
       
  1643               _delta2->erase(v);
       
  1644             }
       
  1645           }
       
  1646         }
       
  1647       }
       
  1648       if (min != INVALID) {
       
  1649         _pred->set(node, min);
       
  1650         _delta2->push(node, minrw);
       
  1651       } else {
       
  1652         _pred->set(node, INVALID);
       
  1653       }
       
  1654     }
       
  1655 
       
  1656     void oddToMatched(Node node) {
       
  1657       _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
       
  1658       Arc min = INVALID;
       
  1659       Value minrw = std::numeric_limits<Value>::max();
       
  1660       for (InArcIt a(_graph, node); a != INVALID; ++a) {
       
  1661         Node v = _graph.source(a);
       
  1662         if ((*_status)[v] != EVEN) continue;
       
  1663         Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
       
  1664           dualScale * _weight[a];
       
  1665 
       
  1666         if (minrw > rw) {
       
  1667           min = _graph.oppositeArc(a);
       
  1668           minrw = rw;
       
  1669         }
       
  1670       }
       
  1671       if (min != INVALID) {
       
  1672         _pred->set(node, min);
       
  1673         _delta2->push(node, minrw);
       
  1674       } else {
       
  1675         _pred->set(node, INVALID);
       
  1676       }
       
  1677     }
       
  1678 
       
  1679     void alternatePath(Node even, int tree) {
       
  1680       Node odd;
       
  1681 
       
  1682       _status->set(even, MATCHED);
       
  1683       evenToMatched(even, tree);
       
  1684 
       
  1685       Arc prev = (*_matching)[even];
       
  1686       while (prev != INVALID) {
       
  1687         odd = _graph.target(prev);
       
  1688         even = _graph.target((*_pred)[odd]);
       
  1689         _matching->set(odd, (*_pred)[odd]);
       
  1690         _status->set(odd, MATCHED);
       
  1691         oddToMatched(odd);
       
  1692 
       
  1693         prev = (*_matching)[even];
       
  1694         _status->set(even, MATCHED);
       
  1695         _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
       
  1696         evenToMatched(even, tree);
       
  1697       }
       
  1698     }
       
  1699 
       
  1700     void destroyTree(int tree) {
       
  1701       for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
       
  1702         if ((*_status)[n] == EVEN) {
       
  1703           _status->set(n, MATCHED);
       
  1704           evenToMatched(n, tree);
       
  1705         } else if ((*_status)[n] == ODD) {
       
  1706           _status->set(n, MATCHED);
       
  1707           oddToMatched(n);
       
  1708         }
       
  1709       }
       
  1710       _tree_set->eraseClass(tree);
       
  1711     }
       
  1712 
       
  1713     void augmentOnEdge(const Edge& edge) {
       
  1714       Node left = _graph.u(edge);
       
  1715       int left_tree = _tree_set->find(left);
       
  1716 
       
  1717       alternatePath(left, left_tree);
       
  1718       destroyTree(left_tree);
       
  1719       _matching->set(left, _graph.direct(edge, true));
       
  1720 
       
  1721       Node right = _graph.v(edge);
       
  1722       int right_tree = _tree_set->find(right);
       
  1723 
       
  1724       alternatePath(right, right_tree);
       
  1725       destroyTree(right_tree);
       
  1726       _matching->set(right, _graph.direct(edge, false));
       
  1727     }
       
  1728 
       
  1729     void augmentOnArc(const Arc& arc) {
       
  1730       Node left = _graph.source(arc);
       
  1731       _status->set(left, MATCHED);
       
  1732       _matching->set(left, arc);
       
  1733       _pred->set(left, arc);
       
  1734 
       
  1735       Node right = _graph.target(arc);
       
  1736       int right_tree = _tree_set->find(right);
       
  1737 
       
  1738       alternatePath(right, right_tree);
       
  1739       destroyTree(right_tree);
       
  1740       _matching->set(right, _graph.oppositeArc(arc));
       
  1741     }
       
  1742 
       
  1743     void extendOnArc(const Arc& arc) {
       
  1744       Node base = _graph.target(arc);
       
  1745       int tree = _tree_set->find(base);
       
  1746 
       
  1747       Node odd = _graph.source(arc);
       
  1748       _tree_set->insert(odd, tree);
       
  1749       _status->set(odd, ODD);
       
  1750       matchedToOdd(odd, tree);
       
  1751       _pred->set(odd, arc);
       
  1752 
       
  1753       Node even = _graph.target((*_matching)[odd]);
       
  1754       _tree_set->insert(even, tree);
       
  1755       _status->set(even, EVEN);
       
  1756       matchedToEven(even, tree);
       
  1757     }
       
  1758 
       
  1759     void cycleOnEdge(const Edge& edge, int tree) {
       
  1760       Node nca = INVALID;
       
  1761       std::vector<Node> left_path, right_path;
       
  1762 
       
  1763       {
       
  1764         std::set<Node> left_set, right_set;
       
  1765         Node left = _graph.u(edge);
       
  1766         left_path.push_back(left);
       
  1767         left_set.insert(left);
       
  1768 
       
  1769         Node right = _graph.v(edge);
       
  1770         right_path.push_back(right);
       
  1771         right_set.insert(right);
       
  1772 
       
  1773         while (true) {
       
  1774 
       
  1775           if (left_set.find(right) != left_set.end()) {
       
  1776             nca = right;
       
  1777             break;
       
  1778           }
       
  1779 
       
  1780           if ((*_matching)[left] == INVALID) break;
       
  1781 
       
  1782           left = _graph.target((*_matching)[left]);
       
  1783           left_path.push_back(left);
       
  1784           left = _graph.target((*_pred)[left]);
       
  1785           left_path.push_back(left);
       
  1786 
       
  1787           left_set.insert(left);
       
  1788 
       
  1789           if (right_set.find(left) != right_set.end()) {
       
  1790             nca = left;
       
  1791             break;
       
  1792           }
       
  1793 
       
  1794           if ((*_matching)[right] == INVALID) break;
       
  1795 
       
  1796           right = _graph.target((*_matching)[right]);
       
  1797           right_path.push_back(right);
       
  1798           right = _graph.target((*_pred)[right]);
       
  1799           right_path.push_back(right);
       
  1800 
       
  1801           right_set.insert(right);
       
  1802 
       
  1803         }
       
  1804 
       
  1805         if (nca == INVALID) {
       
  1806           if ((*_matching)[left] == INVALID) {
       
  1807             nca = right;
       
  1808             while (left_set.find(nca) == left_set.end()) {
       
  1809               nca = _graph.target((*_matching)[nca]);
       
  1810               right_path.push_back(nca);
       
  1811               nca = _graph.target((*_pred)[nca]);
       
  1812               right_path.push_back(nca);
       
  1813             }
       
  1814           } else {
       
  1815             nca = left;
       
  1816             while (right_set.find(nca) == right_set.end()) {
       
  1817               nca = _graph.target((*_matching)[nca]);
       
  1818               left_path.push_back(nca);
       
  1819               nca = _graph.target((*_pred)[nca]);
       
  1820               left_path.push_back(nca);
       
  1821             }
       
  1822           }
       
  1823         }
       
  1824       }
       
  1825 
       
  1826       alternatePath(nca, tree);
       
  1827       Arc prev;
       
  1828 
       
  1829       prev = _graph.direct(edge, true);
       
  1830       for (int i = 0; left_path[i] != nca; i += 2) {
       
  1831         _matching->set(left_path[i], prev);
       
  1832         _status->set(left_path[i], MATCHED);
       
  1833         evenToMatched(left_path[i], tree);
       
  1834 
       
  1835         prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
       
  1836         _status->set(left_path[i + 1], MATCHED);
       
  1837         oddToMatched(left_path[i + 1]);
       
  1838       }
       
  1839       _matching->set(nca, prev);
       
  1840 
       
  1841       for (int i = 0; right_path[i] != nca; i += 2) {
       
  1842         _status->set(right_path[i], MATCHED);
       
  1843         evenToMatched(right_path[i], tree);
       
  1844 
       
  1845         _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
       
  1846         _status->set(right_path[i + 1], MATCHED);
       
  1847         oddToMatched(right_path[i + 1]);
       
  1848       }
       
  1849 
       
  1850       destroyTree(tree);
       
  1851     }
       
  1852 
       
  1853     void extractCycle(const Arc &arc) {
       
  1854       Node left = _graph.source(arc);
       
  1855       Node odd = _graph.target((*_matching)[left]);
       
  1856       Arc prev;
       
  1857       while (odd != left) {
       
  1858         Node even = _graph.target((*_matching)[odd]);
       
  1859         prev = (*_matching)[odd];
       
  1860         odd = _graph.target((*_matching)[even]);
       
  1861         _matching->set(even, _graph.oppositeArc(prev));
       
  1862       }
       
  1863       _matching->set(left, arc);
       
  1864 
       
  1865       Node right = _graph.target(arc);
       
  1866       int right_tree = _tree_set->find(right);
       
  1867       alternatePath(right, right_tree);
       
  1868       destroyTree(right_tree);
       
  1869       _matching->set(right, _graph.oppositeArc(arc));
       
  1870     }
       
  1871 
       
  1872   public:
       
  1873 
       
  1874     /// \brief Constructor
       
  1875     ///
       
  1876     /// Constructor.
       
  1877     MaxWeightedPerfectFractionalMatching(const Graph& graph,
       
  1878                                          const WeightMap& weight,
       
  1879                                          bool allow_loops = true)
       
  1880       : _graph(graph), _weight(weight), _matching(0),
       
  1881       _node_potential(0), _node_num(0), _allow_loops(allow_loops),
       
  1882       _status(0),  _pred(0),
       
  1883       _tree_set_index(0), _tree_set(0),
       
  1884 
       
  1885       _delta2_index(0), _delta2(0),
       
  1886       _delta3_index(0), _delta3(0),
       
  1887 
       
  1888       _delta_sum() {}
       
  1889 
       
  1890     ~MaxWeightedPerfectFractionalMatching() {
       
  1891       destroyStructures();
       
  1892     }
       
  1893 
       
  1894     /// \name Execution Control
       
  1895     /// The simplest way to execute the algorithm is to use the
       
  1896     /// \ref run() member function.
       
  1897 
       
  1898     ///@{
       
  1899 
       
  1900     /// \brief Initialize the algorithm
       
  1901     ///
       
  1902     /// This function initializes the algorithm.
       
  1903     void init() {
       
  1904       createStructures();
       
  1905 
       
  1906       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1907         (*_delta2_index)[n] = _delta2->PRE_HEAP;
       
  1908       }
       
  1909       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  1910         (*_delta3_index)[e] = _delta3->PRE_HEAP;
       
  1911       }
       
  1912 
       
  1913       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1914         Value max = - std::numeric_limits<Value>::max();
       
  1915         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
       
  1916           if (_graph.target(e) == n && !_allow_loops) continue;
       
  1917           if ((dualScale * _weight[e]) / 2 > max) {
       
  1918             max = (dualScale * _weight[e]) / 2;
       
  1919           }
       
  1920         }
       
  1921         _node_potential->set(n, max);
       
  1922 
       
  1923         _tree_set->insert(n);
       
  1924 
       
  1925         _matching->set(n, INVALID);
       
  1926         _status->set(n, EVEN);
       
  1927       }
       
  1928 
       
  1929       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  1930         Node left = _graph.u(e);
       
  1931         Node right = _graph.v(e);
       
  1932         if (left == right && !_allow_loops) continue;
       
  1933         _delta3->push(e, ((*_node_potential)[left] +
       
  1934                           (*_node_potential)[right] -
       
  1935                           dualScale * _weight[e]) / 2);
       
  1936       }
       
  1937     }
       
  1938 
       
  1939     /// \brief Start the algorithm
       
  1940     ///
       
  1941     /// This function starts the algorithm.
       
  1942     ///
       
  1943     /// \pre \ref init() must be called before using this function.
       
  1944     bool start() {
       
  1945       enum OpType {
       
  1946         D2, D3
       
  1947       };
       
  1948 
       
  1949       int unmatched = _node_num;
       
  1950       while (unmatched > 0) {
       
  1951         Value d2 = !_delta2->empty() ?
       
  1952           _delta2->prio() : std::numeric_limits<Value>::max();
       
  1953 
       
  1954         Value d3 = !_delta3->empty() ?
       
  1955           _delta3->prio() : std::numeric_limits<Value>::max();
       
  1956 
       
  1957         _delta_sum = d3; OpType ot = D3;
       
  1958         if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
       
  1959 
       
  1960         if (_delta_sum == std::numeric_limits<Value>::max()) {
       
  1961           return false;
       
  1962         }
       
  1963 
       
  1964         switch (ot) {
       
  1965         case D2:
       
  1966           {
       
  1967             Node n = _delta2->top();
       
  1968             Arc a = (*_pred)[n];
       
  1969             if ((*_matching)[n] == INVALID) {
       
  1970               augmentOnArc(a);
       
  1971               --unmatched;
       
  1972             } else {
       
  1973               Node v = _graph.target((*_matching)[n]);
       
  1974               if ((*_matching)[n] !=
       
  1975                   _graph.oppositeArc((*_matching)[v])) {
       
  1976                 extractCycle(a);
       
  1977                 --unmatched;
       
  1978               } else {
       
  1979                 extendOnArc(a);
       
  1980               }
       
  1981             }
       
  1982           } break;
       
  1983         case D3:
       
  1984           {
       
  1985             Edge e = _delta3->top();
       
  1986 
       
  1987             Node left = _graph.u(e);
       
  1988             Node right = _graph.v(e);
       
  1989 
       
  1990             int left_tree = _tree_set->find(left);
       
  1991             int right_tree = _tree_set->find(right);
       
  1992 
       
  1993             if (left_tree == right_tree) {
       
  1994               cycleOnEdge(e, left_tree);
       
  1995               --unmatched;
       
  1996             } else {
       
  1997               augmentOnEdge(e);
       
  1998               unmatched -= 2;
       
  1999             }
       
  2000           } break;
       
  2001         }
       
  2002       }
       
  2003       return true;
       
  2004     }
       
  2005 
       
  2006     /// \brief Run the algorithm.
       
  2007     ///
       
  2008     /// This method runs the \c %MaxWeightedMatching algorithm.
       
  2009     ///
       
  2010     /// \note mwfm.run() is just a shortcut of the following code.
       
  2011     /// \code
       
  2012     ///   mwpfm.init();
       
  2013     ///   mwpfm.start();
       
  2014     /// \endcode
       
  2015     bool run() {
       
  2016       init();
       
  2017       return start();
       
  2018     }
       
  2019 
       
  2020     /// @}
       
  2021 
       
  2022     /// \name Primal Solution
       
  2023     /// Functions to get the primal solution, i.e. the maximum weighted
       
  2024     /// matching.\n
       
  2025     /// Either \ref run() or \ref start() function should be called before
       
  2026     /// using them.
       
  2027 
       
  2028     /// @{
       
  2029 
       
  2030     /// \brief Return the weight of the matching.
       
  2031     ///
       
  2032     /// This function returns the weight of the found matching. This
       
  2033     /// value is scaled by \ref primalScale "primal scale".
       
  2034     ///
       
  2035     /// \pre Either run() or start() must be called before using this function.
       
  2036     Value matchingWeight() const {
       
  2037       Value sum = 0;
       
  2038       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  2039         if ((*_matching)[n] != INVALID) {
       
  2040           sum += _weight[(*_matching)[n]];
       
  2041         }
       
  2042       }
       
  2043       return sum * primalScale / 2;
       
  2044     }
       
  2045 
       
  2046     /// \brief Return the number of covered nodes in the matching.
       
  2047     ///
       
  2048     /// This function returns the number of covered nodes in the matching.
       
  2049     ///
       
  2050     /// \pre Either run() or start() must be called before using this function.
       
  2051     int matchingSize() const {
       
  2052       int num = 0;
       
  2053       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  2054         if ((*_matching)[n] != INVALID) {
       
  2055           ++num;
       
  2056         }
       
  2057       }
       
  2058       return num;
       
  2059     }
       
  2060 
       
  2061     /// \brief Return \c true if the given edge is in the matching.
       
  2062     ///
       
  2063     /// This function returns \c true if the given edge is in the
       
  2064     /// found matching. The result is scaled by \ref primalScale
       
  2065     /// "primal scale".
       
  2066     ///
       
  2067     /// \pre Either run() or start() must be called before using this function.
       
  2068     Value matching(const Edge& edge) const {
       
  2069       return Value(edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
       
  2070         * primalScale / 2 + Value(edge == (*_matching)[_graph.v(edge)] ? 1 : 0)
       
  2071         * primalScale / 2;
       
  2072     }
       
  2073 
       
  2074     /// \brief Return the fractional matching arc (or edge) incident
       
  2075     /// to the given node.
       
  2076     ///
       
  2077     /// This function returns one of the fractional matching arc (or
       
  2078     /// edge) incident to the given node in the found matching or \c
       
  2079     /// INVALID if the node is not covered by the matching or if the
       
  2080     /// node is on an odd length cycle then it is the successor edge
       
  2081     /// on the cycle.
       
  2082     ///
       
  2083     /// \pre Either run() or start() must be called before using this function.
       
  2084     Arc matching(const Node& node) const {
       
  2085       return (*_matching)[node];
       
  2086     }
       
  2087 
       
  2088     /// \brief Return a const reference to the matching map.
       
  2089     ///
       
  2090     /// This function returns a const reference to a node map that stores
       
  2091     /// the matching arc (or edge) incident to each node.
       
  2092     const MatchingMap& matchingMap() const {
       
  2093       return *_matching;
       
  2094     }
       
  2095 
       
  2096     /// @}
       
  2097 
       
  2098     /// \name Dual Solution
       
  2099     /// Functions to get the dual solution.\n
       
  2100     /// Either \ref run() or \ref start() function should be called before
       
  2101     /// using them.
       
  2102 
       
  2103     /// @{
       
  2104 
       
  2105     /// \brief Return the value of the dual solution.
       
  2106     ///
       
  2107     /// This function returns the value of the dual solution.
       
  2108     /// It should be equal to the primal value scaled by \ref dualScale
       
  2109     /// "dual scale".
       
  2110     ///
       
  2111     /// \pre Either run() or start() must be called before using this function.
       
  2112     Value dualValue() const {
       
  2113       Value sum = 0;
       
  2114       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  2115         sum += nodeValue(n);
       
  2116       }
       
  2117       return sum;
       
  2118     }
       
  2119 
       
  2120     /// \brief Return the dual value (potential) of the given node.
       
  2121     ///
       
  2122     /// This function returns the dual value (potential) of the given node.
       
  2123     ///
       
  2124     /// \pre Either run() or start() must be called before using this function.
       
  2125     Value nodeValue(const Node& n) const {
       
  2126       return (*_node_potential)[n];
       
  2127     }
       
  2128 
       
  2129     /// @}
       
  2130 
       
  2131   };
       
  2132 
       
  2133 } //END OF NAMESPACE LEMON
       
  2134 
       
  2135 #endif //LEMON_FRACTIONAL_MATCHING_H