//==================================================================================================
// G r a p h _ p r o b l e m                                                              Interface
// M i n _ c o s t _ t e n s i o n
// A l g o r i t h m
//                                                                                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 provides basic algorithms for the minimum cost tension problem in graphs. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "graph_problem/min_cost_tension/algorithm.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemMinCostTensionAlgorithm
#define guGraphProblemMinCostTensionAlgorithm

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph_problem/min_cost_tension/structure.hpp> /*INCLUDE*/

namespace bpp {

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

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostTensionAlgorithm
#define private_area graphProblemMinCostTensionAlgorithm_private

namespace public_area  { /*NAMESPACE*/ using namespace graphProblemMinCostTensionStructure; }
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 {
 //------------------------------------------------------------------------------------------Classes
 template <tdGraph> class clRestrictConstraintsAlgo;
 template <tdGraph> class clRestrictConstraintsAlgoI;
 template <tdGraph> class clRestrictConstraintsAlgoII;
 template <tdGraph> class clBinarySolver;
 template <tdGraph> class clConvexSolver;
 template <tdGraph> class clDiscreteSolver;
 template <tdGraph> class clLinearSolver;
 template <tdGraph> class clPiecewiseSolver;
}

namespace private_area {}

namespace graphProblemMinCostTensionConformingConvex { template <tdGraph> class clSolveAlgoIII; }
namespace graphProblemMinCostTensionConformingPiecewise { template <tdGraph> class clSolveAlgo; }
namespace graphProblemMinCostTensionDualCostScaling { template <tdGraph> class clSolveAlgo; }
namespace graphProblemMinCostTensionLinearSystem { template <tdGraph> class clBinarySolveAlgoI; }
namespace graphProblemMinCostTensionLinearSystem { template <tdGraph> class clDiscreteSolveAlgoI; }

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 template <tdGraph> tyReal adjustOptimalTensions(clGraph<tuGraph> &);
 template <tdGraph> tyReal totalCost(const clGraph<tuGraph> &);
}

namespace private_area { testing_mode ( function void test(void); ) }

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

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

