//==================================================================================================
// G r a p h _ p r o b l e m                                                              Interface
// M i n _ c o s t _ f l o w
// C o s t _ s c a l i n g
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module implements the cost-scaling algorithm to solve the minimum cost flow problem
   (with piecewise linear and convex costs) in graphs. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "graph_problem/min_cost_flow/cost_scaling.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemMinCostFlowCostScaling
#define guGraphProblemMinCostFlowCostScaling

// Headers //---------------------------------------------------------------------------------------
#include <list> /*INCLUDE*/
#include <bpp/graph_problem/min_cost_flow/algorithm.hpp> /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef GRAPH_PROBLEM_MIN_COST_FLOW_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostFlowCostScaling
#define private_area graphProblemMinCostFlowCostScaling_private

namespace public_area  { /*NAMESPACE*/ using namespace graphProblemMinCostFlowAlgorithm; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------

// Macrocommands //---------------------------------------------------------------------------------
/*ALIAS*/
#define tdGraph class prArcData,class prNodeData //

/*ALIAS*/
#define tuGraph prArcData,prNodeData //

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 template <tdGraph> class clLinearConformity;
 template <tdGraph> class clSolveAlgo;
}

namespace private_area {
 template <tdGraph,class prConformity> class clCostScalingAdmissibility;
}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 template <tdGraph,class prConformity>
 tyInteger findMinimumCostFlow(clGraph<tuGraph> &,const prConformity &);
}

namespace private_area {
 template <tdGraph,class prConformity>
 tyInteger balanceNode(clNode<tuGraph> &,tyReal,std_list(clNode<tuGraph> *) &,
                       const prConformity &,tyBoolean);

 template <tdGraph,class prConformity>
 tyInteger findEpsilonOptimalFlow(clGraph<tuGraph> &,tyReal,const prConformity &,tyBoolean);

 testing_mode ( function void test(void); )
}

// Errors //----------------------------------------------------------------------------------------
namespace public_area {}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// L i n e a r C o n f o r m i t y  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clLinearConformity */
 /* Represents the conformity curve of an arc (the optimality conditions) for the minimum cost
    flow problem with linear costs. */
 template <tdGraph> class clLinearConformity {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clLinearConformity */ /* Type of the arcs that carry the cost defined by the curve. */
  public_property typedef clArc<tuGraph> cpArc;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clLinearConformity(const clLinearConformity &);
  private_property clLinearConformity & operator = (const clLinearConformity &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clLinearConformity(void);
  public_property destructor clLinearConformity(void);

  public_property tyReal leftBoundary(const cpArc &) const;
  public_property tyReal rightBoundary(const cpArc &) const;
  public_property tyReal leftDerivative(const cpArc &) const;
  public_property tyReal rightDerivative(const cpArc &) const;
  public_property tyReal maximumDerivative(const cpArc &) const;
  public_property void   nullCost(cpArc &) const;
 };
}

// S o l v e A l g o  Interface //------------------------------------------------------------------
namespace public_area {
 /*CLASS clSolveAlgo */
 /* Represents an algorithm to solve the minimum cost flow problem (with linear costs) in a graph
    using the cost-scaling method. */
 template <tdGraph> class clSolveAlgo : public clSolver<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clSolveAlgo(const clSolveAlgo &);
  private_property clSolveAlgo & operator = (const clSolveAlgo &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clSolveAlgo(void);
  public_property virtual destructor clSolveAlgo(void);

  public_property tyInteger run(clGraph<tuGraph> &) const;
 };
}

