src/work/athos/mincostflow.h
author alpar
Mon, 06 Sep 2004 08:21:42 +0000
changeset 804 6874a72dbdc5
parent 671 708df4dc6ab6
child 921 818510fa3d99
permissions -rw-r--r--
One more thing to do...
athos@610
     1
// -*- c++ -*-
athos@633
     2
#ifndef HUGO_MINCOSTFLOW_H
athos@633
     3
#define HUGO_MINCOSTFLOW_H
athos@610
     4
athos@610
     5
///\ingroup galgs
athos@610
     6
///\file
athos@645
     7
///\brief An algorithm for finding the minimum cost flow of given value in an uncapacitated network
athos@611
     8
athos@610
     9
#include <hugo/dijkstra.h>
athos@610
    10
#include <hugo/graph_wrapper.h>
athos@610
    11
#include <hugo/maps.h>
athos@610
    12
#include <vector>
athos@657
    13
#include <list>
athos@662
    14
#include <values.h>
athos@661
    15
#include <hugo/for_each_macros.h>
athos@661
    16
#include <hugo/unionfind.h>
athos@662
    17
#include <hugo/bin_heap.h>
athos@662
    18
#include <bfs_dfs.h>
athos@610
    19
athos@610
    20
namespace hugo {
athos@610
    21
athos@610
    22
/// \addtogroup galgs
athos@610
    23
/// @{
athos@610
    24
athos@661
    25
  ///\brief Implementation of an algorithm for solving the minimum cost general
athos@661
    26
  /// flow problem in an uncapacitated network
athos@610
    27
  /// 
athos@610
    28
  ///
athos@633
    29
  /// The class \ref hugo::MinCostFlow "MinCostFlow" implements
athos@633
    30
  /// an algorithm for solving the following general minimum cost flow problem>
athos@633
    31
  /// 
athos@633
    32
  ///
athos@633
    33
  ///
athos@633
    34
  /// \warning It is assumed here that the problem has a feasible solution
athos@633
    35
  ///
athos@661
    36
  /// The range of the cost (weight) function is nonnegative reals but 
athos@610
    37
  /// the range of capacity function is the set of nonnegative integers. 
athos@610
    38
  /// It is not a polinomial time algorithm for counting the minimum cost
athos@610
    39
  /// maximal flow, since it counts the minimum cost flow for every value 0..M
athos@610
    40
  /// where \c M is the value of the maximal flow.
athos@610
    41
  ///
athos@610
    42
  ///\author Attila Bernath
athos@661
    43
  template <typename Graph, typename CostMap, typename SupplyDemandMap>
athos@633
    44
  class MinCostFlow {
athos@610
    45
athos@661
    46
    typedef typename CostMap::ValueType Cost;
athos@610
    47
athos@633
    48
athos@635
    49
    typedef typename SupplyDemandMap::ValueType SupplyDemand;
athos@610
    50
    
athos@610
    51
    typedef typename Graph::Node Node;
athos@610
    52
    typedef typename Graph::NodeIt NodeIt;
athos@610
    53
    typedef typename Graph::Edge Edge;
athos@610
    54
    typedef typename Graph::OutEdgeIt OutEdgeIt;
athos@661
    55
    typedef typename Graph::template EdgeMap<SupplyDemand> FlowMap;
athos@661
    56
    typedef ConstMap<Edge,SupplyDemand> ConstEdgeMap;
athos@610
    57
athos@610
    58
    //    typedef ConstMap<Edge,int> ConstMap;
athos@610
    59
athos@661
    60
    typedef ResGraphWrapper<const Graph,int,ConstEdgeMap,FlowMap> ResGraph;
athos@661
    61
    typedef typename ResGraph::Edge ResGraphEdge;
athos@610
    62
athos@661
    63
    class ModCostMap {   
athos@661
    64
      //typedef typename ResGraph::template NodeMap<Cost> NodeMap;
athos@661
    65
      typedef typename Graph::template NodeMap<Cost> NodeMap;
athos@661
    66
      const ResGraph& res_graph;
athos@610
    67
      //      const EdgeIntMap& rev;
athos@661
    68
      const CostMap &ol;
athos@610
    69
      const NodeMap &pot;
athos@610
    70
    public :
athos@661
    71
      typedef typename CostMap::KeyType KeyType;
athos@661
    72
      typedef typename CostMap::ValueType ValueType;
athos@610
    73
	
athos@661
    74
      ValueType operator[](typename ResGraph::Edge e) const {     
athos@659
    75
	if (res_graph.forward(e))
athos@659
    76
	  return  ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
athos@610
    77
	else
athos@659
    78
	  return -ol[e]-(pot[res_graph.head(e)]-pot[res_graph.tail(e)]);   
athos@610
    79
      }     
athos@610
    80
	
athos@661
    81
      ModCostMap(const ResGraph& _res_graph,
athos@661
    82
		   const CostMap &o,  const NodeMap &p) : 
athos@659
    83
	res_graph(_res_graph), /*rev(_rev),*/ ol(o), pot(p){}; 
athos@661
    84
    };//ModCostMap
athos@610
    85
athos@610
    86
athos@610
    87
  protected:
athos@610
    88
    
athos@610
    89
    //Input
athos@659
    90
    const Graph& graph;
athos@661
    91
    const CostMap& cost;
athos@635
    92
    const SupplyDemandMap& supply_demand;//supply or demand of nodes
athos@610
    93
athos@610
    94
athos@610
    95
    //auxiliary variables
athos@610
    96
athos@610
    97
    //To store the flow
athos@661
    98
    FlowMap flow; 
athos@662
    99
    //To store the potential (dual variables)
athos@662
   100
    typedef typename Graph::template NodeMap<Cost> PotentialMap;
athos@662
   101
    PotentialMap potential;
athos@610
   102
    
athos@610
   103
athos@661
   104
    Cost total_cost;
athos@610
   105
athos@610
   106
athos@610
   107
  public :
athos@610
   108
athos@610
   109
athos@662
   110
   MinCostFlow(Graph& _graph, CostMap& _cost, SupplyDemandMap& _supply_demand):
athos@662
   111
     graph(_graph), 
athos@662
   112
     cost(_cost), 
athos@662
   113
     supply_demand(_supply_demand), 
athos@662
   114
     flow(_graph), 
athos@672
   115
     potential(_graph){ }
athos@610
   116
athos@610
   117
    
athos@610
   118
    ///Runs the algorithm.
athos@610
   119
athos@610
   120
    ///Runs the algorithm.
athos@635
   121
athos@610
   122
    ///\todo May be it does make sense to be able to start with a nonzero 
athos@610
   123
    /// feasible primal-dual solution pair as well.
athos@659
   124
    void run() {
athos@610
   125
athos@672
   126
      //To store excess-deficit values
athos@672
   127
      SupplyDemandMap excess_deficit(graph);
athos@672
   128
athos@610
   129
      //Resetting variables from previous runs
athos@661
   130
      //total_cost = 0;
athos@635
   131
athos@672
   132
athos@635
   133
      typedef typename Graph::template NodeMap<int> HeapMap;
athos@662
   134
      typedef BinHeap< Node, SupplyDemand, typename Graph::template NodeMap<int>,
athos@635
   135
	std::greater<SupplyDemand> > 	HeapType;
athos@635
   136
athos@635
   137
      //A heap for the excess nodes
athos@659
   138
      HeapMap excess_nodes_map(graph,-1);
athos@635
   139
      HeapType excess_nodes(excess_nodes_map);
athos@635
   140
athos@635
   141
      //A heap for the deficit nodes
athos@659
   142
      HeapMap deficit_nodes_map(graph,-1);
athos@635
   143
      HeapType deficit_nodes(deficit_nodes_map);
athos@635
   144
athos@657
   145
      //A container to store nonabundant arcs
athos@662
   146
      std::list<Edge> nonabundant_arcs;
athos@659
   147
athos@659
   148
	
athos@659
   149
      FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@610
   150
	flow.set(e,0);
athos@657
   151
	nonabundant_arcs.push_back(e);
athos@610
   152
      }
athos@633
   153
athos@633
   154
      //Initial value for delta
athos@635
   155
      SupplyDemand delta = 0;
athos@635
   156
athos@657
   157
      typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
athos@657
   158
athos@657
   159
      //A union-find structure to store the abundant components
athos@662
   160
      typename UFE::MapType abund_comp_map(graph);
athos@657
   161
      UFE abundant_components(abund_comp_map);
athos@657
   162
athos@657
   163
athos@657
   164
athos@659
   165
      FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@635
   166
       	excess_deficit.set(n,supply_demand[n]);
athos@635
   167
	//A supply node
athos@635
   168
	if (excess_deficit[n] > 0){
athos@635
   169
	  excess_nodes.push(n,excess_deficit[n]);
athos@633
   170
	}
athos@635
   171
	//A demand node
athos@635
   172
	if (excess_deficit[n] < 0){
athos@635
   173
	  deficit_nodes.push(n, - excess_deficit[n]);
athos@635
   174
	}
athos@635
   175
	//Finding out starting value of delta
athos@635
   176
	if (delta < abs(excess_deficit[n])){
athos@635
   177
	  delta = abs(excess_deficit[n]);
athos@635
   178
	}
athos@633
   179
	//Initialize the copy of the Dijkstra potential to zero
athos@610
   180
	potential.set(n,0);
athos@657
   181
	//Every single point is an abundant component initially 
athos@657
   182
	abundant_components.insert(n);
athos@610
   183
      }
athos@610
   184
athos@635
   185
      //It'll be allright as an initial value, though this value 
athos@635
   186
      //can be the maximum deficit here
athos@635
   187
      SupplyDemand max_excess = delta;
athos@610
   188
      
athos@661
   189
      ///\bug This is a serious cheat here, before we have an uncapacitated ResGraph
athos@662
   190
      ConstEdgeMap const_inf_map(MAXINT);
athos@661
   191
      
athos@633
   192
      //We need a residual graph which is uncapacitated
athos@661
   193
      ResGraph res_graph(graph, const_inf_map, flow);
athos@659
   194
      
athos@659
   195
      //An EdgeMap to tell which arcs are abundant
athos@662
   196
      typename Graph::template EdgeMap<bool> abundant_arcs(graph);
athos@610
   197
athos@659
   198
      //Let's construct the sugraph consisting only of the abundant edges
athos@659
   199
      typedef ConstMap< typename Graph::Node, bool > ConstNodeMap;
athos@672
   200
athos@659
   201
      ConstNodeMap const_true_map(true);
athos@662
   202
      typedef SubGraphWrapper< const Graph, ConstNodeMap, 
athos@662
   203
	 typename Graph::template EdgeMap<bool> > 
athos@659
   204
	AbundantGraph;
athos@659
   205
      AbundantGraph abundant_graph(graph, const_true_map, abundant_arcs );
athos@659
   206
      
athos@659
   207
      //Let's construct the residual graph for the abundant graph
athos@662
   208
      typedef ResGraphWrapper<const AbundantGraph,int,ConstEdgeMap,FlowMap> 
athos@659
   209
	ResAbGraph;
athos@659
   210
      //Again uncapacitated
athos@661
   211
      ResAbGraph res_ab_graph(abundant_graph, const_inf_map, flow);
athos@659
   212
      
athos@659
   213
      //We need things for the bfs
athos@662
   214
      typename ResAbGraph::template NodeMap<bool> bfs_reached(res_ab_graph);
athos@662
   215
      typename ResAbGraph::template NodeMap<typename ResAbGraph::Edge> 
athos@659
   216
	bfs_pred(res_ab_graph); 
athos@662
   217
      NullMap<typename ResAbGraph::Node, int> bfs_dist_dummy;
athos@671
   218
      //Teszt celbol:
athos@671
   219
      //BfsIterator<ResAbGraph, typename ResAbGraph::template NodeMap<bool> > 
athos@671
   220
      //izebize(res_ab_graph, bfs_reached);
athos@659
   221
      //We want to run bfs-es (more) on this graph 'res_ab_graph'
athos@671
   222
      Bfs < const ResAbGraph , 
athos@662
   223
	typename ResAbGraph::template NodeMap<bool>, 
athos@662
   224
	typename ResAbGraph::template NodeMap<typename ResAbGraph::Edge>,
athos@659
   225
	NullMap<typename ResAbGraph::Node, int> > 
athos@659
   226
	bfs(res_ab_graph, bfs_reached, bfs_pred, bfs_dist_dummy);
athos@662
   227
      /*This is what Marci wants for a bfs
athos@662
   228
	template <typename Graph, 
athos@662
   229
	    typename ReachedMap=typename Graph::template NodeMap<bool>, 
athos@662
   230
	    typename PredMap
athos@662
   231
	    =typename Graph::template NodeMap<typename Graph::Edge>, 
athos@662
   232
	    typename DistMap=typename Graph::template NodeMap<int> > 
athos@662
   233
	    class Bfs : public BfsIterator<Graph, ReachedMap> {
athos@662
   234
athos@662
   235
       */
athos@610
   236
      
athos@661
   237
      ModCostMap mod_cost(res_graph, cost, potential);
athos@610
   238
athos@661
   239
      Dijkstra<ResGraph, ModCostMap> dijkstra(res_graph, mod_cost);
athos@610
   240
athos@671
   241
      //We will use the number of the nodes of the graph often
athos@671
   242
      int number_of_nodes = graph.nodeNum();
athos@633
   243
athos@635
   244
      while (max_excess > 0){
athos@635
   245
athos@657
   246
	//Reset delta if still too big
athos@657
   247
	if (8*number_of_nodes*max_excess <= delta){
athos@657
   248
	  delta = max_excess;
athos@657
   249
	  
athos@657
   250
	}
athos@657
   251
athos@645
   252
	/*
athos@645
   253
	 * Beginning of the delta scaling phase 
athos@645
   254
	*/
athos@635
   255
	//Merge and stuff
athos@657
   256
	{
athos@657
   257
	  SupplyDemand buf=8*number_of_nodes*delta;
athos@662
   258
	  typename std::list<Edge>::iterator i = nonabundant_arcs.begin();
athos@657
   259
	  while ( i != nonabundant_arcs.end() ){
athos@671
   260
	    if (flow[*i]>=buf){
athos@671
   261
	      Node a = abundant_components.find(res_graph.head(*i));
athos@671
   262
	      Node b = abundant_components.find(res_graph.tail(*i));
athos@657
   263
	      //Merge
athos@657
   264
	      if (a != b){
athos@657
   265
		abundant_components.join(a,b);
athos@659
   266
		//We want to push the smaller
athos@659
   267
		//Which has greater absolut value excess/deficit
athos@659
   268
		Node root=(abs(excess_deficit[a])>abs(excess_deficit[b]))?a:b;
athos@659
   269
		//Which is the other
athos@659
   270
		Node non_root = ( a == root ) ? b : a ;
athos@659
   271
		abundant_components.makeRep(root);
athos@659
   272
		SupplyDemand qty_to_augment = abs(excess_deficit[non_root]); 
athos@659
   273
		//Push the positive value
athos@659
   274
		if (excess_deficit[non_root] < 0)
athos@659
   275
		  swap(root, non_root);
athos@659
   276
		//If the non_root node has excess/deficit at all
athos@659
   277
		if (qty_to_augment>0){
athos@659
   278
		  //Find path and augment
athos@671
   279
		  bfs.run(typename AbundantGraph::Node(non_root));
athos@659
   280
		  //root should be reached
athos@659
   281
		  
athos@659
   282
		  //Augmenting on the found path
athos@659
   283
		  Node n=root;
athos@659
   284
		  ResGraphEdge e;
athos@659
   285
		  while (n!=non_root){
athos@671
   286
		    e = bfs_pred[n];
athos@659
   287
		    n = res_graph.tail(e);
athos@659
   288
		    res_graph.augment(e,qty_to_augment);
athos@659
   289
		  }
athos@659
   290
	  
athos@659
   291
		  //We know that non_root had positive excess
athos@671
   292
		  excess_nodes.set(non_root,
athos@671
   293
				   excess_nodes[non_root] - qty_to_augment);
athos@659
   294
		  //But what about root node
athos@659
   295
		  //It might have been positive and so became larger
athos@659
   296
		  if (excess_deficit[root]>0){
athos@671
   297
		    excess_nodes.set(root, 
athos@671
   298
				     excess_nodes[root] + qty_to_augment);
athos@659
   299
		  }
athos@659
   300
		  else{
athos@659
   301
		    //Or negative but not turned into positive
athos@671
   302
		    deficit_nodes.set(root, 
athos@671
   303
				      deficit_nodes[root] - qty_to_augment);
athos@659
   304
		  }
athos@659
   305
athos@659
   306
		  //Update the excess_deficit map
athos@659
   307
		  excess_deficit[non_root] -= qty_to_augment;
athos@659
   308
		  excess_deficit[root] += qty_to_augment;
athos@659
   309
athos@659
   310
		  
athos@659
   311
		}
athos@657
   312
	      }
athos@657
   313
	      //What happens to i?
athos@659
   314
	      //Marci and Zsolt says I shouldn't do such things
athos@659
   315
	      nonabundant_arcs.erase(i++);
athos@671
   316
	      abundant_arcs[*i] = true;
athos@657
   317
	    }
athos@657
   318
	    else
athos@657
   319
	      ++i;
athos@657
   320
	  }
athos@657
   321
	}
athos@657
   322
athos@635
   323
athos@635
   324
	Node s = excess_nodes.top(); 
athos@672
   325
	max_excess = excess_nodes[s];
athos@635
   326
	Node t = deficit_nodes.top(); 
athos@659
   327
	if (max_excess < deficit_nodes[t]){
athos@659
   328
	  max_excess = deficit_nodes[t];
athos@635
   329
	}
athos@635
   330
athos@635
   331
athos@662
   332
	while(max_excess > (number_of_nodes-1)*delta/number_of_nodes){
athos@659
   333
	  
athos@635
   334
	  
athos@635
   335
	  //s es t valasztasa
athos@659
   336
	  
athos@635
   337
	  //Dijkstra part	
athos@635
   338
	  dijkstra.run(s);
athos@659
   339
	  
athos@635
   340
	  /*We know from theory that t can be reached
athos@635
   341
	  if (!dijkstra.reached(t)){
athos@635
   342
	    //There are no k paths from s to t
athos@635
   343
	    break;
athos@635
   344
	  };
athos@635
   345
	  */
athos@635
   346
	  
athos@635
   347
	  //We have to change the potential
athos@661
   348
	  FOR_EACH_LOC(typename ResGraph::NodeIt, n, res_graph){
athos@635
   349
	    potential[n] += dijkstra.distMap()[n];
athos@635
   350
	  }
athos@635
   351
athos@635
   352
athos@635
   353
	  //Augmenting on the sortest path
athos@635
   354
	  Node n=t;
athos@635
   355
	  ResGraphEdge e;
athos@635
   356
	  while (n!=s){
athos@635
   357
	    e = dijkstra.pred(n);
athos@635
   358
	    n = dijkstra.predNode(n);
athos@635
   359
	    res_graph.augment(e,delta);
athos@635
   360
	    /*
athos@661
   361
	    //Let's update the total cost
athos@635
   362
	    if (res_graph.forward(e))
athos@661
   363
	      total_cost += cost[e];
athos@635
   364
	    else 
athos@661
   365
	      total_cost -= cost[e];	    
athos@635
   366
	    */
athos@635
   367
	  }
athos@659
   368
	  
athos@659
   369
	  //Update the excess_deficit map
athos@659
   370
	  excess_deficit[s] -= delta;
athos@659
   371
	  excess_deficit[t] += delta;
athos@659
   372
	  
athos@635
   373
athos@635
   374
	  //Update the excess_nodes heap
athos@672
   375
	  if (delta > excess_nodes[s]){
athos@635
   376
	    if (delta > excess_nodes[s])
athos@635
   377
	      deficit_nodes.push(s,delta - excess_nodes[s]);
athos@635
   378
	    excess_nodes.pop();
athos@635
   379
	    
athos@635
   380
	  } 
athos@635
   381
	  else{
athos@671
   382
	    excess_nodes.set(s, excess_nodes[s] - delta);
athos@635
   383
	  }
athos@635
   384
	  //Update the deficit_nodes heap
athos@672
   385
	  if (delta > deficit_nodes[t]){
athos@635
   386
	    if (delta > deficit_nodes[t])
athos@635
   387
	      excess_nodes.push(t,delta - deficit_nodes[t]);
athos@635
   388
	    deficit_nodes.pop();
athos@635
   389
	    
athos@635
   390
	  } 
athos@635
   391
	  else{
athos@671
   392
	    deficit_nodes.set(t, deficit_nodes[t] - delta);
athos@635
   393
	  }
athos@635
   394
	  //Dijkstra part ends here
athos@659
   395
	  
athos@659
   396
	  //Choose s and t again
athos@659
   397
	  s = excess_nodes.top(); 
athos@659
   398
	  max_excess = excess_nodes[s];
athos@659
   399
	  t = deficit_nodes.top(); 
athos@659
   400
	  if (max_excess < deficit_nodes[t]){
athos@659
   401
	    max_excess = deficit_nodes[t];
athos@659
   402
	  }
athos@659
   403
athos@633
   404
	}
athos@633
   405
athos@633
   406
	/*
athos@635
   407
	 * End of the delta scaling phase 
athos@635
   408
	*/
athos@633
   409
athos@635
   410
	//Whatever this means
athos@635
   411
	delta = delta / 2;
athos@635
   412
athos@635
   413
	/*This is not necessary here
athos@635
   414
	//Update the max_excess
athos@635
   415
	max_excess = 0;
athos@659
   416
	FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@635
   417
	  if (max_excess < excess_deficit[n]){
athos@635
   418
	    max_excess = excess_deficit[n];
athos@610
   419
	  }
athos@610
   420
	}
athos@633
   421
	*/
athos@657
   422
athos@610
   423
	  
athos@635
   424
      }//while(max_excess > 0)
athos@610
   425
      
athos@610
   426
athos@671
   427
      //return i;
athos@610
   428
    }
