1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 #ifndef LEMON_FRACTIONAL_MATCHING_H
20 #define LEMON_FRACTIONAL_MATCHING_H
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>
36 ///\brief Fractional matching algorithms in general graphs.
40 /// \brief Default traits class of MaxFractionalMatching class.
42 /// Default traits class of MaxFractionalMatching class.
43 /// \tparam GR Graph type.
44 template <typename GR>
45 struct MaxFractionalMatchingDefaultTraits {
47 /// \brief The type of the graph the algorithm runs on.
50 /// \brief The type of the map that stores the matching.
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;
56 /// \brief Instantiates a MatchingMap.
58 /// This function instantiates a \ref MatchingMap.
59 /// \param graph The graph for which we would like to define
61 static MatchingMap* createMatchingMap(const Graph& graph) {
62 return new MatchingMap(graph);
65 /// \brief The elevator type used by MaxFractionalMatching algorithm.
67 /// The elevator type used by MaxFractionalMatching algorithm.
70 /// \sa LinkedElevator
71 typedef LinkedElevator<Graph, typename Graph::Node> Elevator;
73 /// \brief Instantiates an Elevator.
75 /// This function instantiates an \ref Elevator.
76 /// \param graph The graph for which we would like to define
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);
86 /// \brief Max cardinality fractional matching
88 /// This class provides an implementation of fractional matching
89 /// algorithm based on push-relabel principle.
91 /// The maximum cardinality fractional matching is a relaxation of the
92 /// maximum cardinality matching problem where the odd set constraints
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.
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.
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.
113 /// The primal solution is multiplied by
114 /// \ref MaxFractionalMatching::primalScale "2".
116 /// \tparam GR The undirected graph type the algorithm runs on.
118 template <typename GR, typename TR>
120 template <typename GR,
121 typename TR = MaxFractionalMatchingDefaultTraits<GR> >
123 class MaxFractionalMatching {
126 /// \brief The \ref MaxFractionalMatchingDefaultTraits "traits
127 /// class" of the algorithm.
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;
136 /// \brief Scaling factor for primal solution
138 /// Scaling factor for primal solution.
139 static const int primalScale = 2;
148 TEMPLATE_GRAPH_TYPEDEFS(Graph);
150 bool _local_matching;
151 MatchingMap *_matching;
156 typedef typename Graph::template NodeMap<int> InDegMap;
159 void createStructures() {
160 _node_num = countNodes(_graph);
163 _local_matching = true;
164 _matching = Traits::createMatchingMap(_graph);
168 _level = Traits::createElevator(_graph, _node_num);
171 _indeg = new InDegMap(_graph);
175 void destroyStructures() {
176 if (_local_matching) {
187 void postprocessing() {
188 for (NodeIt n(_graph); n != INVALID; ++n) {
189 if ((*_indeg)[n] != 0) continue;
192 while ((*_matching)[u] != INVALID) {
193 Node v = _graph.target((*_matching)[u]);
195 Arc a = _graph.oppositeArc((*_matching)[u]);
196 u = _graph.target((*_matching)[v]);
198 _matching->set(v, a);
202 for (NodeIt n(_graph); n != INVALID; ++n) {
203 if ((*_indeg)[n] != 1) continue;
207 Node u = _graph.target((*_matching)[n]);
210 u = _graph.target((*_matching)[u]);
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);
219 prev = _graph.oppositeArc((*_matching)[u]);
220 v = _graph.target((*_matching)[u]);
221 u = _graph.target((*_matching)[v]);
222 _matching->set(v, prev);
230 typedef MaxFractionalMatching Create;
232 ///\name Named Template Parameters
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
245 /// \brief \ref named-templ-param "Named parameter" for setting
248 /// \ref named-templ-param "Named parameter" for setting MatchingMap
250 template <typename T>
251 struct SetMatchingMap
252 : public MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > {
253 typedef MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > Create;
256 template <typename T>
257 struct SetElevatorTraits : public Traits {
259 static Elevator *createElevator(const Graph&, int) {
260 LEMON_ASSERT(false, "Elevator is not initialized");
261 return 0; // ignore warnings
265 /// \brief \ref named-templ-param "Named parameter" for setting
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>
276 : public MaxFractionalMatching<Graph, SetElevatorTraits<T> > {
277 typedef MaxFractionalMatching<Graph, SetElevatorTraits<T> > Create;
280 template <typename T>
281 struct SetStandardElevatorTraits : public Traits {
283 static Elevator *createElevator(const Graph& graph, int max_level) {
284 return new Elevator(graph, max_level);
288 /// \brief \ref named-templ-param "Named parameter" for setting
289 /// Elevator type with automatic allocation
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().
300 template <typename T>
301 struct SetStandardElevator
302 : public MaxFractionalMatching<Graph, SetStandardElevatorTraits<T> > {
303 typedef MaxFractionalMatching<Graph,
304 SetStandardElevatorTraits<T> > Create;
311 MaxFractionalMatching() {}
315 /// \brief Constructor
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)
325 ~MaxFractionalMatching() {
329 /// \brief Sets the matching map.
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,
336 /// \return <tt>(*this)</tt>
337 MaxFractionalMatching& matchingMap(MatchingMap& map) {
338 if (_local_matching) {
340 _local_matching = false;
346 /// \brief Sets the elevator used by algorithm.
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,
353 /// \return <tt>(*this)</tt>
354 MaxFractionalMatching& elevator(Elevator& elevator) {
357 _local_level = false;
363 /// \brief Returns a const reference to the elevator.
365 /// Returns a const reference to the elevator.
367 /// \pre Either \ref run() or \ref init() must be called before
368 /// using this function.
369 const Elevator& elevator() const {
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()
382 /// \brief Initializes the internal data structures.
384 /// Initializes the internal data structures and sets the initial
390 for (NodeIt n(_graph); n != INVALID; ++n) {
392 _matching->set(n, INVALID);
393 _level->initAddItem(n);
395 _level->initFinish();
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);
408 for (NodeIt n(_graph); n != INVALID; ++n) {
409 if ((*_indeg)[n] == 0) {
415 /// \brief Starts the algorithm and computes a fractional matching
417 /// The algorithm computes a maximum fractional matching.
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) {
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) {
439 _matching->set(u, a);
440 _indeg->set(n, (*_indeg)[n] + 1);
441 _level->deactivate(n);
443 } else if (new_level > (*_level)[v]) {
444 new_level = (*_level)[v];
448 if (new_level + 1 < _level->maxLevel()) {
449 _level->liftHighestActive(new_level + 1);
451 _level->liftHighestActiveToTop();
453 if (_level->emptyLevel(level)) {
454 _level->liftToTop(level);
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);
472 /// \brief Starts the algorithm and computes a perfect fractional
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.
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) {
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) {
499 _matching->set(u, a);
500 _indeg->set(n, (*_indeg)[n] + 1);
501 _level->deactivate(n);
503 } else if (new_level > (*_level)[v]) {
504 new_level = (*_level)[v];
508 if (new_level + 1 < _level->maxLevel()) {
509 _level->liftHighestActive(new_level + 1);
511 _level->liftHighestActiveToTop();
512 _empty_level = _level->maxLevel() - 1;
515 if (_level->emptyLevel(level)) {
516 _level->liftToTop(level);
517 _empty_level = level;
529 /// \brief Runs the algorithm
531 /// Just a shortcut for the next code:
536 void run(bool postprocess = true) {
541 /// \brief Runs the algorithm to find a perfect fractional matching
543 /// Just a shortcut for the next code:
548 bool runPerfect(bool postprocess = true) {
550 return startPerfect(postprocess);
555 /// \name Query Functions
556 /// The result of the %Matching algorithm can be obtained using these
558 /// Before the use of these functions,
559 /// either run() or start() must be called.
563 /// \brief Return the number of covered nodes in the matching.
565 /// This function returns the number of covered nodes in the matching.
567 /// \pre Either run() or start() must be called before using this function.
568 int matchingSize() const {
570 for (NodeIt n(_graph); n != INVALID; ++n) {
571 if ((*_matching)[n] != INVALID) {
578 /// \brief Returns a const reference to the matching map.
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.
584 /// \pre Either \ref run() or \ref init() must be called before
585 /// using this function.
586 const MatchingMap& matchingMap() const {
590 /// \brief Return \c true if the given edge is in the matching.
592 /// This function returns \c true if the given edge is in the
593 /// found matching. The result is scaled by \ref primalScale
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);
602 /// \brief Return the fractional matching arc (or edge) incident
603 /// to the given node.
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
611 /// \pre Either run() or start() must be called before using this function.
612 Arc matching(const Node& node) const {
613 return (*_matching)[node];
616 /// \brief Returns true if the node is in the barrier
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;
630 /// \ingroup matching
632 /// \brief Weighted fractional matching in general graphs
634 /// This class provides an efficient implementation of fractional
635 /// matching algorithm. The implementation uses priority queues and
636 /// provides \f$O(nm\log n)\f$ time complexity.
638 /// The maximum weighted fractional matching is a relaxation of the
639 /// maximum weighted matching problem where the odd set constraints
641 /// It can be formulated with the following linear program.
642 /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
643 /// \f[x_e \ge 0\quad \forall e\in E\f]
644 /// \f[\max \sum_{e\in E}x_ew_e\f]
645 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
646 /// \f$X\f$. The result must be the union of a matching with one
647 /// value edges and a set of odd length cycles with half value edges.
649 /// The algorithm calculates an optimal fractional matching and a
650 /// proof of the optimality. The solution of the dual problem can be
651 /// used to check the result of the algorithm. The dual linear
652 /// problem is the following.
653 /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
654 /// \f[y_u \ge 0 \quad \forall u \in V\f]
655 /// \f[\min \sum_{u \in V}y_u \f]
657 /// The algorithm can be executed with the run() function.
658 /// After it the matching (the primal solution) and the dual solution
659 /// can be obtained using the query functions.
661 /// The primal solution is multiplied by
662 /// \ref MaxWeightedFractionalMatching::primalScale "2".
663 /// If the value type is integer, then the dual
664 /// solution is scaled by
665 /// \ref MaxWeightedFractionalMatching::dualScale "4".
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>".
671 template <typename GR, typename WM>
673 template <typename GR,
674 typename WM = typename GR::template EdgeMap<int> >
676 class MaxWeightedFractionalMatching {
679 /// The graph type of the algorithm
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;
686 /// The type of the matching map
687 typedef typename Graph::template NodeMap<typename Graph::Arc>
690 /// \brief Scaling factor for primal solution
692 /// Scaling factor for primal solution.
693 static const int primalScale = 2;
695 /// \brief Scaling factor for dual solution
697 /// Scaling factor for dual solution. It is equal to 4 or 1
698 /// according to the value type.
699 static const int dualScale =
700 std::numeric_limits<Value>::is_integer ? 4 : 1;
704 TEMPLATE_GRAPH_TYPEDEFS(Graph);
706 typedef typename Graph::template NodeMap<Value> NodePotential;
709 const WeightMap& _weight;
711 MatchingMap* _matching;
712 NodePotential* _node_potential;
718 EVEN = -1, MATCHED = 0, ODD = 1
721 typedef typename Graph::template NodeMap<Status> StatusMap;
724 typedef typename Graph::template NodeMap<Arc> PredMap;
727 typedef ExtendFindEnum<IntNodeMap> TreeSet;
729 IntNodeMap *_tree_set_index;
732 IntNodeMap *_delta1_index;
733 BinHeap<Value, IntNodeMap> *_delta1;
735 IntNodeMap *_delta2_index;
736 BinHeap<Value, IntNodeMap> *_delta2;
738 IntEdgeMap *_delta3_index;
739 BinHeap<Value, IntEdgeMap> *_delta3;
743 void createStructures() {
744 _node_num = countNodes(_graph);
747 _matching = new MatchingMap(_graph);
749 if (!_node_potential) {
750 _node_potential = new NodePotential(_graph);
753 _status = new StatusMap(_graph);
756 _pred = new PredMap(_graph);
759 _tree_set_index = new IntNodeMap(_graph);
760 _tree_set = new TreeSet(*_tree_set_index);
763 _delta1_index = new IntNodeMap(_graph);
764 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
767 _delta2_index = new IntNodeMap(_graph);
768 _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
771 _delta3_index = new IntEdgeMap(_graph);
772 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
776 void destroyStructures() {
780 if (_node_potential) {
781 delete _node_potential;
790 delete _tree_set_index;
794 delete _delta1_index;
798 delete _delta2_index;
802 delete _delta3_index;
807 void matchedToEven(Node node, int tree) {
808 _tree_set->insert(node, tree);
809 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
810 _delta1->push(node, (*_node_potential)[node]);
812 if (_delta2->state(node) == _delta2->IN_HEAP) {
813 _delta2->erase(node);
816 for (InArcIt a(_graph, node); a != INVALID; ++a) {
817 Node v = _graph.source(a);
818 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
819 dualScale * _weight[a];
821 if (_allow_loops && _graph.direction(a)) {
822 _delta3->push(a, rw / 2);
824 } else if ((*_status)[v] == EVEN) {
825 _delta3->push(a, rw / 2);
826 } else if ((*_status)[v] == MATCHED) {
827 if (_delta2->state(v) != _delta2->IN_HEAP) {
829 _delta2->push(v, rw);
830 } else if ((*_delta2)[v] > rw) {
832 _delta2->decrease(v, rw);
838 void matchedToOdd(Node node, int tree) {
839 _tree_set->insert(node, tree);
840 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
842 if (_delta2->state(node) == _delta2->IN_HEAP) {
843 _delta2->erase(node);
847 void evenToMatched(Node node, int tree) {
848 _delta1->erase(node);
849 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
851 Value minrw = std::numeric_limits<Value>::max();
852 for (InArcIt a(_graph, node); a != INVALID; ++a) {
853 Node v = _graph.source(a);
854 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
855 dualScale * _weight[a];
858 if (_allow_loops && _graph.direction(a)) {
861 } else if ((*_status)[v] == EVEN) {
864 min = _graph.oppositeArc(a);
867 } else if ((*_status)[v] == MATCHED) {
868 if ((*_pred)[v] == a) {
870 Value minrwa = std::numeric_limits<Value>::max();
871 for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
872 Node va = _graph.target(aa);
873 if ((*_status)[va] != EVEN ||
874 _tree_set->find(va) == tree) continue;
875 Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
876 dualScale * _weight[aa];
882 if (mina != INVALID) {
884 _delta2->increase(v, minrwa);
886 _pred->set(v, INVALID);
892 if (min != INVALID) {
893 _pred->set(node, min);
894 _delta2->push(node, minrw);
896 _pred->set(node, INVALID);
900 void oddToMatched(Node node) {
901 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
903 Value minrw = std::numeric_limits<Value>::max();
904 for (InArcIt a(_graph, node); a != INVALID; ++a) {
905 Node v = _graph.source(a);
906 if ((*_status)[v] != EVEN) continue;
907 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
908 dualScale * _weight[a];
911 min = _graph.oppositeArc(a);
915 if (min != INVALID) {
916 _pred->set(node, min);
917 _delta2->push(node, minrw);
919 _pred->set(node, INVALID);
923 void alternatePath(Node even, int tree) {
926 _status->set(even, MATCHED);
927 evenToMatched(even, tree);
929 Arc prev = (*_matching)[even];
930 while (prev != INVALID) {
931 odd = _graph.target(prev);
932 even = _graph.target((*_pred)[odd]);
933 _matching->set(odd, (*_pred)[odd]);
934 _status->set(odd, MATCHED);
937 prev = (*_matching)[even];
938 _status->set(even, MATCHED);
939 _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
940 evenToMatched(even, tree);
944 void destroyTree(int tree) {
945 for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
946 if ((*_status)[n] == EVEN) {
947 _status->set(n, MATCHED);
948 evenToMatched(n, tree);
949 } else if ((*_status)[n] == ODD) {
950 _status->set(n, MATCHED);
954 _tree_set->eraseClass(tree);
958 void unmatchNode(const Node& node) {
959 int tree = _tree_set->find(node);
961 alternatePath(node, tree);
964 _matching->set(node, INVALID);
968 void augmentOnEdge(const Edge& edge) {
969 Node left = _graph.u(edge);
970 int left_tree = _tree_set->find(left);
972 alternatePath(left, left_tree);
973 destroyTree(left_tree);
974 _matching->set(left, _graph.direct(edge, true));
976 Node right = _graph.v(edge);
977 int right_tree = _tree_set->find(right);
979 alternatePath(right, right_tree);
980 destroyTree(right_tree);
981 _matching->set(right, _graph.direct(edge, false));
984 void augmentOnArc(const Arc& arc) {
985 Node left = _graph.source(arc);
986 _status->set(left, MATCHED);
987 _matching->set(left, arc);
988 _pred->set(left, arc);
990 Node right = _graph.target(arc);
991 int right_tree = _tree_set->find(right);
993 alternatePath(right, right_tree);
994 destroyTree(right_tree);
995 _matching->set(right, _graph.oppositeArc(arc));
998 void extendOnArc(const Arc& arc) {
999 Node base = _graph.target(arc);
1000 int tree = _tree_set->find(base);
1002 Node odd = _graph.source(arc);
1003 _tree_set->insert(odd, tree);
1004 _status->set(odd, ODD);
1005 matchedToOdd(odd, tree);
1006 _pred->set(odd, arc);
1008 Node even = _graph.target((*_matching)[odd]);
1009 _tree_set->insert(even, tree);
1010 _status->set(even, EVEN);
1011 matchedToEven(even, tree);
1014 void cycleOnEdge(const Edge& edge, int tree) {
1016 std::vector<Node> left_path, right_path;
1019 std::set<Node> left_set, right_set;
1020 Node left = _graph.u(edge);
1021 left_path.push_back(left);
1022 left_set.insert(left);
1024 Node right = _graph.v(edge);
1025 right_path.push_back(right);
1026 right_set.insert(right);
1030 if (left_set.find(right) != left_set.end()) {
1035 if ((*_matching)[left] == INVALID) break;
1037 left = _graph.target((*_matching)[left]);
1038 left_path.push_back(left);
1039 left = _graph.target((*_pred)[left]);
1040 left_path.push_back(left);
1042 left_set.insert(left);
1044 if (right_set.find(left) != right_set.end()) {
1049 if ((*_matching)[right] == INVALID) break;
1051 right = _graph.target((*_matching)[right]);
1052 right_path.push_back(right);
1053 right = _graph.target((*_pred)[right]);
1054 right_path.push_back(right);
1056 right_set.insert(right);
1060 if (nca == INVALID) {
1061 if ((*_matching)[left] == INVALID) {
1063 while (left_set.find(nca) == left_set.end()) {
1064 nca = _graph.target((*_matching)[nca]);
1065 right_path.push_back(nca);
1066 nca = _graph.target((*_pred)[nca]);
1067 right_path.push_back(nca);
1071 while (right_set.find(nca) == right_set.end()) {
1072 nca = _graph.target((*_matching)[nca]);
1073 left_path.push_back(nca);
1074 nca = _graph.target((*_pred)[nca]);
1075 left_path.push_back(nca);
1081 alternatePath(nca, tree);
1084 prev = _graph.direct(edge, true);
1085 for (int i = 0; left_path[i] != nca; i += 2) {
1086 _matching->set(left_path[i], prev);
1087 _status->set(left_path[i], MATCHED);
1088 evenToMatched(left_path[i], tree);
1090 prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1091 _status->set(left_path[i + 1], MATCHED);
1092 oddToMatched(left_path[i + 1]);
1094 _matching->set(nca, prev);
1096 for (int i = 0; right_path[i] != nca; i += 2) {
1097 _status->set(right_path[i], MATCHED);
1098 evenToMatched(right_path[i], tree);
1100 _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
1101 _status->set(right_path[i + 1], MATCHED);
1102 oddToMatched(right_path[i + 1]);
1108 void extractCycle(const Arc &arc) {
1109 Node left = _graph.source(arc);
1110 Node odd = _graph.target((*_matching)[left]);
1112 while (odd != left) {
1113 Node even = _graph.target((*_matching)[odd]);
1114 prev = (*_matching)[odd];
1115 odd = _graph.target((*_matching)[even]);
1116 _matching->set(even, _graph.oppositeArc(prev));
1118 _matching->set(left, arc);
1120 Node right = _graph.target(arc);
1121 int right_tree = _tree_set->find(right);
1122 alternatePath(right, right_tree);
1123 destroyTree(right_tree);
1124 _matching->set(right, _graph.oppositeArc(arc));
1129 /// \brief Constructor
1132 MaxWeightedFractionalMatching(const Graph& graph, const WeightMap& weight,
1133 bool allow_loops = true)
1134 : _graph(graph), _weight(weight), _matching(0),
1135 _node_potential(0), _node_num(0), _allow_loops(allow_loops),
1136 _status(0), _pred(0),
1137 _tree_set_index(0), _tree_set(0),
1139 _delta1_index(0), _delta1(0),
1140 _delta2_index(0), _delta2(0),
1141 _delta3_index(0), _delta3(0),
1145 ~MaxWeightedFractionalMatching() {
1146 destroyStructures();
1149 /// \name Execution Control
1150 /// The simplest way to execute the algorithm is to use the
1151 /// \ref run() member function.
1155 /// \brief Initialize the algorithm
1157 /// This function initializes the algorithm.
1161 for (NodeIt n(_graph); n != INVALID; ++n) {
1162 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1163 (*_delta2_index)[n] = _delta2->PRE_HEAP;
1165 for (EdgeIt e(_graph); e != INVALID; ++e) {
1166 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1169 for (NodeIt n(_graph); n != INVALID; ++n) {
1171 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1172 if (_graph.target(e) == n && !_allow_loops) continue;
1173 if ((dualScale * _weight[e]) / 2 > max) {
1174 max = (dualScale * _weight[e]) / 2;
1177 _node_potential->set(n, max);
1178 _delta1->push(n, max);
1180 _tree_set->insert(n);
1182 _matching->set(n, INVALID);
1183 _status->set(n, EVEN);
1186 for (EdgeIt e(_graph); e != INVALID; ++e) {
1187 Node left = _graph.u(e);
1188 Node right = _graph.v(e);
1189 if (left == right && !_allow_loops) continue;
1190 _delta3->push(e, ((*_node_potential)[left] +
1191 (*_node_potential)[right] -
1192 dualScale * _weight[e]) / 2);
1196 /// \brief Start the algorithm
1198 /// This function starts the algorithm.
1200 /// \pre \ref init() must be called before using this function.
1206 int unmatched = _node_num;
1207 while (unmatched > 0) {
1208 Value d1 = !_delta1->empty() ?
1209 _delta1->prio() : std::numeric_limits<Value>::max();
1211 Value d2 = !_delta2->empty() ?
1212 _delta2->prio() : std::numeric_limits<Value>::max();
1214 Value d3 = !_delta3->empty() ?
1215 _delta3->prio() : std::numeric_limits<Value>::max();
1217 _delta_sum = d3; OpType ot = D3;
1218 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1219 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1224 Node n = _delta1->top();
1231 Node n = _delta2->top();
1232 Arc a = (*_pred)[n];
1233 if ((*_matching)[n] == INVALID) {
1237 Node v = _graph.target((*_matching)[n]);
1238 if ((*_matching)[n] !=
1239 _graph.oppositeArc((*_matching)[v])) {
1249 Edge e = _delta3->top();
1251 Node left = _graph.u(e);
1252 Node right = _graph.v(e);
1254 int left_tree = _tree_set->find(left);
1255 int right_tree = _tree_set->find(right);
1257 if (left_tree == right_tree) {
1258 cycleOnEdge(e, left_tree);
1269 /// \brief Run the algorithm.
1271 /// This method runs the \c %MaxWeightedFractionalMatching algorithm.
1273 /// \note mwfm.run() is just a shortcut of the following code.
1285 /// \name Primal Solution
1286 /// Functions to get the primal solution, i.e. the maximum weighted
1288 /// Either \ref run() or \ref start() function should be called before
1293 /// \brief Return the weight of the matching.
1295 /// This function returns the weight of the found matching. This
1296 /// value is scaled by \ref primalScale "primal scale".
1298 /// \pre Either run() or start() must be called before using this function.
1299 Value matchingWeight() const {
1301 for (NodeIt n(_graph); n != INVALID; ++n) {
1302 if ((*_matching)[n] != INVALID) {
1303 sum += _weight[(*_matching)[n]];
1306 return sum * primalScale / 2;
1309 /// \brief Return the number of covered nodes in the matching.
1311 /// This function returns the number of covered nodes in the matching.
1313 /// \pre Either run() or start() must be called before using this function.
1314 int matchingSize() const {
1316 for (NodeIt n(_graph); n != INVALID; ++n) {
1317 if ((*_matching)[n] != INVALID) {
1324 /// \brief Return \c true if the given edge is in the matching.
1326 /// This function returns \c true if the given edge is in the
1327 /// found matching. The result is scaled by \ref primalScale
1330 /// \pre Either run() or start() must be called before using this function.
1331 int matching(const Edge& edge) const {
1332 return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
1333 + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
1336 /// \brief Return the fractional matching arc (or edge) incident
1337 /// to the given node.
1339 /// This function returns one of the fractional matching arc (or
1340 /// edge) incident to the given node in the found matching or \c
1341 /// INVALID if the node is not covered by the matching or if the
1342 /// node is on an odd length cycle then it is the successor edge
1345 /// \pre Either run() or start() must be called before using this function.
1346 Arc matching(const Node& node) const {
1347 return (*_matching)[node];
1350 /// \brief Return a const reference to the matching map.
1352 /// This function returns a const reference to a node map that stores
1353 /// the matching arc (or edge) incident to each node.
1354 const MatchingMap& matchingMap() const {
1360 /// \name Dual Solution
1361 /// Functions to get the dual solution.\n
1362 /// Either \ref run() or \ref start() function should be called before
1367 /// \brief Return the value of the dual solution.
1369 /// This function returns the value of the dual solution.
1370 /// It should be equal to the primal value scaled by \ref dualScale
1373 /// \pre Either run() or start() must be called before using this function.
1374 Value dualValue() const {
1376 for (NodeIt n(_graph); n != INVALID; ++n) {
1377 sum += nodeValue(n);
1382 /// \brief Return the dual value (potential) of the given node.
1384 /// This function returns the dual value (potential) of the given node.
1386 /// \pre Either run() or start() must be called before using this function.
1387 Value nodeValue(const Node& n) const {
1388 return (*_node_potential)[n];
1395 /// \ingroup matching
1397 /// \brief Weighted fractional perfect matching in general graphs
1399 /// This class provides an efficient implementation of fractional
1400 /// matching algorithm. The implementation uses priority queues and
1401 /// provides \f$O(nm\log n)\f$ time complexity.
1403 /// The maximum weighted fractional perfect matching is a relaxation
1404 /// of the maximum weighted perfect matching problem where the odd
1405 /// set constraints are omitted.
1406 /// It can be formulated with the following linear program.
1407 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1408 /// \f[x_e \ge 0\quad \forall e\in E\f]
1409 /// \f[\max \sum_{e\in E}x_ew_e\f]
1410 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1411 /// \f$X\f$. The result must be the union of a matching with one
1412 /// value edges and a set of odd length cycles with half value edges.
1414 /// The algorithm calculates an optimal fractional matching and a
1415 /// proof of the optimality. The solution of the dual problem can be
1416 /// used to check the result of the algorithm. The dual linear
1417 /// problem is the following.
1418 /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
1419 /// \f[\min \sum_{u \in V}y_u \f]
1421 /// The algorithm can be executed with the run() function.
1422 /// After it the matching (the primal solution) and the dual solution
1423 /// can be obtained using the query functions.
1425 /// The primal solution is multiplied by
1426 /// \ref MaxWeightedPerfectFractionalMatching::primalScale "2".
1427 /// If the value type is integer, then the dual
1428 /// solution is scaled by
1429 /// \ref MaxWeightedPerfectFractionalMatching::dualScale "4".
1431 /// \tparam GR The undirected graph type the algorithm runs on.
1432 /// \tparam WM The type edge weight map. The default type is
1433 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
1435 template <typename GR, typename WM>
1437 template <typename GR,
1438 typename WM = typename GR::template EdgeMap<int> >
1440 class MaxWeightedPerfectFractionalMatching {
1443 /// The graph type of the algorithm
1445 /// The type of the edge weight map
1446 typedef WM WeightMap;
1447 /// The value type of the edge weights
1448 typedef typename WeightMap::Value Value;
1450 /// The type of the matching map
1451 typedef typename Graph::template NodeMap<typename Graph::Arc>
1454 /// \brief Scaling factor for primal solution
1456 /// Scaling factor for primal solution.
1457 static const int primalScale = 2;
1459 /// \brief Scaling factor for dual solution
1461 /// Scaling factor for dual solution. It is equal to 4 or 1
1462 /// according to the value type.
1463 static const int dualScale =
1464 std::numeric_limits<Value>::is_integer ? 4 : 1;
1468 TEMPLATE_GRAPH_TYPEDEFS(Graph);
1470 typedef typename Graph::template NodeMap<Value> NodePotential;
1472 const Graph& _graph;
1473 const WeightMap& _weight;
1475 MatchingMap* _matching;
1476 NodePotential* _node_potential;
1482 EVEN = -1, MATCHED = 0, ODD = 1
1485 typedef typename Graph::template NodeMap<Status> StatusMap;
1488 typedef typename Graph::template NodeMap<Arc> PredMap;
1491 typedef ExtendFindEnum<IntNodeMap> TreeSet;
1493 IntNodeMap *_tree_set_index;
1496 IntNodeMap *_delta2_index;
1497 BinHeap<Value, IntNodeMap> *_delta2;
1499 IntEdgeMap *_delta3_index;
1500 BinHeap<Value, IntEdgeMap> *_delta3;
1504 void createStructures() {
1505 _node_num = countNodes(_graph);
1508 _matching = new MatchingMap(_graph);
1510 if (!_node_potential) {
1511 _node_potential = new NodePotential(_graph);
1514 _status = new StatusMap(_graph);
1517 _pred = new PredMap(_graph);
1520 _tree_set_index = new IntNodeMap(_graph);
1521 _tree_set = new TreeSet(*_tree_set_index);
1524 _delta2_index = new IntNodeMap(_graph);
1525 _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
1528 _delta3_index = new IntEdgeMap(_graph);
1529 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
1533 void destroyStructures() {
1537 if (_node_potential) {
1538 delete _node_potential;
1547 delete _tree_set_index;
1551 delete _delta2_index;
1555 delete _delta3_index;
1560 void matchedToEven(Node node, int tree) {
1561 _tree_set->insert(node, tree);
1562 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
1564 if (_delta2->state(node) == _delta2->IN_HEAP) {
1565 _delta2->erase(node);
1568 for (InArcIt a(_graph, node); a != INVALID; ++a) {
1569 Node v = _graph.source(a);
1570 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1571 dualScale * _weight[a];
1573 if (_allow_loops && _graph.direction(a)) {
1574 _delta3->push(a, rw / 2);
1576 } else if ((*_status)[v] == EVEN) {
1577 _delta3->push(a, rw / 2);
1578 } else if ((*_status)[v] == MATCHED) {
1579 if (_delta2->state(v) != _delta2->IN_HEAP) {
1581 _delta2->push(v, rw);
1582 } else if ((*_delta2)[v] > rw) {
1584 _delta2->decrease(v, rw);
1590 void matchedToOdd(Node node, int tree) {
1591 _tree_set->insert(node, tree);
1592 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
1594 if (_delta2->state(node) == _delta2->IN_HEAP) {
1595 _delta2->erase(node);
1599 void evenToMatched(Node node, int tree) {
1600 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
1602 Value minrw = std::numeric_limits<Value>::max();
1603 for (InArcIt a(_graph, node); a != INVALID; ++a) {
1604 Node v = _graph.source(a);
1605 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1606 dualScale * _weight[a];
1609 if (_allow_loops && _graph.direction(a)) {
1612 } else if ((*_status)[v] == EVEN) {
1615 min = _graph.oppositeArc(a);
1618 } else if ((*_status)[v] == MATCHED) {
1619 if ((*_pred)[v] == a) {
1621 Value minrwa = std::numeric_limits<Value>::max();
1622 for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
1623 Node va = _graph.target(aa);
1624 if ((*_status)[va] != EVEN ||
1625 _tree_set->find(va) == tree) continue;
1626 Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
1627 dualScale * _weight[aa];
1633 if (mina != INVALID) {
1634 _pred->set(v, mina);
1635 _delta2->increase(v, minrwa);
1637 _pred->set(v, INVALID);
1643 if (min != INVALID) {
1644 _pred->set(node, min);
1645 _delta2->push(node, minrw);
1647 _pred->set(node, INVALID);
1651 void oddToMatched(Node node) {
1652 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
1654 Value minrw = std::numeric_limits<Value>::max();
1655 for (InArcIt a(_graph, node); a != INVALID; ++a) {
1656 Node v = _graph.source(a);
1657 if ((*_status)[v] != EVEN) continue;
1658 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1659 dualScale * _weight[a];
1662 min = _graph.oppositeArc(a);
1666 if (min != INVALID) {
1667 _pred->set(node, min);
1668 _delta2->push(node, minrw);
1670 _pred->set(node, INVALID);
1674 void alternatePath(Node even, int tree) {
1677 _status->set(even, MATCHED);
1678 evenToMatched(even, tree);
1680 Arc prev = (*_matching)[even];
1681 while (prev != INVALID) {
1682 odd = _graph.target(prev);
1683 even = _graph.target((*_pred)[odd]);
1684 _matching->set(odd, (*_pred)[odd]);
1685 _status->set(odd, MATCHED);
1688 prev = (*_matching)[even];
1689 _status->set(even, MATCHED);
1690 _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
1691 evenToMatched(even, tree);
1695 void destroyTree(int tree) {
1696 for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
1697 if ((*_status)[n] == EVEN) {
1698 _status->set(n, MATCHED);
1699 evenToMatched(n, tree);
1700 } else if ((*_status)[n] == ODD) {
1701 _status->set(n, MATCHED);
1705 _tree_set->eraseClass(tree);
1708 void augmentOnEdge(const Edge& edge) {
1709 Node left = _graph.u(edge);
1710 int left_tree = _tree_set->find(left);
1712 alternatePath(left, left_tree);
1713 destroyTree(left_tree);
1714 _matching->set(left, _graph.direct(edge, true));
1716 Node right = _graph.v(edge);
1717 int right_tree = _tree_set->find(right);
1719 alternatePath(right, right_tree);
1720 destroyTree(right_tree);
1721 _matching->set(right, _graph.direct(edge, false));
1724 void augmentOnArc(const Arc& arc) {
1725 Node left = _graph.source(arc);
1726 _status->set(left, MATCHED);
1727 _matching->set(left, arc);
1728 _pred->set(left, arc);
1730 Node right = _graph.target(arc);
1731 int right_tree = _tree_set->find(right);
1733 alternatePath(right, right_tree);
1734 destroyTree(right_tree);
1735 _matching->set(right, _graph.oppositeArc(arc));
1738 void extendOnArc(const Arc& arc) {
1739 Node base = _graph.target(arc);
1740 int tree = _tree_set->find(base);
1742 Node odd = _graph.source(arc);
1743 _tree_set->insert(odd, tree);
1744 _status->set(odd, ODD);
1745 matchedToOdd(odd, tree);
1746 _pred->set(odd, arc);
1748 Node even = _graph.target((*_matching)[odd]);
1749 _tree_set->insert(even, tree);
1750 _status->set(even, EVEN);
1751 matchedToEven(even, tree);
1754 void cycleOnEdge(const Edge& edge, int tree) {
1756 std::vector<Node> left_path, right_path;
1759 std::set<Node> left_set, right_set;
1760 Node left = _graph.u(edge);
1761 left_path.push_back(left);
1762 left_set.insert(left);
1764 Node right = _graph.v(edge);
1765 right_path.push_back(right);
1766 right_set.insert(right);
1770 if (left_set.find(right) != left_set.end()) {
1775 if ((*_matching)[left] == INVALID) break;
1777 left = _graph.target((*_matching)[left]);
1778 left_path.push_back(left);
1779 left = _graph.target((*_pred)[left]);
1780 left_path.push_back(left);
1782 left_set.insert(left);
1784 if (right_set.find(left) != right_set.end()) {
1789 if ((*_matching)[right] == INVALID) break;
1791 right = _graph.target((*_matching)[right]);
1792 right_path.push_back(right);
1793 right = _graph.target((*_pred)[right]);
1794 right_path.push_back(right);
1796 right_set.insert(right);
1800 if (nca == INVALID) {
1801 if ((*_matching)[left] == INVALID) {
1803 while (left_set.find(nca) == left_set.end()) {
1804 nca = _graph.target((*_matching)[nca]);
1805 right_path.push_back(nca);
1806 nca = _graph.target((*_pred)[nca]);
1807 right_path.push_back(nca);
1811 while (right_set.find(nca) == right_set.end()) {
1812 nca = _graph.target((*_matching)[nca]);
1813 left_path.push_back(nca);
1814 nca = _graph.target((*_pred)[nca]);
1815 left_path.push_back(nca);
1821 alternatePath(nca, tree);
1824 prev = _graph.direct(edge, true);
1825 for (int i = 0; left_path[i] != nca; i += 2) {
1826 _matching->set(left_path[i], prev);
1827 _status->set(left_path[i], MATCHED);
1828 evenToMatched(left_path[i], tree);
1830 prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1831 _status->set(left_path[i + 1], MATCHED);
1832 oddToMatched(left_path[i + 1]);
1834 _matching->set(nca, prev);
1836 for (int i = 0; right_path[i] != nca; i += 2) {
1837 _status->set(right_path[i], MATCHED);
1838 evenToMatched(right_path[i], tree);
1840 _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
1841 _status->set(right_path[i + 1], MATCHED);
1842 oddToMatched(right_path[i + 1]);
1848 void extractCycle(const Arc &arc) {
1849 Node left = _graph.source(arc);
1850 Node odd = _graph.target((*_matching)[left]);
1852 while (odd != left) {
1853 Node even = _graph.target((*_matching)[odd]);
1854 prev = (*_matching)[odd];
1855 odd = _graph.target((*_matching)[even]);
1856 _matching->set(even, _graph.oppositeArc(prev));
1858 _matching->set(left, arc);
1860 Node right = _graph.target(arc);
1861 int right_tree = _tree_set->find(right);
1862 alternatePath(right, right_tree);
1863 destroyTree(right_tree);
1864 _matching->set(right, _graph.oppositeArc(arc));
1869 /// \brief Constructor
1872 MaxWeightedPerfectFractionalMatching(const Graph& graph,
1873 const WeightMap& weight,
1874 bool allow_loops = true)
1875 : _graph(graph), _weight(weight), _matching(0),
1876 _node_potential(0), _node_num(0), _allow_loops(allow_loops),
1877 _status(0), _pred(0),
1878 _tree_set_index(0), _tree_set(0),
1880 _delta2_index(0), _delta2(0),
1881 _delta3_index(0), _delta3(0),
1885 ~MaxWeightedPerfectFractionalMatching() {
1886 destroyStructures();
1889 /// \name Execution Control
1890 /// The simplest way to execute the algorithm is to use the
1891 /// \ref run() member function.
1895 /// \brief Initialize the algorithm
1897 /// This function initializes the algorithm.
1901 for (NodeIt n(_graph); n != INVALID; ++n) {
1902 (*_delta2_index)[n] = _delta2->PRE_HEAP;
1904 for (EdgeIt e(_graph); e != INVALID; ++e) {
1905 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1908 for (NodeIt n(_graph); n != INVALID; ++n) {
1909 Value max = - std::numeric_limits<Value>::max();
1910 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1911 if (_graph.target(e) == n && !_allow_loops) continue;
1912 if ((dualScale * _weight[e]) / 2 > max) {
1913 max = (dualScale * _weight[e]) / 2;
1916 _node_potential->set(n, max);
1918 _tree_set->insert(n);
1920 _matching->set(n, INVALID);
1921 _status->set(n, EVEN);
1924 for (EdgeIt e(_graph); e != INVALID; ++e) {
1925 Node left = _graph.u(e);
1926 Node right = _graph.v(e);
1927 if (left == right && !_allow_loops) continue;
1928 _delta3->push(e, ((*_node_potential)[left] +
1929 (*_node_potential)[right] -
1930 dualScale * _weight[e]) / 2);
1934 /// \brief Start the algorithm
1936 /// This function starts the algorithm.
1938 /// \pre \ref init() must be called before using this function.
1944 int unmatched = _node_num;
1945 while (unmatched > 0) {
1946 Value d2 = !_delta2->empty() ?
1947 _delta2->prio() : std::numeric_limits<Value>::max();
1949 Value d3 = !_delta3->empty() ?
1950 _delta3->prio() : std::numeric_limits<Value>::max();
1952 _delta_sum = d3; OpType ot = D3;
1953 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1955 if (_delta_sum == std::numeric_limits<Value>::max()) {
1962 Node n = _delta2->top();
1963 Arc a = (*_pred)[n];
1964 if ((*_matching)[n] == INVALID) {
1968 Node v = _graph.target((*_matching)[n]);
1969 if ((*_matching)[n] !=
1970 _graph.oppositeArc((*_matching)[v])) {
1980 Edge e = _delta3->top();
1982 Node left = _graph.u(e);
1983 Node right = _graph.v(e);
1985 int left_tree = _tree_set->find(left);
1986 int right_tree = _tree_set->find(right);
1988 if (left_tree == right_tree) {
1989 cycleOnEdge(e, left_tree);
2001 /// \brief Run the algorithm.
2003 /// This method runs the \c %MaxWeightedPerfectFractionalMatching
2006 /// \note mwfm.run() is just a shortcut of the following code.
2018 /// \name Primal Solution
2019 /// Functions to get the primal solution, i.e. the maximum weighted
2021 /// Either \ref run() or \ref start() function should be called before
2026 /// \brief Return the weight of the matching.
2028 /// This function returns the weight of the found matching. This
2029 /// value is scaled by \ref primalScale "primal scale".
2031 /// \pre Either run() or start() must be called before using this function.
2032 Value matchingWeight() const {
2034 for (NodeIt n(_graph); n != INVALID; ++n) {
2035 if ((*_matching)[n] != INVALID) {
2036 sum += _weight[(*_matching)[n]];
2039 return sum * primalScale / 2;
2042 /// \brief Return the number of covered nodes in the matching.
2044 /// This function returns the number of covered nodes in the matching.
2046 /// \pre Either run() or start() must be called before using this function.
2047 int matchingSize() const {
2049 for (NodeIt n(_graph); n != INVALID; ++n) {
2050 if ((*_matching)[n] != INVALID) {
2057 /// \brief Return \c true if the given edge is in the matching.
2059 /// This function returns \c true if the given edge is in the
2060 /// found matching. The result is scaled by \ref primalScale
2063 /// \pre Either run() or start() must be called before using this function.
2064 int matching(const Edge& edge) const {
2065 return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
2066 + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
2069 /// \brief Return the fractional matching arc (or edge) incident
2070 /// to the given node.
2072 /// This function returns one of the fractional matching arc (or
2073 /// edge) incident to the given node in the found matching or \c
2074 /// INVALID if the node is not covered by the matching or if the
2075 /// node is on an odd length cycle then it is the successor edge
2078 /// \pre Either run() or start() must be called before using this function.
2079 Arc matching(const Node& node) const {
2080 return (*_matching)[node];
2083 /// \brief Return a const reference to the matching map.
2085 /// This function returns a const reference to a node map that stores
2086 /// the matching arc (or edge) incident to each node.
2087 const MatchingMap& matchingMap() const {
2093 /// \name Dual Solution
2094 /// Functions to get the dual solution.\n
2095 /// Either \ref run() or \ref start() function should be called before
2100 /// \brief Return the value of the dual solution.
2102 /// This function returns the value of the dual solution.
2103 /// It should be equal to the primal value scaled by \ref dualScale
2106 /// \pre Either run() or start() must be called before using this function.
2107 Value dualValue() const {
2109 for (NodeIt n(_graph); n != INVALID; ++n) {
2110 sum += nodeValue(n);
2115 /// \brief Return the dual value (potential) of the given node.
2117 /// This function returns the dual value (potential) of the given node.
2119 /// \pre Either run() or start() must be called before using this function.
2120 Value nodeValue(const Node& n) const {
2121 return (*_node_potential)[n];
2128 } //END OF NAMESPACE LEMON
2130 #endif //LEMON_FRACTIONAL_MATCHING_H