# HG changeset patch
# User athos
# Date 1084290131 0
# Node ID 327f7cf13843854e06213cbb88756cd8ea9ec541
# Parent  81a0c2f2f7c61ea4812222f0592b5ad02e26eb6f
Finished MinLengthPaths: a specialization of MinCostFlows.

diff -r 81a0c2f2f7c6 -r 327f7cf13843 src/work/athos/makefile
--- a/src/work/athos/makefile	Tue May 11 14:58:09 2004 +0000
+++ b/src/work/athos/makefile	Tue May 11 15:42:11 2004 +0000
@@ -1,4 +1,4 @@
-BINARIES = suurballe minlength_demo mincostflows_test
+BINARIES = minlengthpaths_test minlength_demo
 INCLUDEDIRS= -I../.. -I.. -I../{athos,klao,marci,jacint,alpar,johanna,akos} 
 include ../makefile
 
diff -r 81a0c2f2f7c6 -r 327f7cf13843 src/work/athos/mincostflows.h
--- a/src/work/athos/mincostflows.h	Tue May 11 14:58:09 2004 +0000
+++ b/src/work/athos/mincostflows.h	Tue May 11 15:42:11 2004 +0000
@@ -8,7 +8,7 @@
 
 #include <iostream>
 #include <hugo/dijkstra.h>
-#include <graph_wrapper.h>
+#include <hugo/graph_wrapper.h>
 #include <hugo/maps.h>
 #include <vector>
 #include <for_each_macros.h>
@@ -77,12 +77,14 @@
     };//ModLengthMap
 
 
+  protected:
     
     //Input
     const Graph& G;
     const LengthMap& length;
     const CapacityMap& capacity;
 
+
     //auxiliary variables
 
     //To store the flow
@@ -98,6 +100,7 @@
 
     Length total_length;
 
+
   public :
 
 
@@ -110,6 +113,8 @@
     ///Runs the algorithm.
     ///Returns k if there are at least k edge-disjoint paths from s to t.
     ///Otherwise it returns the number of found edge-disjoint paths from s to t.
+    ///\todo May be it does make sense to be able to start with a nonzero 
+    /// feasible primal-dual solution pair as well.
     int run(Node s, Node t, int k) {
 
       //Resetting variables from previous runs
@@ -185,10 +190,20 @@
       return total_length;
     }
 