athos@610
   429
athos@610
   430
athos@610
   431
athos@610
   432
athos@661
   433
    ///This function gives back the total cost of the found paths.
athos@610
   434
    ///Assumes that \c run() has been run and nothing changed since then.
athos@661
   435
    Cost totalCost(){
athos@661
   436
      return total_cost;
athos@610
   437
    }
athos@610
   438
athos@610
   439
    ///Returns a const reference to the EdgeMap \c flow. \pre \ref run() must
athos@610
   440
    ///be called before using this function.
athos@662
   441
    const FlowMap &getFlow() const { return flow;}
athos@610
   442
athos@610
   443
  ///Returns a const reference to the NodeMap \c potential (the dual solution).
athos@610
   444
    /// \pre \ref run() must be called before using this function.
athos@662
   445
    const PotentialMap &getPotential() const { return potential;}
athos@610
   446
athos@610
   447
    ///This function checks, whether the given solution is optimal
athos@610
   448
    ///Running after a \c run() should return with true
athos@672
   449
    ///In this "state of the art" this only checks optimality, doesn't bother with feasibility
athos@610
   450
    ///
athos@610
   451
    ///\todo Is this OK here?
athos@610
   452
    bool checkComplementarySlackness(){
athos@661
   453
      Cost mod_pot;
athos@661
   454
      Cost fl_e;
athos@659
   455
      FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@610
   456
	//C^{\Pi}_{i,j}
athos@661
   457
	mod_pot = cost[e]-potential[graph.head(e)]+potential[graph.tail(e)];
athos@610
   458
	fl_e = flow[e];
athos@610
   459
	//	std::cout << fl_e << std::endl;
athos@672
   460
	if (mod_pot > 0 && fl_e != 0)
athos@672
   461
	  return false;
athos@672
   462
athos@610
   463
      }
