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 MaxWeightedMatching::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 is based on extensive use
636 /// of priority queues and provides \f$O(nm\log n)\f$ time
639 /// The maximum weighted fractional matching is a relaxation of the
640 /// maximum weighted matching problem where the odd set constraints
642 /// It can be formulated with the following linear program.
643 /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
644 /// \f[x_e \ge 0\quad \forall e\in E\f]
645 /// \f[\max \sum_{e\in E}x_ew_e\f]
646 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
647 /// \f$X\f$. The result must be the union of a matching with one
648 /// value edges and a set of odd length cycles with half value edges.
650 /// The algorithm calculates an optimal fractional matching and a
651 /// proof of the optimality. The solution of the dual problem can be
652 /// used to check the result of the algorithm. The dual linear
653 /// problem is the following.
654 /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
655 /// \f[y_u \ge 0 \quad \forall u \in V\f]
656 /// \f[\min \sum_{u \in V}y_u \f] ///
658 /// The algorithm can be executed with the run() function.
659 /// After it the matching (the primal solution) and the dual solution
660 /// can be obtained using the query functions.
662 /// If the value type is integer, then the primal and the dual
663 /// solutions are multiplied by
664 /// \ref MaxWeightedMatching::primalScale "2" and
665 /// \ref MaxWeightedMatching::dualScale "4" respectively.
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. It is equal to 2 or 1
693 /// according to the value type.
694 static const int primalScale =
695 std::numeric_limits<Value>::is_integer ? 2 : 1;
697 /// \brief Scaling factor for dual solution
699 /// Scaling factor for dual solution. It is equal to 4 or 1
700 /// according to the value type.
701 static const int dualScale =
702 std::numeric_limits<Value>::is_integer ? 4 : 1;
706 TEMPLATE_GRAPH_TYPEDEFS(Graph);
708 typedef typename Graph::template NodeMap<Value> NodePotential;
711 const WeightMap& _weight;
713 MatchingMap* _matching;
714 NodePotential* _node_potential;
720 EVEN = -1, MATCHED = 0, ODD = 1
723 typedef typename Graph::template NodeMap<Status> StatusMap;
726 typedef typename Graph::template NodeMap<Arc> PredMap;
729 typedef ExtendFindEnum<IntNodeMap> TreeSet;
731 IntNodeMap *_tree_set_index;
734 IntNodeMap *_delta1_index;
735 BinHeap<Value, IntNodeMap> *_delta1;
737 IntNodeMap *_delta2_index;
738 BinHeap<Value, IntNodeMap> *_delta2;
740 IntEdgeMap *_delta3_index;
741 BinHeap<Value, IntEdgeMap> *_delta3;
745 void createStructures() {
746 _node_num = countNodes(_graph);
749 _matching = new MatchingMap(_graph);
751 if (!_node_potential) {
752 _node_potential = new NodePotential(_graph);
755 _status = new StatusMap(_graph);
758 _pred = new PredMap(_graph);
761 _tree_set_index = new IntNodeMap(_graph);
762 _tree_set = new TreeSet(*_tree_set_index);
765 _delta1_index = new IntNodeMap(_graph);
766 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
769 _delta2_index = new IntNodeMap(_graph);
770 _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
773 _delta3_index = new IntEdgeMap(_graph);
774 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
778 void destroyStructures() {
782 if (_node_potential) {
783 delete _node_potential;
792 delete _tree_set_index;
796 delete _delta1_index;
800 delete _delta2_index;
804 delete _delta3_index;
809 void matchedToEven(Node node, int tree) {
810 _tree_set->insert(node, tree);
811 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
812 _delta1->push(node, (*_node_potential)[node]);
814 if (_delta2->state(node) == _delta2->IN_HEAP) {
815 _delta2->erase(node);
818 for (InArcIt a(_graph, node); a != INVALID; ++a) {
819 Node v = _graph.source(a);
820 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
821 dualScale * _weight[a];
823 if (_allow_loops && _graph.direction(a)) {
824 _delta3->push(a, rw / 2);
826 } else if ((*_status)[v] == EVEN) {
827 _delta3->push(a, rw / 2);
828 } else if ((*_status)[v] == MATCHED) {
829 if (_delta2->state(v) != _delta2->IN_HEAP) {
831 _delta2->push(v, rw);
832 } else if ((*_delta2)[v] > rw) {
834 _delta2->decrease(v, rw);
840 void matchedToOdd(Node node, int tree) {
841 _tree_set->insert(node, tree);
842 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
844 if (_delta2->state(node) == _delta2->IN_HEAP) {
845 _delta2->erase(node);
849 void evenToMatched(Node node, int tree) {
850 _delta1->erase(node);
851 _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
853 Value minrw = std::numeric_limits<Value>::max();
854 for (InArcIt a(_graph, node); a != INVALID; ++a) {
855 Node v = _graph.source(a);
856 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
857 dualScale * _weight[a];
860 if (_allow_loops && _graph.direction(a)) {
863 } else if ((*_status)[v] == EVEN) {
866 min = _graph.oppositeArc(a);
869 } else if ((*_status)[v] == MATCHED) {
870 if ((*_pred)[v] == a) {
872 Value minrwa = std::numeric_limits<Value>::max();
873 for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
874 Node va = _graph.target(aa);
875 if ((*_status)[va] != EVEN ||
876 _tree_set->find(va) == tree) continue;
877 Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
878 dualScale * _weight[aa];
884 if (mina != INVALID) {
886 _delta2->increase(v, minrwa);
888 _pred->set(v, INVALID);
894 if (min != INVALID) {
895 _pred->set(node, min);
896 _delta2->push(node, minrw);
898 _pred->set(node, INVALID);
902 void oddToMatched(Node node) {
903 _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
905 Value minrw = std::numeric_limits<Value>::max();
906 for (InArcIt a(_graph, node); a != INVALID; ++a) {
907 Node v = _graph.source(a);
908 if ((*_status)[v] != EVEN) continue;
909 Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
910 dualScale * _weight[a];
913 min = _graph.oppositeArc(a);
917 if (min != INVALID) {
918 _pred->set(node, min);
919 _delta2->push(node, minrw);
921 _pred->set(node, INVALID);
925 void alternatePath(Node even, int tree) {
928 _status->set(even, MATCHED);
929 evenToMatched(even, tree);
931 Arc prev = (*_matching)[even];
932 while (prev != INVALID) {
933 odd = _graph.target(prev);
934 even = _graph.target((*_pred)[odd]);
935 _matching->set(odd, (*_pred)[odd]);
936 _status->set(odd, MATCHED);
939 prev = (*_matching)[even];
940 _status->set(even, MATCHED);
941 _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
942 evenToMatched(even, tree);
946 void destroyTree(int tree) {
947 for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
948 if ((*_status)[n] == EVEN) {
949 _status->set(n, MATCHED);
950 evenToMatched(n, tree);
951 } else if ((*_status)[n] == ODD) {
952 _status->set(n, MATCHED);
956 _tree_set->eraseClass(tree);
960 void unmatchNode(const Node& node) {
961 int tree = _tree_set->find(node);
963 alternatePath(node, tree);
966 _matching->set(node, INVALID);
970 void augmentOnEdge(const Edge& edge) {
971 Node left = _graph.u(edge);
972 int left_tree = _tree_set->find(left);
974 alternatePath(left, left_tree);
975 destroyTree(left_tree);
976 _matching->set(left, _graph.direct(edge, true));
978 Node right = _graph.v(edge);
979 int right_tree = _tree_set->find(right);
981 alternatePath(right, right_tree);
982 destroyTree(right_tree);
983 _matching->set(right, _graph.direct(edge, false));
986 void augmentOnArc(const Arc& arc) {
987 Node left = _graph.source(arc);
988 _status->set(left, MATCHED);
989 _matching->set(left, arc);
990 _pred->set(left, arc);
992 Node right = _graph.target(arc);
993 int right_tree = _tree_set->find(right);
995 alternatePath(right, right_tree);
996 destroyTree(right_tree);
997 _matching->set(right, _graph.oppositeArc(arc));
1000 void extendOnArc(const Arc& arc) {
1001 Node base = _graph.target(arc);
1002 int tree = _tree_set->find(base);
1004 Node odd = _graph.source(arc);
1005 _tree_set->insert(odd, tree);
1006 _status->set(odd, ODD);
1007 matchedToOdd(odd, tree);
1008 _pred->set(odd, arc);
1010 Node even = _graph.target((*_matching)[odd]);
1011 _tree_set->insert(even, tree);
1012 _status->set(even, EVEN);
1013 matchedToEven(even, tree);
1016 void cycleOnEdge(const Edge& edge, int tree) {
1018 std::vector<Node> left_path, right_path;
1021 std::set<Node> left_set, right_set;
1022 Node left = _graph.u(edge);
1023 left_path.push_back(left);
1024 left_set.insert(left);
1026 Node right = _graph.v(edge);
1027 right_path.push_back(right);
1028 right_set.insert(right);
1032 if (left_set.find(right) != left_set.end()) {
1037 if ((*_matching)[left] == INVALID) break;
1039 left = _graph.target((*_matching)[left]);
1040 left_path.push_back(left);
1041 left = _graph.target((*_pred)[left]);
1042 left_path.push_back(left);
1044 left_set.insert(left);
1046 if (right_set.find(left) != right_set.end()) {
1051 if ((*_matching)[right] == INVALID) break;
1053 right = _graph.target((*_matching)[right]);
1054 right_path.push_back(right);
1055 right = _graph.target((*_pred)[right]);
1056 right_path.push_back(right);
1058 right_set.insert(right);
1062 if (nca == INVALID) {
1063 if ((*_matching)[left] == INVALID) {
1065 while (left_set.find(nca) == left_set.end()) {
1066 nca = _graph.target((*_matching)[nca]);
1067 right_path.push_back(nca);
1068 nca = _graph.target((*_pred)[nca]);
1069 right_path.push_back(nca);
1073 while (right_set.find(nca) == right_set.end()) {
1074 nca = _graph.target((*_matching)[nca]);
1075 left_path.push_back(nca);
1076 nca = _graph.target((*_pred)[nca]);
1077 left_path.push_back(nca);
1083 alternatePath(nca, tree);
1086 prev = _graph.direct(edge, true);
1087 for (int i = 0; left_path[i] != nca; i += 2) {
1088 _matching->set(left_path[i], prev);
1089 _status->set(left_path[i], MATCHED);
1090 evenToMatched(left_path[i], tree);
1092 prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1093 _status->set(left_path[i + 1], MATCHED);
1094 oddToMatched(left_path[i + 1]);
1096 _matching->set(nca, prev);
1098 for (int i = 0; right_path[i] != nca; i += 2) {
1099 _status->set(right_path[i], MATCHED);
1100 evenToMatched(right_path[i], tree);
1102 _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
1103 _status->set(right_path[i + 1], MATCHED);
1104 oddToMatched(right_path[i + 1]);
1110 void extractCycle(const Arc &arc) {
1111 Node left = _graph.source(arc);
1112 Node odd = _graph.target((*_matching)[left]);
1114 while (odd != left) {
1115 Node even = _graph.target((*_matching)[odd]);
1116 prev = (*_matching)[odd];
1117 odd = _graph.target((*_matching)[even]);
1118 _matching->set(even, _graph.oppositeArc(prev));
1120 _matching->set(left, arc);
1122 Node right = _graph.target(arc);
1123 int right_tree = _tree_set->find(right);
1124 alternatePath(right, right_tree);
1125 destroyTree(right_tree);
1126 _matching->set(right, _graph.oppositeArc(arc));
1131 /// \brief Constructor
1134 MaxWeightedFractionalMatching(const Graph& graph, const WeightMap& weight,
1135 bool allow_loops = true)
1136 : _graph(graph), _weight(weight), _matching(0),
1137 _node_potential(0), _node_num(0), _allow_loops(allow_loops),
1138 _status(0), _pred(0),
1139 _tree_set_index(0), _tree_set(0),
1141 _delta1_index(0), _delta1(0),
1142 _delta2_index(0), _delta2(0),
1143 _delta3_index(0), _delta3(0),
1147 ~MaxWeightedFractionalMatching() {
1148 destroyStructures();
1151 /// \name Execution Control
1152 /// The simplest way to execute the algorithm is to use the
1153 /// \ref run() member function.
1157 /// \brief Initialize the algorithm
1159 /// This function initializes the algorithm.
1163 for (NodeIt n(_graph); n != INVALID; ++n) {
1164 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1165 (*_delta2_index)[n] = _delta2->PRE_HEAP;
1167 for (EdgeIt e(_graph); e != INVALID; ++e) {
1168 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1171 for (NodeIt n(_graph); n != INVALID; ++n) {
1173 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1174 if (_graph.target(e) == n && !_allow_loops) continue;
1175 if ((dualScale * _weight[e]) / 2 > max) {
1176 max = (dualScale * _weight[e]) / 2;
1179 _node_potential->set(n, max);
1180 _delta1->push(n, max);
1182 _tree_set->insert(n);
1184 _matching->set(n, INVALID);
1185 _status->set(n, EVEN);
1188 for (EdgeIt e(_graph); e != INVALID; ++e) {
1189 Node left = _graph.u(e);
1190 Node right = _graph.v(e);
1191 if (left == right && !_allow_loops) continue;
1192 _delta3->push(e, ((*_node_potential)[left] +
1193 (*_node_potential)[right] -
1194 dualScale * _weight[e]) / 2);
1198 /// \brief Start the algorithm
1200 /// This function starts the algorithm.
1202 /// \pre \ref init() must be called before using this function.
1208 int unmatched = _node_num;
1209 while (unmatched > 0) {
1210 Value d1 = !_delta1->empty() ?
1211 _delta1->prio() : std::numeric_limits<Value>::max();
1213 Value d2 = !_delta2->empty() ?
1214 _delta2->prio() : std::numeric_limits<Value>::max();
1216 Value d3 = !_delta3->empty() ?
1217 _delta3->prio() : std::numeric_limits<Value>::max();
1219 _delta_sum = d3; OpType ot = D3;
1220 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1221 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1226 Node n = _delta1->top();
1233 Node n = _delta2->top();
1234 Arc a = (*_pred)[n];
1235 if ((*_matching)[n] == INVALID) {
1239 Node v = _graph.target((*_matching)[n]);
1240 if ((*_matching)[n] !=
1241 _graph.oppositeArc((*_matching)[v])) {
1251 Edge e = _delta3->top();
1253 Node left = _graph.u(e);
1254 Node right = _graph.v(e);
1256 int left_tree = _tree_set->find(left);
1257 int right_tree = _tree_set->find(right);
1259 if (left_tree == right_tree) {
1260 cycleOnEdge(e, left_tree);
1271 /// \brief Run the algorithm.
1273 /// This method runs the \c %MaxWeightedMatching algorithm.
1275 /// \note mwfm.run() is just a shortcut of the following code.
1287 /// \name Primal Solution
1288 /// Functions to get the primal solution, i.e. the maximum weighted
1290 /// Either \ref run() or \ref start() function should be called before
1295 /// \brief Return the weight of the matching.
1297 /// This function returns the weight of the found matching. This
1298 /// value is scaled by \ref primalScale "primal scale".
1300 /// \pre Either run() or start() must be called before using this function.
1301 Value matchingWeight() const {
1303 for (NodeIt n(_graph); n != INVALID; ++n) {
1304 if ((*_matching)[n] != INVALID) {
1305 sum += _weight[(*_matching)[n]];
1308 return sum * primalScale / 2;
1311 /// \brief Return the number of covered nodes in the matching.
1313 /// This function returns the number of covered nodes in the matching.
1315 /// \pre Either run() or start() must be called before using this function.
1316 int matchingSize() const {
1318 for (NodeIt n(_graph); n != INVALID; ++n) {
1319 if ((*_matching)[n] != INVALID) {
1326 /// \brief Return \c true if the given edge is in the matching.
1328 /// This function returns \c true if the given edge is in the
1329 /// found matching. The result is scaled by \ref primalScale
1332 /// \pre Either run() or start() must be called before using this function.
1333 Value matching(const Edge& edge) const {
1334 return Value(edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
1335 * primalScale / 2 + Value(edge == (*_matching)[_graph.v(edge)] ? 1 : 0)
1339 /// \brief Return the fractional matching arc (or edge) incident
1340 /// to the given node.
1342 /// This function returns one of the fractional matching arc (or
1343 /// edge) incident to the given node in the found matching or \c
1344 /// INVALID if the node is not covered by the matching or if the
1345 /// node is on an odd length cycle then it is the successor edge
1348 /// \pre Either run() or start() must be called before using this function.
1349 Arc matching(const Node& node) const {
1350 return (*_matching)[node];
1353 /// \brief Return a const reference to the matching map.
1355 /// This function returns a const reference to a node map that stores
1356 /// the matching arc (or edge) incident to each node.
1357 const MatchingMap& matchingMap() const {
1363 /// \name Dual Solution
1364 /// Functions to get the dual solution.\n
1365 /// Either \ref run() or \ref start() function should be called before
1370 /// \brief Return the value of the dual solution.
1372 /// This function returns the value of the dual solution.
1373 /// It should be equal to the primal value scaled by \ref dualScale
1376 /// \pre Either run() or start() must be called before using this function.
1377 Value dualValue() const {
1379 for (NodeIt n(_graph); n != INVALID; ++n) {
1380 sum += nodeValue(n);
1385 /// \brief Return the dual value (potential) of the given node.
1387 /// This function returns the dual value (potential) of the given node.
1389 /// \pre Either run() or start() must be called before using this function.
1390 Value nodeValue(const Node& n) const {
1391 return (*_node_potential)[n];
1398 /// \ingroup matching
1400 /// \brief Weighted fractional perfect matching in general graphs
1402 /// This class provides an efficient implementation of fractional
1403 /// matching algorithm. The implementation is based on extensive use
1404 /// of priority queues and provides \f$O(nm\log n)\f$ time
1407 /// The maximum weighted fractional perfect matching is a relaxation
1408 /// of the maximum weighted perfect matching problem where the odd
1409 /// set constraints are omitted.
1410 /// It can be formulated with the following linear program.
1411 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1412 /// \f[x_e \ge 0\quad \forall e\in E\f]
1413 /// \f[\max \sum_{e\in E}x_ew_e\f]
1414 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1415 /// \f$X\f$. The result must be the union of a matching with one
1416 /// value edges and a set of odd length cycles with half value edges.
1418 /// The algorithm calculates an optimal fractional matching and a
1419 /// proof of the optimality. The solution of the dual problem can be
1420 /// used to check the result of the algorithm. The dual linear
1421 /// problem is the following.
1422 /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
1423 /// \f[\min \sum_{u \in V}y_u \f] ///
1425 /// The algorithm can be executed with the run() function.
1426 /// After it the matching (the primal solution) and the dual solution
1427 /// can be obtained using the query functions.
1429 /// If the value type is integer, then the primal and the dual
1430 /// solutions are multiplied by
1431 /// \ref MaxWeightedMatching::primalScale "2" and
1432 /// \ref MaxWeightedMatching::dualScale "4" respectively.
1434 /// \tparam GR The undirected graph type the algorithm runs on.
1435 /// \tparam WM The type edge weight map. The default type is
1436 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
1438 template <typename GR, typename WM>
1440 template <typename GR,
1441 typename WM = typename GR::template EdgeMap<int> >
1443 class MaxWeightedPerfectFractionalMatching {
1446 /// The graph type of the algorithm
1448 /// The type of the edge weight map
1449 typedef WM WeightMap;
1450 /// The value type of the edge weights
1451 typedef typename WeightMap::Value Value;
1453 /// The type of the matching map
1454 typedef typename Graph::template NodeMap<typename Graph::Arc>
1457 /// \brief Scaling factor for primal solution
1459 /// Scaling factor for primal solution. It is equal to 2 or 1
1460 /// according to the value type.
1461 static const int primalScale =
1462 std::numeric_limits<Value>::is_integer ? 2 : 1;
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;
1913 for (NodeIt n(_graph); n != INVALID; ++n) {
1914 Value max = - std::numeric_limits<Value>::max();
1915 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1916 if (_graph.target(e) == n && !_allow_loops) continue;
1917 if ((dualScale * _weight[e]) / 2 > max) {
1918 max = (dualScale * _weight[e]) / 2;
1921 _node_potential->set(n, max);
1923 _tree_set->insert(n);
1925 _matching->set(n, INVALID);
1926 _status->set(n, EVEN);
1929 for (EdgeIt e(_graph); e != INVALID; ++e) {
1930 Node left = _graph.u(e);
1931 Node right = _graph.v(e);
1932 if (left == right && !_allow_loops) continue;
1933 _delta3->push(e, ((*_node_potential)[left] +
1934 (*_node_potential)[right] -
1935 dualScale * _weight[e]) / 2);
1939 /// \brief Start the algorithm
1941 /// This function starts the algorithm.
1943 /// \pre \ref init() must be called before using this function.
1949 int unmatched = _node_num;
1950 while (unmatched > 0) {
1951 Value d2 = !_delta2->empty() ?
1952 _delta2->prio() : std::numeric_limits<Value>::max();
1954 Value d3 = !_delta3->empty() ?
1955 _delta3->prio() : std::numeric_limits<Value>::max();
1957 _delta_sum = d3; OpType ot = D3;
1958 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1960 if (_delta_sum == std::numeric_limits<Value>::max()) {
1967 Node n = _delta2->top();
1968 Arc a = (*_pred)[n];
1969 if ((*_matching)[n] == INVALID) {
1973 Node v = _graph.target((*_matching)[n]);
1974 if ((*_matching)[n] !=
1975 _graph.oppositeArc((*_matching)[v])) {
1985 Edge e = _delta3->top();
1987 Node left = _graph.u(e);
1988 Node right = _graph.v(e);
1990 int left_tree = _tree_set->find(left);
1991 int right_tree = _tree_set->find(right);
1993 if (left_tree == right_tree) {
1994 cycleOnEdge(e, left_tree);
2006 /// \brief Run the algorithm.
2008 /// This method runs the \c %MaxWeightedMatching algorithm.
2010 /// \note mwfm.run() is just a shortcut of the following code.
2022 /// \name Primal Solution
2023 /// Functions to get the primal solution, i.e. the maximum weighted
2025 /// Either \ref run() or \ref start() function should be called before
2030 /// \brief Return the weight of the matching.
2032 /// This function returns the weight of the found matching. This
2033 /// value is scaled by \ref primalScale "primal scale".
2035 /// \pre Either run() or start() must be called before using this function.
2036 Value matchingWeight() const {
2038 for (NodeIt n(_graph); n != INVALID; ++n) {
2039 if ((*_matching)[n] != INVALID) {
2040 sum += _weight[(*_matching)[n]];
2043 return sum * primalScale / 2;
2046 /// \brief Return the number of covered nodes in the matching.
2048 /// This function returns the number of covered nodes in the matching.
2050 /// \pre Either run() or start() must be called before using this function.
2051 int matchingSize() const {
2053 for (NodeIt n(_graph); n != INVALID; ++n) {
2054 if ((*_matching)[n] != INVALID) {
2061 /// \brief Return \c true if the given edge is in the matching.
2063 /// This function returns \c true if the given edge is in the
2064 /// found matching. The result is scaled by \ref primalScale
2067 /// \pre Either run() or start() must be called before using this function.
2068 Value matching(const Edge& edge) const {
2069 return Value(edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
2070 * primalScale / 2 + Value(edge == (*_matching)[_graph.v(edge)] ? 1 : 0)
2074 /// \brief Return the fractional matching arc (or edge) incident
2075 /// to the given node.
2077 /// This function returns one of the fractional matching arc (or
2078 /// edge) incident to the given node in the found matching or \c
2079 /// INVALID if the node is not covered by the matching or if the
2080 /// node is on an odd length cycle then it is the successor edge
2083 /// \pre Either run() or start() must be called before using this function.
2084 Arc matching(const Node& node) const {
2085 return (*_matching)[node];
2088 /// \brief Return a const reference to the matching map.
2090 /// This function returns a const reference to a node map that stores
2091 /// the matching arc (or edge) incident to each node.
2092 const MatchingMap& matchingMap() const {
2098 /// \name Dual Solution
2099 /// Functions to get the dual solution.\n
2100 /// Either \ref run() or \ref start() function should be called before
2105 /// \brief Return the value of the dual solution.
2107 /// This function returns the value of the dual solution.
2108 /// It should be equal to the primal value scaled by \ref dualScale
2111 /// \pre Either run() or start() must be called before using this function.
2112 Value dualValue() const {
2114 for (NodeIt n(_graph); n != INVALID; ++n) {
2115 sum += nodeValue(n);
2120 /// \brief Return the dual value (potential) of the given node.
2122 /// This function returns the dual value (potential) of the given node.
2124 /// \pre Either run() or start() must be called before using this function.
2125 Value nodeValue(const Node& n) const {
2126 return (*_node_potential)[n];
2133 } //END OF NAMESPACE LEMON
2135 #endif //LEMON_FRACTIONAL_MATCHING_H