lemon/bp_matching.h
author alpar
Thu, 25 Jan 2007 14:38:55 +0000
changeset 2353 c43f8802c90a
child 2391 14a343be7a5a
permissions -rw-r--r--
A push/relabel type max cardinality matching implementation.
(slightly incompatible with bipartite_matching.h)
alpar@2353
     1
/* -*- C++ -*-
alpar@2353
     2
 * lemon/preflow_matching.h - Part of LEMON, a generic C++ optimization library
alpar@2353
     3
 *
alpar@2353
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@2353
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@2353
     6
 *
alpar@2353
     7
 * Permission to use, modify and distribute this software is granted
alpar@2353
     8
 * provided that this copyright notice appears in all copies. For
alpar@2353
     9
 * precise terms see the accompanying LICENSE file.
alpar@2353
    10
 *
alpar@2353
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@2353
    12
 * express or implied, and with no claim as to its suitability for any
alpar@2353
    13
 * purpose.
alpar@2353
    14
 *
alpar@2353
    15
 */
alpar@2353
    16
alpar@2353
    17
#ifndef LEMON_BP_MATCHING
alpar@2353
    18
#define LEMON_BP_MATCHING
alpar@2353
    19
alpar@2353
    20
#include <lemon/graph_utils.h>
alpar@2353
    21
#include <lemon/iterable_maps.h>
alpar@2353
    22
#include <iostream>
alpar@2353
    23
#include <queue>
alpar@2353
    24
#include <lemon/counter.h>
alpar@2353
    25
#include <lemon/elevator.h>
alpar@2353
    26
alpar@2353
    27
///\ingroup matching
alpar@2353
    28
///\file
alpar@2353
    29
///\brief Push-prelabel maximum matching algorithms in bipartite graphs.
alpar@2353
    30
///
alpar@2353
    31
///\todo This file slightly conflicts with \ref lemon/bipartite_matching.h
alpar@2353
    32
///\todo (Re)move the XYZ_TYPEDEFS macros
alpar@2353
    33