athos@610
   464
      return true;
athos@610
   465
    }
athos@672
   466
athos@672
   467
    /*
athos@672
   468
    //For testing purposes only
athos@672
   469
    //Lists the node_properties
athos@672
   470
    void write_property_vector(const SupplyDemandMap& a,
athos@672
   471
			       char* prop_name="property"){
athos@672
   472
      FOR_EACH_LOC(typename Graph::NodeIt, i, graph){
athos@672
   473
	cout<<"Node id.: "<<graph.id(i)<<", "<<prop_name<<" value: "<<a[i]<<endl;
athos@672
   474
      }
athos@672
   475
      cout<<endl;
athos@672
   476
    }
athos@672
   477
    */
athos@672
   478
    bool checkFeasibility(){
athos@672
   479
      SupplyDemandMap supdem(graph);
athos@672
   480
      FOR_EACH_LOC(typename Graph::EdgeIt, e, graph){
athos@672
   481
athos@672
   482
	if ( flow[e] < 0){
athos@672
   483
athos@672
   484
	  return false;
athos@672
   485
	}
athos@672
   486
	supdem[graph.tail(e)] += flow[e];
athos@672
   487
	supdem[graph.head(e)] -= flow[e];
athos@672
   488
      }
athos@672
   489
      //write_property_vector(supdem, "supdem");
athos@672
   490
      //write_property_vector(supply_demand, "supply_demand");
athos@672
   491
athos@672
   492
      FOR_EACH_LOC(typename Graph::NodeIt, n, graph){
athos@672
   493
athos@672
   494
	if ( supdem[n] != supply_demand[n]){
athos@672
   495
	  //cout<<"Node id.: "<<graph.id(n)<<" : "<<supdem[n]<<", should be: "<<supply_demand[n]<<endl;
athos@672
   496
	  return false;
athos@672
   497
	}
athos@672
   498
      }
athos@672
   499
athos@672
   500
      return true;
athos@672
   501
    }
athos@672
   502
athos@672
   503
    bool checkOptimality(){
athos@672
   504
      return checkFeasibility() && checkComplementarySlackness();
athos@672
   505
    }
athos@610
   506
athos@633
   507
  }; //class MinCostFlow
athos@610
   508
athos@610
   509
  ///@}
athos@610
   510
athos@610
   511
} //namespace hugo
athos@610
   512
athos@610
   513
#endif //HUGO_MINCOSTFLOW_H