Fix wrong iteration in ListGraph snapshot, part II. (#598)
1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2013
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 lemon::MaxFractionalMatchingDefaultTraits
127 /// "traits 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;
1174 for (NodeIt n(_graph); n != INVALID; ++n) {
1176 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1177 if (_graph.target(e) == n && !_allow_loops) continue;
1178 if ((dualScale * _weight[e]) / 2 > max) {
1179 max = (dualScale * _weight[e]) / 2;
1182 _node_potential->set(n, max);
1183 _delta1->push(n, max);
1185 _tree_set->insert(n);
1187 _matching->set(n, INVALID);
1188 _status->set(n, EVEN);
1191 for (EdgeIt e(_graph); e != INVALID; ++e) {
1192 Node left = _graph.u(e);
1193 Node right = _graph.v(e);
1194 if (left == right && !_allow_loops) continue;
1195 _delta3->push(e, ((*_node_potential)[left] +
1196 (*_node_potential)[right] -
1197 dualScale * _weight[e]) / 2);
1201 /// \brief Start the algorithm
1203 /// This function starts the algorithm.
1205 /// \pre \ref init() must be called before using this function.
1211 int unmatched = _node_num;
1212 while (unmatched > 0) {
1213 Value d1 = !_delta1->empty() ?
1214 _delta1->prio() : std::numeric_limits<Value>::max();
1216 Value d2 = !_delta2->empty() ?
1217 _delta2->prio() : std::numeric_limits<Value>::max();
1219 Value d3 = !_delta3->empty() ?
1220 _delta3->prio() : std::numeric_limits<Value>::max();
1222 _delta_sum = d3; OpType ot = D3;
1223 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1224 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1229 Node n = _delta1->top();
1236 Node n = _delta2->top();
1237 Arc a = (*_pred)[n];
1238 if ((*_matching)[n] == INVALID) {
1242 Node v = _graph.target((*_matching)[n]);
1243 if ((*_matching)[n] !=
1244 _graph.oppositeArc((*_matching)[v])) {
1254 Edge e = _delta3->top();
1256 Node left = _graph.u(e);
1257 Node right = _graph.v(e);
1259 int left_tree = _tree_set->find(left);
1260 int right_tree = _tree_set->find(right);
1262 if (left_tree == right_tree) {
1263 cycleOnEdge(e, left_tree);
1274 /// \brief Run the algorithm.
1276 /// This method runs the \c %MaxWeightedFractionalMatching algorithm.
1278 /// \note mwfm.run() is just a shortcut of the following code.
1290 /// \name Primal Solution
1291 /// Functions to get the primal solution, i.e. the maximum weighted
1293 /// Either \ref run() or \ref start() function should be called before
1298 /// \brief Return the weight of the matching.
1300 /// This function returns the weight of the found matching. This
1301 /// value is scaled by \ref primalScale "primal scale".
1303 /// \pre Either run() or start() must be called before using this function.
1304 Value matchingWeight() const {
1306 for (NodeIt n(_graph); n != INVALID; ++n) {
1307 if ((*_matching)[n] != INVALID) {
1308 sum += _weight[(*_matching)[n]];
1311 return sum * primalScale / 2;
1314 /// \brief Return the number of covered nodes in the matching.
1316 /// This function returns the number of covered nodes in the matching.
1318 /// \pre Either run() or start() must be called before using this function.
1319 int matchingSize() const {
1321 for (NodeIt n(_graph); n != INVALID; ++n) {
1322 if ((*_matching)[n] != INVALID) {
1329 /// \brief Return \c true if the given edge is in the matching.
1331 /// This function returns \c true if the given edge is in the
1332 /// found matching. The result is scaled by \ref primalScale
1335 /// \pre Either run() or start() must be called before using this function.
1336 int matching(const Edge& edge) const {
1337 return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
1338 + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
1341 /// \brief Return the fractional matching arc (or edge) incident
1342 /// to the given node.
1344 /// This function returns one of the fractional matching arc (or
1345 /// edge) incident to the given node in the found matching or \c
1346 /// INVALID if the node is not covered by the matching or if the
1347 /// node is on an odd length cycle then it is the successor edge
1350 /// \pre Either run() or start() must be called before using this function.
1351 Arc matching(const Node& node) const {
1352 return (*_matching)[node];
1355 /// \brief Return a const reference to the matching map.
1357 /// This function returns a const reference to a node map that stores
1358 /// the matching arc (or edge) incident to each node.
1359 const MatchingMap& matchingMap() const {
1365 /// \name Dual Solution
1366 /// Functions to get the dual solution.\n
1367 /// Either \ref run() or \ref start() function should be called before
1372 /// \brief Return the value of the dual solution.
1374 /// This function returns the value of the dual solution.
1375 /// It should be equal to the primal value scaled by \ref dualScale
1378 /// \pre Either run() or start() must be called before using this function.
1379 Value dualValue() const {
1381 for (NodeIt n(_graph); n != INVALID; ++n) {
1382 sum += nodeValue(n);
1387 /// \brief Return the dual value (potential) of the given node.
1389 /// This function returns the dual value (potential) of the given node.
1391 /// \pre Either run() or start() must be called before using this function.
1392 Value nodeValue(const Node& n) const {
1393 return (*_node_potential)[n];
1400 /// \ingroup matching
1402 /// \brief Weighted fractional perfect matching in general graphs
1404 /// This class provides an efficient implementation of fractional
1405 /// matching algorithm. The implementation uses priority queues and
1406 /// provides \f$O(nm\log n)\f$ time complexity.
1408 /// The maximum weighted fractional perfect matching is a relaxation
1409 /// of the maximum weighted perfect matching problem where the odd
1410 /// set constraints are omitted.
1411 /// It can be formulated with the following linear program.
1412 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1413 /// \f[x_e \ge 0\quad \forall e\in E\f]
1414 /// \f[\max \sum_{e\in E}x_ew_e\f]
1415 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1416 /// \f$X\f$. The result must be the union of a matching with one
1417 /// value edges and a set of odd length cycles with half value edges.
1419 /// The algorithm calculates an optimal fractional matching and a
1420 /// proof of the optimality. The solution of the dual problem can be
1421 /// used to check the result of the algorithm. The dual linear
1422 /// problem is the following.
1423 /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
1424 /// \f[\min \sum_{u \in V}y_u \f]
1426 /// The algorithm can be executed with the run() function.
1427 /// After it the matching (the primal solution) and the dual solution
1428 /// can be obtained using the query functions.
1430 /// The primal solution is multiplied by
1431 /// \ref MaxWeightedPerfectFractionalMatching::primalScale "2".
1432 /// If the value type is integer, then the dual
1433 /// solution is scaled by
1434 /// \ref MaxWeightedPerfectFractionalMatching::dualScale "4".
1436 /// \tparam GR The undirected graph type the algorithm runs on.
1437 /// \tparam WM The type edge weight map. The default type is
1438 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
1440 template <typename GR, typename WM>
1442 template <typename GR,
1443 typename WM = typename GR::template EdgeMap<int> >
1445 class MaxWeightedPerfectFractionalMatching {
1448 /// The graph type of the algorithm
1450 /// The type of the edge weight map
1451 typedef WM WeightMap;
1452 /// The value type of the edge weights
1453 typedef typename WeightMap::Value Value;
1455 /// The type of the matching map
1456 typedef typename Graph::template NodeMap<typename Graph::Arc>
1459 /// \brief Scaling factor for primal solution
1461 /// Scaling factor for primal solution.
1462 static const int primalScale = 2;
1464 /// \brief Scaling factor for dual solution
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;
1473 TEMPLATE_GRAPH_TYPEDEFS(Graph);
1475 typedef typename Graph::template NodeMap<Value> NodePotential;
1477 const Graph& _graph;
1478 const WeightMap& _weight;
1480 MatchingMap* _matching;
1481 NodePotential* _node_potential;
1487 EVEN = -1, MATCHED = 0, ODD = 1
1490 typedef typename Graph::template NodeMap<Status> StatusMap;
1493 typedef typename Graph::template NodeMap<Arc> PredMap;
1496 typedef ExtendFindEnum<IntNodeMap> TreeSet;
1498 IntNodeMap *_tree_set_index;
1501 IntNodeMap *_delta2_index;
1502 BinHeap<Value, IntNodeMap> *_delta2;
1504 IntEdgeMap *_delta3_index;
1505 BinHeap<Value, IntEdgeMap> *_delta3;
1509 void createStructures() {
1510 _node_num = countNodes(_graph);
1513 _matching = new MatchingMap(_graph);
1515 if (!_node_potential) {
1516 _node_potential = new NodePotential(_graph);
1519 _status = new StatusMap(_graph);
1522 _pred = new PredMap(_graph);
1525 _tree_set_index = new IntNodeMap(_graph);
1526 _tree_set = new TreeSet(*_tree_set_index);
1529 _delta2_index = new IntNodeMap(_graph);
1530 _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
1533 _delta3_index = new IntEdgeMap(_graph);
1534 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
1538 void destroyStructures() {
1542 if (_node_potential) {
1543 delete _node_potential;
1552 delete _tree_set_index;
1556 delete _delta2_index;
1560 delete _delta3_index;
1565 void matchedToEven(Node node, int tree) {
1566 _tree_set->insert(node, tree);
1567 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
1569 if (_delta2->state(node) == _delta2->IN_HEAP) {
1570 _delta2->erase(node);
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];
1578 if (_allow_loops && _graph.direction(a)) {
1579 _delta3->push(a, rw / 2);
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) {
1586 _delta2->push(v, rw);
1587 } else if ((*_delta2)[v] > rw) {
1589 _delta2->decrease(v, rw);
1595 void matchedToOdd(Node node, int tree) {
1596 _tree_set->insert(node, tree);
1597 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
1599 if (_delta2->state(node) == _delta2->IN_HEAP) {
1600 _delta2->erase(node);
1604 void evenToMatched(Node node, int tree) {
1605 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
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];
1614 if (_allow_loops && _graph.direction(a)) {
1617 } else if ((*_status)[v] == EVEN) {
1620 min = _graph.oppositeArc(a);
1623 } else if ((*_status)[v] == MATCHED) {
1624 if ((*_pred)[v] == a) {
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];
1638 if (mina != INVALID) {
1639 _pred->set(v, mina);
1640 _delta2->increase(v, minrwa);
1642 _pred->set(v, INVALID);
1648 if (min != INVALID) {
1649 _pred->set(node, min);
1650 _delta2->push(node, minrw);
1652 _pred->set(node, INVALID);
1656 void oddToMatched(Node node) {
1657 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
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];
1667 min = _graph.oppositeArc(a);
1671 if (min != INVALID) {
1672 _pred->set(node, min);
1673 _delta2->push(node, minrw);
1675 _pred->set(node, INVALID);
1679 void alternatePath(Node even, int tree) {
1682 _status->set(even, MATCHED);
1683 evenToMatched(even, tree);
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);
1693 prev = (*_matching)[even];
1694 _status->set(even, MATCHED);
1695 _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
1696 evenToMatched(even, tree);
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);
1710 _tree_set->eraseClass(tree);
1713 void augmentOnEdge(const Edge& edge) {
1714 Node left = _graph.u(edge);
1715 int left_tree = _tree_set->find(left);
1717 alternatePath(left, left_tree);
1718 destroyTree(left_tree);
1719 _matching->set(left, _graph.direct(edge, true));
1721 Node right = _graph.v(edge);
1722 int right_tree = _tree_set->find(right);
1724 alternatePath(right, right_tree);
1725 destroyTree(right_tree);
1726 _matching->set(right, _graph.direct(edge, false));
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);
1735 Node right = _graph.target(arc);
1736 int right_tree = _tree_set->find(right);
1738 alternatePath(right, right_tree);
1739 destroyTree(right_tree);
1740 _matching->set(right, _graph.oppositeArc(arc));
1743 void extendOnArc(const Arc& arc) {
1744 Node base = _graph.target(arc);
1745 int tree = _tree_set->find(base);
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);
1753 Node even = _graph.target((*_matching)[odd]);
1754 _tree_set->insert(even, tree);
1755 _status->set(even, EVEN);
1756 matchedToEven(even, tree);
1759 void cycleOnEdge(const Edge& edge, int tree) {
1761 std::vector<Node> left_path, right_path;
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);
1769 Node right = _graph.v(edge);
1770 right_path.push_back(right);
1771 right_set.insert(right);
1775 if (left_set.find(right) != left_set.end()) {
1780 if ((*_matching)[left] == INVALID) break;
1782 left = _graph.target((*_matching)[left]);
1783 left_path.push_back(left);
1784 left = _graph.target((*_pred)[left]);
1785 left_path.push_back(left);
1787 left_set.insert(left);
1789 if (right_set.find(left) != right_set.end()) {
1794 if ((*_matching)[right] == INVALID) break;
1796 right = _graph.target((*_matching)[right]);
1797 right_path.push_back(right);
1798 right = _graph.target((*_pred)[right]);
1799 right_path.push_back(right);
1801 right_set.insert(right);
1805 if (nca == INVALID) {
1806 if ((*_matching)[left] == INVALID) {
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);
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);
1826 alternatePath(nca, tree);
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);
1835 prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1836 _status->set(left_path[i + 1], MATCHED);
1837 oddToMatched(left_path[i + 1]);
1839 _matching->set(nca, prev);
1841 for (int i = 0; right_path[i] != nca; i += 2) {
1842 _status->set(right_path[i], MATCHED);
1843 evenToMatched(right_path[i], tree);
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]);
1853 void extractCycle(const Arc &arc) {
1854 Node left = _graph.source(arc);
1855 Node odd = _graph.target((*_matching)[left]);
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));
1863 _matching->set(left, arc);
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));
1874 /// \brief 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),
1885 _delta2_index(0), _delta2(0),
1886 _delta3_index(0), _delta3(0),
1890 ~MaxWeightedPerfectFractionalMatching() {
1891 destroyStructures();
1894 /// \name Execution Control
1895 /// The simplest way to execute the algorithm is to use the
1896 /// \ref run() member function.
1900 /// \brief Initialize the algorithm
1902 /// This function initializes the algorithm.
1906 for (NodeIt n(_graph); n != INVALID; ++n) {
1907 (*_delta2_index)[n] = _delta2->PRE_HEAP;
1909 for (EdgeIt e(_graph); e != INVALID; ++e) {
1910 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1917 for (NodeIt n(_graph); n != INVALID; ++n) {
1918 Value max = - std::numeric_limits<Value>::max();
1919 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1920 if (_graph.target(e) == n && !_allow_loops) continue;
1921 if ((dualScale * _weight[e]) / 2 > max) {
1922 max = (dualScale * _weight[e]) / 2;
1925 _node_potential->set(n, max);
1927 _tree_set->insert(n);
1929 _matching->set(n, INVALID);
1930 _status->set(n, EVEN);
1933 for (EdgeIt e(_graph); e != INVALID; ++e) {
1934 Node left = _graph.u(e);
1935 Node right = _graph.v(e);
1936 if (left == right && !_allow_loops) continue;
1937 _delta3->push(e, ((*_node_potential)[left] +
1938 (*_node_potential)[right] -
1939 dualScale * _weight[e]) / 2);
1943 /// \brief Start the algorithm
1945 /// This function starts the algorithm.
1947 /// \pre \ref init() must be called before using this function.
1953 int unmatched = _node_num;
1954 while (unmatched > 0) {
1955 Value d2 = !_delta2->empty() ?
1956 _delta2->prio() : std::numeric_limits<Value>::max();
1958 Value d3 = !_delta3->empty() ?
1959 _delta3->prio() : std::numeric_limits<Value>::max();
1961 _delta_sum = d3; OpType ot = D3;
1962 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1964 if (_delta_sum == std::numeric_limits<Value>::max()) {
1971 Node n = _delta2->top();
1972 Arc a = (*_pred)[n];
1973 if ((*_matching)[n] == INVALID) {
1977 Node v = _graph.target((*_matching)[n]);
1978 if ((*_matching)[n] !=
1979 _graph.oppositeArc((*_matching)[v])) {
1989 Edge e = _delta3->top();
1991 Node left = _graph.u(e);
1992 Node right = _graph.v(e);
1994 int left_tree = _tree_set->find(left);
1995 int right_tree = _tree_set->find(right);
1997 if (left_tree == right_tree) {
1998 cycleOnEdge(e, left_tree);
2010 /// \brief Run the algorithm.
2012 /// This method runs the \c %MaxWeightedPerfectFractionalMatching
2015 /// \note mwfm.run() is just a shortcut of the following code.
2027 /// \name Primal Solution
2028 /// Functions to get the primal solution, i.e. the maximum weighted
2030 /// Either \ref run() or \ref start() function should be called before
2035 /// \brief Return the weight of the matching.
2037 /// This function returns the weight of the found matching. This
2038 /// value is scaled by \ref primalScale "primal scale".
2040 /// \pre Either run() or start() must be called before using this function.
2041 Value matchingWeight() const {
2043 for (NodeIt n(_graph); n != INVALID; ++n) {
2044 if ((*_matching)[n] != INVALID) {
2045 sum += _weight[(*_matching)[n]];
2048 return sum * primalScale / 2;
2051 /// \brief Return the number of covered nodes in the matching.
2053 /// This function returns the number of covered nodes in the matching.
2055 /// \pre Either run() or start() must be called before using this function.
2056 int matchingSize() const {
2058 for (NodeIt n(_graph); n != INVALID; ++n) {
2059 if ((*_matching)[n] != INVALID) {
2066 /// \brief Return \c true if the given edge is in the matching.
2068 /// This function returns \c true if the given edge is in the
2069 /// found matching. The result is scaled by \ref primalScale
2072 /// \pre Either run() or start() must be called before using this function.
2073 int matching(const Edge& edge) const {
2074 return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
2075 + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
2078 /// \brief Return the fractional matching arc (or edge) incident
2079 /// to the given node.
2081 /// This function returns one of the fractional matching arc (or
2082 /// edge) incident to the given node in the found matching or \c
2083 /// INVALID if the node is not covered by the matching or if the
2084 /// node is on an odd length cycle then it is the successor edge
2087 /// \pre Either run() or start() must be called before using this function.
2088 Arc matching(const Node& node) const {
2089 return (*_matching)[node];
2092 /// \brief Return a const reference to the matching map.
2094 /// This function returns a const reference to a node map that stores
2095 /// the matching arc (or edge) incident to each node.
2096 const MatchingMap& matchingMap() const {
2102 /// \name Dual Solution
2103 /// Functions to get the dual solution.\n
2104 /// Either \ref run() or \ref start() function should be called before
2109 /// \brief Return the value of the dual solution.
2111 /// This function returns the value of the dual solution.
2112 /// It should be equal to the primal value scaled by \ref dualScale
2115 /// \pre Either run() or start() must be called before using this function.
2116 Value dualValue() const {
2118 for (NodeIt n(_graph); n != INVALID; ++n) {
2119 sum += nodeValue(n);
2124 /// \brief Return the dual value (potential) of the given node.
2126 /// This function returns the dual value (potential) of the given node.
2128 /// \pre Either run() or start() must be called before using this function.
2129 Value nodeValue(const Node& n) const {
2130 return (*_node_potential)[n];
2137 } //END OF NAMESPACE LEMON
2139 #endif //LEMON_FRACTIONAL_MATCHING_H