namespace lemon {
alpar@2353
    34
alpar@2353
    35
#define BIPARTITE_TYPEDEFS(Graph)		\
alpar@2353
    36
  GRAPH_TYPEDEFS(Graph)				\
alpar@2353
    37
    typedef Graph::ANodeIt ANodeIt;	\
alpar@2353
    38
    typedef Graph::BNodeIt BNodeIt;
alpar@2353
    39
alpar@2353
    40
#define UNDIRBIPARTITE_TYPEDEFS(Graph)		\
alpar@2353
    41
  UNDIRGRAPH_TYPEDEFS(Graph)			\
alpar@2353
    42
    typedef Graph::ANodeIt ANodeIt;	\
alpar@2353
    43
    typedef Graph::BNodeIt BNodeIt;
alpar@2353
    44
alpar@2353
    45
  template<class Graph,
alpar@2353
    46
	   class MT=typename Graph::template ANodeMap<typename Graph::UEdge> >
alpar@2353
    47
  class BpMatching {
alpar@2353
    48
    typedef typename Graph::Node Node;
alpar@2353
    49
    typedef typename Graph::ANodeIt ANodeIt;
alpar@2353
    50
    typedef typename Graph::BNodeIt BNodeIt;
alpar@2353
    51
    typedef typename Graph::UEdge UEdge;
alpar@2353
    52
    typedef typename Graph::IncEdgeIt IncEdgeIt;
alpar@2353
    53
    
alpar@2353
    54
    const Graph &_g;
alpar@2353
    55
    int _node_num;
alpar@2353
    56
    MT &_matching;
alpar@2353
    57
    Elevator<Graph,typename Graph::BNode> _levels;
alpar@2353
    58
    typename Graph::template BNodeMap<int> _cov;
alpar@2353
    59
alpar@2353
    60
  public:
alpar@2353
    61
    BpMatching(const Graph &g, MT &matching) :
alpar@2353
    62
      _g(g),
alpar@2353
    63
      _node_num(countBNodes(g)),
alpar@2353
    64
      _matching(matching),
alpar@2353
    65
      _levels(g,_node_num),
alpar@2353
    66
      _cov(g,0)
alpar@2353
    67
    {
alpar@2353
    68
    }
alpar@2353
    69
    
alpar@2353
    70
  private:
alpar@2353
    71
    void init() 
alpar@2353
    72
    {
alpar@2353
    73
//     for(BNodeIt n(g);n!=INVALID;++n) cov[n]=0;
alpar@2353
    74
      for(ANodeIt n(_g);n!=INVALID;++n)
alpar@2353
    75
	if((_matching[n]=IncEdgeIt(_g,n))!=INVALID)
alpar@2353
    76
	  ++_cov[_g.oppositeNode(n,_matching[n])];
alpar@2353
    77
alpar@2353
    78
      std::queue<Node> q;
alpar@2353
    79
      _levels.initStart();
alpar@2353
    80
      for(BNodeIt n(_g);n!=INVALID;++n)
alpar@2353
    81
	if(_cov[n]>1) {
alpar@2353
    82
	  _levels.initAddItem(n);
alpar@2353
    83
	  q.push(n);
alpar@2353
    84
	}
alpar@2353
    85
      int hlev=0;
alpar@2353
    86
      while(!q.empty()) {
alpar@2353
    87
	Node n=q.front();
alpar@2353
    88
	q.pop();
alpar@2353
    89
	int nlev=_levels[n]+1;
alpar@2353
    90
	for(IncEdgeIt e(_g,n);e!=INVALID;++e) {
alpar@2353
    91
	  Node m=_g.runningNode(e);
alpar@2353
    92
	  if(e==_matching[m]) {
alpar@2353
    93
	    for(IncEdgeIt f(_g,m);f!=INVALID;++f) {
alpar@2353
    94
	      Node r=_g.runningNode(f);
alpar@2353
    95
	      if(_levels[r]>nlev) {
alpar@2353
    96
		for(;nlev>hlev;hlev++)
alpar@2353
    97
		  _levels.initNewLevel();
alpar@2353
    98
		_levels.initAddItem(r);
alpar@2353
    99
		q.push(r);
alpar@2353
   100
	      }
alpar@2353
   101
	    }
alpar@2353
   102
	  }
alpar@2353
   103
	}
alpar@2353
   104
      }
alpar@2353
   105
      _levels.initFinish();
alpar@2353
   106
      for(BNodeIt n(_g);n!=INVALID;++n)
alpar@2353
   107
	if(_cov[n]<1&&_levels[n]<_node_num)
alpar@2353
   108
	  _levels.activate(n);
alpar@2353
   109
    }
alpar@2353
   110
  public:
alpar@2353
   111
    int run() 
alpar@2353
   112
    {
alpar@2353
   113
      init();
alpar@2353
   114
alpar@2353
   115
      Node act;
alpar@2353
   116
      Node bact=INVALID;
alpar@2353
   117
      Node last_activated=INVALID;
alpar@2353
   118
//       while((act=last_activated!=INVALID?
alpar@2353
   119
// 	     last_activated:_levels.highestActive())
alpar@2353
   120
// 	    !=INVALID)
alpar@2353
   121
      while((act=_levels.highestActive())!=INVALID) {
alpar@2353
   122
	last_activated=INVALID;
alpar@2353
   123
	int actlevel=_levels[act];
alpar@2353
   124
	
alpar@2353
   125
	UEdge bedge=INVALID;
alpar@2353
   126
	int nlevel=_node_num;
alpar@2353
   127
	{
alpar@2353
   128
	  int nnlevel;
alpar@2353
   129
	  for(IncEdgeIt tbedge(_g,act);
alpar@2353
   130
	      tbedge!=INVALID && nlevel>=actlevel;
alpar@2353
   131
	      ++tbedge)
alpar@2353
   132
	    if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
alpar@2353
   133
	       nlevel)
alpar@2353
   134
	      {
alpar@2353
   135
		nlevel=nnlevel;
alpar@2353
   136
		bedge=tbedge;
alpar@2353
   137
	      }
alpar@2353
   138
	}
alpar@2353
   139
	if(nlevel<_node_num) {
alpar@2353
   140
	  if(nlevel>=actlevel)
alpar@2353
   141
	    _levels.liftHighestActiveTo(nlevel+1);
alpar@2353
   142
// 	    _levels.liftTo(act,nlevel+1);
alpar@2353
   143
	  bact=_g.bNode(_matching[_g.aNode(bedge)]);
alpar@2353
   144
	  if(--_cov[bact]<1) {
alpar@2353
   145
	    _levels.activate(bact);
alpar@2353
   146
	    last_activated=bact;
alpar@2353
   147
	  }
alpar@2353
   148
	  _matching[_g.aNode(bedge)]=bedge;
alpar@2353
   149
	  _cov[act]=1;
alpar@2353
   150
	  _levels.deactivate(act);
alpar@2353
   151
	}
alpar@2353
   152
	else {
alpar@2353
   153
	  if(_node_num>actlevel) 
alpar@2353
   154
	    _levels.liftHighestActiveTo(_node_num);
alpar@2353
   155
//  	    _levels.liftTo(act,_node_num);
alpar@2353
   156
	  _levels.deactivate(act); 
alpar@2353
   157
	}
alpar@2353
   158
alpar@2353
   159
	if(_levels.onLevel(actlevel)==0)
alpar@2353
   160
	  _levels.liftToTop(actlevel);
alpar@2353
   161
      }
alpar@2353
   162
      
alpar@2353
   163
      int ret=_node_num;
alpar@2353
   164
      for(ANodeIt n(_g);n!=INVALID;++n)
alpar@2353
   165
	if(_matching[n]==INVALID) ret--;
alpar@2353
   166
	else if (_cov[_g.bNode(_matching[n])]>1) {
alpar@2353
   167
	  _cov[_g.bNode(_matching[n])]--;
alpar@2353
   168
	  ret--;
alpar@2353
   169
	  _matching[n]=INVALID;
alpar@2353
   170
	}
alpar@2353
   171
      return ret;
alpar@2353
   172
    }
alpar@2353
   173
    
alpar@2353
   174
    ///\returns -1 if there is a perfect matching, or an empty level
alpar@2353
   175
    ///if it doesn't exists
alpar@2353
   176
    int runPerfect() 
alpar@2353
   177
    {
alpar@2353
   178
      init();
alpar@2353
   179
alpar@2353
   180
      Node act;
alpar@2353
   181
      Node bact=INVALID;
alpar@2353
   182
      Node last_activated=INVALID;
alpar@2353
   183
      while((act=_levels.highestActive())!=INVALID) {
alpar@2353
   184
	last_activated=INVALID;
alpar@2353
   185
	int actlevel=_levels[act];
alpar@2353
   186
	
alpar@2353
   187
	UEdge bedge=INVALID;
alpar@2353
   188
	int nlevel=_node_num;
alpar@2353
   189
	{
alpar@2353
   190
	  int nnlevel;
alpar@2353
   191
	  for(IncEdgeIt tbedge(_g,act);
alpar@2353
   192
	      tbedge!=INVALID && nlevel>=actlevel;
alpar@2353
   193
	      ++tbedge)
alpar@2353
   194
	    if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
alpar@2353
   195
	       nlevel)
alpar@2353
   196
	      {
alpar@2353
   197
		nlevel=nnlevel;
alpar@2353
   198
		bedge=tbedge;
alpar@2353
   199
	      }
alpar@2353
   200
	}
alpar@2353
   201
	if(nlevel<_node_num) {
alpar@2353
   202
	  if(nlevel>=actlevel)
alpar@2353
   203
	    _levels.liftHighestActiveTo(nlevel+1);
alpar@2353
   204
	  bact=_g.bNode(_matching[_g.aNode(bedge)]);
alpar@2353
   205
	  if(--_cov[bact]<1) {
alpar@2353
   206
	    _levels.activate(bact);
alpar@2353
   207
	    last_activated=bact;
alpar@2353
   208
	  }
alpar@2353
   209
	  _matching[_g.aNode(bedge)]=bedge;
alpar@2353
   210
	  _cov[act]=1;
alpar@2353
   211
	  _levels.deactivate(act);
alpar@2353
   212
	}
alpar@2353
   213
	else {
alpar@2353
   214
	  if(_node_num>actlevel) 
alpar@2353
   215
	    _levels.liftHighestActiveTo(_node_num);
alpar@2353
   216
	  _levels.deactivate(act); 
alpar@2353
   217
	}
alpar@2353
   218
alpar@2353
   219
	if(_levels.onLevel(actlevel)==0)
alpar@2353
   220
	  return actlevel;
alpar@2353
   221
      }
alpar@2353
   222
      return -1;
alpar@2353
   223
    }
