Finished MinLengthPaths: a specialization of MinCostFlows.
authorathos
Tue, 11 May 2004 15:42:11 +0000
changeset 607327f7cf13843
parent 606 81a0c2f2f7c6
child 608 84b04b70ad89
Finished MinLengthPaths: a specialization of MinCostFlows.
src/work/athos/makefile
src/work/athos/mincostflows.h
src/work/athos/minlength_demo.cc
src/work/athos/minlengthpaths.h
src/work/athos/minlengthpaths_test.cc
src/work/athos/old/minlengthpaths.h
src/work/klao/path.h
     1.1 --- a/src/work/athos/makefile	Tue May 11 14:58:09 2004 +0000
     1.2 +++ b/src/work/athos/makefile	Tue May 11 15:42:11 2004 +0000
     1.3 @@ -1,4 +1,4 @@
     1.4 -BINARIES = suurballe minlength_demo mincostflows_test
     1.5 +BINARIES = minlengthpaths_test minlength_demo
     1.6  INCLUDEDIRS= -I../.. -I.. -I../{athos,klao,marci,jacint,alpar,johanna,akos} 
     1.7  include ../makefile
     1.8  
     2.1 --- a/src/work/athos/mincostflows.h	Tue May 11 14:58:09 2004 +0000
     2.2 +++ b/src/work/athos/mincostflows.h	Tue May 11 15:42:11 2004 +0000
     2.3 @@ -8,7 +8,7 @@
     2.4  
     2.5  #include <iostream>
     2.6  #include <hugo/dijkstra.h>
     2.7 -#include <graph_wrapper.h>
     2.8 +#include <hugo/graph_wrapper.h>
     2.9  #include <hugo/maps.h>
    2.10  #include <vector>
    2.11  #include <for_each_macros.h>
    2.12 @@ -77,12 +77,14 @@
    2.13      };//ModLengthMap
    2.14  
    2.15  
    2.16 +  protected:
    2.17      
    2.18      //Input
    2.19      const Graph& G;
    2.20      const LengthMap& length;
    2.21      const CapacityMap& capacity;
    2.22  
    2.23 +
    2.24      //auxiliary variables
    2.25  
    2.26      //To store the flow
    2.27 @@ -98,6 +100,7 @@
    2.28  
    2.29      Length total_length;
    2.30  
    2.31 +
    2.32    public :
    2.33  
    2.34  
    2.35 @@ -110,6 +113,8 @@
    2.36      ///Runs the algorithm.
    2.37      ///Returns k if there are at least k edge-disjoint paths from s to t.
    2.38      ///Otherwise it returns the number of found edge-disjoint paths from s to t.
    2.39 +    ///\todo May be it does make sense to be able to start with a nonzero 
    2.40 +    /// feasible primal-dual solution pair as well.
    2.41      int run(Node s, Node t, int k) {
    2.42  
    2.43        //Resetting variables from previous runs
    2.44 @@ -185,10 +190,20 @@
    2.45        return total_length;
    2.46      }
    2.47  
    2.48 -    //This function checks, whether the given solution is optimal
    2.49 -    //Running after a \c run() should return with true
    2.50 -    //In this "state of the art" this only check optimality, doesn't bother with feasibility
    2.51 -    bool checkSolution(){
    2.52 +    ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
    2.53 +    ///be called before using this function.
    2.54 +    const EdgeIntMap &getFlow() const { return flow;}
    2.55 +
    2.56 +  ///Returns a const reference to the NodeMap \c potential (the dual solution).
    2.57 +    /// \pre \ref run() must be called before using this function.
    2.58 +    const EdgeIntMap &getPotential() const { return potential;}
    2.59 +
    2.60 +    ///This function checks, whether the given solution is optimal
    2.61 +    ///Running after a \c run() should return with true
    2.62 +    ///In this "state of the art" this only check optimality, doesn't bother with feasibility
    2.63 +    ///
    2.64 +    ///\todo Is this OK here?
    2.65 +    bool checkComplementarySlackness(){
    2.66        Length mod_pot;
    2.67        Length fl_e;
    2.68        FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
     3.1 --- a/src/work/athos/minlength_demo.cc	Tue May 11 14:58:09 2004 +0000
     3.2 +++ b/src/work/athos/minlength_demo.cc	Tue May 11 15:42:11 2004 +0000
     3.3 @@ -2,8 +2,9 @@
     3.4  #include <fstream>
     3.5  
     3.6  #include <list_graph.h>
     3.7 -#include <dimacs.h>
     3.8 -#include <minlengthpaths.h>
     3.9 +#include <hugo/dimacs.h>
    3.10 +#include <hugo/time_measure.h>
    3.11 +#include "minlengthpaths.h"
    3.12  //#include <time_measure.h>
    3.13  
    3.14  using namespace hugo;
    3.15 @@ -19,9 +20,9 @@
    3.16    Graph G;
    3.17    Node s, t;
    3.18    Graph::EdgeMap<int> cap(G);
    3.19 -  readDimacsMaxFlow(std::cin, G, s, t, cap);
    3.20 +  readDimacs(std::cin, G, cap, s, t);
    3.21  
    3.22 -  std::cout << "preflow demo (ATHOS)..." << std::endl;
    3.23 +  std::cout << "Minlengthpaths demo (ATHOS)..." << std::endl;
    3.24    //Graph::EdgeMap<int> flow(G); //0 flow
    3.25  
    3.26    //  double pre_time=currTime();
    3.27 @@ -31,8 +32,14 @@
    3.28      k = atoi(argv[1]);
    3.29    MinLengthPaths<Graph, Graph::EdgeMap<int> >
    3.30      surb_test(G,cap);
    3.31 -  std::cout << surb_test.run(s,t,k) << std::endl;
    3.32 -  std::cout << surb_test.totalLength() << std::endl;
    3.33 +  Timer ts;
    3.34 +  ts.reset();
    3.35 +  std::cout << "Number of found paths: " << surb_test.run(s,t,k) << std::endl;
    3.36 +  std::cout << "elapsed time: " << ts << std::endl;
    3.37 +  
    3.38 +  std::cout << "Total length of found paths: " << surb_test.totalLength() << std::endl;
    3.39 +  //std::cout << (surb_test.checkComplementarySlackness() ? "OK (compl. slackn.)." : "Problem (compl. slackn.)!!!") << std::endl;
    3.40 +
    3.41    //preflow_push<Graph, int> max_flow_test(G, s, t, cap);
    3.42    //int flow_value=max_flow_test.run();
    3.43  
     4.1 --- a/src/work/athos/minlengthpaths.h	Tue May 11 14:58:09 2004 +0000
     4.2 +++ b/src/work/athos/minlengthpaths.h	Tue May 11 15:42:11 2004 +0000
     4.3 @@ -7,11 +7,12 @@
     4.4  ///\brief An algorithm for finding k paths of minimal total length.
     4.5  
     4.6  #include <iostream>
     4.7 -#include <dijkstra.h>
     4.8 -#include <graph_wrapper.h>
     4.9 -#include <maps.h>
    4.10 -#include <vector.h>
    4.11 -
    4.12 +//#include <hugo/dijkstra.h>
    4.13 +//#include <hugo/graph_wrapper.h>
    4.14 +#include <hugo/maps.h>
    4.15 +#include <vector>
    4.16 +#include <mincostflows.h>
    4.17 +#include <for_each_macros.h>
    4.18  
    4.19  namespace hugo {
    4.20  
    4.21 @@ -26,9 +27,13 @@
    4.22    /// from a given source node to a given target node in an
    4.23    /// edge-weighted directed graph having minimal total weigth (length).
    4.24    ///
    4.25 +  ///\warning It is assumed that the lengths are positive, since the
    4.26 +  /// general flow-decomposition is not implemented yet.
    4.27 +  ///
    4.28    ///\author Attila Bernath
    4.29    template <typename Graph, typename LengthMap>
    4.30 -  class MinLengthPaths {
    4.31 +  class MinLengthPaths{
    4.32 +
    4.33  
    4.34      typedef typename LengthMap::ValueType Length;
    4.35      
    4.36 @@ -40,114 +45,50 @@
    4.37  
    4.38      typedef ConstMap<Edge,int> ConstMap;
    4.39  
    4.40 -    typedef ResGraphWrapper<const Graph,int,ConstMap,EdgeIntMap> ResGraphType;
    4.41 +    //Input
    4.42 +    const Graph& G;
    4.43  
    4.44 -    class ModLengthMap {   
    4.45 -      typedef typename ResGraphType::template NodeMap<Length> NodeMap;
    4.46 -      const ResGraphType& G;
    4.47 -      const EdgeIntMap& rev;
    4.48 -      const LengthMap &ol;
    4.49 -      const NodeMap &pot;
    4.50 -    public :
    4.51 -      typedef typename LengthMap::KeyType KeyType;
    4.52 -      typedef typename LengthMap::ValueType ValueType;
    4.53 -	
    4.54 -      ValueType operator[](typename ResGraphType::Edge e) const {     
    4.55 -	//if ( (1-2*rev[e])*ol[e]-(pot[G.head(e)]-pot[G.tail(e)] ) <0 ){
    4.56 -	//  std::cout<<"Negative length!!"<<std::endl;
    4.57 -	//}
    4.58 -	return (1-2*rev[e])*ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
    4.59 -      }     
    4.60 -	
    4.61 -      ModLengthMap(const ResGraphType& _G, const EdgeIntMap& _rev, 
    4.62 -		   const LengthMap &o,  const NodeMap &p) : 
    4.63 -	G(_G), rev(_rev), ol(o), pot(p){}; 
    4.64 -    };//ModLengthMap
    4.65 +    //Auxiliary variables
    4.66 +    //This is the capacity map for the mincostflow problem
    4.67 +    ConstMap const1map;
    4.68 +    //This MinCostFlows instance will actually solve the problem
    4.69 +    MinCostFlows<Graph, LengthMap, ConstMap> mincost_flow;
    4.70  
    4.71 -
    4.72 -    
    4.73 -
    4.74 -    const Graph& G;
    4.75 -    const LengthMap& length;
    4.76 -
    4.77 -    //auxiliary variables
    4.78 -
    4.79 -    //The value is 1 iff the edge is reversed. 
    4.80 -    //If the algorithm has finished, the edges of the seeked paths are 
    4.81 -    //exactly those that are reversed 
    4.82 -    EdgeIntMap reversed; 
    4.83 -    
    4.84      //Container to store found paths
    4.85      std::vector< std::vector<Edge> > paths;
    4.86 -    //typedef DirPath<Graph> DPath;
    4.87 -    //DPath paths;
    4.88 -
    4.89 -
    4.90 -    Length total_length;
    4.91  
    4.92    public :
    4.93  
    4.94  
    4.95 -    MinLengthPaths(Graph& _G, LengthMap& _length) : G(_G), 
    4.96 -      length(_length), reversed(_G)/*, dijkstra_dist(_G)*/{ }
    4.97 +    MinLengthPaths(Graph& _G, LengthMap& _length) : G(_G),
    4.98 +      const1map(1), mincost_flow(_G, _length, const1map){}
    4.99  
   4.100 -    
   4.101      ///Runs the algorithm.
   4.102  
   4.103      ///Runs the algorithm.
   4.104      ///Returns k if there are at least k edge-disjoint paths from s to t.
   4.105 -    ///Otherwise it returns the number of found edge-disjoint paths from s to t.
   4.106 +   ///Otherwise it returns the number of found edge-disjoint paths from s to t.
   4.107      int run(Node s, Node t, int k) {
   4.108 -      ConstMap const1map(1);
   4.109  
   4.110 +      int i = mincost_flow.run(s,t,k);
   4.111 +      
   4.112  
   4.113 -      //We need a residual graph, in which some of the edges are reversed
   4.114 -      ResGraphType res_graph(G, const1map, reversed);
   4.115  
   4.116 -      //Initialize the copy of the Dijkstra potential to zero
   4.117 -      typename ResGraphType::template NodeMap<Length> dijkstra_dist(res_graph);
   4.118 -      ModLengthMap mod_length(res_graph, reversed, length, dijkstra_dist);
   4.119 -
   4.120 -      Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length);
   4.121 -
   4.122 -      int i;
   4.123 -      for (i=0; i<k; ++i){
   4.124 -	dijkstra.run(s);
   4.125 -	if (!dijkstra.reached(t)){
   4.126 -	  //There are no k paths from s to t
   4.127 -	  break;
   4.128 -	};
   4.129 -	
   4.130 -	{
   4.131 -	  //We have to copy the potential
   4.132 -	  typename ResGraphType::NodeIt n;
   4.133 -	  for ( res_graph.first(n) ; res_graph.valid(n) ; res_graph.next(n) ) {
   4.134 -	      dijkstra_dist[n] += dijkstra.distMap()[n];
   4.135 -	  }
   4.136 -	}
   4.137 -
   4.138 -
   4.139 -	//Reversing the sortest path
   4.140 -	Node n=t;
   4.141 -	Edge e;
   4.142 -	while (n!=s){
   4.143 -	  e = dijkstra.pred(n);
   4.144 -	  n = dijkstra.predNode(n);
   4.145 -	  reversed[e] = 1-reversed[e];
   4.146 -	}
   4.147 -
   4.148 -	  
   4.149 -      }
   4.150 -      
   4.151        //Let's find the paths
   4.152        //We put the paths into stl vectors (as an inner representation). 
   4.153        //In the meantime we lose the information stored in 'reversed'.
   4.154        //We suppose the lengths to be positive now.
   4.155  
   4.156 -      //Meanwhile we put the total length of the found paths 
   4.157 -      //in the member variable total_length
   4.158 +      //We don't want to change the flow of mincost_flow, so we make a copy
   4.159 +      //The name here suggests that the flow has only 0/1 values.
   4.160 +      EdgeIntMap reversed(G); 
   4.161 +
   4.162 +      FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
   4.163 +	reversed[e] = mincost_flow.getFlow()[e];
   4.164 +      }
   4.165 +      
   4.166        paths.clear();
   4.167 -      total_length=0;
   4.168 +      //total_length=0;
   4.169        paths.resize(k);
   4.170        for (int j=0; j<i; ++j){
   4.171  	Node n=s;
   4.172 @@ -163,27 +104,48 @@
   4.173  	  }
   4.174  	  n = G.head(e);
   4.175  	  paths[j].push_back(e);
   4.176 -	  total_length += length[e];
   4.177 +	  //total_length += length[e];
   4.178  	  reversed[e] = 1-reversed[e];
   4.179  	}
   4.180  	
   4.181        }
   4.182 -
   4.183        return i;
   4.184      }
   4.185  
   4.186 +    
   4.187      ///This function gives back the total length of the found paths.
   4.188      ///Assumes that \c run() has been run and nothing changed since then.
   4.189      Length totalLength(){
   4.190 -      return total_length;
   4.191 +      return mincost_flow.totalLength();
   4.192 +    }
   4.193 +
   4.194 +    ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
   4.195 +    ///be called before using this function.
   4.196 +    const EdgeIntMap &getFlow() const { return mincost_flow.flow;}
   4.197 +
   4.198 +  ///Returns a const reference to the NodeMap \c potential (the dual solution).
   4.199 +    /// \pre \ref run() must be called before using this function.
   4.200 +    const EdgeIntMap &getPotential() const { return mincost_flow.potential;}
   4.201 +
   4.202 +    ///This function checks, whether the given solution is optimal
   4.203 +    ///Running after a \c run() should return with true
   4.204 +    ///In this "state of the art" this only checks optimality, doesn't bother with feasibility
   4.205 +    ///
   4.206 +    ///\todo Is this OK here?
   4.207 +    bool checkComplementarySlackness(){
   4.208 +      return mincost_flow.checkComplementarySlackness();
   4.209      }
   4.210  
   4.211      ///This function gives back the \c j-th path in argument p.
   4.212      ///Assumes that \c run() has been run and nothing changed since then.
   4.213 -    /// \warning It is assumed that \c p is constructed to be a path of graph \c G. If \c j is greater than the result of previous \c run, then the result here will be an empty path.
   4.214 +    /// \warning It is assumed that \c p is constructed to be a path of graph \c G. If \c j is not less than the result of previous \c run, then the result here will be an empty path (\c j can be 0 as well).
   4.215      template<typename DirPath>
   4.216 -    void getPath(DirPath& p, int j){
   4.217 +    void getPath(DirPath& p, size_t j){
   4.218 +      
   4.219        p.clear();
   4.220 +      if (j>paths.size()-1){
   4.221 +	return;
   4.222 +      }
   4.223        typename DirPath::Builder B(p);
   4.224        for(typename std::vector<Edge>::iterator i=paths[j].begin(); 
   4.225  	  i!=paths[j].end(); ++i ){
     5.1 --- a/src/work/athos/minlengthpaths_test.cc	Tue May 11 14:58:09 2004 +0000
     5.2 +++ b/src/work/athos/minlengthpaths_test.cc	Tue May 11 15:42:11 2004 +0000
     5.3 @@ -69,6 +69,8 @@
     5.4  
     5.5    check(  surb_test.run(s,t,k) == 2 && surb_test.totalLength() == 46,"Two paths, total length should be 46");
     5.6  
     5.7 +  check(  surb_test.checkComplementarySlackness(), "Complementary slackness conditions are not met.");
     5.8 +
     5.9    typedef DirPath<ListGraph> DPath;
    5.10    DPath P(graph);
    5.11  
    5.12 @@ -80,6 +82,8 @@
    5.13    
    5.14    k=1;
    5.15    check(  surb_test.run(s,t,k) == 1 && surb_test.totalLength() == 19,"One path, total length should be 19");
    5.16 +
    5.17 +  check(  surb_test.checkComplementarySlackness(), "Complementary slackness conditions are not met.");
    5.18   
    5.19    surb_test.getPath(P,0);
    5.20    check(P.length() == 4, "First path should contain 4 edges.");  
     6.1 --- a/src/work/athos/old/minlengthpaths.h	Tue May 11 14:58:09 2004 +0000
     6.2 +++ b/src/work/athos/old/minlengthpaths.h	Tue May 11 15:42:11 2004 +0000
     6.3 @@ -7,10 +7,10 @@
     6.4  ///\brief An algorithm for finding k paths of minimal total length.
     6.5  
     6.6  #include <iostream>
     6.7 -#include <dijkstra.h>
     6.8 -#include <graph_wrapper.h>
     6.9 -#include <maps.h>
    6.10 -#include <vector.h>
    6.11 +#include <hugo/dijkstra.h>
    6.12 +#include <hugo/graph_wrapper.h>
    6.13 +#include <hugo/maps.h>
    6.14 +#include <vector>
    6.15  
    6.16  
    6.17  namespace hugo {
     7.1 --- a/src/work/klao/path.h	Tue May 11 14:58:09 2004 +0000
     7.2 +++ b/src/work/klao/path.h	Tue May 11 15:42:11 2004 +0000
     7.3 @@ -11,8 +11,8 @@
     7.4  #include <vector>
     7.5  #include <algorithm>
     7.6  
     7.7 -#include <invalid.h>
     7.8 -#include <error.h>
     7.9 +#include <hugo/invalid.h>
    7.10 +#include <hugo/error.h>
    7.11  #include <debug.h>
    7.12  
    7.13  namespace hugo {