lemon/hao_orlin.h
changeset 2217 4a10a45d55f6
child 2225 bb3d5e6f9fcb
equal deleted inserted replaced
-1:000000000000 0:538cdd8b5554
       
     1 /* -*- C++ -*-
       
     2  * lemon/hao_orlin.h - Part of LEMON, a generic C++ optimization library
       
     3  *
       
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
       
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
       
     6  *
       
     7  * Permission to use, modify and distribute this software is granted
       
     8  * provided that this copyright notice appears in all copies. For
       
     9  * precise terms see the accompanying LICENSE file.
       
    10  *
       
    11  * This software is provided "AS IS" with no warranty of any kind,
       
    12  * express or implied, and with no claim as to its suitability for any
       
    13  * purpose.
       
    14  *
       
    15  */
       
    16 
       
    17 #ifndef LEMON_HAO_ORLIN_H
       
    18 #define LEMON_HAO_ORLIN_H
       
    19 
       
    20 #include <vector>
       
    21 #include <queue>
       
    22 #include <limits>
       
    23 
       
    24 #include <lemon/maps.h>
       
    25 #include <lemon/graph_utils.h>
       
    26 #include <lemon/graph_adaptor.h>
       
    27 #include <lemon/iterable_maps.h>
       
    28  
       
    29 
       
    30 /// \file
       
    31 /// \ingroup flowalgs
       
    32 /// Implementation of the Hao-Orlin algorithms class for testing network 
       
    33 /// reliability.
       
    34 
       
    35 namespace lemon {
       
    36 
       
    37   /// \addtogroup flowalgs
       
    38   /// @{                                                   
       
    39 
       
    40   /// %Hao-Orlin algorithm for calculate minimum cut in directed graphs.
       
    41   ///
       
    42   /// Hao-Orlin calculates the minimum cut in directed graphs. It
       
    43   /// separates the nodes of the graph into two disjoint sets and the
       
    44   /// summary of the edge capacities go from the first set to the
       
    45   /// second set is the minimum.  The algorithm is a modified
       
    46   /// push-relabel preflow algorithm and it calculates the minimum cat
       
    47   /// in \f$ O(n^3) \f$ time. The purpose of such algorithm is testing
       
    48   /// network reliability. For sparse undirected graph you can use the
       
    49   /// algorithm of Nagamochi and Ibraki which solves the undirected
       
    50   /// problem in \f$ O(n^3) \f$ time. 
       
    51   ///
       
    52   /// \author Attila Bernath and Balazs Dezso
       
    53   template <typename _Graph,
       
    54 	    typename _CapacityMap = typename _Graph::template EdgeMap<int>,
       
    55             typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
       
    56   class HaoOrlin {
       
    57   protected:
       
    58 
       
    59     typedef _Graph Graph;
       
    60     typedef _CapacityMap CapacityMap;
       
    61     typedef _Tolerance Tolerance;
       
    62 
       
    63     typedef typename CapacityMap::Value Value;
       
    64 
       
    65     
       
    66     typedef typename Graph::Node Node;
       
    67     typedef typename Graph::NodeIt NodeIt;
       
    68     typedef typename Graph::EdgeIt EdgeIt;
       
    69     typedef typename Graph::OutEdgeIt OutEdgeIt;
       
    70     typedef typename Graph::InEdgeIt InEdgeIt;
       
    71 
       
    72     const Graph* _graph;
       
    73     const CapacityMap* _capacity;
       
    74 
       
    75     typedef typename Graph::template EdgeMap<Value> FlowMap;
       
    76 
       
    77     FlowMap* _preflow;
       
    78 
       
    79     Node _source, _target;
       
    80     int _node_num;
       
    81 
       
    82     typedef ResGraphAdaptor<const Graph, Value, CapacityMap, 
       
    83                             FlowMap, Tolerance> ResGraph;
       
    84     typedef typename ResGraph::Node ResNode;
       
    85     typedef typename ResGraph::NodeIt ResNodeIt;
       
    86     typedef typename ResGraph::EdgeIt ResEdgeIt;
       
    87     typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
       
    88     typedef typename ResGraph::Edge ResEdge;
       
    89     typedef typename ResGraph::InEdgeIt ResInEdgeIt;
       
    90 
       
    91     ResGraph* _res_graph;
       
    92 
       
    93     typedef typename Graph::template NodeMap<ResEdge> CurrentArcMap;
       
    94     CurrentArcMap* _current_arc;  
       
    95 
       
    96 
       
    97     typedef IterableBoolMap<Graph, Node> WakeMap;
       
    98     WakeMap* _wake;
       
    99 
       
   100     typedef typename Graph::template NodeMap<int> DistMap;
       
   101     DistMap* _dist;  
       
   102     
       
   103     typedef typename Graph::template NodeMap<Value> ExcessMap;
       
   104     ExcessMap* _excess;
       
   105 
       
   106     typedef typename Graph::template NodeMap<bool> SourceSetMap;
       
   107     SourceSetMap* _source_set;
       
   108 
       
   109     std::vector<int> _level_size;
       
   110 
       
   111     int _highest_active;
       
   112     std::vector<std::list<Node> > _active_nodes;
       
   113 
       
   114     int _dormant_max;
       
   115     std::vector<std::list<Node> > _dormant;
       
   116 
       
   117 
       
   118     Value _min_cut;
       
   119 
       
   120     typedef typename Graph::template NodeMap<bool> MinCutMap;
       
   121     MinCutMap* _min_cut_map;
       
   122 
       
   123     Tolerance _tolerance;
       
   124 
       
   125   public: 
       
   126 
       
   127     HaoOrlin(const Graph& graph, const CapacityMap& capacity, 
       
   128              const Tolerance& tolerance = Tolerance()) :
       
   129       _graph(&graph), _capacity(&capacity), 
       
   130       _preflow(0), _source(), _target(), _res_graph(0), _current_arc(0),
       
   131       _wake(0),_dist(0), _excess(0), _source_set(0), 
       
   132       _highest_active(), _active_nodes(), _dormant_max(), _dormant(), 
       
   133       _min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
       
   134 
       
   135     ~HaoOrlin() {
       
   136       if (_res_graph) {
       
   137         delete _res_graph;
       
   138       }
       
   139       if (_min_cut_map) {
       
   140         delete _min_cut_map;
       
   141       } 
       
   142       if (_current_arc) {
       
   143         delete _current_arc;
       
   144       }
       
   145       if (_source_set) {
       
   146         delete _source_set;
       
   147       }
       
   148       if (_excess) {
       
   149         delete _excess;
       
   150       }
       
   151       if (_dist) {
       
   152         delete _dist;
       
   153       }
       
   154       if (_wake) {
       
   155         delete _wake;
       
   156       }
       
   157       if (_preflow) {
       
   158         delete _preflow;
       
   159       }
       
   160     }
       
   161     
       
   162   private:
       
   163     
       
   164     void relabel(Node i) {
       
   165       int k = (*_dist)[i];
       
   166       if (_level_size[k] == 1) {
       
   167 	++_dormant_max;
       
   168 	for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   169 	  if ((*_wake)[it] && (*_dist)[it] >= k) {
       
   170 	    (*_wake)[it] = false;
       
   171 	    _dormant[_dormant_max].push_front(it);
       
   172 	    --_level_size[(*_dist)[it]];
       
   173 	  }
       
   174 	}
       
   175 	--_highest_active;
       
   176       } else {
       
   177 	ResOutEdgeIt e(*_res_graph, i);
       
   178 	while (e != INVALID && !(*_wake)[_res_graph->target(e)]) {
       
   179 	  ++e;
       
   180 	}
       
   181 
       
   182 	if (e == INVALID){
       
   183 	  ++_dormant_max;
       
   184 	  (*_wake)[i] = false;
       
   185 	  _dormant[_dormant_max].push_front(i);
       
   186 	  --_level_size[(*_dist)[i]];
       
   187 	} else{	    
       
   188 	  Node j = _res_graph->target(e);
       
   189 	  int new_dist = (*_dist)[j];
       
   190 	  ++e;
       
   191 	  while (e != INVALID){
       
   192 	    Node j = _res_graph->target(e);
       
   193 	    if ((*_wake)[j] && new_dist > (*_dist)[j]) {
       
   194 	      new_dist = (*_dist)[j];
       
   195             }
       
   196 	    ++e;
       
   197 	  }
       
   198 	  --_level_size[(*_dist)[i]];
       
   199 	  (*_dist)[i] = new_dist + 1;
       
   200 	  _highest_active = (*_dist)[i];
       
   201 	  _active_nodes[_highest_active].push_front(i);
       
   202 	  ++_level_size[(*_dist)[i]];
       
   203 	  _res_graph->firstOut((*_current_arc)[i], i);
       
   204 	}
       
   205       }
       
   206     }
       
   207 
       
   208     bool selectNewSink(){
       
   209       Node old_target = _target;
       
   210       (*_wake)[_target] = false;
       
   211       --_level_size[(*_dist)[_target]];
       
   212       _dormant[0].push_front(_target);
       
   213       (*_source_set)[_target] = true;
       
   214       if ((int)_dormant[0].size() == _node_num){
       
   215         _dormant[0].clear();
       
   216 	return false;
       
   217       }
       
   218 
       
   219       bool wake_was_empty = false;
       
   220 
       
   221       if(_wake->trueNum() == 0) {
       
   222 	while (!_dormant[_dormant_max].empty()){
       
   223 	  (*_wake)[_dormant[_dormant_max].front()] = true;
       
   224 	  ++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
       
   225 	  _dormant[_dormant_max].pop_front();
       
   226 	}
       
   227 	--_dormant_max;
       
   228 	wake_was_empty = true;
       
   229       }
       
   230 
       
   231       int min_dist = std::numeric_limits<int>::max();
       
   232       for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
       
   233 	if (min_dist > (*_dist)[it]){
       
   234 	  _target = it;
       
   235 	  min_dist = (*_dist)[it];
       
   236 	}
       
   237       }
       
   238 
       
   239       if (wake_was_empty){
       
   240 	for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
       
   241           if (_tolerance.positive((*_excess)[it])) {
       
   242 	    if ((*_wake)[it] && it != _target) {
       
   243 	      _active_nodes[(*_dist)[it]].push_front(it);
       
   244             }
       
   245 	    if (_highest_active < (*_dist)[it]) {
       
   246 	      _highest_active = (*_dist)[it];		    
       
   247             }
       
   248 	  }
       
   249 	}
       
   250       }
       
   251 
       
   252       for (ResOutEdgeIt e(*_res_graph, old_target); e!=INVALID; ++e){
       
   253 	if (!(*_source_set)[_res_graph->target(e)]){
       
   254 	  push(e, _res_graph->rescap(e));
       
   255 	}
       
   256       }
       
   257       
       
   258       return true;
       
   259     }
       
   260     
       
   261     Node findActiveNode() {
       
   262       while (_highest_active > 0 && _active_nodes[_highest_active].empty()){ 
       
   263 	--_highest_active;
       
   264       }
       
   265       if( _highest_active > 0) {
       
   266        	Node n = _active_nodes[_highest_active].front();
       
   267 	_active_nodes[_highest_active].pop_front();
       
   268 	return n;
       
   269       } else {
       
   270 	return INVALID;
       
   271       }
       
   272     }
       
   273 
       
   274     ResEdge findAdmissibleEdge(const Node& n){
       
   275       ResEdge e = (*_current_arc)[n];
       
   276       while (e != INVALID && 
       
   277              ((*_dist)[n] <= (*_dist)[_res_graph->target(e)] || 
       
   278               !(*_wake)[_res_graph->target(e)])) {
       
   279 	_res_graph->nextOut(e);
       
   280       }
       
   281       if (e != INVALID) {
       
   282 	(*_current_arc)[n] = e;	
       
   283 	return e;
       
   284       } else {
       
   285 	return INVALID;
       
   286       }
       
   287     }
       
   288 
       
   289     void push(ResEdge& e,const Value& delta){
       
   290       _res_graph->augment(e, delta);
       
   291       if (!_tolerance.positive(delta)) return;
       
   292       
       
   293       (*_excess)[_res_graph->source(e)] -= delta;
       
   294       Node a = _res_graph->target(e);
       
   295       if (!_tolerance.positive((*_excess)[a]) && (*_wake)[a] && a != _target) {
       
   296 	_active_nodes[(*_dist)[a]].push_front(a);
       
   297 	if (_highest_active < (*_dist)[a]) {
       
   298 	  _highest_active = (*_dist)[a];
       
   299         }
       
   300       }
       
   301       (*_excess)[a] += delta;
       
   302     }
       
   303     
       
   304     Value cutValue() {
       
   305       Value value = 0;
       
   306       for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
       
   307 	for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
       
   308 	  if (!(*_wake)[_graph->source(e)]){
       
   309 	    value += (*_capacity)[e];
       
   310 	  }	
       
   311 	}
       
   312       }
       
   313       return value;
       
   314     }    
       
   315 
       
   316   public:
       
   317 
       
   318     /// \brief Initializes the internal data structures.
       
   319     ///
       
   320     /// Initializes the internal data structures. It creates
       
   321     /// the maps, residual graph adaptor and some bucket structures
       
   322     /// for the algorithm. 
       
   323     void init() {
       
   324       init(NodeIt(*_graph));
       
   325     }
       
   326 
       
   327     /// \brief Initializes the internal data structures.
       
   328     ///
       
   329     /// Initializes the internal data structures. It creates
       
   330     /// the maps, residual graph adaptor and some bucket structures
       
   331     /// for the algorithm. The \c source node is used as the push-relabel
       
   332     /// algorithm's source.
       
   333     void init(const Node& source) {
       
   334       _source = source;
       
   335       _node_num = countNodes(*_graph);
       
   336 
       
   337       _dormant.resize(_node_num);
       
   338       _level_size.resize(_node_num, 0);
       
   339       _active_nodes.resize(_node_num);
       
   340 
       
   341       if (!_preflow) {
       
   342         _preflow = new FlowMap(*_graph);
       
   343       }
       
   344       if (!_wake) {
       
   345         _wake = new WakeMap(*_graph);
       
   346       }
       
   347       if (!_dist) {
       
   348         _dist = new DistMap(*_graph);
       
   349       }
       
   350       if (!_excess) {
       
   351         _excess = new ExcessMap(*_graph);
       
   352       }
       
   353       if (!_source_set) {
       
   354         _source_set = new SourceSetMap(*_graph);
       
   355       }
       
   356       if (!_current_arc) {
       
   357         _current_arc = new CurrentArcMap(*_graph);
       
   358       }
       
   359       if (!_min_cut_map) {
       
   360         _min_cut_map = new MinCutMap(*_graph);
       
   361       }
       
   362       if (!_res_graph) {
       
   363         _res_graph = new ResGraph(*_graph, *_capacity, *_preflow);
       
   364       }
       
   365 
       
   366       _min_cut = std::numeric_limits<Value>::max();
       
   367     }
       
   368 
       
   369 
       
   370     /// \brief Calculates the minimum cut with the \c source node
       
   371     /// in the first partition.
       
   372     ///
       
   373     /// Calculates the minimum cut with the \c source node
       
   374     /// in the first partition.
       
   375     void calculateOut() {
       
   376       for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   377         if (it != _source) {
       
   378           calculateOut(it);
       
   379           return;
       
   380         }
       
   381       }
       
   382     }
       
   383 
       
   384     /// \brief Calculates the minimum cut with the \c source node
       
   385     /// in the first partition.
       
   386     ///
       
   387     /// Calculates the minimum cut with the \c source node
       
   388     /// in the first partition. The \c target is the initial target
       
   389     /// for the push-relabel algorithm.
       
   390     void calculateOut(const Node& target) {
       
   391       for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   392         (*_wake)[it] = true;
       
   393         (*_dist)[it] = 1;
       
   394         (*_excess)[it] = 0;
       
   395         (*_source_set)[it] = false;
       
   396 
       
   397         _res_graph->firstOut((*_current_arc)[it], it);
       
   398       }
       
   399 
       
   400       _target = target;
       
   401       (*_dist)[target] = 0;
       
   402 
       
   403       for (ResOutEdgeIt it(*_res_graph, _source); it != INVALID; ++it) {
       
   404 	push(it, _res_graph->rescap(it));
       
   405       }
       
   406 
       
   407       _dormant[0].push_front(_source);
       
   408       (*_source_set)[_source] = true;
       
   409       _dormant_max = 0;
       
   410       (*_wake)[_source]=false;
       
   411 
       
   412       _level_size[0] = 1;
       
   413       _level_size[1] = _node_num - 1;
       
   414 
       
   415       do {
       
   416 	Node n;
       
   417 	while ((n = findActiveNode()) != INVALID) {
       
   418 	  ResEdge e;
       
   419 	  while (_tolerance.positive((*_excess)[n]) && 
       
   420                  (e = findAdmissibleEdge(n)) != INVALID){
       
   421 	    Value delta;
       
   422 	    if ((*_excess)[n] < _res_graph->rescap(e)) {
       
   423 	      delta = (*_excess)[n];
       
   424 	    } else {
       
   425 	      delta = _res_graph->rescap(e);
       
   426 	      _res_graph->nextOut((*_current_arc)[n]);
       
   427 	    }
       
   428             if (!_tolerance.positive(delta)) continue;
       
   429 	    _res_graph->augment(e, delta);
       
   430 	    (*_excess)[_res_graph->source(e)] -= delta;
       
   431 	    Node a = _res_graph->target(e);
       
   432 	    if (!_tolerance.positive((*_excess)[a]) && a != _target) {
       
   433 	      _active_nodes[(*_dist)[a]].push_front(a);
       
   434 	    }
       
   435 	    (*_excess)[a] += delta;
       
   436 	  }
       
   437 	  if (_tolerance.positive((*_excess)[n])) {
       
   438 	    relabel(n);
       
   439           }
       
   440 	}
       
   441 
       
   442 	Value current_value = cutValue();
       
   443  	if (_min_cut > current_value){
       
   444 	  for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   445             _min_cut_map->set(it, !(*_wake)[it]);
       
   446 	  }
       
   447 
       
   448 	  _min_cut = current_value;
       
   449  	}
       
   450 
       
   451       } while (selectNewSink());
       
   452     }
       
   453 
       
   454     void calculateIn() {
       
   455       for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   456         if (it != _source) {
       
   457           calculateIn(it);
       
   458           return;
       
   459         }
       
   460       }
       
   461     }
       
   462 
       
   463     void run() {
       
   464       init();
       
   465       for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   466         if (it != _source) {
       
   467           startOut(it);
       
   468           //          startIn(it);
       
   469           return;
       
   470         }
       
   471       }
       
   472     }
       
   473 
       
   474     void run(const Node& s) {
       
   475       init(s);
       
   476       for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   477         if (it != _source) {
       
   478           startOut(it);
       
   479           //          startIn(it);
       
   480           return;
       
   481         }
       
   482       }
       
   483     }
       
   484 
       
   485     void run(const Node& s, const Node& t) {
       
   486       init(s);
       
   487       startOut(t);
       
   488       startIn(t);
       
   489     }
       
   490     
       
   491     /// \brief Returns the value of the minimum value cut with node \c
       
   492     /// source on the source side.
       
   493     /// 
       
   494     /// Returns the value of the minimum value cut with node \c source
       
   495     /// on the source side. This function can be called after running
       
   496     /// \ref findMinCut.
       
   497     Value minCut() const {
       
   498       return _min_cut;
       
   499     }
       
   500 
       
   501 
       
   502     /// \brief Returns a minimum value cut.
       
   503     ///
       
   504     /// Sets \c nodeMap to the characteristic vector of a minimum
       
   505     /// value cut with node \c source on the source side. This
       
   506     /// function can be called after running \ref findMinCut.  
       
   507     /// \pre nodeMap should be a bool-valued node-map.
       
   508     template <typename NodeMap>
       
   509     Value minCut(NodeMap& nodeMap) const {
       
   510       for (NodeIt it(*_graph); it != INVALID; ++it) {
       
   511 	nodeMap.set(it, (*_min_cut_map)[it]);
       
   512       }
       
   513       return minCut();
       
   514     }
       
   515     
       
   516   }; //class HaoOrlin 
       
   517 
       
   518 
       
   519 } //namespace lemon
       
   520 
       
   521 #endif //LEMON_HAO_ORLIN_H