alpar@2353
   224
 
alpar@2353
   225
    template<class GT>
alpar@2353
   226
    void aBarrier(GT &bar,int empty_level=-1) 
alpar@2353
   227
    {
alpar@2353
   228
      if(empty_level==-1)
alpar@2353
   229
	for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
alpar@2353
   230
      for(ANodeIt n(_g);n!=INVALID;++n)
alpar@2353
   231
	bar[n] = _matching[n]==INVALID ||
alpar@2353
   232
	  _levels[_g.bNode(_matching[n])]<empty_level;  
alpar@2353
   233
    }  
alpar@2353
   234
    template<class GT>
alpar@2353
   235
    void bBarrier(GT &bar, int empty_level=-1) 
alpar@2353
   236
    {
alpar@2353
   237
      if(empty_level==-1)
alpar@2353
   238
	for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
alpar@2353
   239
      for(BNodeIt n(_g);n!=INVALID;++n) bar[n]=(_levels[n]>empty_level);  
alpar@2353
   240
    }  
alpar@2353
   241
  
alpar@2353
   242
  };
alpar@2353
   243
  
alpar@2353
   244
  
alpar@2353
   245
  ///Maximum cardinality of the matchings in a bipartite graph
alpar@2353
   246
alpar@2353
   247
  ///\ingroup matching
