src/work/athos/mincostflow.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000 (2004-09-08)
changeset 822 88226d9fe821
parent 671 708df4dc6ab6
child 921 818510fa3d99
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
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