// C o s t S c a l i n g A d m i s s i b i l i t y  Interface //------------------------------------
namespace private_area {
 template <tdGraph,class prConformity> class clCostScalingAdmissibility {
  //-------------------------------------------------------------------------------------------Types
  public_property typedef clArc<tuGraph> cpArc;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clCostScalingAdmissibility(const clCostScalingAdmissibility &);
  private_property clCostScalingAdmissibility & operator = (const clCostScalingAdmissibility &);

  private_property const prConformity & atConformity;
  private_property tyReal               atEpsilon;
  //------------------------------------------------------------------------------------------Public
  public_property constructor clCostScalingAdmissibility(const prConformity &,tyReal);
  public_property destructor clCostScalingAdmissibility(void) {}

  public_property tyBoolean direct(const cpArc &) const;
  public_property tyBoolean indirect(const cpArc &) const;
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// L i n e a r C o n f o r m i t y  Inline //-------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearConformity */ /* Builds a conformity curve. */
 template <tdGraph> inline clLinearConformity<tuGraph>::clLinearConformity(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clLinearConformity */ /* Destructs the conformity curve. */
 template <tdGraph> inline clLinearConformity<tuGraph>::~clLinearConformity(void) {}
 //-------------------------------------------------------------------------------------LeftBoundary
 /*METHOD clLinearConformity */
 /* Returns the decrease boundary of the flow of an arc so the arc becomes or stays conform. */
 template <tdGraph>
 inline tyReal clLinearConformity<tuGraph>::leftBoundary(const cpArc & agArc) const
 { return (agArc.data().minimum()); }
 //------------------------------------------------------------------------------------RightBoundary
 /*METHOD clLinearConformity */
 /* Returns the increase boundary of the flow of an arc so the arc becomes or stays conform. */
 template <tdGraph>
 inline tyReal clLinearConformity<tuGraph>::rightBoundary(const cpArc & agArc) const
 { return (agArc.data().maximum()); }
 //-----------------------------------------------------------------------------------LeftDerivative
 /*METHOD clLinearConformity */
 /* Returns the decrease boundary of the tension of an arc so the arc becomes or stays conform. */
 template <tdGraph>
 inline tyReal clLinearConformity<tuGraph>::leftDerivative(const cpArc & agArc) const
 { return (agArc.data().unitCost()); }
 //----------------------------------------------------------------------------------RightDerivative
 /*METHOD clLinearConformity */
 /* Returns the increase boundary of the tension of an arc so the arc becomes or stays conform. */
 template <tdGraph>
 inline tyReal clLinearConformity<tuGraph>::rightDerivative(const cpArc & agArc) const
 { return (agArc.data().unitCost()); }
 //--------------------------------------------------------------------------------MaximumDerivative
 /*METHOD clLinearConformity */
 /* Returns the maximum possible increase boundary of the tension of an arc. */
 template <tdGraph>
 inline tyReal clLinearConformity<tuGraph>::maximumDerivative(const cpArc & agArc) const
 { return (agArc.data().unitCost()); }
 //-----------------------------------------------------------------------------------------NullCost
 /*METHOD clLinearConformity */ /* Builds a null cost function for an arc. */
 template <tdGraph> inline void clLinearConformity<tuGraph>::nullCost(cpArc & agArc) const
 { agArc.data().unitCost()=0; }
}

// S o l v e A l g o  Inline //---------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clSolveAlgo */
 /* Builds an algorithm to solve the minimum cost flow problem in a graph. */
 template <tdGraph> inline clSolveAlgo<tuGraph>::clSolveAlgo(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clSolveAlgo */ /* Destructs the algorithm. */
 template <tdGraph> inline clSolveAlgo<tuGraph>::~clSolveAlgo(void) {}
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clSolveAlgo */
 /* Solves the minimum cost flow problem using the cost-scaling method. */
 template <tdGraph> inline tyInteger clSolveAlgo<tuGraph>::run(clGraph<tuGraph> & agGraph) const {
  clLinearConformity<tuGraph> lcConformity;

  return (findMinimumCostFlow(agGraph,lcConformity));
 }
}

// C o s t S c a l i n g A d m i s s i b i l i t y  Inline //---------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------Constructor
 template <tdGraph,class prConformity>
 inline clCostScalingAdmissibility<tuGraph,prConformity>::
 clCostScalingAdmissibility(const prConformity & agConformity,tyReal agEpsilon)
 : atConformity(agConformity),atEpsilon(agEpsilon) {}
 //-------------------------------------------------------------------------------------------Direct
 template <tdGraph,class prConformity> inline
 tyBoolean clCostScalingAdmissibility<tuGraph,prConformity>::direct(const cpArc & agArc) const {
  tyReal lcIncrement;

  tyReal lcTension = agArc.targetNode()->data().potential()-agArc.sourceNode()->data().potential();
  tyReal lcDerivative = atConformity.rightDerivative(agArc);

  if (lcTension>lcDerivative and lcTension<=lcDerivative+atEpsilon) {
   lcIncrement=atConformity.rightBoundary(agArc)-agArc.data().flow();
   return (lcIncrement>0.0);
  }

  return (false);
 }
 //-----------------------------------------------------------------------------------------Indirect
 template <tdGraph,class prConformity> inline
 tyBoolean clCostScalingAdmissibility<tuGraph,prConformity>::indirect(const cpArc & agArc) const {
  tyReal lcIncrement;

  tyReal lcTension = agArc.targetNode()->data().potential()-agArc.sourceNode()->data().potential();
  tyReal lcDerivative = atConformity.leftDerivative(agArc);

  if (lcTension<lcDerivative and lcTension>=lcDerivative-atEpsilon) {
   lcIncrement=agArc.data().flow()-atConformity.leftBoundary(agArc);
   return (lcIncrement>0.0);
  }

  return (false);
 }
}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------FindMinimumCostFlow
 /*FUNCTION*/
 /* Finds a minimum cost flow in a graph with any piecewise linear and convex costs. The second
    argument of the function is the description of the conformity curve (e.g. the class
    <CODE>clLinearConformity</CODE>). */
 template <tdGraph,class prConformity>
 tyInteger findMinimumCostFlow(clGraph<tuGraph> & agGraph,const prConformity & agConformity) {
  method_name("findMinimumCostFlow");

  typedef clArc<tuGraph>  cpArc;
  typedef clNode<tuGraph> cpNode;

  typedef typename clGraph<tuGraph>::cpArcX::const_iterator  cpArcIterator1;
  typedef typename clNode<tuGraph>::cpArcX::const_iterator   cpArcIterator2;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;

  cpArcIterator1 lcCurrentArc1;
  cpArcIterator2 lcCurrentArc2;
  cpNodeIterator lcCurrentNode;
  tyReal         lcDerivative;
  cpArcIterator1 lcLastArc1;
  cpArcIterator2 lcLastArc2;
  cpNodeIterator lcLastNode;
  cpArc *        lcReturnLoop;

  tyCardinal lcCounter     = 0;
  tyReal     lcEpsilon     = -1.0;
  tyInteger  lcNbIteration = 0;
  tyReal *   lcRealS       = new_array(tyReal,agGraph.nodes().size());
  cpNode *   lcSourceNode  = firstNode(agGraph);
  cpNode *   lcTargetNode  = lastNode(agGraph);

  // Flow Initialization //
  findCompatibleFlow(agGraph,false);
  if (agGraph.solved()==false) return (-1);
  agGraph.solved()=false;

  // Return Loop Adding //
  if (lcSourceNode==nil or lcTargetNode==nil) send_error(erInvalidFlowGraph);

  lcReturnLoop=new_object(cpArc(agGraph,agGraph.getNewArcKey(),prArcData(),
                                lcTargetNode->key(),lcSourceNode->key()));

  lcReturnLoop->data().minimum()=0.0;
  lcReturnLoop->data().maximum()=0.0;
  lcCurrentArc2=lcSourceNode->outgoingArcs().begin();
  lcLastArc2=lcSourceNode->outgoingArcs().end();

  while (lcCurrentArc2!=lcLastArc2) {
   lcReturnLoop->data().minimum()+=(*lcCurrentArc2).second->data().minimum();
   lcReturnLoop->data().maximum()+=(*lcCurrentArc2).second->data().maximum();
   lcCurrentArc2++;
  }

  agConformity.nullCost(*lcReturnLoop);
  lcReturnLoop->data().flow()=0.0;

  lcCurrentArc2=lcReturnLoop->sourceNode()->incomingArcs().begin();
  lcLastArc2=lcReturnLoop->sourceNode()->incomingArcs().end();

  while (lcCurrentArc2!=lcLastArc2) {
   lcReturnLoop->data().flow()+=(*lcCurrentArc2).second->data().flow();
   lcCurrentArc2++;
  }

  // Potential & Workspace Initialization //
  lcCurrentNode=agGraph.nodes().begin();
  lcLastNode=agGraph.nodes().end();

  while (lcCurrentNode!=lcLastNode) {
   (*lcCurrentNode).second->data().potential()=0.0;
   (*lcCurrentNode).second->work()=lcRealS+lcCounter;
   lcCurrentNode++;
   lcCounter++;
  }

  // Maximal Cost Search //
  lcCurrentArc1=agGraph.arcs().begin();
  lcLastArc1=agGraph.arcs().end();

  while (lcCurrentArc1!=lcLastArc1) {
   lcDerivative=agConformity.maximumDerivative(*((*lcCurrentArc1).second));
   if (lcDerivative>lcEpsilon) lcEpsilon=lcDerivative;
   lcCurrentArc1++;
  }

  // Flow Improving //
  while (lcEpsilon>=1.0/agGraph.nodes().size()) {
   lcEpsilon/=2.0;
   lcNbIteration+=private_area::findEpsilonOptimalFlow(agGraph,lcEpsilon,agConformity,false);
  }

  delete_array(lcRealS);
  delete_object(lcReturnLoop);
  agGraph.solved()=true;
  return (lcNbIteration);
 }
}

