lemon/suurballe.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1875 98698b69a902
child 2276 1a8a66b6c6ce
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@906
    18
alpar@921
    19
#ifndef LEMON_SUURBALLE_H
alpar@921
    20
#define LEMON_SUURBALLE_H
alpar@899
    21
alpar@899
    22
///\ingroup flowalgs
alpar@899
    23
///\file
alpar@899
    24
///\brief An algorithm for finding k paths of minimal total length.
alpar@899
    25
alpar@899
    26
alpar@921
    27
#include <lemon/maps.h>
alpar@899
    28
#include <vector>
alpar@921
    29
#include <lemon/min_cost_flow.h>
alpar@899
    30
alpar@921
    31
namespace lemon {
alpar@899
    32
alpar@899
    33
/// \addtogroup flowalgs
alpar@899
    34
/// @{
alpar@899
    35
alpar@899
    36
  ///\brief Implementation of an algorithm for finding k edge-disjoint paths between 2 nodes 
alpar@899
    37
  /// of minimal total length 
alpar@899
    38
  ///
alpar@921
    39
  /// The class \ref lemon::Suurballe implements
alpar@899
    40
  /// an algorithm for finding k edge-disjoint paths
alpar@899
    41
  /// from a given source node to a given target node in an
alpar@899
    42
  /// edge-weighted directed graph having minimal total weight (length).
alpar@899
    43
  ///
athos@1527
    44
  ///\warning Length values should be nonnegative!
alpar@899
    45
  /// 
alpar@899
    46
  ///\param Graph The directed graph type the algorithm runs on.
alpar@899
    47
  ///\param LengthMap The type of the length map (values should be nonnegative).
alpar@899
    48
  ///
alpar@968
    49
  ///\note It it questionable whether it is correct to call this method after
alpar@1020
    50
  ///%Suurballe for it is just a special case of Edmonds' and Karp's algorithm
alpar@968
    51
  ///for finding minimum cost flows. In fact, this implementation just
alpar@899
    52
  ///wraps the MinCostFlow algorithms. The paper of both %Suurballe and
alpar@899
    53
  ///Edmonds-Karp published in 1972, therefore it is possibly right to
alpar@899
    54
  ///state that they are
alpar@899
    55
  ///independent results. Most frequently this special case is referred as
alpar@899
    56
  ///%Suurballe method in the literature, especially in communication
alpar@899
    57
  ///network context.
alpar@899
    58
  ///\author Attila Bernath
alpar@899
    59
  template <typename Graph, typename LengthMap>
alpar@899
    60
  class Suurballe{
alpar@899
    61
alpar@899
    62
alpar@987
    63
    typedef typename LengthMap::Value Length;
alpar@899
    64
    
alpar@899
    65
    typedef typename Graph::Node Node;
alpar@899
    66
    typedef typename Graph::NodeIt NodeIt;
alpar@899
    67
    typedef typename Graph::Edge Edge;
alpar@899
    68
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@899
    69
    typedef typename Graph::template EdgeMap<int> EdgeIntMap;
alpar@899
    70
alpar@899
    71
    typedef ConstMap<Edge,int> ConstMap;
alpar@899
    72
alpar@899
    73
    const Graph& G;
alpar@899
    74
marci@941
    75
    Node s;
marci@941
    76
    Node t;
marci@941
    77
alpar@899
    78
    //Auxiliary variables
alpar@899
    79
    //This is the capacity map for the mincostflow problem
alpar@899
    80
    ConstMap const1map;
alpar@899
    81
    //This MinCostFlow instance will actually solve the problem
marci@941
    82
    MinCostFlow<Graph, LengthMap, ConstMap> min_cost_flow;
alpar@899
    83
alpar@899
    84
    //Container to store found paths
alpar@899
    85
    std::vector< std::vector<Edge> > paths;
alpar@899
    86
alpar@899
    87
  public :
alpar@899
    88
alpar@899
    89
marci@941
    90
    /*! \brief The constructor of the class.
alpar@899
    91
    
marci@941
    92
    \param _G The directed graph the algorithm runs on. 
marci@941
    93
    \param _length The length (weight or cost) of the edges. 
marci@941
    94
    \param _s Source node.
marci@941
    95
    \param _t Target node.
marci@941
    96
    */
marci@941
    97
    Suurballe(Graph& _G, LengthMap& _length, Node _s, Node _t) : 
marci@941
    98
      G(_G), s(_s), t(_t), const1map(1), 
marci@941
    99
      min_cost_flow(_G, _length, const1map, _s, _t) { }
alpar@899
   100
alpar@899
   101
    ///Runs the algorithm.
alpar@899
   102
alpar@899
   103
    ///Runs the algorithm.
alpar@899
   104
    ///Returns k if there are at least k edge-disjoint paths from s to t.
marci@941
   105
    ///Otherwise it returns the number of edge-disjoint paths found 
marci@941
   106
    ///from s to t.
alpar@899
   107
    ///
alpar@899
   108
    ///\param k How many paths are we looking for?
alpar@899
   109
    ///
marci@941
   110
    int run(int k) {
marci@941
   111
      int i = min_cost_flow.run(k);
alpar@899
   112
alpar@899
   113
      //Let's find the paths
alpar@899
   114
      //We put the paths into stl vectors (as an inner representation). 
alpar@899
   115
      //In the meantime we lose the information stored in 'reversed'.
alpar@899
   116
      //We suppose the lengths to be positive now.
alpar@899
   117
marci@941
   118
      //We don't want to change the flow of min_cost_flow, so we make a copy
alpar@899
   119
      //The name here suggests that the flow has only 0/1 values.
alpar@899
   120
      EdgeIntMap reversed(G); 
alpar@899
   121
alpar@899
   122
      for(typename Graph::EdgeIt e(G); e!=INVALID; ++e) 
marci@941
   123
	reversed[e] = min_cost_flow.getFlow()[e];
alpar@899
   124
      
alpar@899
   125
      paths.clear();
alpar@899
   126
      paths.resize(k);
alpar@899
   127
      for (int j=0; j<i; ++j){
alpar@899
   128
	Node n=s;
alpar@899
   129
alpar@899
   130
	while (n!=t){
alpar@899
   131
klao@946
   132
	  OutEdgeIt e(G, n);
alpar@899
   133
	  
alpar@899
   134
	  while (!reversed[e]){
alpar@899
   135
	    ++e;
alpar@899
   136
	  }
alpar@986
   137
	  n = G.target(e);
alpar@899
   138
	  paths[j].push_back(e);
alpar@899
   139
	  reversed[e] = 1-reversed[e];
alpar@899
   140
	}
alpar@899
   141
	
alpar@899
   142
      }
alpar@899
   143
      return i;
alpar@899
   144
    }
alpar@899
   145
alpar@899
   146
    
marci@941
   147
    ///Returns the total length of the paths.
alpar@899
   148
    
alpar@899
   149
    ///This function gives back the total length of the found paths.
alpar@899
   150
    Length totalLength(){
marci@941
   151
      return min_cost_flow.totalLength();
alpar@899
   152
    }
alpar@899
   153
alpar@899
   154
    ///Returns the found flow.
alpar@899
   155
alpar@899
   156
    ///This function returns a const reference to the EdgeMap \c flow.
marci@941
   157
    const EdgeIntMap &getFlow() const { return min_cost_flow.flow;}
alpar@899
   158
alpar@899
   159
    /// Returns the optimal dual solution
alpar@899
   160
    
alpar@899
   161
    ///This function returns a const reference to the NodeMap
alpar@899
   162
    ///\c potential (the dual solution).
marci@941
   163
    const EdgeIntMap &getPotential() const { return min_cost_flow.potential;}
alpar@899
   164
alpar@899
   165
    ///Checks whether the complementary slackness holds.
alpar@899
   166
alpar@899
   167
    ///This function checks, whether the given solution is optimal.
alpar@899
   168
    ///Currently this function only checks optimality,
athos@1527
   169
    ///doesn't bother with feasibility.
alpar@899
   170
    ///It is meant for testing purposes.
alpar@899
   171
    bool checkComplementarySlackness(){
marci@941
   172
      return min_cost_flow.checkComplementarySlackness();
alpar@899
   173
    }
alpar@899
   174
alpar@899
   175
    ///Read the found paths.
alpar@899
   176
    
alpar@899
   177
    ///This function gives back the \c j-th path in argument p.
athos@1527
   178
    ///Assumes that \c run() has been run and nothing has changed since then.
alpar@899
   179
    /// \warning It is assumed that \c p is constructed to
alpar@899
   180
    ///be a path of graph \c G.
alpar@899
   181
    ///If \c j is not less than the result of previous \c run,
alpar@899
   182
    ///then the result here will be an empty path (\c j can be 0 as well).
alpar@899
   183
    ///
alpar@921
   184
    ///\param Path The type of the path structure to put the result to (must meet lemon path concept).
athos@1527
   185
    ///\param p The path to put the result to.
athos@1527
   186
    ///\param j Which path you want to get from the found paths (in a real application you would get the found paths iteratively).
alpar@899
   187
    template<typename Path>
alpar@899
   188
    void getPath(Path& p, size_t j){
alpar@899
   189
alpar@899
   190
      p.clear();
alpar@899
   191
      if (j>paths.size()-1){
alpar@899
   192
	return;
alpar@899
   193
      }
alpar@899
   194
      typename Path::Builder B(p);
alpar@899
   195
      for(typename std::vector<Edge>::iterator i=paths[j].begin(); 
alpar@899
   196
	  i!=paths[j].end(); ++i ){
alpar@899
   197
	B.pushBack(*i);
alpar@899
   198
      }
alpar@899
   199
alpar@899
   200
      B.commit();
alpar@899
   201
    }
alpar@899
   202
alpar@899
   203
  }; //class Suurballe
alpar@899
   204
alpar@899
   205
  ///@}
alpar@899
   206
alpar@921
   207
} //namespace lemon
alpar@899
   208
alpar@921
   209
#endif //LEMON_SUURBALLE_H