[Lemon-commits] alpar: r3149 - hugo/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Thu Jan 25 15:38:55 CET 2007
Author: alpar
Date: Thu Jan 25 15:38:55 2007
New Revision: 3149
Added:
hugo/trunk/lemon/bp_matching.h
Modified:
hugo/trunk/lemon/Makefile.am
Log:
A push/relabel type max cardinality matching implementation.
(slightly incompatible with bipartite_matching.h)
Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am (original)
+++ hugo/trunk/lemon/Makefile.am Thu Jan 25 15:38:55 2007
@@ -37,6 +37,7 @@
lemon/bfs.h \
lemon/bin_heap.h \
lemon/bipartite_matching.h \
+ lemon/bp_matching.h \
lemon/bpugraph_adaptor.h \
lemon/bucket_heap.h \
lemon/color.h \
Added: hugo/trunk/lemon/bp_matching.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/bp_matching.h Thu Jan 25 15:38:55 2007
@@ -0,0 +1,381 @@
+/* -*- C++ -*-
+ * lemon/preflow_matching.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 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_BP_MATCHING
+#define LEMON_BP_MATCHING
+
+#include <lemon/graph_utils.h>
+#include <lemon/iterable_maps.h>
+#include <iostream>
+#include <queue>
+#include <lemon/counter.h>
+#include <lemon/elevator.h>
+
+///\ingroup matching
+///\file
+///\brief Push-prelabel maximum matching algorithms in bipartite graphs.
+///
+///\todo This file slightly conflicts with \ref lemon/bipartite_matching.h
+///\todo (Re)move the XYZ_TYPEDEFS macros
+namespace lemon {
+
+#define BIPARTITE_TYPEDEFS(Graph) \
+ GRAPH_TYPEDEFS(Graph) \
+ typedef Graph::ANodeIt ANodeIt; \
+ typedef Graph::BNodeIt BNodeIt;
+
+#define UNDIRBIPARTITE_TYPEDEFS(Graph) \
+ UNDIRGRAPH_TYPEDEFS(Graph) \
+ typedef Graph::ANodeIt ANodeIt; \
+ typedef Graph::BNodeIt BNodeIt;
+
+ template<class Graph,
+ class MT=typename Graph::template ANodeMap<typename Graph::UEdge> >
+ class BpMatching {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::ANodeIt ANodeIt;
+ typedef typename Graph::BNodeIt BNodeIt;
+ typedef typename Graph::UEdge UEdge;
+ typedef typename Graph::IncEdgeIt IncEdgeIt;
+
+ const Graph &_g;
+ int _node_num;
+ MT &_matching;
+ Elevator<Graph,typename Graph::BNode> _levels;
+ typename Graph::template BNodeMap<int> _cov;
+
+ public:
+ BpMatching(const Graph &g, MT &matching) :
+ _g(g),
+ _node_num(countBNodes(g)),
+ _matching(matching),
+ _levels(g,_node_num),
+ _cov(g,0)
+ {
+ }
+
+ private:
+ void init()
+ {
+// for(BNodeIt n(g);n!=INVALID;++n) cov[n]=0;
+ for(ANodeIt n(_g);n!=INVALID;++n)
+ if((_matching[n]=IncEdgeIt(_g,n))!=INVALID)
+ ++_cov[_g.oppositeNode(n,_matching[n])];
+
+ std::queue<Node> q;
+ _levels.initStart();
+ for(BNodeIt n(_g);n!=INVALID;++n)
+ if(_cov[n]>1) {
+ _levels.initAddItem(n);
+ q.push(n);
+ }
+ int hlev=0;
+ while(!q.empty()) {
+ Node n=q.front();
+ q.pop();
+ int nlev=_levels[n]+1;
+ for(IncEdgeIt e(_g,n);e!=INVALID;++e) {
+ Node m=_g.runningNode(e);
+ if(e==_matching[m]) {
+ for(IncEdgeIt f(_g,m);f!=INVALID;++f) {
+ Node r=_g.runningNode(f);
+ if(_levels[r]>nlev) {
+ for(;nlev>hlev;hlev++)
+ _levels.initNewLevel();
+ _levels.initAddItem(r);
+ q.push(r);
+ }
+ }
+ }
+ }
+ }
+ _levels.initFinish();
+ for(BNodeIt n(_g);n!=INVALID;++n)
+ if(_cov[n]<1&&_levels[n]<_node_num)
+ _levels.activate(n);
+ }
+ public:
+ int run()
+ {
+ init();
+
+ Node act;
+ Node bact=INVALID;
+ Node last_activated=INVALID;
+// while((act=last_activated!=INVALID?
+// last_activated:_levels.highestActive())
+// !=INVALID)
+ while((act=_levels.highestActive())!=INVALID) {
+ last_activated=INVALID;
+ int actlevel=_levels[act];
+
+ UEdge bedge=INVALID;
+ int nlevel=_node_num;
+ {
+ int nnlevel;
+ for(IncEdgeIt tbedge(_g,act);
+ tbedge!=INVALID && nlevel>=actlevel;
+ ++tbedge)
+ if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
+ nlevel)
+ {
+ nlevel=nnlevel;
+ bedge=tbedge;
+ }
+ }
+ if(nlevel<_node_num) {
+ if(nlevel>=actlevel)
+ _levels.liftHighestActiveTo(nlevel+1);
+// _levels.liftTo(act,nlevel+1);
+ bact=_g.bNode(_matching[_g.aNode(bedge)]);
+ if(--_cov[bact]<1) {
+ _levels.activate(bact);
+ last_activated=bact;
+ }
+ _matching[_g.aNode(bedge)]=bedge;
+ _cov[act]=1;
+ _levels.deactivate(act);
+ }
+ else {
+ if(_node_num>actlevel)
+ _levels.liftHighestActiveTo(_node_num);
+// _levels.liftTo(act,_node_num);
+ _levels.deactivate(act);
+ }
+
+ if(_levels.onLevel(actlevel)==0)
+ _levels.liftToTop(actlevel);
+ }
+
+ int ret=_node_num;
+ for(ANodeIt n(_g);n!=INVALID;++n)
+ if(_matching[n]==INVALID) ret--;
+ else if (_cov[_g.bNode(_matching[n])]>1) {
+ _cov[_g.bNode(_matching[n])]--;
+ ret--;
+ _matching[n]=INVALID;
+ }
+ return ret;
+ }
+
+ ///\returns -1 if there is a perfect matching, or an empty level
+ ///if it doesn't exists
+ int runPerfect()
+ {
+ init();
+
+ Node act;
+ Node bact=INVALID;
+ Node last_activated=INVALID;
+ while((act=_levels.highestActive())!=INVALID) {
+ last_activated=INVALID;
+ int actlevel=_levels[act];
+
+ UEdge bedge=INVALID;
+ int nlevel=_node_num;
+ {
+ int nnlevel;
+ for(IncEdgeIt tbedge(_g,act);
+ tbedge!=INVALID && nlevel>=actlevel;
+ ++tbedge)
+ if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
+ nlevel)
+ {
+ nlevel=nnlevel;
+ bedge=tbedge;
+ }
+ }
+ if(nlevel<_node_num) {
+ if(nlevel>=actlevel)
+ _levels.liftHighestActiveTo(nlevel+1);
+ bact=_g.bNode(_matching[_g.aNode(bedge)]);
+ if(--_cov[bact]<1) {
+ _levels.activate(bact);
+ last_activated=bact;
+ }
+ _matching[_g.aNode(bedge)]=bedge;
+ _cov[act]=1;
+ _levels.deactivate(act);
+ }
+ else {
+ if(_node_num>actlevel)
+ _levels.liftHighestActiveTo(_node_num);
+ _levels.deactivate(act);
+ }
+
+ if(_levels.onLevel(actlevel)==0)
+ return actlevel;
+ }
+ return -1;
+ }
+
+ template<class GT>
+ void aBarrier(GT &bar,int empty_level=-1)
+ {
+ if(empty_level==-1)
+ for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
+ for(ANodeIt n(_g);n!=INVALID;++n)
+ bar[n] = _matching[n]==INVALID ||
+ _levels[_g.bNode(_matching[n])]<empty_level;
+ }
+ template<class GT>
+ void bBarrier(GT &bar, int empty_level=-1)
+ {
+ if(empty_level==-1)
+ for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
+ for(BNodeIt n(_g);n!=INVALID;++n) bar[n]=(_levels[n]>empty_level);
+ }
+
+ };
+
+
+ ///Maximum cardinality of the matchings in a bipartite graph
+
+ ///\ingroup matching
+ ///This function finds the maximum cardinality of the matchings
+ ///in a bipartite graph \c g.
+ ///\param g An undirected bipartite graph.
+ ///\return The cardinality of the maximum matching.
+ ///
+ ///\note The the implementation is based
+ ///on the push-relabel principle.
+ template<class Graph>
+ int maxBpMatching(const Graph &g)
+ {
+ typename Graph::template ANodeMap<typename Graph::UEdge> matching(g);
+ return maxBpMatching(g,matching);
+ }
+
+ ///Maximum cardinality matching in a bipartite graph
+
+ ///\ingroup matching
+ ///This function finds a maximum cardinality matching
+ ///in a bipartite graph \c g.
+ ///\param g An undirected bipartite graph.
+ ///\retval matching A readwrite ANodeMap of value type \c Edge.
+ /// The found edges will be returned in this map,
+ /// i.e. for an \c ANode \c n,
+ /// the edge <tt>matching[n]</tt> is the one that covers the node \c n, or
+ /// \ref INVALID if it is uncovered.
+ ///\return The cardinality of the maximum matching.
+ ///
+ ///\note The the implementation is based
+ ///on the push-relabel principle.
+ template<class Graph,class MT>
+ int maxBpMatching(const Graph &g,MT &matching)
+ {
+ return BpMatching<Graph,MT>(g,matching).run();
+ }
+
+ ///Maximum cardinality matching in a bipartite graph
+
+ ///\ingroup matching
+ ///This function finds a maximum cardinality matching
+ ///in a bipartite graph \c g.
+ ///\param g An undirected bipartite graph.
+ ///\retval matching A readwrite ANodeMap of value type \c Edge.
+ /// The found edges will be returned in this map,
+ /// i.e. for an \c ANode \c n,
+ /// the edge <tt>matching[n]</tt> is the one that covers the node \c n, or
+ /// \ref INVALID if it is uncovered.
+ ///\retval barrier A \c bool WriteMap on the BNodes. The map will be set
+ /// exactly once for each BNode. The nodes with \c true value represent
+ /// a barrier \e B, i.e. the cardinality of \e B minus the number of its
+ /// neighbor is equal to the number of the <tt>BNode</tt>s minus the
+ /// cardinality of the maximum matching.
+ ///\return The cardinality of the maximum matching.
+ ///
+ ///\note The the implementation is based
+ ///on the push-relabel principle.
+ template<class Graph,class MT, class GT>
+ int maxBpMatching(const Graph &g,MT &matching,GT &barrier)
+ {
+ BpMatching<Graph,MT> bpm(g,matching);
+ int ret=bpm.run();
+ bpm.barrier(barrier);
+ return ret;
+ }
+
+ ///Perfect matching in a bipartite graph
+
+ ///\ingroup matching
+ ///This function checks whether the bipartite graph \c g
+ ///has a perfect matching.
+ ///\param g An undirected bipartite graph.
+ ///\return \c true iff \c g has a perfect matching.
+ ///
+ ///\note The the implementation is based
+ ///on the push-relabel principle.
+ template<class Graph>
+ bool perfectBpMatching(const Graph &g)
+ {
+ typename Graph::template ANodeMap<typename Graph::UEdge> matching(g);
+ return perfectBpMatching(g,matching);
+ }
+
+ ///Perfect matching in a bipartite graph
+
+ ///\ingroup matching
+ ///This function finds a perfect matching in a bipartite graph \c g.
+ ///\param g An undirected bipartite graph.
+ ///\retval matching A readwrite ANodeMap of value type \c Edge.
+ /// The found edges will be returned in this map,
+ /// i.e. for an \c ANode \c n,
+ /// the edge <tt>matching[n]</tt> is the one that covers the node \c n.
+ /// The values are unspecified if the graph
+ /// has no perfect matching.
+ ///\return \c true iff \c g has a perfect matching.
+ ///
+ ///\note The the implementation is based
+ ///on the push-relabel principle.
+ template<class Graph,class MT>
+ bool perfectBpMatching(const Graph &g,MT &matching)
+ {
+ return BpMatching<Graph,MT>(g,matching).runPerfect()<0;
+ }
+
+ ///Perfect matching in a bipartite graph
+
+ ///\ingroup matching
+ ///This function finds a perfect matching in a bipartite graph \c g.
+ ///\param g An undirected bipartite graph.
+ ///\retval matching A readwrite ANodeMap of value type \c Edge.
+ /// The found edges will be returned in this map,
+ /// i.e. for an \c ANode \c n,
+ /// the edge <tt>matching[n]</tt> is the one that covers the node \c n.
+ /// The values are unspecified if the graph
+ /// has no perfect matching.
+ ///\retval barrier A \c bool WriteMap on the BNodes. The map will only
+ /// be set if \c g has no perfect matching. In this case it is set
+ /// exactly once for each BNode. The nodes with \c true value represent
+ /// a barrier, i.e. a subset \e B a of BNodes with the property that
+ /// the cardinality of \e B is greater than the numner of its neighbors.
+ ///\return \c true iff \c g has a perfect matching.
+ ///
+ ///\note The the implementation is based
+ ///on the push-relabel principle.
+ template<class Graph,class MT, class GT>
+ int perfectBpMatching(const Graph &g,MT &matching,GT &barrier)
+ {
+ BpMatching<Graph,MT> bpm(g,matching);
+ int ret=bpm.run();
+ if(ret>=0)
+ bpm.barrier(barrier,ret);
+ return ret<0;
+ }
+}
+
+#endif
More information about the Lemon-commits
mailing list