// R e s t r i c t C o n s t r a i n t s A l g o  Interface //--------------------------------------
namespace public_area {
 /*CLASS clRestrictConstraintsAlgo */
 /* Represents an algorithm to restrict the tension capacity constraints upon the arcs of a graph.
    It is an abstract class. */
 template <tdGraph> class clRestrictConstraintsAlgo {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clRestrictConstraintsAlgo(const clRestrictConstraintsAlgo &);
  private_property clRestrictConstraintsAlgo & operator = (const clRestrictConstraintsAlgo &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clRestrictConstraintsAlgo(void);
  public_property virtual destructor clRestrictConstraintsAlgo(void);

  /*AMETHOD clRestrictConstraintsAlgo */ /* Executes the algorithm. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;

  public_property static tyInteger defaultRun(clGraph<tuGraph> &);
 };
}

// R e s t r i c t C o n s t r a i n t s A l g o I  Interface //------------------------------------
namespace public_area {
 /*CLASS clRestrictConstraintsAlgoI */
 /* Represents an algorithm to restrict the tension capacity constraints upon the arcs of a graph
    (method I). */
 template <tdGraph> class clRestrictConstraintsAlgoI : public clRestrictConstraintsAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clRestrictConstraintsAlgoI(const clRestrictConstraintsAlgoI &);
  private_property clRestrictConstraintsAlgoI & operator = (const clRestrictConstraintsAlgoI &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clRestrictConstraintsAlgoI(void);
  public_property virtual destructor clRestrictConstraintsAlgoI(void);

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

// R e s t r i c t C o n s t r a i n t s A l g o I I  Interface //----------------------------------
namespace public_area {
 /*CLASS clRestrictConstraintsAlgoII */
 /* Represents an algorithm to restrict the tension capacity constraints upon the arcs of a graph
    (method II). */
 template <tdGraph> class clRestrictConstraintsAlgoII : public clRestrictConstraintsAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clRestrictConstraintsAlgoII(const clRestrictConstraintsAlgoII &);
  private_property clRestrictConstraintsAlgoII & operator = (const clRestrictConstraintsAlgoII &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clRestrictConstraintsAlgoII(void);
  public_property virtual destructor clRestrictConstraintsAlgoII(void);

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

// B i n a r y S o l v e r  Interface //------------------------------------------------------------
namespace public_area {
 /*CLASS clBinarySolver */
 /* Represents a solver for the minimum cost tension problem in a graph. It is an abstract
    class. The cost functions of the arcs must be binary functions as defined by the
    <CODE>clBinaryArcData</CODE> class of the <CODE>Structure</CODE> module. */
 template <tdGraph> class clBinarySolver {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clBinarySolver */ /* Type of the default solver (linear modeling, version I). */
  public_property
  typedef graphProblemMinCostTensionLinearSystem::clBinarySolveAlgoI<tuGraph> clDefaultSolver;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clBinarySolver(const clBinarySolver &);
  private_property
   clBinarySolver & operator = (const clBinarySolver &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clBinarySolver(void);
  public_property virtual destructor clBinarySolver(void);

  /*AMETHOD clBinarySolver */
  /* Solves the minimum cost tension problem in a graph. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;
 };
}

// C o n v e x S o l v e r  Interface //------------------------------------------------------------
namespace public_area {
 /*CLASS clConvexSolver */
 /* Represents a solver for the minimum cost tension problem in a graph. It is an abstract class.
    The cost functions of the arcs must be convex functions as defined by the
    <CODE>clConvexArcData1</CODE> or <CODE>clConvexArcData2</CODE> class of the
    <CODE>Structure</CODE> module. */
 template <tdGraph> class clConvexSolver {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clConvexSolver */ /* Type of the default solver (conforming method, version III). */
  public_property
  typedef graphProblemMinCostTensionConformingConvex::clSolveAlgoIII<tuGraph> clDefaultSolver;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clConvexSolver(const clConvexSolver &);
  private_property clConvexSolver & operator = (const clConvexSolver &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clConvexSolver(void);
  public_property virtual destructor clConvexSolver(void);

  /*AMETHOD clConvexSolver */
  /* Solves the minimum cost tension problem in a graph with a given precision. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph,tyReal agPrecision) const = 0;
 };
}

// D i s c r e t e S o l v e r  Interface //--------------------------------------------------------
namespace public_area {
 /*CLASS clDiscreteSolver */
 /* Represents a solver for the minimum cost discrete tension problem in a graph. It is an abstract
    class. The cost functions of the arcs must be linear functions as defined by the
    <CODE>clDiscreteArcData</CODE> class of the <CODE>Structure</CODE> module. */
 template <tdGraph> class clDiscreteSolver {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clDiscreteSolver */ /* Type of the default solver (linear modeling, version I). */
  public_property
  typedef graphProblemMinCostTensionLinearSystem::clDiscreteSolveAlgoI<tuGraph> clDefaultSolver;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clDiscreteSolver(const clDiscreteSolver &);
  private_property clDiscreteSolver & operator = (const clDiscreteSolver &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clDiscreteSolver(void);
  public_property virtual destructor clDiscreteSolver(void);

  /*AMETHOD clDiscreteSolver */
  /* Solves the minimum cost discrete tension problem in a graph. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;
 };
}

// L i n e a r S o l v e r  Interface //------------------------------------------------------------
namespace public_area {
 /*CLASS clLinearSolver */
 /* Represents a solver for the minimum cost tension problem in a graph. It is an abstract class.
    The cost functions of the arcs must be linear functions as defined by the
    <CODE>clLinearArcData</CODE> class of the <CODE>Structure</CODE> module. */
 template <tdGraph> class clLinearSolver {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clLinearSolver */ /* Type of the default solver (dual cost scaling method). */
  public_property
  typedef graphProblemMinCostTensionDualCostScaling::clSolveAlgo<tuGraph> clDefaultSolver;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clLinearSolver(const clLinearSolver &);
  private_property clLinearSolver & operator = (const clLinearSolver &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clLinearSolver(void);
  public_property virtual destructor clLinearSolver(void);

  /*AMETHOD clLinearSolver */
  /* Solves the minimum cost tension problem in a graph. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;
 };
}

// P i e c e w i s e S o l v e r  Interface //------------------------------------------------------
namespace public_area {
 /*CLASS clPiecewiseSolver */
 /* Represents a solver for the minimum cost tension problem in a graph. It is an abstract class.
    The cost functions of the arcs must be piecewise functions as defined by the
    <CODE>clPiecewiseArcData</CODE> class of the <CODE>Structure</CODE> module. */
 template <tdGraph> class clPiecewiseSolver {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clPiecewiseSolver */ /* Type of the default solver (conforming method). */
  public_property
  typedef graphProblemMinCostTensionConformingPiecewise::clSolveAlgo<tuGraph> clDefaultSolver;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clPiecewiseSolver(const clPiecewiseSolver &);
  private_property clPiecewiseSolver & operator = (const clPiecewiseSolver &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clPiecewiseSolver(void);
  public_property virtual destructor clPiecewiseSolver(void);

  /*AMETHOD clPiecewiseSolver */
  /* Solves the minimum cost tension problem in a graph. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;
 };
}

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

// R e s t r i c t C o n s t r a i n t s A l g o  Inline //-----------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clRestrictConstraintsAlgo */
 /* Builds an algorithm to restrict the capacity constraints upon the arcs of a graph. */
 template <tdGraph> inline clRestrictConstraintsAlgo<tuGraph>::clRestrictConstraintsAlgo(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clRestrictConstraintsAlgo */ /* Destructs the algorithm. */
 template <tdGraph> inline clRestrictConstraintsAlgo<tuGraph>::~clRestrictConstraintsAlgo(void) {}
}

// R e s t r i c t C o n s t r a i n t s A l g o I  Inline //---------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clRestrictConstraintsAlgoI */
 /* Builds an algorithm to restrict the capacity constraints upon the arcs of a graph. */
 template <tdGraph> inline clRestrictConstraintsAlgoI<tuGraph>::clRestrictConstraintsAlgoI(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clRestrictConstraintsAlgoI */ /* Destructs the algorithm. */
 template <tdGraph>
 inline clRestrictConstraintsAlgoI<tuGraph>::~clRestrictConstraintsAlgoI(void) {}
}

// R e s t r i c t C o n s t r a i n t s A l g o I I  Inline //-------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clRestrictConstraintsAlgoII */
 /* Builds an algorithm to restrict the capacity constraints upon the arcs of a graph. */
 template <tdGraph> inline clRestrictConstraintsAlgoII<tuGraph>::clRestrictConstraintsAlgoII() {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clRestrictConstraintsAlgoII */ /* Destructs the algorithm. */
 template <tdGraph> inline clRestrictConstraintsAlgoII<tuGraph>::~clRestrictConstraintsAlgoII() {}
}

// B i n a r y S o l v e r  Inline //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinarySolver */
 /* Builds a solver for the minimum cost tension problem in a graph. */
 template <tdGraph> inline clBinarySolver<tuGraph>::clBinarySolver(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clBinarySolver */ /* Destructs the solver. */
 template <tdGraph> inline clBinarySolver<tuGraph>::~clBinarySolver(void) {}
}

// C o n v e x S o l v e r  Inline //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexSolver */ /* Builds a solver for the minimum cost tension problem in a graph. */
 template <tdGraph> inline clConvexSolver<tuGraph>::clConvexSolver(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clConvexSolver */ /* Destructs the solver. */
 template <tdGraph> inline clConvexSolver<tuGraph>::~clConvexSolver(void) {}
}

// D i s c r e t e S o l v e r  Inline //-----------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteSolver */
 /* Builds a solver for the minimum cost discrete tension problem in a graph. */
 template <tdGraph> inline clDiscreteSolver<tuGraph>::clDiscreteSolver(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clDiscreteSolver */ /* Destructs the solver. */
 template <tdGraph> inline clDiscreteSolver<tuGraph>::~clDiscreteSolver(void) {}
}

// L i n e a r S o l v e r  Inline //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearSolver */ /* Builds a solver for the minimum cost tension problem in a graph. */
 template <tdGraph> inline clLinearSolver<tuGraph>::clLinearSolver(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clLinearSolver */ /* Destructs the solver. */
 template <tdGraph> inline clLinearSolver<tuGraph>::~clLinearSolver(void) {}
}

// P i e c e w i s e S o l v e r  Inline //---------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clPiecewiseSolver */
 /* Builds a solver for the minimum cost tension problem in a graph. */
 template <tdGraph> inline clPiecewiseSolver<tuGraph>::clPiecewiseSolver(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clPiecewiseSolver */ /* Destructs the solver. */
 template <tdGraph> inline clPiecewiseSolver<tuGraph>::~clPiecewiseSolver(void) {}
}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------AdjustOptimalTensions
 /*FUNCTION*/
 /* Adjusts the optimal tension of each arc, i.e. if the optimal tension of an arc is out of its
    bounds, it is moved back in the interval. The cost offset implied by these changes is
    returned. */
 template <tdGraph> tyReal adjustOptimalTensions(clGraph<tuGraph> & agGraph) {
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;

  clArc<tuGraph> * lcArc;
  tyReal           lcIncrement;

  tyReal        lcCostOffset = 0.0;
  cpArcIterator lcCurrentArc = agGraph.arcs().begin();
  cpArcIterator lcLastArc    = agGraph.arcs().end();

  while (lcCurrentArc!=lcLastArc) {
   lcArc=(*lcCurrentArc).second;

   if (lcArc->data().optimum()<lcArc->data().minimum()) {
    lcIncrement=lcArc->data().minimum()-lcArc->data().optimum();
    lcArc->data().optimum()=lcArc->data().minimum();
    lcCostOffset+=lcIncrement*lcArc->data().stretchingCost();
   }
   else if (lcArc->data().optimum()>lcArc->data().maximum()) {
    lcIncrement=lcArc->data().optimum()-lcArc->data().maximum();
    lcArc->data().optimum()=lcArc->data().maximum();
    lcCostOffset+=lcIncrement*lcArc->data().shrinkingCost();
   }

   ++lcCurrentArc;
  }

  return (lcCostOffset);
 }
 //----------------------------------------------------------------------------------------TotalCost
 /*FUNCTION*/ /* Computes the total cost of a tension in a graph. */
 template <tdGraph> tyReal totalCost(const clGraph<tuGraph> & agGraph) {
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator clArcIterator;

  tyReal        lcCost       = 0.0;
  clArcIterator lcCurrentArc = agGraph.arcs().begin();
  clArcIterator lcLastArc    = agGraph.arcs().end();

  while (lcCurrentArc!=lcLastArc) {
   lcCost+=(*lcCurrentArc).second->data().cost();
   lcCurrentArc++;
  }

  return (lcCost);
 }
}

namespace private_area {}

// R e s t r i c t C o n s t r a i n t s A l g o  Implementation //---------------------------------
namespace public_area {
 //---------------------------------------------------------------------------------------DefaultRun
 /*METHOD clRestrictConstraintsAlgo */
 /* Restricts the tension capacity constraints upon the arcs of a graph using the default
    version of the algorithm (method II). Static method. */
 template <tdGraph> tyInteger inline
 clRestrictConstraintsAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph)
 { return (clRestrictConstraintsAlgoII<tuGraph>().run(agGraph)); }
}

// R e s t r i c t C o n s t r a i n t s A l g o I  Implementation //-------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clRestrictConstraintsAlgoI */
 /* Restricts the tension capacity constraints upon the arcs of a graph. */
 template <tdGraph>
 tyInteger clRestrictConstraintsAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph) const {
  method_name("restrictConstraintsAlgoI::run");

  typedef typename clNode<tuGraph>::cpArcX::const_iterator   clArcIterator;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator clNodeIterator;
  typedef std_vector(clNode<tuGraph> *)                      clNodeS;

  clArc<tuGraph> *  lcArc;
  tyBoolean         lcChanged;
  clArcIterator     lcCurrentArc;
  clNodeIterator    lcCurrentNode2;
  clArcIterator     lcLastArc;
  clNodeIterator    lcLastNode2;
  tyReal            lcMax;
  tyReal            lcMin;
  clNode<tuGraph> * lcNode1;
  clNode<tuGraph> * lcNode2;
  clNodeS           lcNodeS;

  clNodeIterator lcCurrentNode1 = agGraph.nodes().begin();
  clNodeIterator lcLastNode1    = agGraph.nodes().end();
  tyMark         lcMark1        = agGraph.mark();
  tyMark         lcMark2        = ++(agGraph.mark());
  tyInteger      lcNbIteration  = 0;

  while (lcCurrentNode1!=lcLastNode1) {
   lcCurrentNode2=agGraph.nodes().begin();
   lcLastNode2=agGraph.nodes().end();

   while (lcCurrentNode2!=lcLastNode2) {
    lcNode1=(*lcCurrentNode2).second;
    lcNode1->data().minimum()=prNodeData::negativeInfinity();
    lcNode1->data().maximum()=prNodeData::positiveInfinity();
    lcCurrentNode2++;
   }

   lcNode1=(*lcCurrentNode1).second;
   lcNodeS.push_back(lcNode1);
   lcNode1->mark()=lcMark2;
   lcNode1->data().minimum()=0;
   lcNode1->data().maximum()=0;

   while (not lcNodeS.empty()) {
    lcNode1=lcNodeS.back();
    lcNodeS.pop_back();
    lcNode1->mark()=lcMark1;

    // Outgoing Arcs //
    lcCurrentArc=lcNode1->outgoingArcs().begin();
    lcLastArc=lcNode1->outgoingArcs().end();

    while (lcCurrentArc!=lcLastArc) {
     lcNbIteration++;
     lcArc=(*lcCurrentArc).second;
     lcNode2=lcArc->targetNode();
     if (lcNode2==nil) send_error(erArcExtremityNotFixed);
     lcChanged=false;

     // Target Event Date Update //
     lcMin=lcNode1->data().minimum()+lcArc->data().minimum();
     lcMax=lcNode1->data().maximum()+lcArc->data().maximum();

     if (lcMin>lcNode2->data().minimum()) {
      lcNode2->data().minimum()=lcMin;
      lcChanged=true;
     }

     if (lcMax<lcNode2->data().maximum()) {
      lcNode2->data().maximum()=lcMax;
      lcChanged=true;
     }

     if (lcNode2->data().minimum()>lcNode2->data().maximum()) return (-1);

     if (lcChanged and lcNode2->mark()!=lcMark2) {
      lcNodeS.push_back(lcNode2);
      lcNode2->mark()=lcMark2;
     }

     // Arc Duration Update //
     lcArc->data().minimum()=maxi(lcNode2->data().minimum()-lcNode1->data().maximum(),
                             lcArc->data().minimum());

     lcArc->data().maximum()=mini(lcNode2->data().maximum()-lcNode1->data().minimum(),
                             lcArc->data().maximum());

     if (lcArc->data().minimum()>lcArc->data().maximum()) return (-1);
     lcCurrentArc++;
    }

    // Incoming Arcs //
    lcCurrentArc=lcNode1->incomingArcs().begin();
    lcLastArc=lcNode1->incomingArcs().end();

    while (lcCurrentArc!=lcLastArc) {
     lcNbIteration++;
     lcArc=(*lcCurrentArc).second;
     lcNode2=lcArc->sourceNode();
     if (lcNode2==nil) send_error(erArcExtremityNotFixed);

     // Source Event Date Update //
     lcMin=lcNode1->data().minimum()-lcArc->data().maximum();
     lcMax=lcNode1->data().maximum()-lcArc->data().minimum();
     lcChanged=false;

     if (lcMin>lcNode2->data().minimum()) {
      lcNode2->data().minimum()=lcMin;
      lcChanged=true;
     }

     if (lcMax<lcNode2->data().maximum()) {
      lcNode2->data().maximum()=lcMax;
      lcChanged=true;
     }

     if (lcChanged and lcNode2->mark()!=lcMark2) {
      lcNodeS.push_back(lcNode2);
      lcNode2->mark()=lcMark2;
     }

     if (lcNode2->data().minimum()>lcNode2->data().maximum()) return (-1);

     // Arc Duration Update //
     lcArc->data().minimum()=maxi(lcNode1->data().minimum()-lcNode2->data().maximum(),
                             lcArc->data().minimum());

     lcArc->data().maximum()=mini(lcNode1->data().maximum()-lcNode2->data().minimum(),
                             lcArc->data().maximum());

     if (lcArc->data().minimum()>lcArc->data().maximum()) return (-1);
     lcCurrentArc++;
    }
   }

   lcCurrentNode1++;
  }

  return (lcNbIteration);
 }
}

// R e s t r i c t C o n s t r a i n t s A l g o I I  Implementation //-----------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clRestrictConstraintsAlgoII */
 /* Restricts the tension capacity constraints upon the arcs of a graph. */
 template <tdGraph>
 tyInteger clRestrictConstraintsAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph) const {
  method_name("restrictConstraintsAlgoII::run");

  typedef typename clNode<tuGraph>::cpArcX::const_iterator   clArcIterator;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator clNodeIterator;
  typedef std_vector(clNode<tuGraph> *)                      clNodeS;

  clArc<tuGraph> *  lcArc;
  tyBoolean         lcChanged;
  clArcIterator     lcCurrentArc;
  clNodeIterator    lcCurrentNode2;
  clArcIterator     lcLastArc;
  clNodeIterator    lcLastNode2;
  tyReal            lcMax;
  tyReal            lcMin;
  clNode<tuGraph> * lcNode1;
  clNode<tuGraph> * lcNode2;

  clNodeIterator lcCurrentNode1 = agGraph.nodes().begin();
  clNodeS *      lcCurrentNodeS = new_object(clNodeS);
  clNodeIterator lcLastNode1    = agGraph.nodes().end();
  tyMark         lcMark1        = agGraph.mark();
  tyMark         lcMark2        = ++(agGraph.mark());
  tyInteger      lcNbIteration  = 0;
  clNodeS *      lcNextNodeS    = new_object(clNodeS);

  while (lcCurrentNode1!=lcLastNode1) {
   lcCurrentNode2=agGraph.nodes().begin();
   lcLastNode2=agGraph.nodes().end();

   while (lcCurrentNode2!=lcLastNode2) {
    lcNode1=(*lcCurrentNode2).second;
    lcNode1->data().minimum()=prNodeData::negativeInfinity();
    lcNode1->data().maximum()=prNodeData::positiveInfinity();
    lcCurrentNode2++;
   }

   lcNode1=(*lcCurrentNode1).second;
   lcNextNodeS->push_back(lcNode1);
   lcNode1->mark()=lcMark2;
   lcNode1->data().minimum()=0;
   lcNode1->data().maximum()=0;

   while (not lcNextNodeS->empty()) {
    standard::swap(lcNextNodeS,lcCurrentNodeS);

    while (not lcCurrentNodeS->empty()) {
     lcNode1=lcCurrentNodeS->back();
     lcCurrentNodeS->pop_back();
     lcNode1->mark()=lcMark1;

     // Outgoing Arcs //
     lcCurrentArc=lcNode1->outgoingArcs().begin();
     lcLastArc=lcNode1->outgoingArcs().end();

     while (lcCurrentArc!=lcLastArc) {
      lcNbIteration++;
      lcArc=(*lcCurrentArc).second;
      lcNode2=lcArc->targetNode();
      if (lcNode2==nil) send_error(erArcExtremityNotFixed);
      lcChanged=false;

      // Target Event Date Update //
      lcMin=lcNode1->data().minimum()+lcArc->data().minimum();
      lcMax=lcNode1->data().maximum()+lcArc->data().maximum();

      if (lcMin>lcNode2->data().minimum()) {
       lcNode2->data().minimum()=lcMin;
       lcChanged=true;
      }

      if (lcMax<lcNode2->data().maximum()) {
       lcNode2->data().maximum()=lcMax;
       lcChanged=true;
      }

      if (lcNode2->data().minimum()>lcNode2->data().maximum()) goto lbError;

      if (lcChanged and lcNode2->mark()!=lcMark2) {
       lcNextNodeS->push_back(lcNode2);
       lcNode2->mark()=lcMark2;
      }

      // Arc Duration Update //
      lcArc->data().minimum()=maxi(lcNode2->data().minimum()-lcNode1->data().maximum(),
                              lcArc->data().minimum());

      lcArc->data().maximum()=mini(lcNode2->data().maximum()-lcNode1->data().minimum(),
                              lcArc->data().maximum());

      if (lcArc->data().minimum()>lcArc->data().maximum()) goto lbError;
      lcCurrentArc++;
     }

     // Incoming Arcs //
     lcCurrentArc=lcNode1->incomingArcs().begin();
     lcLastArc=lcNode1->incomingArcs().end();

     while (lcCurrentArc!=lcLastArc) {
      lcNbIteration++;
      lcArc=(*lcCurrentArc).second;
      lcNode2=lcArc->sourceNode();
      if (lcNode2==nil) send_error(erArcExtremityNotFixed);

      // Source Event Date Update //
      lcMin=lcNode1->data().minimum()-lcArc->data().maximum();
      lcMax=lcNode1->data().maximum()-lcArc->data().minimum();
      lcChanged=false;

      if (lcMin>lcNode2->data().minimum()) {
       lcNode2->data().minimum()=lcMin;
       lcChanged=true;
      }

      if (lcMax<lcNode2->data().maximum()) {
       lcNode2->data().maximum()=lcMax;
       lcChanged=true;
      }

      if (lcChanged and lcNode2->mark()!=lcMark2) {
       lcNextNodeS->push_back(lcNode2);
       lcNode2->mark()=lcMark2;
      }

      if (lcNode2->data().minimum()>lcNode2->data().maximum()) goto lbError;

      // Arc Duration Update //
      lcArc->data().minimum()=maxi(lcNode1->data().minimum()-lcNode2->data().maximum(),
                              lcArc->data().minimum());

      lcArc->data().maximum()=mini(lcNode1->data().maximum()-lcNode2->data().minimum(),
                              lcArc->data().maximum());

      if (lcArc->data().minimum()>lcArc->data().maximum()) goto lbError;
      lcCurrentArc++;
     }
    }
   }

   lcCurrentNode1++;
  }

  delete_object(lcCurrentNodeS);
  delete_object(lcNextNodeS);
  return (lcNbIteration);

  lbError:
  delete_object(lcCurrentNodeS);
  delete_object(lcNextNodeS);
  return (-1);
 }
}

// 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 _ t e n s i o n
// A l g o r i t h m
//                                                                                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_tension/algorithm.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define GRAPH_PROBLEM_MIN_COST_TENSION_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph_problem/min_cost_tension/algorithm.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostTensionAlgorithm
#define private_area graphProblemMinCostTensionAlgorithm_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Min_cost_tension/Algorithm");

// 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 {}

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