-    //This function checks, whether the given solution is optimal
-    //Running after a \c run() should return with true
-    //In this "state of the art" this only check optimality, doesn't bother with feasibility
-    bool checkSolution(){
+    ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
+    ///be called before using this function.
+    const EdgeIntMap &getFlow() const { return flow;}
+
+  ///Returns a const reference to the NodeMap \c potential (the dual solution).
+    /// \pre \ref run() must be called before using this function.
+    const EdgeIntMap &getPotential() const { return potential;}
+
+    ///This function checks, whether the given solution is optimal
+    ///Running after a \c run() should return with true
+    ///In this "state of the art" this only check optimality, doesn't bother with feasibility
+    ///
+    ///\todo Is this OK here?
+    bool checkComplementarySlackness(){
       Length mod_pot;
       Length fl_e;
       FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
diff -r 81a0c2f2f7c6 -r 327f7cf13843 src/work/athos/minlength_demo.cc
--- a/src/work/athos/minlength_demo.cc	Tue May 11 14:58:09 2004 +0000
+++ b/src/work/athos/minlength_demo.cc	Tue May 11 15:42:11 2004 +0000
@@ -2,8 +2,9 @@
 #include <fstream>
 
 #include <list_graph.h>
-#include <dimacs.h>
-#include <minlengthpaths.h>
+#include <hugo/dimacs.h>
+#include <hugo/time_measure.h>
+#include "minlengthpaths.h"
 //#include <time_measure.h>
 
 using namespace hugo;
@@ -19,9 +20,9 @@
   Graph G;
   Node s, t;
   Graph::EdgeMap<int> cap(G);
-  readDimacsMaxFlow(std::cin, G, s, t, cap);
+  readDimacs(std::cin, G, cap, s, t);
 
-  std::cout << "preflow demo (ATHOS)..." << std::endl;
+  std::cout << "Minlengthpaths demo (ATHOS)..." << std::endl;
   //Graph::EdgeMap<int> flow(G); //0 flow
 
   //  double pre_time=currTime();
@@ -31,8 +32,14 @@
     k = atoi(argv[1]);
   MinLengthPaths<Graph, Graph::EdgeMap<int> >
     surb_test(G,cap);
-  std::cout << surb_test.run(s,t,k) << std::endl;
-  std::cout << surb_test.totalLength() << std::endl;
+  Timer ts;
+  ts.reset();
+  std::cout << "Number of found paths: " << surb_test.run(s,t,k) << std::endl;
+  std::cout << "elapsed time: " << ts << std::endl;
+  
+  std::cout << "Total length of found paths: " << surb_test.totalLength() << std::endl;
+  //std::cout << (surb_test.checkComplementarySlackness() ? "OK (compl. slackn.)." : "Problem (compl. slackn.)!!!") << std::endl;
+
   //preflow_push<Graph, int> max_flow_test(G, s, t, cap);
   //int flow_value=max_flow_test.run();
 
diff -r 81a0c2f2f7c6 -r 327f7cf13843 src/work/athos/minlengthpaths.h
--- a/src/work/athos/minlengthpaths.h	Tue May 11 14:58:09 2004 +0000
+++ b/src/work/athos/minlengthpaths.h	Tue May 11 15:42:11 2004 +0000
@@ -7,11 +7,12 @@
 ///\brief An algorithm for finding k paths of minimal total length.
 
 #include <iostream>
-#include <dijkstra.h>
-#include <graph_wrapper.h>
-#include <maps.h>
-#include <vector.h>
-
+//#include <hugo/dijkstra.h>
+//#include <hugo/graph_wrapper.h>
+#include <hugo/maps.h>
+#include <vector>
+#include <mincostflows.h>
+#include <for_each_macros.h>
 
 namespace hugo {
 
@@ -26,9 +27,13 @@
   /// from a given source node to a given target node in an
   /// edge-weighted directed graph having minimal total weigth (length).
   ///
+  ///\warning It is assumed that the lengths are positive, since the
+  /// general flow-decomposition is not implemented yet.
+  ///
   ///\author Attila Bernath
   template <typename Graph, typename LengthMap>
-  class MinLengthPaths {
+  class MinLengthPaths{
+
 
     typedef typename LengthMap::ValueType Length;
     
@@ -40,114 +45,50 @@
 
     typedef ConstMap<Edge,int> ConstMap;
 
-    typedef ResGraphWrapper<const Graph,int,ConstMap,EdgeIntMap> ResGraphType;
+    //Input
+    const Graph& G;
 
-    class ModLengthMap {   
-      typedef typename ResGraphType::template NodeMap<Length> NodeMap;
-      const ResGraphType& G;
-      const EdgeIntMap& rev;
-      const LengthMap &ol;
-      const NodeMap &pot;
-    public :
-      typedef typename LengthMap::KeyType KeyType;
-      typedef typename LengthMap::ValueType ValueType;
-	
-      ValueType operator[](typename ResGraphType::Edge e) const {     
-	//if ( (1-2*rev[e])*ol[e]-(pot[G.head(e)]-pot[G.tail(e)] ) <0 ){
-	//  std::cout<<"Negative length!!"<<std::endl;
-	//}
-	return (1-2*rev[e])*ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
-      }     
-	
-      ModLengthMap(const ResGraphType& _G, const EdgeIntMap& _rev, 
-		   const LengthMap &o,  const NodeMap &p) : 
-	G(_G), rev(_rev), ol(o), pot(p){}; 
-    };//ModLengthMap
+    //Auxiliary variables
+    //This is the capacity map for the mincostflow problem
+    ConstMap const1map;
+    //This MinCostFlows instance will actually solve the problem
+    MinCostFlows<Graph, LengthMap, ConstMap> mincost_flow;
 
-
-    
-
-    const Graph& G;
-    const LengthMap& length;
-
-    //auxiliary variables
-
-    //The value is 1 iff the edge is reversed. 
-    //If the algorithm has finished, the edges of the seeked paths are 
-    //exactly those that are reversed 
-    EdgeIntMap reversed; 
-    
     //Container to store found paths
     std::vector< std::vector<Edge> > paths;
-    //typedef DirPath<Graph> DPath;
-    //DPath paths;
-
-
-    Length total_length;
 
   public :
 
 
-    MinLengthPaths(Graph& _G, LengthMap& _length) : G(_G), 
-      length(_length), reversed(_G)/*, dijkstra_dist(_G)*/{ }
+    MinLengthPaths(Graph& _G, LengthMap& _length) : G(_G),
+      const1map(1), mincost_flow(_G, _length, const1map){}
 
-    
     ///Runs the algorithm.
 
     ///Runs the algorithm.
     ///Returns k if there are at least k edge-disjoint paths from s to t.
-    ///Otherwise it returns the number of found edge-disjoint paths from s to t.
+   ///Otherwise it returns the number of found edge-disjoint paths from s to t.
     int run(Node s, Node t, int k) {
-      ConstMap const1map(1);
 
+      int i = mincost_flow.run(s,t,k);
+      
 
-      //We need a residual graph, in which some of the edges are reversed
-      ResGraphType res_graph(G, const1map, reversed);
 
-      //Initialize the copy of the Dijkstra potential to zero
-      typename ResGraphType::template NodeMap<Length> dijkstra_dist(res_graph);
-      ModLengthMap mod_length(res_graph, reversed, length, dijkstra_dist);
-
-      Dijkstra<ResGraphType, ModLengthMap> dijkstra(res_graph, mod_length);
-
-      int i;
-      for (i=0; i<k; ++i){
-	dijkstra.run(s);
-	if (!dijkstra.reached(t)){
-	  //There are no k paths from s to t
-	  break;
-	};
-	
-	{
-	  //We have to copy the potential
-	  typename ResGraphType::NodeIt n;
-	  for ( res_graph.first(n) ; res_graph.valid(n) ; res_graph.next(n) ) {
-	      dijkstra_dist[n] += dijkstra.distMap()[n];
-	  }
-	}
-
-
-	//Reversing the sortest path
-	Node n=t;
-	Edge e;
-	while (n!=s){
-	  e = dijkstra.pred(n);
-	  n = dijkstra.predNode(n);
-	  reversed[e] = 1-reversed[e];
-	}
-
-	  
-      }
-      
       //Let's find the paths
       //We put the paths into stl vectors (as an inner representation). 
       //In the meantime we lose the information stored in 'reversed'.
       //We suppose the lengths to be positive now.
 
-      //Meanwhile we put the total length of the found paths 
-      //in the member variable total_length
+      //We don't want to change the flow of mincost_flow, so we make a copy
+      //The name here suggests that the flow has only 0/1 values.
+      EdgeIntMap reversed(G); 
+
+      FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
+	reversed[e] = mincost_flow.getFlow()[e];
+      }
+      
       paths.clear();
-      total_length=0;
+      //total_length=0;
       paths.resize(k);
       for (int j=0; j<i; ++j){
 	Node n=s;
@@ -163,27 +104,48 @@
 	  }
 	  n = G.head(e);
 	  paths[j].push_back(e);
-	  total_length += length[e];
+	  //total_length += length[e];
 	  reversed[e] = 1-reversed[e];
 	}
 	
       }
-
       return i;
     }
 
+    
     ///This function gives back the total length of the found paths.
     ///Assumes that \c run() has been run and nothing changed since then.
     Length totalLength(){
-      return total_length;
+      return mincost_flow.totalLength();
+    }
+
+    ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
+    ///be called before using this function.
+    const EdgeIntMap &getFlow() const { return mincost_flow.flow;}
+
+  ///Returns a const reference to the NodeMap \c potential (the dual solution).
+    /// \pre \ref run() must be called before using this function.
+    const EdgeIntMap &getPotential() const { return mincost_flow.potential;}
+
+    ///This function checks, whether the given solution is optimal
+    ///Running after a \c run() should return with true
+    ///In this "state of the art" this only checks optimality, doesn't bother with feasibility
+    ///
+    ///\todo Is this OK here?
+    bool checkComplementarySlackness(){
+      return mincost_flow.checkComplementarySlackness();
     }
 
     ///This function gives back the \c j-th path in argument p.
     ///Assumes that \c run() has been run and nothing changed since then.
-    /// \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.
+    /// \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).
     template<typename DirPath>
-    void getPath(DirPath& p, int j){
+    void getPath(DirPath& p, size_t j){
+      
       p.clear();
+      if (j>paths.size()-1){
+	return;
+      }
       typename DirPath::Builder B(p);
       for(typename std::vector<Edge>::iterator i=paths[j].begin(); 
 	  i!=paths[j].end(); ++i ){
diff -r 81a0c2f2f7c6 -r 327f7cf13843 src/work/athos/minlengthpaths_test.cc
--- a/src/work/athos/minlengthpaths_test.cc	Tue May 11 14:58:09 2004 +0000
+++ b/src/work/athos/minlengthpaths_test.cc	Tue May 11 15:42:11 2004 +0000
@@ -69,6 +69,8 @@
 
   check(  surb_test.run(s,t,k) == 2 && surb_test.totalLength() == 46,"Two paths, total length should be 46");
 
+  check(  surb_test.checkComplementarySlackness(), "Complementary slackness conditions are not met.");
+
   typedef DirPath<ListGraph> DPath;
   DPath P(graph);
 
@@ -80,6 +82,8 @@
   
   k=1;
   check(  surb_test.run(s,t,k) == 1 && surb_test.totalLength() == 19,"One path, total length should be 19");
+
+  check(  surb_test.checkComplementarySlackness(), "Complementary slackness conditions are not met.");
  
   surb_test.getPath(P,0);
   check(P.length() == 4, "First path should contain 4 edges.");  
diff -r 81a0c2f2f7c6 -r 327f7cf13843 src/work/athos/old/minlengthpaths.h
--- a/src/work/athos/old/minlengthpaths.h	Tue May 11 14:58:09 2004 +0000
+++ b/src/work/athos/old/minlengthpaths.h	Tue May 11 15:42:11 2004 +0000
@@ -7,10 +7,10 @@
 ///\brief An algorithm for finding k paths of minimal total length.
 
 #include <iostream>
-#include <dijkstra.h>
-#include <graph_wrapper.h>
-#include <maps.h>
-#include <vector.h>
+#include <hugo/dijkstra.h>
+#include <hugo/graph_wrapper.h>
+#include <hugo/maps.h>
+#include <vector>
 
 
 namespace hugo {
diff -r 81a0c2f2f7c6 -r 327f7cf13843 src/work/klao/path.h
--- a/src/work/klao/path.h	Tue May 11 14:58:09 2004 +0000
+++ b/src/work/klao/path.h	Tue May 11 15:42:11 2004 +0000
@@ -11,8 +11,8 @@
 #include <vector>
 #include <algorithm>
 
-#include <invalid.h>
-#include <error.h>
+#include <hugo/invalid.h>
+#include <hugo/error.h>
 #include <debug.h>
 
 namespace hugo {