COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/pr_bipartite_matching.h @ 2553:bfced05fa852

Last change on this file since 2553:bfced05fa852 was 2553:bfced05fa852, checked in by Alpar Juttner, 12 years ago

Happy New Year to LEMON (+ better update-copyright-header script)

File size: 18.7 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
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.
12 *
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
15 * purpose.
16 *
17 */
18
19#ifndef LEMON_PR_BIPARTITE_MATCHING
20#define LEMON_PR_BIPARTITE_MATCHING
21
22#include <lemon/graph_utils.h>
23#include <lemon/iterable_maps.h>
24#include <iostream>
25#include <queue>
26#include <lemon/elevator.h>
27
28///\ingroup matching
29///\file
30///\brief Push-prelabel maximum matching algorithms in bipartite graphs.
31///
32namespace lemon {
33
34  ///Max cardinality matching algorithm based on push-relabel principle
35
36  ///\ingroup matching
37  ///Bipartite Max Cardinality Matching algorithm. This class uses the
38  ///push-relabel principle which in several cases has better runtime
39  ///performance than the augmenting path solutions.
40  ///
41  ///\author Alpar Juttner
42  template<class Graph>
43  class PrBipartiteMatching {
44    typedef typename Graph::Node Node;
45    typedef typename Graph::ANodeIt ANodeIt;
46    typedef typename Graph::BNodeIt BNodeIt;
47    typedef typename Graph::UEdge UEdge;
48    typedef typename Graph::UEdgeIt UEdgeIt;
49    typedef typename Graph::IncEdgeIt IncEdgeIt;
50   
51    const Graph &_g;
52    int _node_num;
53    int _matching_size;
54    int _empty_level;
55   
56    typename Graph::template ANodeMap<typename Graph::UEdge> _matching;
57    Elevator<Graph,typename Graph::BNode> _levels;
58    typename Graph::template BNodeMap<int> _cov;
59
60  public:
61
62    /// Constructor
63
64    /// Constructor
65    ///
66    PrBipartiteMatching(const Graph &g) :
67      _g(g),
68      _node_num(countBNodes(g)),
69      _matching(g),
70      _levels(g,_node_num),
71      _cov(g,0)
72    {
73    }
74   
75    /// \name Execution control
76    /// The simplest way to execute the algorithm is to use one of the
77    /// member functions called \c run(). \n
78    /// If you need more control on the execution, first
79    /// you must call \ref init() and then one variant of the start()
80    /// member.
81
82    /// @{
83
84    ///Initialize the data structures
85
86    ///This function constructs a prematching first, which is a
87    ///regular matching on the A-side of the graph, but on the B-side
88    ///each node could cover more matching edges. After that, the
89    ///B-nodes which multiple matched, will be pushed into the lowest
90    ///level of the Elevator. The remaning B-nodes will be pushed to
91    ///the consequent levels respect to a Bfs on following graph: the
92    ///nodes are the B-nodes of the original bipartite graph and two
93    ///nodes are adjacent if a node can pass over a matching edge to
94    ///an other node. The source of the Bfs are the lowest level
95    ///nodes. Last, the reached B-nodes without covered matching edge
96    ///becomes active.
97    void init() {
98      _matching_size=0;
99      _empty_level=_node_num;
100      for(ANodeIt n(_g);n!=INVALID;++n)
101        if((_matching[n]=IncEdgeIt(_g,n))!=INVALID)
102          ++_cov[_g.bNode(_matching[n])];
103
104      std::queue<Node> q;
105      _levels.initStart();
106      for(BNodeIt n(_g);n!=INVALID;++n)
107        if(_cov[n]>1) {
108          _levels.initAddItem(n);
109          q.push(n);
110        }
111      int hlev=0;
112      while(!q.empty()) {
113        Node n=q.front();
114        q.pop();
115        int nlev=_levels[n]+1;
116        for(IncEdgeIt e(_g,n);e!=INVALID;++e) {
117          Node m=_g.runningNode(e);
118          if(e==_matching[m]) {
119            for(IncEdgeIt f(_g,m);f!=INVALID;++f) {
120              Node r=_g.runningNode(f);
121              if(_levels[r]>nlev) {
122                for(;nlev>hlev;hlev++)
123                  _levels.initNewLevel();
124                _levels.initAddItem(r);
125                q.push(r);
126              }
127            }
128          }
129        }
130      }
131      _levels.initFinish();
132      for(BNodeIt n(_g);n!=INVALID;++n)
133        if(_cov[n]<1&&_levels[n]<_node_num)
134          _levels.activate(n);
135    }
136
137    ///Start the main phase of the algorithm
138   
139    ///This algorithm calculates the maximum matching with the
140    ///push-relabel principle. This function should be called just
141    ///after the init() function which already set the initial
142    ///prematching, the level function on the B-nodes and the active,
143    ///ie. unmatched B-nodes.
144    ///
145    ///The algorithm always takes highest active B-node, and it try to
146    ///find a B-node which is eligible to pass over one of it's
147    ///matching edge. This condition holds when the B-node is one
148    ///level lower, and the opposite node of it's matching edge is
149    ///adjacent to the highest active node. In this case the current
150    ///node steals the matching edge and becomes inactive. If there is
151    ///not eligible node then the highest active node should be lift
152    ///to the next proper level.
153    ///
154    ///The nodes should not lift higher than the number of the
155    ///B-nodes, if a node reach this level it remains unmatched. If
156    ///during the execution one level becomes empty the nodes above it
157    ///can be deactivated and lift to the highest level.
158    void start() {
159      Node act;
160      Node bact=INVALID;
161      Node last_activated=INVALID;
162      while((act=_levels.highestActive())!=INVALID) {
163        last_activated=INVALID;
164        int actlevel=_levels[act];
165       
166        UEdge bedge=INVALID;
167        int nlevel=_node_num;
168        {
169          int nnlevel;
170          for(IncEdgeIt tbedge(_g,act);
171              tbedge!=INVALID && nlevel>=actlevel;
172              ++tbedge)
173            if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
174               nlevel)
175              {
176                nlevel=nnlevel;
177                bedge=tbedge;
178              }
179        }
180        if(nlevel<_node_num) {
181          if(nlevel>=actlevel)
182            _levels.liftHighestActive(nlevel+1);
183          bact=_g.bNode(_matching[_g.aNode(bedge)]);
184          if(--_cov[bact]<1) {
185            _levels.activate(bact);
186            last_activated=bact;
187          }
188          _matching[_g.aNode(bedge)]=bedge;
189          _cov[act]=1;
190          _levels.deactivate(act);
191        }
192        else {
193          _levels.liftHighestActiveToTop();
194        }
195
196        if(_levels.emptyLevel(actlevel))
197          _levels.liftToTop(actlevel);
198      }
199     
200      for(ANodeIt n(_g);n!=INVALID;++n) {
201        if (_matching[n]==INVALID)continue;
202        if (_cov[_g.bNode(_matching[n])]>1) {
203          _cov[_g.bNode(_matching[n])]--;
204          _matching[n]=INVALID;
205        } else {
206          ++_matching_size;
207        }
208      }
209    }
210
211    ///Start the algorithm to find a perfect matching
212
213    ///This function is close to identical to the simple start()
214    ///member function but it calculates just perfect matching.
215    ///However, the perfect property is only checked on the B-side of
216    ///the graph
217    ///
218    ///The main difference between the two function is the handling of
219    ///the empty levels. The simple start() function let the nodes
220    ///above the empty levels unmatched while this variant if it find
221    ///an empty level immediately terminates and gives back false
222    ///return value.
223    bool startPerfect() {
224      Node act;
225      Node bact=INVALID;
226      Node last_activated=INVALID;
227      while((act=_levels.highestActive())!=INVALID) {
228        last_activated=INVALID;
229        int actlevel=_levels[act];
230       
231        UEdge bedge=INVALID;
232        int nlevel=_node_num;
233        {
234          int nnlevel;
235          for(IncEdgeIt tbedge(_g,act);
236              tbedge!=INVALID && nlevel>=actlevel;
237              ++tbedge)
238            if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
239               nlevel)
240              {
241                nlevel=nnlevel;
242                bedge=tbedge;
243              }
244        }
245        if(nlevel<_node_num) {
246          if(nlevel>=actlevel)
247            _levels.liftHighestActive(nlevel+1);
248          bact=_g.bNode(_matching[_g.aNode(bedge)]);
249          if(--_cov[bact]<1) {
250            _levels.activate(bact);
251            last_activated=bact;
252          }
253          _matching[_g.aNode(bedge)]=bedge;
254          _cov[act]=1;
255          _levels.deactivate(act);
256        }
257        else {
258          _levels.liftHighestActiveToTop();
259        }
260
261        if(_levels.emptyLevel(actlevel))
262          _empty_level=actlevel;
263          return false;
264      }
265      _matching_size = _node_num;
266      return true;
267    }
268 
269    ///Runs the algorithm
270   
271    ///Just a shortcut for the next code:
272    ///\code
273    /// init();
274    /// start();
275    ///\endcode
276    void run() {
277      init();
278      start();
279    }
280   
281    ///Runs the algorithm to find a perfect matching
282   
283    ///Just a shortcut for the next code:
284    ///\code
285    /// init();
286    /// startPerfect();
287    ///\endcode
288    ///
289    ///\note If the two nodesets of the graph have different size then
290    ///this algorithm checks the perfect property on the B-side.
291    bool runPerfect() {
292      init();
293      return startPerfect();
294    }
295
296    ///Runs the algorithm to find a perfect matching
297   
298    ///Just a shortcut for the next code:
299    ///\code
300    /// init();
301    /// startPerfect();
302    ///\endcode
303    ///
304    ///\note It checks that the size of the two nodesets are equal.
305    bool checkedRunPerfect() {
306      if (countANodes(_g) != _node_num) return false;
307      init();
308      return startPerfect();
309    }
310
311    ///@}
312
313    /// \name Query Functions
314    /// The result of the %Matching algorithm can be obtained using these
315    /// functions.\n
316    /// Before the use of these functions,
317    /// either run() or start() must be called.
318    ///@{
319
320    ///Set true all matching uedge in the map.
321
322    ///Set true all matching uedge in the map. It does not change the
323    ///value mapped to the other uedges.
324    ///\return The number of the matching edges.
325    template <typename MatchingMap>
326    int quickMatching(MatchingMap& mm) const {
327      for (ANodeIt n(_g);n!=INVALID;++n) {
328        if (_matching[n]!=INVALID) mm.set(_matching[n],true);
329      }
330      return _matching_size;
331    }
332
333    ///Set true all matching uedge in the map and the others to false.
334
335    ///Set true all matching uedge in the map and the others to false.
336    ///\return The number of the matching edges.
337    template<class MatchingMap>
338    int matching(MatchingMap& mm) const {
339      for (UEdgeIt e(_g);e!=INVALID;++e) {
340        mm.set(e,e==_matching[_g.aNode(e)]);
341      }
342      return _matching_size;
343    }
344
345    ///Gives back the matching in an ANodeMap.
346
347    ///Gives back the matching in an ANodeMap. The parameter should
348    ///be a write ANodeMap of UEdge values.
349    ///\return The number of the matching edges.
350    template<class MatchingMap>
351    int aMatching(MatchingMap& mm) const {
352      for (ANodeIt n(_g);n!=INVALID;++n) {
353        mm.set(n,_matching[n]);
354      }
355      return _matching_size;
356    }
357
358    ///Gives back the matching in a BNodeMap.
359
360    ///Gives back the matching in a BNodeMap. The parameter should
361    ///be a write BNodeMap of UEdge values.
362    ///\return The number of the matching edges.
363    template<class MatchingMap>
364    int bMatching(MatchingMap& mm) const {
365      for (BNodeIt n(_g);n!=INVALID;++n) {
366        mm.set(n,INVALID);
367      }
368      for (ANodeIt n(_g);n!=INVALID;++n) {
369        if (_matching[n]!=INVALID)
370          mm.set(_g.bNode(_matching[n]),_matching[n]);
371      }
372      return _matching_size;
373    }
374
375
376    ///Returns true if the given uedge is in the matching.
377
378    ///It returns true if the given uedge is in the matching.
379    ///
380    bool matchingEdge(const UEdge& e) const {
381      return _matching[_g.aNode(e)]==e;
382    }
383
384    ///Returns the matching edge from the node.
385
386    ///Returns the matching edge from the node. If there is not such
387    ///edge it gives back \c INVALID. 
388    ///\note If the parameter node is a B-node then the running time is
389    ///propotional to the degree of the node.
390    UEdge matchingEdge(const Node& n) const {
391      if (_g.aNode(n)) {
392        return _matching[n];
393      } else {
394        for (IncEdgeIt e(_g,n);e!=INVALID;++e)
395          if (e==_matching[_g.aNode(e)]) return e;
396        return INVALID;
397      }
398    }
399
400    ///Gives back the number of the matching edges.
401
402    ///Gives back the number of the matching edges.
403    int matchingSize() const {
404      return _matching_size;
405    }
406
407    ///Gives back a barrier on the A-nodes
408   
409    ///The barrier is s subset of the nodes on the same side of the
410    ///graph. If we tried to find a perfect matching and it failed
411    ///then the barrier size will be greater than its neighbours. If
412    ///the maximum matching searched then the barrier size minus its
413    ///neighbours will be exactly the unmatched nodes on the A-side.
414    ///\retval bar A WriteMap on the ANodes with bool value.
415    template<class BarrierMap>
416    void aBarrier(BarrierMap &bar) const
417    {
418      for(ANodeIt n(_g);n!=INVALID;++n)
419        bar.set(n,_matching[n]==INVALID ||
420          _levels[_g.bNode(_matching[n])]<_empty_level); 
421    } 
422
423    ///Gives back a barrier on the B-nodes
424   
425    ///The barrier is s subset of the nodes on the same side of the
426    ///graph. If we tried to find a perfect matching and it failed
427    ///then the barrier size will be greater than its neighbours. If
428    ///the maximum matching searched then the barrier size minus its
429    ///neighbours will be exactly the unmatched nodes on the B-side.
430    ///\retval bar A WriteMap on the BNodes with bool value.
431    template<class BarrierMap>
432    void bBarrier(BarrierMap &bar) const
433    {
434      for(BNodeIt n(_g);n!=INVALID;++n) bar.set(n,_levels[n]>=_empty_level); 
435    }
436
437    ///Returns a minimum covering of the nodes.
438
439    ///The minimum covering set problem is the dual solution of the
440    ///maximum bipartite matching. It provides a solution for this
441    ///problem what is proof of the optimality of the matching.
442    ///\param covering NodeMap of bool values, the nodes of the cover
443    ///set will set true while the others false. 
444    ///\return The size of the cover set.
445    ///\note This function can be called just after the algorithm have
446    ///already found a matching.
447    template<class CoverMap>
448    int coverSet(CoverMap& covering) const {
449      int ret=0;
450      for(BNodeIt n(_g);n!=INVALID;++n) {
451        if (_levels[n]<_empty_level) { covering.set(n,true); ++ret; }
452        else covering.set(n,false);
453      }
454      for(ANodeIt n(_g);n!=INVALID;++n) {
455        if (_matching[n]!=INVALID &&
456            _levels[_g.bNode(_matching[n])]>=_empty_level)
457          { covering.set(n,true); ++ret; }
458        else covering.set(n,false);
459      }
460      return ret;
461    }
462
463
464    /// @}
465   
466  };
467 
468 
469  ///Maximum cardinality of the matchings in a bipartite graph
470
471  ///\ingroup matching
472  ///This function finds the maximum cardinality of the matchings
473  ///in a bipartite graph \c g.
474  ///\param g An undirected bipartite graph.
475  ///\return The cardinality of the maximum matching.
476  ///
477  ///\note The the implementation is based
478  ///on the push-relabel principle.
479  template<class Graph>
480  int prBipartiteMatching(const Graph &g)
481  {
482    PrBipartiteMatching<Graph> bpm(g);
483    return bpm.matchingSize();
484  }
485
486  ///Maximum cardinality matching in a bipartite graph
487
488  ///\ingroup matching
489  ///This function finds a maximum cardinality matching
490  ///in a bipartite graph \c g.
491  ///\param g An undirected bipartite graph.
492  ///\retval matching A write ANodeMap of value type \c UEdge.
493  /// The found edges will be returned in this map,
494  /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
495  /// that covers the node \c n.
496  ///\return The cardinality of the maximum matching.
497  ///
498  ///\note The the implementation is based
499  ///on the push-relabel principle.
500  template<class Graph,class MT>
501  int prBipartiteMatching(const Graph &g,MT &matching)
502  {
503    PrBipartiteMatching<Graph> bpm(g);
504    bpm.run();
505    bpm.aMatching(matching);
506    return bpm.matchingSize();
507  }
508
509  ///Maximum cardinality matching in a bipartite graph
510
511  ///\ingroup matching
512  ///This function finds a maximum cardinality matching
513  ///in a bipartite graph \c g.
514  ///\param g An undirected bipartite graph.
515  ///\retval matching A write ANodeMap of value type \c UEdge.
516  /// The found edges will be returned in this map,
517  /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
518  /// that covers the node \c n.
519  ///\retval barrier A \c bool WriteMap on the BNodes. The map will be set
520  /// exactly once for each BNode. The nodes with \c true value represent
521  /// a barrier \e B, i.e. the cardinality of \e B minus the number of its
522  /// neighbor is equal to the number of the <tt>BNode</tt>s minus the
523  /// cardinality of the maximum matching.
524  ///\return The cardinality of the maximum matching.
525  ///
526  ///\note The the implementation is based
527  ///on the push-relabel principle.
528  template<class Graph,class MT, class GT>
529  int prBipartiteMatching(const Graph &g,MT &matching,GT &barrier)
530  {
531    PrBipartiteMatching<Graph> bpm(g);
532    bpm.run();
533    bpm.aMatching(matching);
534    bpm.bBarrier(barrier);
535    return bpm.matchingSize();
536  } 
537
538  ///Perfect matching in a bipartite graph
539
540  ///\ingroup matching
541  ///This function checks whether the bipartite graph \c g
542  ///has a perfect matching.
543  ///\param g An undirected bipartite graph.
544  ///\return \c true iff \c g has a perfect matching.
545  ///
546  ///\note The the implementation is based
547  ///on the push-relabel principle.
548  template<class Graph>
549  bool prPerfectBipartiteMatching(const Graph &g)
550  {
551    PrBipartiteMatching<Graph> bpm(g);
552    return bpm.runPerfect();
553  }
554
555  ///Perfect matching in a bipartite graph
556
557  ///\ingroup matching
558  ///This function finds a perfect matching in a bipartite graph \c g.
559  ///\param g An undirected bipartite graph.
560  ///\retval matching A write ANodeMap of value type \c UEdge.
561  /// The found edges will be returned in this map,
562  /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
563  /// that covers the node \c n.
564  /// The values are unchanged if the graph
565  /// has no perfect matching.
566  ///\return \c true iff \c g has a perfect matching.
567  ///
568  ///\note The the implementation is based
569  ///on the push-relabel principle.
570  template<class Graph,class MT>
571  bool prPerfectBipartiteMatching(const Graph &g,MT &matching)
572  {
573    PrBipartiteMatching<Graph> bpm(g);
574    bool ret = bpm.checkedRunPerfect();
575    if (ret) bpm.aMatching(matching);
576    return ret;
577  }
578
579  ///Perfect matching in a bipartite graph
580
581  ///\ingroup matching
582  ///This function finds a perfect matching in a bipartite graph \c g.
583  ///\param g An undirected bipartite graph.
584  ///\retval matching A write ANodeMap of value type \c UEdge.
585  /// The found edges will be returned in this map,
586  /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
587  /// that covers the node \c n.
588  /// The values are unchanged if the graph
589  /// has no perfect matching.
590  ///\retval barrier A \c bool WriteMap on the BNodes. The map will only
591  /// be set if \c g has no perfect matching. In this case it is set
592  /// exactly once for each BNode. The nodes with \c true value represent
593  /// a barrier, i.e. a subset \e B a of BNodes with the property that
594  /// the cardinality of \e B is greater than the number of its neighbors.
595  ///\return \c true iff \c g has a perfect matching.
596  ///
597  ///\note The the implementation is based
598  ///on the push-relabel principle.
599  template<class Graph,class MT, class GT>
600  bool prPerfectBipartiteMatching(const Graph &g,MT &matching,GT &barrier)
601  {
602    PrBipartiteMatching<Graph> bpm(g);
603    bool ret=bpm.checkedRunPerfect();
604    if(ret)
605      bpm.aMatching(matching);
606    else
607      bpm.bBarrier(barrier);
608    return ret;
609  } 
610}
611
612#endif
Note: See TracBrowser for help on using the repository browser.