[Lemon-commits] Alpar Juttner: Merge
Lemon HG
hg at lemon.cs.elte.hu
Wed Oct 22 15:41:49 CEST 2008
details: http://lemon.cs.elte.hu/hg/lemon/rev/9c2a532aa5ef
changeset: 345:9c2a532aa5ef
user: Alpar Juttner <alpar [at] cs.elte.hu>
date: Wed Oct 22 14:41:18 2008 +0100
description:
Merge
diffstat:
5 files changed, 3418 insertions(+)
lemon/Makefile.am | 1
lemon/max_matching.h | 3104 +++++++++++++++++++++++++++++++++++++++++++++
test/CMakeLists.txt | 1
test/Makefile.am | 2
test/max_matching_test.cc | 310 ++++
diffs (truncated from 3463 to 300 lines):
diff -r 3f9f3550dbf5 -r 9c2a532aa5ef lemon/Makefile.am
--- a/lemon/Makefile.am Wed Oct 22 14:39:04 2008 +0100
+++ b/lemon/Makefile.am Wed Oct 22 14:41:18 2008 +0100
@@ -35,6 +35,7 @@
lemon/list_graph.h \
lemon/maps.h \
lemon/math.h \
+ lemon/max_matching.h \
lemon/path.h \
lemon/random.h \
lemon/smart_graph.h \
diff -r 3f9f3550dbf5 -r 9c2a532aa5ef lemon/max_matching.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/max_matching.h Wed Oct 22 14:41:18 2008 +0100
@@ -0,0 +1,3104 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2008
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_MAX_MATCHING_H
+#define LEMON_MAX_MATCHING_H
+
+#include <vector>
+#include <queue>
+#include <set>
+#include <limits>
+
+#include <lemon/core.h>
+#include <lemon/unionfind.h>
+#include <lemon/bin_heap.h>
+#include <lemon/maps.h>
+
+///\ingroup matching
+///\file
+///\brief Maximum matching algorithms in general graphs.
+
+namespace lemon {
+
+ /// \ingroup matching
+ ///
+ /// \brief Edmonds' alternating forest maximum matching algorithm.
+ ///
+ /// This class implements Edmonds' alternating forest matching
+ /// algorithm. The algorithm can be started from an arbitrary initial
+ /// matching (the default is the empty one)
+ ///
+ /// The dual solution of the problem is a map of the nodes to
+ /// MaxMatching::Status, having values \c EVEN/D, \c ODD/A and \c
+ /// MATCHED/C showing the Gallai-Edmonds decomposition of the
+ /// graph. The nodes in \c EVEN/D induce a graph with
+ /// factor-critical components, the nodes in \c ODD/A form the
+ /// barrier, and the nodes in \c MATCHED/C induce a graph having a
+ /// perfect matching. The number of the factor-critical components
+ /// minus the number of barrier nodes is a lower bound on the
+ /// unmatched nodes, and the matching is optimal if and only if this bound is
+ /// tight. This decomposition can be attained by calling \c
+ /// decomposition() after running the algorithm.
+ ///
+ /// \param _Graph The graph type the algorithm runs on.
+ template <typename _Graph>
+ class MaxMatching {
+ public:
+
+ typedef _Graph Graph;
+ typedef typename Graph::template NodeMap<typename Graph::Arc>
+ MatchingMap;
+
+ ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
+ ///
+ ///Indicates the Gallai-Edmonds decomposition of the graph. The
+ ///nodes with Status \c EVEN/D induce a graph with factor-critical
+ ///components, the nodes in \c ODD/A form the canonical barrier,
+ ///and the nodes in \c MATCHED/C induce a graph having a perfect
+ ///matching.
+ enum Status {
+ EVEN = 1, D = 1, MATCHED = 0, C = 0, ODD = -1, A = -1, UNMATCHED = -2
+ };
+
+ typedef typename Graph::template NodeMap<Status> StatusMap;
+
+ private:
+
+ TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+ typedef UnionFindEnum<IntNodeMap> BlossomSet;
+ typedef ExtendFindEnum<IntNodeMap> TreeSet;
+ typedef RangeMap<Node> NodeIntMap;
+ typedef MatchingMap EarMap;
+ typedef std::vector<Node> NodeQueue;
+
+ const Graph& _graph;
+ MatchingMap* _matching;
+ StatusMap* _status;
+
+ EarMap* _ear;
+
+ IntNodeMap* _blossom_set_index;
+ BlossomSet* _blossom_set;
+ NodeIntMap* _blossom_rep;
+
+ IntNodeMap* _tree_set_index;
+ TreeSet* _tree_set;
+
+ NodeQueue _node_queue;
+ int _process, _postpone, _last;
+
+ int _node_num;
+
+ private:
+
+ void createStructures() {
+ _node_num = countNodes(_graph);
+ if (!_matching) {
+ _matching = new MatchingMap(_graph);
+ }
+ if (!_status) {
+ _status = new StatusMap(_graph);
+ }
+ if (!_ear) {
+ _ear = new EarMap(_graph);
+ }
+ if (!_blossom_set) {
+ _blossom_set_index = new IntNodeMap(_graph);
+ _blossom_set = new BlossomSet(*_blossom_set_index);
+ }
+ if (!_blossom_rep) {
+ _blossom_rep = new NodeIntMap(_node_num);
+ }
+ if (!_tree_set) {
+ _tree_set_index = new IntNodeMap(_graph);
+ _tree_set = new TreeSet(*_tree_set_index);
+ }
+ _node_queue.resize(_node_num);
+ }
+
+ void destroyStructures() {
+ if (_matching) {
+ delete _matching;
+ }
+ if (_status) {
+ delete _status;
+ }
+ if (_ear) {
+ delete _ear;
+ }
+ if (_blossom_set) {
+ delete _blossom_set;
+ delete _blossom_set_index;
+ }
+ if (_blossom_rep) {
+ delete _blossom_rep;
+ }
+ if (_tree_set) {
+ delete _tree_set_index;
+ delete _tree_set;
+ }
+ }
+
+ void processDense(const Node& n) {
+ _process = _postpone = _last = 0;
+ _node_queue[_last++] = n;
+
+ while (_process != _last) {
+ Node u = _node_queue[_process++];
+ for (OutArcIt a(_graph, u); a != INVALID; ++a) {
+ Node v = _graph.target(a);
+ if ((*_status)[v] == MATCHED) {
+ extendOnArc(a);
+ } else if ((*_status)[v] == UNMATCHED) {
+ augmentOnArc(a);
+ return;
+ }
+ }
+ }
+
+ while (_postpone != _last) {
+ Node u = _node_queue[_postpone++];
+
+ for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
+ Node v = _graph.target(a);
+
+ if ((*_status)[v] == EVEN) {
+ if (_blossom_set->find(u) != _blossom_set->find(v)) {
+ shrinkOnEdge(a);
+ }
+ }
+
+ while (_process != _last) {
+ Node w = _node_queue[_process++];
+ for (OutArcIt b(_graph, w); b != INVALID; ++b) {
+ Node x = _graph.target(b);
+ if ((*_status)[x] == MATCHED) {
+ extendOnArc(b);
+ } else if ((*_status)[x] == UNMATCHED) {
+ augmentOnArc(b);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void processSparse(const Node& n) {
+ _process = _last = 0;
+ _node_queue[_last++] = n;
+ while (_process != _last) {
+ Node u = _node_queue[_process++];
+ for (OutArcIt a(_graph, u); a != INVALID; ++a) {
+ Node v = _graph.target(a);
+
+ if ((*_status)[v] == EVEN) {
+ if (_blossom_set->find(u) != _blossom_set->find(v)) {
+ shrinkOnEdge(a);
+ }
+ } else if ((*_status)[v] == MATCHED) {
+ extendOnArc(a);
+ } else if ((*_status)[v] == UNMATCHED) {
+ augmentOnArc(a);
+ return;
+ }
+ }
+ }
+ }
+
+ void shrinkOnEdge(const Edge& e) {
+ Node nca = INVALID;
+
+ {
+ std::set<Node> left_set, right_set;
+
+ Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
+ left_set.insert(left);
+
+ Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
+ right_set.insert(right);
+
+ while (true) {
+ if ((*_matching)[left] == INVALID) break;
+ left = _graph.target((*_matching)[left]);
+ left = (*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[left]))];
+ if (right_set.find(left) != right_set.end()) {
+ nca = left;
+ break;
+ }
+ left_set.insert(left);
+
+ if ((*_matching)[right] == INVALID) break;
+ right = _graph.target((*_matching)[right]);
+ right = (*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[right]))];
+ if (left_set.find(right) != left_set.end()) {
+ nca = right;
+ break;
+ }
+ right_set.insert(right);
+ }
+
+ if (nca == INVALID) {
+ if ((*_matching)[left] == INVALID) {
+ nca = right;
+ while (left_set.find(nca) == left_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ nca =(*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[nca]))];
+ }
+ } else {
+ nca = left;
+ while (right_set.find(nca) == right_set.end()) {
+ nca = _graph.target((*_matching)[nca]);
+ nca = (*_blossom_rep)[_blossom_set->
+ find(_graph.target((*_ear)[nca]))];
+ }
+ }
+ }
+ }
+
+ {
+
+ Node node = _graph.u(e);
+ Arc arc = _graph.direct(e, true);
+ Node base = (*_blossom_rep)[_blossom_set->find(node)];
+
+ while (base != nca) {
+ _ear->set(node, arc);
More information about the Lemon-commits
mailing list