namespace private_area {
 //--------------------------------------------------------------------------------------BalanceNode
 template <tdGraph,class prConformity>
 tyInteger balanceNode(clNode<tuGraph> & agNode,tyReal agEpsilon,
                       std_list(clNode<tuGraph> *) & agNodeS,const prConformity & agConformity,
                       tyBoolean agManageNodes) {
  typedef typename clNode<tuGraph>::cpArcX::const_iterator cpIterator;

  clArc<tuGraph> * lcArc;
  tyBoolean        lcBalanced;
  cpIterator       lcCurrentArc;
  tyReal           lcDerivative;
  tyReal           lcIncrement;
  cpIterator       lcLastArc;
  tyReal           lcTension;
  tyReal *         lcWork;

  tyReal    lcBalance     = *((tyReal *)agNode.work());
  tyInteger lcNbIteration = 0;

  // Outgoing Arcs //
  lcCurrentArc=agNode.outgoingArcs().begin();
  lcLastArc=agNode.outgoingArcs().end();

  while (lcCurrentArc!=lcLastArc and lcBalance>0.0) {
   lcArc=(*lcCurrentArc).second;
   lcTension=lcArc->targetNode()->data().potential()-agNode.data().potential();
   lcDerivative=agConformity.rightDerivative(*lcArc);

   if (lcTension>lcDerivative and lcTension<=lcDerivative+agEpsilon) {
    lcIncrement=agConformity.rightBoundary(*lcArc)-lcArc->data().flow();

    if (lcIncrement>0.0) {
     lcIncrement=mini(lcBalance,lcIncrement);
     lcArc->data().flow()+=lcIncrement;
     lcBalance-=lcIncrement;

     lcWork=(tyReal *)(lcArc->targetNode()->work());
     lcBalanced=(*lcWork <= 0.0);
     *lcWork+=lcIncrement;
     if (agManageNodes and lcBalanced and *lcWork>0.0) agNodeS.push_back(lcArc->targetNode());
     ++lcNbIteration;
    }
   }

   ++lcCurrentArc;
  }

  // Incoming Arcs //
  lcCurrentArc=agNode.incomingArcs().begin();
  lcLastArc=agNode.incomingArcs().end();

  while (lcCurrentArc!=lcLastArc and lcBalance>0.0) {
   lcArc=(*lcCurrentArc).second;
   lcTension=agNode.data().potential()-lcArc->sourceNode()->data().potential();
   lcDerivative=agConformity.leftDerivative(*lcArc);

   if (lcTension<lcDerivative and lcTension>=lcDerivative-agEpsilon) {
    lcIncrement=lcArc->data().flow()-agConformity.leftBoundary(*lcArc);

    if (lcIncrement>0.0) {
     lcIncrement=mini(lcBalance,lcIncrement);
     lcArc->data().flow()-=lcIncrement;
     lcBalance-=lcIncrement;

     lcWork=(tyReal *)(lcArc->sourceNode()->work());
     lcBalanced=(*lcWork <= 0.0);
     *lcWork+=lcIncrement;
     if (agManageNodes and lcBalanced and *lcWork>0.0) agNodeS.push_back(lcArc->sourceNode());
     ++lcNbIteration;
    }
   }

   ++lcCurrentArc;
  }

  if (lcBalance>0.0) agNode.data().potential()-=agEpsilon;
  *((tyReal *)agNode.work())=lcBalance;
  return (lcNbIteration);
 }
 //---------------------------------------------------------------------------FindEpsilonOptimalFlow
 template <tdGraph,class prConformity>
 tyInteger findEpsilonOptimalFlow(clGraph<tuGraph> & agGraph,tyReal agEpsilon,
                                  const prConformity & agConformity,
                                  tyBoolean agWithTopologicalOrdering) {
  typedef std_list(clNode<tuGraph> *)   cpNodeS;
  typedef std_vector(clNode<tuGraph> *) cpOrdering;

  typedef typename clGraph<tuGraph>::cpArcX::const_iterator  cpArcIterator1;
  typedef typename clNode<tuGraph>::cpArcX::const_iterator   cpArcIterator2;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator1;
  typedef typename cpNodeS::iterator                         cpNodeIterator2;

  clArc<tuGraph> *  lcArc;
  tyReal            lcBalance;
  cpArcIterator2    lcCurrentArc2;
  cpNodeIterator2   lcCurrentNode2;
  cpArcIterator2    lcLastArc2;
  cpNodeIterator2   lcLastNode2;
  clNode<tuGraph> * lcNode;
  cpNodeS           lcNodeS;
  cpOrdering        lcOrdering;
  tyReal            lcTension;

  tyCardinal      lcCounter      = 0;
  cpArcIterator1  lcCurrentArc1  = agGraph.arcs().begin();
  cpNodeIterator1 lcCurrentNode1 = agGraph.nodes().begin();
  cpArcIterator1  lcLastArc1     = agGraph.arcs().end();
  cpNodeIterator1 lcLastNode1    = agGraph.nodes().end();
  tyInteger       lcNbIteration  = 0;

  clCostScalingAdmissibility<tuGraph,prConformity> lcArcAdmissibility(agConformity,agEpsilon);

  // Pseudo-Flow Building //
  while (lcCurrentArc1!=lcLastArc1) {
   lcArc=(*lcCurrentArc1).second;
   lcTension=lcArc->targetNode()->data().potential()-lcArc->sourceNode()->data().potential();

   if (lcTension < agConformity.leftDerivative(*lcArc)-agEpsilon)
    lcArc->data().flow()=agConformity.leftBoundary(*lcArc);
   else if (lcTension > agConformity.rightDerivative(*lcArc)+agEpsilon)
    lcArc->data().flow()=agConformity.rightBoundary(*lcArc);

   ++lcCurrentArc1;
  }

  // Node Balance Initialization //
  while (lcCurrentNode1!=lcLastNode1) {
   lcNode=(*lcCurrentNode1).second;
   lcBalance=0.0;
   lcCurrentArc2=lcNode->incomingArcs().begin();
   lcLastArc2=lcNode->incomingArcs().end();

   while (lcCurrentArc2!=lcLastArc2) {
    lcBalance+=(*lcCurrentArc2).second->data().flow();
    ++lcCurrentArc2;
   }

   lcCurrentArc2=lcNode->outgoingArcs().begin();
   lcLastArc2=lcNode->outgoingArcs().end();

   while (lcCurrentArc2!=lcLastArc2) {
    lcBalance-=(*lcCurrentArc2).second->data().flow();
    ++lcCurrentArc2;
   }

   *((tyReal *)(lcNode->work()))=lcBalance;
   if (not agWithTopologicalOrdering and lcBalance>0.0) lcNodeS.push_back(lcNode);
   ++lcCurrentNode1;
  }

  // Flow Building //
  if (agWithTopologicalOrdering) {
   findTopologicalOrdering(agGraph,lcArcAdmissibility,lcOrdering);

   while (lcCounter<lcOrdering.size()) {
    lcNodeS.push_back(lcOrdering[lcCounter]);
    ++lcCounter;
   }
  }

  lcCurrentNode2=lcNodeS.begin();
  lcLastNode2=lcNodeS.end();

  while (lcCurrentNode2!=lcLastNode2) {
   lcNode=(*lcCurrentNode2);

   if (agWithTopologicalOrdering) {
    if (*((tyReal *)lcNode->work())>0.0) {
     lcNbIteration+=balanceNode(*lcNode,agEpsilon,lcNodeS,agConformity,false);

     if (*((tyReal *)lcNode->work())>0.0) {
      lcNodeS.erase(lcCurrentNode2);
      lcNodeS.push_front(lcNode);
      lcCurrentNode2=lcNodeS.begin();
      lcLastNode2=lcNodeS.end();
     }
     else ++lcCurrentNode2;
    }
    else ++lcCurrentNode2;
   }
   else {
    do { lcNbIteration+=balanceNode(*lcNode,agEpsilon,lcNodeS,agConformity,true); }
    while (*((tyReal *)lcNode->work())>0.0);

    ++lcCurrentNode2;
   }
  }

  return (lcNbIteration);
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef tdGraph
#undef tuGraph
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// G r a p h _ p r o b l e m                                                         Implementation
// M i n _ c o s t _ f l o w
// C o s t _ s c a l i n g
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU Library General Public License for more details (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "graph_problem/min_cost_flow/cost_scaling.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define GRAPH_PROBLEM_MIN_COST_FLOW_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph_problem/min_cost_flow/cost_scaling.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostFlowCostScaling
#define private_area graphProblemMinCostFlowCostScaling_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Min_cost_flow/Cost_scaling");

// Initialization //--------------------------------------------------------------------------------

// Errors //----------------------------------------------------------------------------------------
namespace public_area {}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// X X X  Implementation //-------------------------------------------------------------------------
namespace {}

// End //-------------------------------------------------------------------------------------------
}