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