Almost ready.
authorathos
Tue, 25 May 2004 12:31:18 +0000
changeset 659c5984e925384
parent 658 b3564d0e9c60
child 660 edb42cb9d352
Almost ready.
src/work/athos/min_cost_flow.cc
src/work/athos/mincostflow.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/work/athos/min_cost_flow.cc	Tue May 25 12:31:18 2004 +0000
     1.3 @@ -0,0 +1,110 @@
     1.4 +#include <iostream>
     1.5 +#include "test_tools.h"
     1.6 +#include <hugo/list_graph.h>
     1.7 +#include <mincostflow.h>
     1.8 +//#include <path.h>
     1.9 +//#include <maps.h>
    1.10 +
    1.11 +using namespace std;
    1.12 +using namespace hugo;
    1.13 +
    1.14 +
    1.15 +
    1.16 +bool passed = true;
    1.17 +/*
    1.18 +void check(bool rc, char *msg="") {
    1.19 +  passed = passed && rc;
    1.20 +  if(!rc) {
    1.21 +    std::cerr << "Test failed! ("<< msg << ")" << std::endl; \
    1.22 + 
    1.23 +
    1.24 +  }
    1.25 +}
    1.26 +*/
    1.27 +
    1.28 +
    1.29 +int main()
    1.30 +{
    1.31 +
    1.32 +  typedef ListGraph::Node Node;
    1.33 +  typedef ListGraph::Edge Edge;
    1.34 +
    1.35 +  ListGraph graph;
    1.36 +
    1.37 +  //Ahuja könyv példája
    1.38 +
    1.39 +  Node s=graph.addNode();
    1.40 +  Node v1=graph.addNode();  
    1.41 +  Node v2=graph.addNode();
    1.42 +  Node v3=graph.addNode();
    1.43 +  Node v4=graph.addNode();
    1.44 +  Node v5=graph.addNode();
    1.45 +  Node t=graph.addNode();
    1.46 +
    1.47 +  Edge s_v1=graph.addEdge(s, v1);
    1.48 +  Edge v1_v2=graph.addEdge(v1, v2);
    1.49 +  Edge s_v3=graph.addEdge(s, v3);
    1.50 +  Edge v2_v4=graph.addEdge(v2, v4);
    1.51 +  Edge v2_v5=graph.addEdge(v2, v5);
    1.52 +  Edge v3_v5=graph.addEdge(v3, v5);
    1.53 +  Edge v4_t=graph.addEdge(v4, t);
    1.54 +  Edge v5_t=graph.addEdge(v5, t);
    1.55 +  
    1.56 +
    1.57 +  ListGraph::EdgeMap<int> length(graph);
    1.58 +
    1.59 +  length.set(s_v1, 6);
    1.60 +  length.set(v1_v2, 4);
    1.61 +  length.set(s_v3, 10);
    1.62 +  length.set(v2_v4, 5);
    1.63 +  length.set(v2_v5, 1);
    1.64 +  length.set(v3_v5, 4);
    1.65 +  length.set(v4_t, 8);
    1.66 +  length.set(v5_t, 8);
    1.67 +
    1.68 +  /*
    1.69 +  ListGraph::EdgeMap<int> capacity(graph);
    1.70 +
    1.71 +  capacity.set(s_v1, 2);
    1.72 +  capacity.set(v1_v2, 2);
    1.73 +  capacity.set(s_v3, 1);
    1.74 +  capacity.set(v2_v4, 1);
    1.75 +  capacity.set(v2_v5, 1);
    1.76 +  capacity.set(v3_v5, 1);
    1.77 +  capacity.set(v4_t, 1);
    1.78 +  capacity.set(v5_t, 2);
    1.79 +  */
    1.80 +
    1.81 +  //  ConstMap<Edge, int> const1map(1);
    1.82 +  std::cout << "Enhanced capacity scaling algorithm test (for the mincostflow problem)..." << std::endl;
    1.83 +
    1.84 +  MinCostFlow< ListGraph, ListGraph::EdgeMap<int>, ListGraph::NodeMap<int> >
    1.85 +    min_cost_flow_test(graph, length, supply_demand);
    1.86 +
    1.87 +  int k=1;
    1.88 +
    1.89 +  /*
    1.90 +  check(  min_cost_flow_test.run(s,t,k) == 1 && min_cost_flow_test.totalLength() == 19,"One path, total length should be 19");
    1.91 +
    1.92 +  check(min_cost_flow_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?");
    1.93 +  
    1.94 +  k=2;
    1.95 +  
    1.96 +  check(  min_cost_flow_test.run(s,t,k) == 2 && min_cost_flow_test.totalLength() == 41,"Two paths, total length should be 41");
    1.97 +
    1.98 +  check(min_cost_flow_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?");
    1.99 +  
   1.100 +  
   1.101 +  k=4;
   1.102 +
   1.103 +  check(  min_cost_flow_test.run(s,t,k) == 3 && min_cost_flow_test.totalLength() == 64,"Three paths, total length should be 64");
   1.104 +
   1.105 +  check(min_cost_flow_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?");
   1.106 +
   1.107 +
   1.108 +  cout << (passed ? "All tests passed." : "Some of the tests failed!!!")
   1.109 +       << endl;
   1.110 +
   1.111 +  return passed ? 0 : 1;
   1.112 +  */
   1.113 +}
     2.1 --- a/src/work/athos/mincostflow.h	Mon May 24 14:13:03 2004 +0000
     2.2 +++ b/src/work/athos/mincostflow.h	Tue May 25 12:31:18 2004 +0000
     2.3 @@ -59,7 +59,7 @@
     2.4      class ModLengthMap {   
     2.5        //typedef typename ResGraphType::template NodeMap<Length> NodeMap;
     2.6        typedef typename Graph::template NodeMap<Length> NodeMap;
     2.7 -      const ResGraphType& G;
     2.8 +      const ResGraphType& res_graph;
     2.9        //      const EdgeIntMap& rev;
    2.10        const LengthMap &ol;
    2.11        const NodeMap &pot;
    2.12 @@ -68,22 +68,22 @@
    2.13        typedef typename LengthMap::ValueType ValueType;
    2.14  	
    2.15        ValueType operator[](typename ResGraphType::Edge e) const {     
    2.16 -	if (G.forward(e))
    2.17 -	  return  ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
    2.18 +	if (res_graph.forward(e))
    2.19 +	  return  ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
    2.20  	else
    2.21 -	  return -ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);   
    2.22 +	  return -ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
    2.23        }     
    2.24  	
    2.25 -      ModLengthMap(const ResGraphType& _G,
    2.26 +      ModLengthMap(const ResGraphType& _res_graph,
    2.27  		   const LengthMap &o,  const NodeMap &p) : 
    2.28 -	G(_G), /*rev(_rev),*/ ol(o), pot(p){}; 
    2.29 +	res_graph(_res_graph), /*rev(_rev),*/ ol(o), pot(p){}; 
    2.30      };//ModLengthMap
    2.31  
    2.32  
    2.33    protected:
    2.34      
    2.35      //Input
    2.36 -    const Graph& G;
    2.37 +    const Graph& graph;
    2.38      const LengthMap& length;
    2.39      const SupplyDemandMap& supply_demand;//supply or demand of nodes
    2.40  
    2.41 @@ -104,8 +104,8 @@
    2.42    public :
    2.43  
    2.44  
    2.45 -    MinCostFlow(Graph& _G, LengthMap& _length, SupplyDemandMap& _supply_demand) : G(_G), 
    2.46 -      length(_length), supply_demand(_supply_demand), flow(_G), potential(_G){ }
    2.47 +    MinCostFlow(Graph& _graph, LengthMap& _length, SupplyDemandMap& _supply_demand) : graph(_graph), 
    2.48 +      length(_length), supply_demand(_supply_demand), flow(_graph), potential(_graph){ }
    2.49  
    2.50      
    2.51      ///Runs the algorithm.
    2.52 @@ -114,7 +114,7 @@
    2.53  
    2.54      ///\todo May be it does make sense to be able to start with a nonzero 
    2.55      /// feasible primal-dual solution pair as well.
    2.56 -    int run() {
    2.57 +    void run() {
    2.58  
    2.59        //Resetting variables from previous runs
    2.60        //total_length = 0;
    2.61 @@ -124,17 +124,18 @@
    2.62  	std::greater<SupplyDemand> > 	HeapType;
    2.63  
    2.64        //A heap for the excess nodes
    2.65 -      HeapMap excess_nodes_map(G,-1);
    2.66 +      HeapMap excess_nodes_map(graph,-1);
    2.67        HeapType excess_nodes(excess_nodes_map);
    2.68  
    2.69        //A heap for the deficit nodes
    2.70 -      HeapMap deficit_nodes_map(G,-1);
    2.71 +      HeapMap deficit_nodes_map(graph,-1);
    2.72        HeapType deficit_nodes(deficit_nodes_map);
    2.73  
    2.74        //A container to store nonabundant arcs
    2.75        list<Edge> nonabundant_arcs;
    2.76 -      
    2.77 -      FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
    2.78 +
    2.79 +	
    2.80 +      FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
    2.81  	flow.set(e,0);
    2.82  	nonabundant_arcs.push_back(e);
    2.83        }
    2.84 @@ -145,12 +146,12 @@
    2.85        typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
    2.86  
    2.87        //A union-find structure to store the abundant components
    2.88 -      UFE::MapType abund_comp_map(G);
    2.89 +      UFE::MapType abund_comp_map(graph);
    2.90        UFE abundant_components(abund_comp_map);
    2.91  
    2.92  
    2.93  
    2.94 -      FOR_EACH_LOC(typename Graph::NodeIt, n, G){
    2.95 +      FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
    2.96         	excess_deficit.set(n,supply_demand[n]);
    2.97  	//A supply node
    2.98  	if (excess_deficit[n] > 0){
    2.99 @@ -174,10 +175,39 @@
   2.100        //can be the maximum deficit here
   2.101        SupplyDemand max_excess = delta;
   2.102        
   2.103 +      //ConstMap<Edge,SupplyDemand> ConstEdgeMap;
   2.104 +
   2.105        //We need a residual graph which is uncapacitated
   2.106 -      ResGraphType res_graph(G, flow);
   2.107 +      ResGraphType res_graph(graph, flow);
   2.108 +      
   2.109 +      //An EdgeMap to tell which arcs are abundant
   2.110 +      template typename Graph::EdgeMap<bool> abundant_arcs(graph);
   2.111  
   2.112 -
   2.113 +      //Let's construct the sugraph consisting only of the abundant edges
   2.114 +      typedef ConstMap< typename Graph::Node, bool > ConstNodeMap;
   2.115 +      ConstNodeMap const_true_map(true);
   2.116 +      typedef SubGraphWrapper< Graph, ConstNodeMap, 
   2.117 +	 template typename Graph::EdgeMap<bool> > 
   2.118 +	AbundantGraph;
   2.119 +      AbundantGraph abundant_graph(graph, const_true_map, abundant_arcs );
   2.120 +      
   2.121 +      //Let's construct the residual graph for the abundant graph
   2.122 +      typedef ResGraphWrapper<const AbundantGraph,int,CapacityMap,EdgeIntMap> 
   2.123 +	ResAbGraph;
   2.124 +      //Again uncapacitated
   2.125 +      ResAbGraph res_ab_graph(abundant_graph, flow);
   2.126 +      
   2.127 +      //We need things for the bfs
   2.128 +      typename ResAbGraph::NodeMap<bool> bfs_reached(res_ab_graph);
   2.129 +      typename ResAbGraph::NodeMap<typename ResAbGraph::Edge> 
   2.130 +	bfs_pred(res_ab_graph); 
   2.131 +      NullMap<typename ResAbGraph::Node, int> bfs_dist_dummy(res_ab_graph);
   2.132 +      //We want to run bfs-es (more) on this graph 'res_ab_graph'
   2.133 +      Bfs < ResAbGraph , 
   2.134 +	typename ResAbGraph::NodeMap<bool>, 
   2.135 +	typename ResAbGraph::NodeMap<typename ResAbGraph::Edge>,
   2.136 +	NullMap<typename ResAbGraph::Node, int> > 
   2.137 +	bfs(res_ab_graph, bfs_reached, bfs_pred, bfs_dist_dummy);
   2.138        
   2.139        ModLengthMap mod_length(res_graph, length, potential);
   2.140  
   2.141 @@ -205,13 +235,55 @@
   2.142  	      Node b = abundant_components.find(res_graph.tail(i));
   2.143  	      //Merge
   2.144  	      if (a != b){
   2.145 -		//Find path and augment
   2.146 -		//!!!
   2.147 -		//Find path and augment
   2.148  		abundant_components.join(a,b);
   2.149 +		//We want to push the smaller
   2.150 +		//Which has greater absolut value excess/deficit
   2.151 +		Node root=(abs(excess_deficit[a])>abs(excess_deficit[b]))?a:b;
   2.152 +		//Which is the other
   2.153 +		Node non_root = ( a == root ) ? b : a ;
   2.154 +		abundant_components.makeRep(root);
   2.155 +		SupplyDemand qty_to_augment = abs(excess_deficit[non_root]); 
   2.156 +		//Push the positive value
   2.157 +		if (excess_deficit[non_root] < 0)
   2.158 +		  swap(root, non_root);
   2.159 +		//If the non_root node has excess/deficit at all
   2.160 +		if (qty_to_augment>0){
   2.161 +		  //Find path and augment
   2.162 +		  bfs.run(non_root);
   2.163 +		  //root should be reached
   2.164 +		  
   2.165 +		  //Augmenting on the found path
   2.166 +		  Node n=root;
   2.167 +		  ResGraphEdge e;
   2.168 +		  while (n!=non_root){
   2.169 +		    e = bfs_pred(n);
   2.170 +		    n = res_graph.tail(e);
   2.171 +		    res_graph.augment(e,qty_to_augment);
   2.172 +		  }
   2.173 +	  
   2.174 +		  //We know that non_root had positive excess
   2.175 +		  excess_nodes[non_root] -= qty_to_augment;
   2.176 +		  //But what about root node
   2.177 +		  //It might have been positive and so became larger
   2.178 +		  if (excess_deficit[root]>0){
   2.179 +		    excess_nodes[root] += qty_to_augment;
   2.180 +		  }
   2.181 +		  else{
   2.182 +		    //Or negative but not turned into positive
   2.183 +		    deficit_nodes[root] -= qty_to_augment;
   2.184 +		  }
   2.185 +
   2.186 +		  //Update the excess_deficit map
   2.187 +		  excess_deficit[non_root] -= qty_to_augment;
   2.188 +		  excess_deficit[root] += qty_to_augment;
   2.189 +
   2.190 +		  
   2.191 +		}
   2.192  	      }
   2.193  	      //What happens to i?
   2.194 -	      nonabundant_arcs.erase(i);
   2.195 +	      //Marci and Zsolt says I shouldn't do such things
   2.196 +	      nonabundant_arcs.erase(i++);
   2.197 +	      abundant_arcs[i] = true;
   2.198  	    }
   2.199  	    else
   2.200  	      ++i;
   2.201 @@ -222,19 +294,19 @@
   2.202  	Node s = excess_nodes.top(); 
   2.203  	SupplyDemand max_excess = excess_nodes[s];
   2.204  	Node t = deficit_nodes.top(); 
   2.205 -	if (max_excess < dificit_nodes[t]){
   2.206 -	  max_excess = dificit_nodes[t];
   2.207 +	if (max_excess < deficit_nodes[t]){
   2.208 +	  max_excess = deficit_nodes[t];
   2.209  	}
   2.210  
   2.211  
   2.212 -	while(max_excess > 0){
   2.213 -
   2.214 +	while(max_excess > (n-1)*delta/n){
   2.215 +	  
   2.216  	  
   2.217  	  //s es t valasztasa
   2.218 -
   2.219 +	  
   2.220  	  //Dijkstra part	
   2.221  	  dijkstra.run(s);
   2.222 -
   2.223 +	  
   2.224  	  /*We know from theory that t can be reached
   2.225  	  if (!dijkstra.reached(t)){
   2.226  	    //There are no k paths from s to t
   2.227 @@ -263,6 +335,11 @@
   2.228  	      total_length -= length[e];	    
   2.229  	    */
   2.230  	  }
   2.231 +	  
   2.232 +	  //Update the excess_deficit map
   2.233 +	  excess_deficit[s] -= delta;
   2.234 +	  excess_deficit[t] += delta;
   2.235 +	  
   2.236  
   2.237  	  //Update the excess_nodes heap
   2.238  	  if (delta >= excess_nodes[s]){
   2.239 @@ -285,6 +362,15 @@
   2.240  	    deficit_nodes[t] -= delta;
   2.241  	  }
   2.242  	  //Dijkstra part ends here
   2.243 +	  
   2.244 +	  //Choose s and t again
   2.245 +	  s = excess_nodes.top(); 
   2.246 +	  max_excess = excess_nodes[s];
   2.247 +	  t = deficit_nodes.top(); 
   2.248 +	  if (max_excess < deficit_nodes[t]){
   2.249 +	    max_excess = deficit_nodes[t];
   2.250 +	  }
   2.251 +
   2.252  	}
   2.253  
   2.254  	/*
   2.255 @@ -297,7 +383,7 @@
   2.256  	/*This is not necessary here
   2.257  	//Update the max_excess
   2.258  	max_excess = 0;
   2.259 -	FOR_EACH_LOC(typename Graph::NodeIt, n, G){
   2.260 +	FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
   2.261  	  if (max_excess < excess_deficit[n]){
   2.262  	    max_excess = excess_deficit[n];
   2.263  	  }
   2.264 @@ -336,9 +422,9 @@
   2.265      bool checkComplementarySlackness(){
   2.266        Length mod_pot;
   2.267        Length fl_e;
   2.268 -      FOR_EACH_LOC(typename Graph::EdgeIt, e, G){
   2.269 +      FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
   2.270  	//C^{\Pi}_{i,j}
   2.271 -	mod_pot = length[e]-potential[G.head(e)]+potential[G.tail(e)];
   2.272 +	mod_pot = length[e]-potential[graph.head(e)]+potential[graph.tail(e)];
   2.273  	fl_e = flow[e];
   2.274  	//	std::cout << fl_e << std::endl;
   2.275  	if (0<fl_e && fl_e<capacity[e]){