alpar@2353
   248
  ///This function finds the maximum cardinality of the matchings
alpar@2353
   249
  ///in a bipartite graph \c g.
alpar@2353
   250
  ///\param g An undirected bipartite graph.
alpar@2353
   251
  ///\return The cardinality of the maximum matching.
alpar@2353
   252
  ///
alpar@2353
   253
  ///\note The the implementation is based
alpar@2353
   254
  ///on the push-relabel principle.
alpar@2353
   255
  template<class Graph>
alpar@2353
   256
  int maxBpMatching(const Graph &g)
alpar@2353
   257
  {
alpar@2353
   258
    typename Graph::template ANodeMap<typename Graph::UEdge> matching(g);
alpar@2353
   259
    return maxBpMatching(g,matching);
alpar@2353
   260
  }
alpar@2353
   261
alpar@2353
   262
  ///Maximum cardinality matching in a bipartite graph
alpar@2353
   263
alpar@2353
   264
  ///\ingroup matching
alpar@2353
   265
  ///This function finds a maximum cardinality matching
alpar@2353
   266
  ///in a bipartite graph \c g.
alpar@2353
   267
  ///\param g An undirected bipartite graph.
alpar@2353
   268
  ///\retval matching A readwrite ANodeMap of value type \c Edge.
alpar@2353
   269
  /// The found edges will be returned in this map,
alpar@2353
   270
  /// i.e. for an \c ANode \c n,
alpar@2353
   271
  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n, or
alpar@2353
   272
  /// \ref INVALID if it is uncovered.
alpar@2353
   273
  ///\return The cardinality of the maximum matching.
alpar@2353
   274
  ///
alpar@2353
   275
  ///\note The the implementation is based
alpar@2353
   276
  ///on the push-relabel principle.
alpar@2353
   277
  template<class Graph,class MT>
alpar@2353
   278
  int maxBpMatching(const Graph &g,MT &matching) 
alpar@2353
   279
  {
alpar@2353
   280
    return BpMatching<Graph,MT>(g,matching).run();
alpar@2353
   281
  }
alpar@2353
   282
alpar@2353
   283
  ///Maximum cardinality matching in a bipartite graph
alpar@2353
   284
alpar@2353
   285
  ///\ingroup matching
alpar@2353
   286
  ///This function finds a maximum cardinality matching
alpar@2353
   287
  ///in a bipartite graph \c g.
alpar@2353
   288
  ///\param g An undirected bipartite graph.
alpar@2353
   289
  ///\retval matching A readwrite ANodeMap of value type \c Edge.
alpar@2353
   290
  /// The found edges will be returned in this map,
alpar@2353
   291
  /// i.e. for an \c ANode \c n,
alpar@2353
   292
  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n, or
alpar@2353
   293
  /// \ref INVALID if it is uncovered.
alpar@2353
   294
  ///\retval barrier A \c bool WriteMap on the BNodes. The map will be set
alpar@2353
   295
  /// exactly once for each BNode. The nodes with \c true value represent
alpar@2353
   296
  /// a barrier \e B, i.e. the cardinality of \e B minus the number of its
alpar@2353
   297
  /// neighbor is equal to the number of the <tt>BNode</tt>s minus the
alpar@2353
   298
  /// cardinality of the maximum matching.
alpar@2353
   299
  ///\return The cardinality of the maximum matching.
alpar@2353
   300
  ///
alpar@2353
   301
  ///\note The the implementation is based
alpar@2353
   302
  ///on the push-relabel principle.
alpar@2353
   303
  template<class Graph,class MT, class GT>
alpar@2353
   304
  int maxBpMatching(const Graph &g,MT &matching,GT &barrier) 
alpar@2353
   305
  {
alpar@2353
   306
    BpMatching<Graph,MT> bpm(g,matching);
alpar@2353
   307
    int ret=bpm.run();
alpar@2353
   308
    bpm.barrier(barrier);
alpar@2353
   309
    return ret;
alpar@2353
   310
  }  
alpar@2353
   311
alpar@2353
   312
  ///Perfect matching in a bipartite graph
alpar@2353
   313
alpar@2353
   314
  ///\ingroup matching
alpar@2353
   315
  ///This function checks whether the bipartite graph \c g
alpar@2353
   316
  ///has a perfect matching.
alpar@2353
   317
  ///\param g An undirected bipartite graph.
alpar@2353
   318
  ///\return \c true iff \c g has a perfect matching.
alpar@2353
   319
  ///
alpar@2353
   320
  ///\note The the implementation is based
alpar@2353
   321
  ///on the push-relabel principle.
alpar@2353
   322
  template<class Graph>
alpar@2353
   323
  bool perfectBpMatching(const Graph &g)
alpar@2353
   324
  {
alpar@2353
   325
    typename Graph::template ANodeMap<typename Graph::UEdge> matching(g);
alpar@2353
   326
    return perfectBpMatching(g,matching);
alpar@2353
   327
  }
alpar@2353
   328
alpar@2353
   329
  ///Perfect matching in a bipartite graph
alpar@2353
   330
alpar@2353
   331
  ///\ingroup matching
alpar@2353
   332
  ///This function finds a perfect matching in a bipartite graph \c g.
alpar@2353
   333
  ///\param g An undirected bipartite graph.
alpar@2353
   334
  ///\retval matching A readwrite ANodeMap of value type \c Edge.
alpar@2353
   335
  /// The found edges will be returned in this map,
alpar@2353
   336
  /// i.e. for an \c ANode \c n,
alpar@2353
   337
  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n.
alpar@2353
   338
  /// The values are unspecified if the graph
alpar@2353
   339
  /// has no perfect matching.
alpar@2353
   340
  ///\return \c true iff \c g has a perfect matching.
alpar@2353
   341
  ///
alpar@2353
   342
  ///\note The the implementation is based
alpar@2353
   343
  ///on the push-relabel principle.
alpar@2353
   344
  template<class Graph,class MT>
alpar@2353
   345
  bool perfectBpMatching(const Graph &g,MT &matching) 
alpar@2353
   346
  {
alpar@2353
   347
    return BpMatching<Graph,MT>(g,matching).runPerfect()<0;
alpar@2353
   348
  }
alpar@2353
   349
alpar@2353
   350
  ///Perfect matching in a bipartite graph
alpar@2353
   351
alpar@2353
   352
  ///\ingroup matching
alpar@2353
   353
  ///This function finds a perfect matching in a bipartite graph \c g.
alpar@2353
   354
  ///\param g An undirected bipartite graph.
alpar@2353
   355
  ///\retval matching A readwrite ANodeMap of value type \c Edge.
alpar@2353
   356
  /// The found edges will be returned in this map,
alpar@2353
   357
  /// i.e. for an \c ANode \c n,
alpar@2353
   358
  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n.
alpar@2353
   359
  /// The values are unspecified if the graph
alpar@2353
   360
  /// has no perfect matching.
alpar@2353
   361
  ///\retval barrier A \c bool WriteMap on the BNodes. The map will only
alpar@2353
   362
  /// be set if \c g has no perfect matching. In this case it is set 
alpar@2353
   363
  /// exactly once for each BNode. The nodes with \c true value represent
alpar@2353
   364
  /// a barrier, i.e. a subset \e B a of BNodes with the property that
alpar@2353
   365
  /// the cardinality of \e B is greater than the numner of its neighbors.
alpar@2353
   366
  ///\return \c true iff \c g has a perfect matching.
alpar@2353
   367
  ///
alpar@2353
   368
  ///\note The the implementation is based
alpar@2353
   369
  ///on the push-relabel principle.
alpar@2353
   370
  template<class Graph,class MT, class GT>
alpar@2353
   371
  int perfectBpMatching(const Graph &g,MT &matching,GT &barrier) 
alpar@2353
   372
  {
alpar@2353
   373
    BpMatching<Graph,MT> bpm(g,matching);
alpar@2353
   374
    int ret=bpm.run();
alpar@2353
   375
    if(ret>=0)
alpar@2353
   376
      bpm.barrier(barrier,ret);
alpar@2353
   377
    return ret<0;
alpar@2353
   378
  }  
alpar@2353
   379
}
alpar@2353
   380
alpar@2353
   381
#endif