//==================================================================================================
// 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
// L i n e a r _ s y s t e 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 facilities to solve the minimum cost tension problem in graphs using
   linear program modeling. */

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

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemMinCostTensionLinearSystem
#define guGraphProblemMinCostTensionLinearSystem

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph_problem/min_cost_tension/algorithm.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  graphProblemMinCostTensionLinearSystem
#define private_area graphProblemMinCostTensionLinearSystem_private

namespace public_area  { /*NAMESPACE*/ using namespace graphProblemMinCostTensionAlgorithm; }
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 clBinarySolveAlgo;
 template <tdGraph> class clBinarySolveAlgoI;
 template <tdGraph> class clBinarySolveAlgoII;

 template <tdGraph> class clDiscreteSolveAlgo;
 template <tdGraph> class clDiscreteSolveAlgoI;
 template <tdGraph> class clDiscreteSolveAlgoII;

 template <tdGraph> class clLinearSolveAlgo;
 template <tdGraph> class clLinearSolveAlgoI;
 template <tdGraph> class clLinearSolveAlgoII;
 template <tdGraph> class clLinearSolveAlgoIII;
}

namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {}

namespace private_area {
 template <tdGraph> void findCycles(clGraph<tuGraph> &,clCycleS &,tyBoolean);
 testing_mode ( function void test(void); )
}

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

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

// B i n a r y S o l v e A l g o  Interface //------------------------------------------------------
namespace public_area {
 /*CLASS clBinarySolveAlgo */
 /* Represents an algorithm to solve the minimum binary cost tension problem in a graph using a
    linear program modeling. It is an abstract class. The cost functions of the arcs in the graph
    must be binary as defined by the <CODE>clBinaryArcData</CODE> class of the
    <CODE>Structure</CODE> module. */
 template <tdGraph> class clBinarySolveAlgo {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clBinarySolveAlgo(const clBinarySolveAlgo &);
  private_property clBinarySolveAlgo & operator = (const clBinarySolveAlgo &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clBinarySolveAlgo(void);
  public_property virtual destructor clBinarySolveAlgo(void);

  /*AMETHOD clBinarySolveAlgo */
  /* Builds a linear program equivalent to the minimum cost tension problem of a graph.
     Abstract method. */
  public_property virtual void buildLinearSystem(clTensionSystem & agSystem,
                                                 clGraph<tuGraph> & agGraph) const = 0;

  /*AMETHOD clBinarySolveAlgo */
  /* Solves the minimum cost tension problem of a graph using a given linear program solver.
     Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph,
                                        ctTensionSystemSolver & agLinearSolver) const = 0;

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

  public_property void buildLinearRelaxation(clTensionSystem &,clGraph<tuGraph> &) const;

  public_property
  tyInteger solveLinearRelaxation(clGraph<tuGraph> &,ctTensionSystemSolver &,tyReal &) const;

  /*AMETHOD clBinarySolveAlgo */
  /* Builds a Lagrangean relaxation of the linear program equivalent to the minimum binary cost
     tension problem of a graph. Lagrangean coefficients for the relaxed constraints must be
     given. Abstract method. */
  public_property virtual void
  buildLagrangeanRelaxation(clTensionSystem & agSystem,clGraph<tuGraph> & agGraph,
                            std_map(clArc<tuGraph> *,tyPairReal) & agCoefficientX) const = 0;

  public_property tyInteger solveLagrangeanRelaxation(clGraph<tuGraph> &,ctTensionSystemSolver &,
                                                      tyCardinal,tyReal &) const;

  public_property tyInteger solveLagrangeanRelaxation(clGraph<tuGraph> &,
                                                     ctTensionSystemSolver &,tyCardinal,
                                                     tyCardinal,tyReal &,tyReal &,
                                                     std_map(clArc<tuGraph> *,tyPairReal) &) const;
 };
}

// D i s c r e t e S o l v e A l g o  Interface //--------------------------------------------------
namespace public_area {
 /*CLASS clDiscreteSolveAlgo */
 /* Represents an algorithm to solve the minimum cost discrete tension problem in a graph using a
    linear program modeling. It is an abstract class. The cost functions of the arcs in the graph
    must be linear as defined by the <CODE>clDiscreteArcData</CODE> class of the
    <CODE>Structure</CODE> module. */
 template <tdGraph> class clDiscreteSolveAlgo {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clDiscreteSolveAlgo(const clDiscreteSolveAlgo &);
  private_property clDiscreteSolveAlgo & operator = (const clDiscreteSolveAlgo &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clDiscreteSolveAlgo(void);
  public_property virtual destructor clDiscreteSolveAlgo(void);

  /*AMETHOD clDiscreteSolveAlgo */
  /* Builds a linear program equivalent to the minimum cost tension problem of a graph.
     Abstract method. */
  public_property virtual void buildLinearSystem(clTensionSystem & agSystem,
                                                 clGraph<tuGraph> & agGraph) const = 0;

  /*AMETHOD clDiscreteSolveAlgo */
  /* Solves the minimum cost tension problem of a graph using a given linear program solver.
     Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph,
                                        ctTensionSystemSolver & agLinearSolver) const = 0;

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

// L i n e a r S o l v e A l g o  Interface //------------------------------------------------------
namespace public_area {
 /*CLASS clLinearSolveAlgo */
 /* Represents an algorithm to solve the minimum linear cost tension problem in a graph using a
    linear program modeling. It is an abstract class. The cost functions of the arcs in the graph
    must be linear as defined by the <CODE>clLinearArcData</CODE> class of the
    <CODE>Structure</CODE> module. */
 template <tdGraph> class clLinearSolveAlgo {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clLinearSolveAlgo(const clLinearSolveAlgo &);
  private_property clLinearSolveAlgo & operator = (const clLinearSolveAlgo &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clLinearSolveAlgo(void);
  public_property virtual destructor clLinearSolveAlgo(void);

  /*AMETHOD clLinearSolveAlgo */
  /* Builds a linear program equivalent to the minimum cost tension problem of a graph.
     Abstract method. */
  public_property virtual void buildLinearSystem(clTensionSystem & agSystem,
                                                 clGraph<tuGraph> & agGraph) const = 0;

  /*AMETHOD clLinearSolveAlgo */
  /* Solves the minimum cost tension problem of a graph using a given linear program solver.
     Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph,
                                        ctTensionSystemSolver & agLinearSolver) const = 0;

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

// B i n a r y S o l v e A l g o I  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clBinarySolveAlgoI */
 /* Represents an algorithm to solve the minimum cost tension problem with binary costs in a
    graph using the linear program modeling I (using a cycle base). */
 template <tdGraph> class clBinarySolveAlgoI : public clBinarySolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clBinarySolveAlgoI(const clBinarySolveAlgoI &);
  private_property clBinarySolveAlgoI & operator = (const clBinarySolveAlgoI &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clBinarySolveAlgoI */ /* Indicates if short cycles must be used for the base. */
  read_only_attribute(tyBoolean,atShortCycles,shortCycles);

  public_property constructor clBinarySolveAlgoI(tyBoolean=true);
  public_property destructor clBinarySolveAlgoI(void);

  public_property void      buildLinearSystem(clTensionSystem &,clGraph<tuGraph> &) const;
  public_property tyInteger run(clGraph<tuGraph> &,ctTensionSystemSolver &) const;

  public_property
  void buildLagrangeanRelaxation(clTensionSystem &,clGraph<tuGraph> &,
                                 std_map(clArc<tuGraph> *,tyPairReal) &) const;
 };
}

// D i s c r e t e S o l v e A l g o I  Interface //------------------------------------------------
namespace public_area {
 /*CLASS clDiscreteSolveAlgoI */
 /* Represents an algorithm to solve the minimum cost discrete tension problem in a graph
    using the linear program modeling I (using a cycle base). */
 template <tdGraph> class clDiscreteSolveAlgoI : public clDiscreteSolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clDiscreteSolveAlgoI(const clDiscreteSolveAlgoI &);
  private_property clDiscreteSolveAlgoI & operator = (const clDiscreteSolveAlgoI &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clDiscreteSolveAlgoI */ /* Indicates if short cycles must be used for the base. */
  read_only_attribute(tyBoolean,atShortCycles,shortCycles);

  public_property constructor clDiscreteSolveAlgoI(tyBoolean=true);
  public_property destructor clDiscreteSolveAlgoI(void);

  public_property void      buildLinearSystem(clTensionSystem &,clGraph<tuGraph> &) const;
  public_property tyInteger run(clGraph<tuGraph> &,ctTensionSystemSolver &) const;
 };
}

// L i n e a r S o l v e A l g o I  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clLinearSolveAlgoI */
 /* Represents an algorithm to solve the minimum cost tension problem with linear costs in a
    graph using the linear program modeling I (using a cycle base). */
 template <tdGraph> class clLinearSolveAlgoI : public clLinearSolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clLinearSolveAlgoI(const clLinearSolveAlgoI &);
  private_property clLinearSolveAlgoI & operator = (const clLinearSolveAlgoI &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clLinearSolveAlgoI */ /* Indicates if short cycles must be used for the base. */
  read_only_attribute(tyBoolean,atShortCycles,shortCycles);

  public_property constructor clLinearSolveAlgoI(tyBoolean=true);
  public_property destructor clLinearSolveAlgoI(void);

  public_property void      buildLinearSystem(clTensionSystem &,clGraph<tuGraph> &) const;
  public_property tyInteger run(clGraph<tuGraph> &,ctTensionSystemSolver &) const;
 };
}

// B i n a r y S o l v e A l g o I I  Interface //--------------------------------------------------
namespace public_area {
 /*CLASS clBinarySolveAlgoII */
 /* Represents an algorithm to solve the minimum cost tension problem with binary costs in a
    graph using the linear program modeling II (using the incidence matrix). */
 template <tdGraph> class clBinarySolveAlgoII : public clBinarySolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clBinarySolveAlgoII(const clBinarySolveAlgoII &);
  private_property clBinarySolveAlgoII & operator = (const clBinarySolveAlgoII &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clBinarySolveAlgoII(void);
  public_property destructor clBinarySolveAlgoII(void);

  public_property void      buildLinearSystem(clTensionSystem &,clGraph<tuGraph> &) const;
  public_property tyInteger run(clGraph<tuGraph> &,ctTensionSystemSolver &) const;

  public_property
  void buildLagrangeanRelaxation(clTensionSystem &,clGraph<tuGraph> &,
                                 std_map(clArc<tuGraph> *,tyPairReal) &) const;
 };
}

// D i s c r e t e S o l v e A l g o I I  Interface //----------------------------------------------
namespace public_area {
 /*CLASS clDiscreteSolveAlgoII */
 /* Represents an algorithm to solve the minimum cost discrete tension problem in a graph
    using the linear program modeling II (using the incidence matrix). */
 template <tdGraph> class clDiscreteSolveAlgoII : public clDiscreteSolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clDiscreteSolveAlgoII(const clDiscreteSolveAlgoII &);
  private_property clDiscreteSolveAlgoII & operator = (const clDiscreteSolveAlgoII &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clDiscreteSolveAlgoII(void);
  public_property destructor clDiscreteSolveAlgoII(void);

  public_property void      buildLinearSystem(clTensionSystem &,clGraph<tuGraph> &) const;
  public_property tyInteger run(clGraph<tuGraph> &,ctTensionSystemSolver &) const;
 };
}

// L i n e a r S o l v e A l g o I I  Interface //--------------------------------------------------
namespace public_area {
 /*CLASS clLinearSolveAlgoII */
 /* Represents an algorithm to solve the minimum cost tension problem with linear costs in a
    graph using the linear program modeling II (using a cycle base). */
 template <tdGraph> class clLinearSolveAlgoII : public clLinearSolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clLinearSolveAlgoII(const clLinearSolveAlgoII &);
  private_property clLinearSolveAlgoII & operator = (const clLinearSolveAlgoII &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clLinearSolveAlgoII */ /* Indicates if short cycles must be used for the base. */
  read_only_attribute(tyBoolean,atShortCycles,shortCycles);

  public_property constructor clLinearSolveAlgoII(tyBoolean=true);
  public_property destructor clLinearSolveAlgoII(void);

  public_property void      buildLinearSystem(clTensionSystem &,clGraph<tuGraph> &) const;
  public_property tyInteger run(clGraph<tuGraph> &,ctTensionSystemSolver &) const;
 };
}

// L i n e a r S o l v e A l g o I I I  Interface //------------------------------------------------
namespace public_area {
 /*CLASS clLinearSolveAlgoIII */
 /* Represents an algorithm to solve the minimum linear cost tension problem with linear costs in a
    graph using the linear program modeling III (using the incidence matrix). */
 template <tdGraph> class clLinearSolveAlgoIII : public clLinearSolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clLinearSolveAlgoIII(const clLinearSolveAlgoIII &);
  private_property clLinearSolveAlgoIII & operator = (const clLinearSolveAlgoIII &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clLinearSolveAlgoIII(void);
  public_property destructor clLinearSolveAlgoIII(void);

  public_property void      buildLinearSystem(clTensionSystem &,clGraph<tuGraph> &) const;
  public_property tyInteger run(clGraph<tuGraph> &,ctTensionSystemSolver &) const;
 };
}

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

// B i n a r y S o l v e A l g o  Inline //---------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinarySolveAlgo */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clBinarySolveAlgo<tuGraph>::clBinarySolveAlgo(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clBinarySolveAlgo */ /* Destructs the algorithm. */
 template <tdGraph> inline clBinarySolveAlgo<tuGraph>::~clBinarySolveAlgo(void) {}
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clBinarySolveAlgo */
 /* Solves the minimum cost tension problem using the default linear program solver. */
 template <tdGraph>
 inline tyInteger clBinarySolveAlgo<tuGraph>::run(clGraph<tuGraph> & agGraph) const
 { return (run(agGraph,clTensionSystemSolver::defaultSolver())); }
 //---------------------------------------------------------------------------------------DefaultRun
 /*METHOD clBinarySolveAlgo */
 /* Solves the minimum cost tension problem of a graph using the default version of the algorithm
    (modeling I) with the default linear program solver. Static method. */
 template <tdGraph>
 inline tyInteger clBinarySolveAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph)
 { return (clBinarySolveAlgoI<tuGraph>().clBinarySolveAlgo<tuGraph>::run(agGraph)); }
}

// D i s c r e t e S o l v e A l g o  Inline //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteSolveAlgo */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clDiscreteSolveAlgo<tuGraph>::clDiscreteSolveAlgo(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clDiscreteSolveAlgo */ /* Destructs the algorithm. */
 template <tdGraph> inline clDiscreteSolveAlgo<tuGraph>::~clDiscreteSolveAlgo(void) {}
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clDiscreteSolveAlgo */
 /* Solves the minimum cost tension problem using the default linear program solver. */
 template <tdGraph>
 inline tyInteger clDiscreteSolveAlgo<tuGraph>::run(clGraph<tuGraph> & agGraph) const
 { return (run(agGraph,clTensionSystemSolver::defaultSolver())); }
 //---------------------------------------------------------------------------------------DefaultRun
 /*METHOD clDiscreteSolveAlgo */
 /* Solves the minimum cost tension problem of a graph using the default version of the algorithm
    (modeling I) with the default linear program solver. Static method. */
 template <tdGraph>
 inline tyInteger clDiscreteSolveAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph)
 { return (clDiscreteSolveAlgoI<tuGraph>().clDiscreteSolveAlgo<tuGraph>::run(agGraph)); }
}

// L i n e a r S o l v e A l g o  Inline //---------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearSolveAlgo */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clLinearSolveAlgo<tuGraph>::clLinearSolveAlgo(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clLinearSolveAlgo */ /* Destructs the algorithm. */
 template <tdGraph> inline clLinearSolveAlgo<tuGraph>::~clLinearSolveAlgo(void) {}
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clLinearSolveAlgo */
 /* Solves the minimum cost tension problem using the default linear program solver. */
 template <tdGraph>
 inline tyInteger clLinearSolveAlgo<tuGraph>::run(clGraph<tuGraph> & agGraph) const
 { return (run(agGraph,clTensionSystemSolver::defaultSolver())); }
 //---------------------------------------------------------------------------------------DefaultRun
 /*METHOD clLinearSolveAlgo */
 /* Solves the minimum cost tension problem of a graph using the default version of the algorithm
    (modeling II) with the default linear program solver. Static method. */
 template <tdGraph>
 inline tyInteger clLinearSolveAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph)
 { return (clLinearSolveAlgoII<tuGraph>().clLinearSolveAlgo<tuGraph>::run(agGraph)); }
}

// B i n a r y S o l v e A l g o I  Inline //-------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinarySolveAlgoI */
 /* Builds an algorithm to solve the minimum cost tension problem. Short or long cycles can be
    chosen to create the cycle base used by the linear program model (default is short). */
 template <tdGraph> inline clBinarySolveAlgoI<tuGraph>::clBinarySolveAlgoI(tyBoolean agShortCycles)
 : atShortCycles(agShortCycles) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clBinarySolveAlgoI */ /* Destructs the algorithm. */
 template <tdGraph> inline clBinarySolveAlgoI<tuGraph>::~clBinarySolveAlgoI(void) {}
}

// D i s c r e t e S o l v e A l g o I  Inline //---------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteSolveAlgoI */
 /* Builds an algorithm to solve the minimum cost tension problem. Short or long cycles can be
    chosen to create the cycle base used by the linear program model (default is short). */
 template <tdGraph>
 inline clDiscreteSolveAlgoI<tuGraph>::clDiscreteSolveAlgoI(tyBoolean agShortCycles)
 : atShortCycles(agShortCycles) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clDiscreteSolveAlgoI */ /* Destructs the algorithm. */
 template <tdGraph> inline clDiscreteSolveAlgoI<tuGraph>::~clDiscreteSolveAlgoI(void) {}
}

// L i n e a r S o l v e A l g o I  Inline //-------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearSolveAlgoI */
 /* Builds an algorithm to solve the minimum cost tension problem. Short or long cycles can be
    chosen to create the cycle base used by the linear program model (default is short). */
 template <tdGraph> inline clLinearSolveAlgoI<tuGraph>::clLinearSolveAlgoI(tyBoolean agShortCycles)
 : atShortCycles(agShortCycles) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clLinearSolveAlgoI */ /* Destructs the algorithm. */
 template <tdGraph> inline clLinearSolveAlgoI<tuGraph>::~clLinearSolveAlgoI(void) {}
}

// B i n a r y S o l v e A l g o I I  Inline //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinarySolveAlgoII */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph>
 inline clBinarySolveAlgoII<tuGraph>::clBinarySolveAlgoII(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clBinarySolveAlgoII */ /* Destructs the algorithm. */
 template <tdGraph> inline clBinarySolveAlgoII<tuGraph>::~clBinarySolveAlgoII(void) {}
}

// D i s c r e t e S o l v e A l g o I I  Inline //-------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteSolveAlgoII */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph>
 inline clDiscreteSolveAlgoII<tuGraph>::clDiscreteSolveAlgoII(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clDiscreteSolveAlgoII */ /* Destructs the algorithm. */
 template <tdGraph> inline clDiscreteSolveAlgoII<tuGraph>::~clDiscreteSolveAlgoII(void) {}
}

// L i n e a r S o l v e A l g o I I  Inline //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearSolveAlgoII */
 /* Builds an algorithm to solve the minimum cost tension problem. Short or long cycles can be
    chosen to create the cycle base used by the linear program model (default is short). */
 template <tdGraph>
 inline clLinearSolveAlgoII<tuGraph>::clLinearSolveAlgoII(tyBoolean agShortCycles)
 : atShortCycles(agShortCycles) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clLinearSolveAlgoII */ /* Destructs the algorithm. */
 template <tdGraph> inline clLinearSolveAlgoII<tuGraph>::~clLinearSolveAlgoII(void) {}
}

// L i n e a r S o l v e A l g o I I I  Inline //---------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearSolveAlgoIII */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clLinearSolveAlgoIII<tuGraph>::clLinearSolveAlgoIII(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clLinearSolveAlgoIII */ /* Destructs the algorithm. */
 template <tdGraph> inline clLinearSolveAlgoIII<tuGraph>::~clLinearSolveAlgoIII(void) {}
}

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

namespace private_area {
 //---------------------------------------------------------------------------------------FindCycles
 template <tdGraph>
 void findCycles(clGraph<tuGraph> & agGraph,clCycleS & agCycleS,tyBoolean atShortCycles) {
  typedef clCycleS::const_iterator clCycleIterator;

  clCycleIterator lcCurrentCycle;
  clCycleS        lcCycleS;
  clCycleIterator lcLastCycle;

  tyCardinal lcCounter1 = 0;
  tyCardinal lcCounter2 = 0;

  if (atShortCycles) {
   graphAlgorithm::findCycles(agGraph,agCycleS,true);
   lcCurrentCycle=agCycleS.begin();
   lcLastCycle=agCycleS.end();

   while (lcCurrentCycle!=lcLastCycle) {
    lcCounter1+=(*lcCurrentCycle).size();
    ++lcCurrentCycle;
   }

   graphAlgorithm::findCycles(agGraph,lcCycleS,true);
   lcCurrentCycle=lcCycleS.begin();
   lcLastCycle=lcCycleS.end();

   while (lcCurrentCycle!=lcLastCycle) {
    lcCounter2+=(*lcCurrentCycle).size();
    ++lcCurrentCycle;
   }

   if (lcCounter2<lcCounter1) {
    agCycleS.erase(agCycleS.begin(),agCycleS.end());
    agCycleS=lcCycleS;
   }
  }
  else graphAlgorithm::findCycles(agGraph,agCycleS,false);
 }
}

// B i n a r y S o l v e A l g o  Implementation //-------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------BuildLinearRelaxation
 /*METHOD clBinarySolveAlgo */
 /* Builds a linear relaxation of the linear program equivalent to the minimum binary cost tension
    problem of a graph. */
 template <tdGraph>
 void clBinarySolveAlgo<tuGraph>::buildLinearRelaxation(clTensionSystem & agSystem,
                                                        clGraph<tuGraph> & agGraph) const {
  typedef clTensionSystem::cpVariableX::const_iterator clVariableIterator;

  clVariableIterator  lcCurrentVariable;
  clVariableIterator  lcLastVariable;
  clTensionVariable * lcVariable;

  buildLinearSystem(agSystem,agGraph);
  lcCurrentVariable=agSystem.variables().begin();
  lcLastVariable=agSystem.variables().end();

  while (lcCurrentVariable!=lcLastVariable) {
   lcVariable=(*lcCurrentVariable).second;
   if (lcVariable->content().significance()==binary) lcVariable->kind()=linearSystem::realVariable;
   ++lcCurrentVariable;
  }
 }
 //----------------------------------------------------------------------------SolveLinearRelaxation
 /*METHOD clBinarySolveAlgo */
 /* Solves the linear relaxation of the minimum binary cost tension problem of a graph using a
    given linear program solver. A lower bound for the original problem can be collected. */
 template <tdGraph> tyInteger
 clBinarySolveAlgo<tuGraph>::solveLinearRelaxation(clGraph<tuGraph> & agGraph,
                                                   ctTensionSystemSolver & agLinearSolver,
                                                   tyReal & agLowerBound) const {
  typedef clTensionSystem::cpVariableX::const_iterator clVariableIterator;

  clArc<tuGraph> *    lcArc;
  clVariableIterator  lcCurrentVariable;
  tyInteger           lcIteration;
  clVariableIterator  lcLastVariable;
  clTensionSystem     lcSystem;
  clTensionVariable * lcVariable;

  agGraph.solved()=false;
  buildLinearRelaxation(lcSystem,agGraph);
  lcIteration=agLinearSolver.run(lcSystem);
  if (not lcSystem.solved()) return (-1);
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();

  while (lcCurrentVariable!=lcLastVariable) {
   lcVariable=(*lcCurrentVariable).second;

   if (lcVariable->content().significance()==tension) {
    lcArc=&(agGraph.arc(lcVariable->content().arc()));
    lcArc->data().expected()=lcVariable->value();
   }

   ++lcCurrentVariable;
  }

  agLowerBound=lcSystem.objective().value();
  agGraph.solved()=true;
  return (lcIteration);
 }
 //------------------------------------------------------------------------SolveLagrangeanRelaxation
 /*METHOD clBinarySolveAlgo */
 /* Solves the Lagrangean relaxation of the minimum binary cost tension problem of a graph using a
    given linear program solver. The maximum number of iterations to solve the relaxation with the
    subgradient method must be given. A lower bound for the original problem can be collected. */
 template <tdGraph> tyInteger
 clBinarySolveAlgo<tuGraph>::solveLagrangeanRelaxation(clGraph<tuGraph> & agGraph,
                                                       ctTensionSystemSolver & agLinearSolver,
                                                       tyCardinal agMaxIteration,
                                                       tyReal & agLowerBound) const {
  typedef clArc<tuGraph>                                    cpArc;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef std_map(cpArc *,tyPairReal)                       cpCoefficientX;

  cpArc *        lcArc;
  cpCoefficientX lcCoefficientX;

  tyCardinal    lcBlockIteration = agGraph.arcs().size();
  cpArcIterator lcCurrentArc     = agGraph.arcs().begin();
  cpArcIterator lcLastArc        = agGraph.arcs().end();
  tyReal        lcStep           = 2.0;

  agLowerBound=0.0;

  // Lagrangean Coefficients Initialization //
  while (lcCurrentArc!=lcLastArc) {
   lcArc=(*lcCurrentArc).second;
   lcCoefficientX.insert(std_make_pair(lcArc,standard::make_pair(0.0,0.0)));
   ++lcCurrentArc;
  }

  // Lagrangean Relaxation Resolution //
  return (solveLagrangeanRelaxation(agGraph,agLinearSolver,agMaxIteration,lcBlockIteration,
                                    lcStep,agLowerBound,lcCoefficientX));
 }
 //------------------------------------------------------------------------SolveLagrangeanRelaxation
 /*METHOD clBinarySolveAlgo */
 /* Solves the Lagrangean relaxation of the minimum binary cost tension problem of a graph using a
    given linear program solver. The maximum and per-block numbers of iterations to solve the
    relaxation with the subgradient method and its step must be given. A lower bound for the
    original problem can be collected. The starting Lagrangean coefficients must also be
    provided. */
 template <tdGraph> tyInteger
 clBinarySolveAlgo<tuGraph>::solveLagrangeanRelaxation(clGraph<tuGraph> & agGraph,
                                     ctTensionSystemSolver & agLinearSolver,
                                     tyCardinal agMaxIteration,tyCardinal agBlockIteration,
                                     tyReal & agStep,tyReal & agLowerBound,
                                     std_map(clArc<tuGraph> *,tyPairReal) & agCoefficientX) const {
  typedef clArc<tuGraph>                               cpArc;
  typedef std_map(cpArc *,tyPairReal)                  cpCoefficientX;
  typedef typename cpCoefficientX::iterator            cpCoefficientIterator;
  typedef clTensionSystem::cpVariableX::const_iterator clVariableIterator;

  typedef graphProblemMinCostTensionStructure::clVariableContent clVariableContent;

  cpArc *               lcArc;
  clVariableContent *   lcContent;
  cpCoefficientIterator lcCurrentCoefficient;
  clVariableIterator    lcCurrentVariable;
  cpCoefficientIterator lcLastCoefficient;
  clVariableIterator    lcLastVariable;
  clTensionSystem       lcSystem;

  tyReal     lcCoefficient1;
  tyReal     lcCoefficient2;
  tyReal     lcCost;
  tyReal     lcDelta;
  tyReal     lcImprovement;
  tyInteger  lcIteration;
  tyReal     lcMaxImprovement;
  tyReal     lcMaximum;
  tyReal     lcMinimum;
  tyReal     lcOptimum;
  tyInteger  lcSelection;

  tyReal     lcRate                 = 0.5;
  tyCardinal lcSubgradientIteration = 0;
  tyInteger  lcTotalIteration       = 0;

  agGraph.solved()=false;

  do {
   // Relaxed System Resolution //
   lcSystem.removeConstraints();
   lcSystem.removeVariables();
   buildLagrangeanRelaxation(lcSystem,agGraph,agCoefficientX);
   lcIteration=agLinearSolver.run(lcSystem);
   if (not lcSystem.solved()) return (-1);
   lcTotalIteration+=lcIteration;

   // Connection With The Graph //
   lcCurrentVariable=lcSystem.variables().begin();
   lcLastVariable=lcSystem.variables().end();

   while (lcCurrentVariable!=lcLastVariable) {
    lcContent=&((*lcCurrentVariable).second->content());

    if (lcContent->significance()==tension) {
     lcArc=&(agGraph.arc(lcContent->arc()));
     lcArc->data().expected()=(*lcCurrentVariable).second->value();
    }

    ++lcCurrentVariable;
   }

   // Subgradient Iteration //
   lcCurrentCoefficient=agCoefficientX.begin();
   lcLastCoefficient=agCoefficientX.end();
   lcMaxImprovement=0.0;
   agLowerBound=0.0;

   while (lcCurrentCoefficient!=lcLastCoefficient) {
    lcArc=(*lcCurrentCoefficient).first;
    lcCoefficient1=(*lcCurrentCoefficient).second.first;
    lcCoefficient2=(*lcCurrentCoefficient).second.second;
    lcMinimum=lcArc->data().minimum();
    lcMaximum=lcArc->data().maximum();
    lcOptimum=lcArc->data().optimum();

    lcCost=lcArc->data().weight()-lcCoefficient1*(lcOptimum-lcMinimum)
           -lcCoefficient2*(lcMaximum-lcOptimum);

    lcSelection=(lcCost<0 ? 1 : 0);
    lcDelta=lcArc->data().tension()+lcSelection*(lcOptimum-lcMinimum)-lcOptimum;

    if (not isEqual(lcDelta,0.0)) {
     (*lcCurrentCoefficient).second.first-=agStep*lcDelta;
     if ((*lcCurrentCoefficient).second.first<0.0) (*lcCurrentCoefficient).second.first=0.0;
     lcImprovement=std::fabs((*lcCurrentCoefficient).second.first-lcCoefficient1);
     lcMaxImprovement=maxi(lcMaxImprovement,lcImprovement);
    }

    if (lcMaximum<lcArc->data().positiveInfinity()) {
     lcDelta=-lcArc->data().tension()+lcSelection*(lcMaximum-lcOptimum)+lcOptimum;

     if (not isEqual(lcDelta,0.0)) {
      (*lcCurrentCoefficient).second.second-=agStep*lcDelta;
      if ((*lcCurrentCoefficient).second.second<0.0) (*lcCurrentCoefficient).second.second=0.0;
      lcImprovement=std::fabs((*lcCurrentCoefficient).second.second-lcCoefficient2);
      lcMaxImprovement=maxi(lcMaxImprovement,lcImprovement);
     }
    }

    lcCost*=lcSelection;
    lcCost+=(lcCoefficient2-lcCoefficient1)*lcArc->data().tension();
    lcCost+=(lcCoefficient1-lcCoefficient2)*lcOptimum;
    agLowerBound+=lcCost;
    ++lcCurrentCoefficient;
   }

   ++lcSubgradientIteration;
   if (lcSubgradientIteration%agBlockIteration==0) agStep*=lcRate;
  }
  while (lcSubgradientIteration<agMaxIteration and lcMaxImprovement>1e-6);

  agGraph.solved()=true;
  return (lcTotalIteration);
 }
}

// B i n a r y S o l v e A l g o I  Implementation //-----------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------BuildLinearSystem
 /*METHOD clBinarySolveAlgoI */
 /* Builds a linear program equivalent to the minimum cost tension problem of a graph. */
 template <tdGraph>
 void clBinarySolveAlgoI<tuGraph>::buildLinearSystem(clTensionSystem & agSystem,
                                                     clGraph<tuGraph> & agGraph) const {
  method_name("binarySolveAlgoI::buildLinearSystem");

  typedef clCycle::const_iterator                           clArcIterator;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clCycleS::const_iterator                          clCycleIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *      lcArc;
  clAssociation         lcAssociation;
  clTensionConstraint * lcBalanceConstraint;
  clTensionConstraint * lcBoundaryConstraint;
  clCycleS              lcCycleS;
  clTensionConstraint * lcMeetingConstraint;
  clTensionVariable *   lcSelectionVariable;
  tyReal                lcTempo;
  clTensionVariable *   lcTensionVariable;

  tyMark          lcArcsMark;
  clArcIterator   lcCurrentArc;
  cpArcIterator   lcCurrentArc2;
  clCycleIterator lcCurrentCycle;
  clArcIterator   lcLastArc;
  cpArcIterator   lcLastArc2;
  clCycleIterator lcLastCycle;

  // Cycles Search //
  agSystem.objective().kind()=linearSystem::minimum;
  private_area::findCycles(agGraph,lcCycleS,atShortCycles);
  lcCurrentCycle=lcCycleS.begin();
  lcLastCycle=lcCycleS.end();
  lcArcsMark=++(agGraph.mark());

  // Constrained Arcs //
  while (lcCurrentCycle!=lcLastCycle) {
   lcMeetingConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcCurrentArc=(*lcCurrentCycle).begin();
   lcLastArc=(*lcCurrentCycle).end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=&(agGraph.arc((*lcCurrentArc).first));

    // Associated Variables //
    if (lcArc->mark()!=lcArcsMark) {
     // Tension Variable //
     lcArc->mark()=lcArcsMark;
     lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcAssociation.insert(std_make_pair(lcArc->key(),lcTensionVariable->key()));
     lcTensionVariable->content().significance()=tension;
     lcTensionVariable->content().arc()=lcArc->key();

     // Selection Variable //
     lcSelectionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcSelectionVariable->kind()=linearSystem::integralVariable;
     lcSelectionVariable->content().significance()=binary;
     lcSelectionVariable->content().arc()=lcArc->key();
     lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
     lcBoundaryConstraint->boundary()=1.0;
     lcBoundaryConstraint->setCoefficient(lcSelectionVariable->key(),+1.0);

     if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
      send_error(erNegativeTension);

     // Minimum //
     lcTempo=lcArc->data().optimum()-lcArc->data().minimum();
     lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::superiority));
     lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
     lcBoundaryConstraint->setCoefficient(lcSelectionVariable->key(),lcTempo);
     lcBoundaryConstraint->boundary()=lcArc->data().optimum();

     // Maximum //
     if (lcArc->data().maximum()!=lcArc->data().positiveInfinity()) {
      lcTempo=lcArc->data().maximum()-lcArc->data().optimum();
      lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
      lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
      lcBoundaryConstraint->setCoefficient(lcSelectionVariable->key(),-lcTempo);
      lcBoundaryConstraint->boundary()=lcArc->data().optimum();
     }

     // Objective //
     agSystem.objective().setCoefficient(lcSelectionVariable->key(),(lcArc->data().weight()));
    }

    // Direction in the cycle //
    lcMeetingConstraint->setCoefficient(lcAssociation[lcArc->key()],(*lcCurrentArc).second);

    lcCurrentArc++;
   }

   lcCurrentCycle++;
  }

  // Unconstrained Arcs //
  lcCurrentArc2=agGraph.arcs().begin();
  lcLastArc2=agGraph.arcs().end();

  while (lcCurrentArc2!=lcLastArc2) {
   lcArc=(*lcCurrentArc2).second;

   // Associated Variables //
   if (lcArc->mark()!=lcArcsMark) {
    lcArc->mark()=lcArcsMark;
    lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcTensionVariable->content().significance()=tension;
    lcTensionVariable->content().arc()=lcArc->key();

    if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
     send_error(erNegativeTension);

    // Variable Is Equal To Optimum //
    lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
    lcBalanceConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
    lcBalanceConstraint->boundary()=lcArc->data().optimum();
   }

   lcCurrentArc2++;
  }
 }
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clBinarySolveAlgoI */
 /* Solves the minimum cost tension problem of a graph using a given linear program solver. */
 template <tdGraph>
 tyInteger clBinarySolveAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                            ctTensionSystemSolver & agLinearSolver) const {
  typedef clArc<tuGraph>                               cpArc;
  typedef clTensionSystem::cpVariableX::const_iterator clVariableIterator;

  typedef graphProblemMinCostTensionStructure::clVariableContent clVariableContent;

  cpArc *             lcArc;
  clVariableContent * lcContent;
  clVariableIterator  lcCurrentVariable;
  clVariableIterator  lcLastVariable;
  tyInteger           lcNbIteration;
  clTensionSystem     lcSystem;

  // Linear System Resolution //
  buildLinearSystem(lcSystem,agGraph);
  lcNbIteration=agLinearSolver.run(lcSystem);
  agGraph.solved()=lcSystem.solved();
  if (not lcSystem.solved()) return (-1);

  // Connection With The Graph //
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();

  while (lcCurrentVariable!=lcLastVariable) {
   lcContent=&((*lcCurrentVariable).second->content());

   if (lcContent->significance()==tension) {
    lcArc=&(agGraph.arc(lcContent->arc()));
    lcArc->data().expected()=(*lcCurrentVariable).second->value();
   }

   ++lcCurrentVariable;
  }

  return (lcNbIteration);
 }
 //------------------------------------------------------------------------BuildLagrangeanRelaxation
 /*METHOD clBinarySolveAlgoI */
 /* Builds a Lagrangean relaxation of the linear program equivalent to the minimum binary cost
    tension problem of a graph. Lagrangean coefficients for the relaxed constraints must be
    given. */
 template <tdGraph>
 void clBinarySolveAlgoI<tuGraph>::buildLagrangeanRelaxation(clTensionSystem & agSystem,
                                   clGraph<tuGraph> & agGraph,
                                   std_map(clArc<tuGraph> *,tyPairReal) & agCoefficientX) const {
  method_name("binarySolveAlgoI::buildLagrangeanRelaxation");

  typedef clCycle::const_iterator                           clArcIterator;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clCycleS::const_iterator                          clCycleIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *      lcArc;
  clAssociation         lcAssociation;
  clTensionConstraint * lcBalanceConstraint;
  clTensionConstraint * lcBoundaryConstraint;
  clCycleS              lcCycleS;
  clTensionConstraint * lcMeetingConstraint;
  clTensionVariable *   lcTensionVariable;
  tyReal                lcTempo;

  tyMark          lcArcsMark;
  clArcIterator   lcCurrentArc;
  cpArcIterator   lcCurrentArc2;
  clCycleIterator lcCurrentCycle;
  clArcIterator   lcLastArc;
  cpArcIterator   lcLastArc2;
  clCycleIterator lcLastCycle;

  agSystem.objective().kind()=linearSystem::minimum;
  private_area::findCycles(agGraph,lcCycleS,atShortCycles);
  lcCurrentCycle=lcCycleS.begin();
  lcLastCycle=lcCycleS.end();
  lcArcsMark=++(agGraph.mark());

  // Constrained Arcs //
  while (lcCurrentCycle!=lcLastCycle) {
   lcMeetingConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcCurrentArc=(*lcCurrentCycle).begin();
   lcLastArc=(*lcCurrentCycle).end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=&(agGraph.arc((*lcCurrentArc).first));

    // Associated Variables //
    if (lcArc->mark()!=lcArcsMark) {
     // Tension Variable //
     lcArc->mark()=lcArcsMark;
     lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcAssociation.insert(std_make_pair(lcArc->key(),lcTensionVariable->key()));
     lcTensionVariable->content().significance()=tension;
     lcTensionVariable->content().arc()=lcArc->key();

     if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
      send_error(erNegativeTension);

     // Minimum //
     lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::superiority));
     lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
     lcBoundaryConstraint->boundary()=lcArc->data().minimum();

     // Maximum //
     if (lcArc->data().maximum()!=lcArc->data().positiveInfinity()) {
      lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
      lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
      lcBoundaryConstraint->boundary()=lcArc->data().maximum();
      lcTempo=agCoefficientX[lcArc].second-agCoefficientX[lcArc].first;
     }
     else lcTempo=-agCoefficientX[lcArc].first;

     // Objective //
     agSystem.objective().setCoefficient(lcTensionVariable->key(),lcTempo);
    }

    // Direction In The Cycle //
    lcMeetingConstraint->setCoefficient(lcAssociation[lcArc->key()],(*lcCurrentArc).second);

    lcCurrentArc++;
   }

   lcCurrentCycle++;
  }

  // Unconstrained Arcs //
  lcCurrentArc2=agGraph.arcs().begin();
  lcLastArc2=agGraph.arcs().end();

  while (lcCurrentArc2!=lcLastArc2) {
   lcArc=(*lcCurrentArc2).second;

   // Associated Variables //
   if (lcArc->mark()!=lcArcsMark) {
    lcArc->mark()=lcArcsMark;
    lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcTensionVariable->content().significance()=tension;
    lcTensionVariable->content().arc()=lcArc->key();

    if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
     send_error(erNegativeTension);

    // Variable Is Equal To Optimum //
    lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
    lcBalanceConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
    lcBalanceConstraint->boundary()=lcArc->data().optimum();
   }

   lcCurrentArc2++;
  }
 }
}

// D i s c r e t e S o l v e A l g o I  Implementation //-------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------BuildLinearSystem
 /*METHOD clDiscreteSolveAlgoI */
 /* Builds a linear program equivalent to the minimum cost tension problem of a graph. */
 template <tdGraph>
 void clDiscreteSolveAlgoI<tuGraph>::buildLinearSystem(clTensionSystem & agSystem,
                                                       clGraph<tuGraph> & agGraph) const {
  method_name("discreteSolveAlgoI::buildLinearSystem");

  typedef clArc<tuGraph>                                    cpArc;
  typedef clCycle::const_iterator                           clArcIterator;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clCycleS::const_iterator                          clCycleIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  cpArc *               lcArc;
  clAssociation         lcAssociation1;
  clAssociation         lcAssociation2;
  clTensionConstraint * lcBalanceConstraint;
  clTensionConstraint * lcBoundaryConstraint;
  tyCardinal            lcCounter;
  clCycleS              lcCycleS;
  clTensionConstraint * lcExclusivityConstraint;
  clTensionConstraint * lcMeetingConstraint;
  clTensionVariable *   lcShrinkVariable;
  clTensionVariable *   lcStretchVariable;
  tyReal                lcTempo;
  clTensionConstraint * lcTensionConstraint;
  clTensionVariable *   lcTensionVariable;

  tyMark          lcArcsMark;
  clArcIterator   lcCurrentArc;
  cpArcIterator   lcCurrentArc2;
  clCycleIterator lcCurrentCycle;
  clArcIterator   lcLastArc;
  cpArcIterator   lcLastArc2;
  clCycleIterator lcLastCycle;

  // Cycles Search //
  agSystem.objective().kind()=linearSystem::minimum;
  private_area::findCycles(agGraph,lcCycleS,atShortCycles);
  lcCurrentCycle=lcCycleS.begin();
  lcLastCycle=lcCycleS.end();
  lcArcsMark=++(agGraph.mark());

  // Constrained Arcs //
  while (lcCurrentCycle!=lcLastCycle) {
   lcMeetingConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcCurrentArc=(*lcCurrentCycle).begin();
   lcLastArc=(*lcCurrentCycle).end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=&(agGraph.arc((*lcCurrentArc).first));

    // Associated Variables //
    if (lcArc->mark()!=lcArcsMark) {
     // Stretching & Shrinking Tensions //
     lcArc->mark()=lcArcsMark;
     lcShrinkVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcStretchVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcAssociation1.insert(std_make_pair(lcArc->key(),lcShrinkVariable->key()));
     lcAssociation2.insert(std_make_pair(lcArc->key(),lcStretchVariable->key()));

     lcShrinkVariable->content().significance()=shrinking;
     lcShrinkVariable->content().arc()=lcArc->key();
     lcStretchVariable->content().significance()=stretching;
     lcStretchVariable->content().arc()=lcArc->key();

     // Feasible Tensions //
     lcCounter=0;
     lcTensionConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
     lcTensionConstraint->boundary()=lcArc->data().optimum();
     lcTensionConstraint->setCoefficient(lcShrinkVariable->key(),1.0);
     lcTensionConstraint->setCoefficient(lcStretchVariable->key(),-1.0);
     lcExclusivityConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
     lcExclusivityConstraint->boundary()=1.0;

     while (lcCounter<lcArc->data().feasibles().size()) {
      lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
      lcTensionVariable->content().significance()=binary;
      lcTensionVariable->content().arc()=lcArc->key();
      lcTensionVariable->kind()=linearSystem::integralVariable;
      lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
      lcBoundaryConstraint->boundary()=1.0;
      lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),1.0);
      lcTempo=lcArc->data().feasibles()[lcCounter];
      lcTensionConstraint->setCoefficient(lcTensionVariable->key(),lcTempo);
      lcExclusivityConstraint->setCoefficient(lcTensionVariable->key(),1.0);
      ++lcCounter;
     }

     if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
      send_error(erNegativeTension);

     // Objective //
     agSystem.objective().setCoefficient(lcShrinkVariable->key(),(lcArc->data().shrinkingCost()));
     agSystem.objective().setCoefficient(lcStretchVariable->key(),lcArc->data().stretchingCost());
    }

    // Direction In The Cycle //
    lcMeetingConstraint->setCoefficient(lcAssociation1[lcArc->key()],-(*lcCurrentArc).second);
    lcMeetingConstraint->setCoefficient(lcAssociation2[lcArc->key()],(*lcCurrentArc).second);
    ((*lcMeetingConstraint).boundary())-=(*lcCurrentArc).second*(lcArc->data().optimum());

    lcCurrentArc++;
   }

   lcCurrentCycle++;
  }

  // Unconstrained Arcs //
  lcCurrentArc2=agGraph.arcs().begin();
  lcLastArc2=agGraph.arcs().end();

  while (lcCurrentArc2!=lcLastArc2) {
   lcArc=(*lcCurrentArc2).second;

   // Associated Variables //
   if (lcArc->mark()!=lcArcsMark) {
    lcArc->mark()=lcArcsMark;
    lcShrinkVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcStretchVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcShrinkVariable->content().significance()=shrinking;
    lcShrinkVariable->content().arc()=lcArc->key();
    lcStretchVariable->content().significance()=stretching;
    lcStretchVariable->content().arc()=lcArc->key();

    if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
     send_error(erNegativeTension);

    // Shrink Variable Is Null //
    lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
    lcBalanceConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
    lcBalanceConstraint->boundary()=0.0;

    // Stretch Variable Is Null //
    lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
    lcBalanceConstraint->setCoefficient(lcStretchVariable->key(),+1.0);
    lcBalanceConstraint->boundary()=0.0;
   }

   lcCurrentArc2++;
  }
 }
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clDiscreteSolveAlgoI */
 /* Solves the minimum cost tension problem of a graph using a given linear program solver. */
 template <tdGraph>
 tyInteger clDiscreteSolveAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                              ctTensionSystemSolver & agLinearSolver) const {
  typedef clArc<tuGraph>                               cpArc;
  typedef clTensionSystem::cpVariableX::const_iterator clVariableIterator;

  typedef graphProblemMinCostTensionStructure::clVariableContent clVariableContent;

  cpArc *             lcArc;
  clVariableContent * lcContent;
  clVariableIterator  lcCurrentVariable;
  clVariableIterator  lcLastVariable;
  tyMark              lcMark;
  tyInteger           lcNbIteration;
  clTensionSystem     lcSystem;

  // Linear System Resolution //
  buildLinearSystem(lcSystem,agGraph);
  lcNbIteration=agLinearSolver.run(lcSystem);
  agGraph.solved()=lcSystem.solved();
  if (not lcSystem.solved()) return (-1);

  // Connection With The Graph //
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();
  lcMark=++(agGraph.mark());

  while (lcCurrentVariable!=lcLastVariable) {
   lcContent=&((*lcCurrentVariable).second->content());

   if (lcContent->significance()==shrinking or lcContent->significance()==stretching) {
    lcArc=&(agGraph.arc(lcContent->arc()));

    if (lcArc->mark()!=lcMark) {
     lcArc->data().expected()=lcArc->data().optimum();
     lcArc->mark()=lcMark;
    }

    if (lcContent->significance()==shrinking)
     lcArc->data().expected()-=(*lcCurrentVariable).second->value();
    else lcArc->data().expected()+=(*lcCurrentVariable).second->value();
   }

   ++lcCurrentVariable;
  }

  return (lcNbIteration);
 }
}

// L i n e a r S o l v e A l g o I  Implementation //-----------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------BuildLinearSystem
 /*METHOD clLinearSolveAlgoI */
 /* Builds a linear program equivalent to the minimum cost tension problem of a graph. */
 template <tdGraph>
 void clLinearSolveAlgoI<tuGraph>::buildLinearSystem(clTensionSystem & agSystem,
                                                     clGraph<tuGraph> & agGraph) const {
  method_name("linearSolveAlgoI::buildLinearSystem");

  typedef clCycle::const_iterator                           clArcIterator;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clCycleS::const_iterator                          clCycleIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *      lcArc;
  clAssociation         lcAssociation;
  clTensionConstraint * lcBalanceConstraint;
  clTensionConstraint * lcBoundaryConstraint;
  clCycleS              lcCycleS;
  clTensionVariable *   lcDurationVariable;
  clTensionConstraint * lcMeetingConstraint;
  clTensionVariable *   lcShrinkVariable;
  clTensionVariable *   lcStretchVariable;
  tyReal                lcTempo;

  tyMark          lcArcsMark;
  clArcIterator   lcCurrentArc;
  cpArcIterator   lcCurrentArc2;
  clCycleIterator lcCurrentCycle;
  clArcIterator   lcLastArc;
  cpArcIterator   lcLastArc2;
  clCycleIterator lcLastCycle;

  // Cycles Search //
  agSystem.objective().kind()=linearSystem::minimum;
  private_area::findCycles(agGraph,lcCycleS,atShortCycles);
  lcCurrentCycle=lcCycleS.begin();
  lcLastCycle=lcCycleS.end();
  lcArcsMark=++(agGraph.mark());

  // Constrained Arcs //
  while (lcCurrentCycle!=lcLastCycle) {
   lcMeetingConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcCurrentArc=(*lcCurrentCycle).begin();
   lcLastArc=(*lcCurrentCycle).end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=&(agGraph.arc((*lcCurrentArc).first));

    // Associated Variables //
    if (lcArc->mark()!=lcArcsMark) {
     lcArc->mark()=lcArcsMark;
     lcDurationVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcShrinkVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcStretchVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcAssociation.insert(std_make_pair(lcArc->key(),lcDurationVariable->key()));

     lcDurationVariable->content().significance()=tension;
     lcDurationVariable->content().arc()=lcArc->key();
     lcShrinkVariable->content().significance()=shrinking;
     lcShrinkVariable->content().arc()=lcArc->key();
     lcStretchVariable->content().significance()=stretching;
     lcStretchVariable->content().arc()=lcArc->key();

     if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
      send_error(erNegativeTension);

     // Minimum //
     lcTempo=lcArc->data().optimum()-lcArc->data().minimum();
     lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
     lcBoundaryConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
     lcBoundaryConstraint->boundary()=(lcTempo<0 ? 0 : lcTempo);

     // Maximum //
     if (lcArc->data().maximum()!=lcArc->data().positiveInfinity()) {
      lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
      lcBoundaryConstraint->setCoefficient(lcStretchVariable->key(),+1.0);
      lcTempo=lcArc->data().maximum()-lcArc->data().optimum();
      lcBoundaryConstraint->boundary()=(lcTempo<0 ? 0 : lcTempo);
     }

     // Balance //
     lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
     lcBalanceConstraint->setCoefficient(lcDurationVariable->key(),+1.0);
     lcBalanceConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
     lcBalanceConstraint->setCoefficient(lcStretchVariable->key(),-1.0);
     lcBalanceConstraint->boundary()=lcArc->data().optimum();

     // Objective //
     agSystem.objective().setCoefficient(lcShrinkVariable->key(),lcArc->data().shrinkingCost());
     agSystem.objective().setCoefficient(lcStretchVariable->key(),lcArc->data().stretchingCost());
    }

    // Direction In The Cycle //
    lcMeetingConstraint->setCoefficient(lcAssociation[lcArc->key()],(*lcCurrentArc).second);

    lcCurrentArc++;
   }

   lcCurrentCycle++;
  }

  // Unconstrained Arcs //
  lcCurrentArc2=agGraph.arcs().begin();
  lcLastArc2=agGraph.arcs().end();

  while (lcCurrentArc2!=lcLastArc2) {
   lcArc=(*lcCurrentArc2).second;

   // Associated Variables //
   if (lcArc->mark()!=lcArcsMark) {
    lcArc->mark()=lcArcsMark;
    lcDurationVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcDurationVariable->content().significance()=tension;
    lcDurationVariable->content().arc()=lcArc->key();

    if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
     send_error(erNegativeTension);

    // Variable Equal To Optimum //
    lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
    lcBalanceConstraint->setCoefficient(lcDurationVariable->key(),+1.0);
    lcBalanceConstraint->boundary()=lcArc->data().optimum();
   }

   lcCurrentArc2++;
  }
 }
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clLinearSolveAlgoI */
 /* Solves the minimum cost tension problem of a graph using a given linear program solver. */
 template <tdGraph>
 tyInteger clLinearSolveAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                            ctTensionSystemSolver & agLinearSolver) const {
  typedef clTensionSystem::cpVariableX::const_iterator clVariableIterator;

  clVariableIterator lcCurrentVariable;
  clVariableIterator lcLastVariable;
  tyInteger          lcNbIteration;
  clTensionSystem    lcSystem;

  // Linear System Resolution //
  buildLinearSystem(lcSystem,agGraph);
  lcNbIteration=agLinearSolver.run(lcSystem);
  agGraph.solved()=lcSystem.solved();
  if (not lcSystem.solved()) return (-1);

  // Connection With The Graph //
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();

  while (lcCurrentVariable!=lcLastVariable) {

   if ((*lcCurrentVariable).second->content().significance()==tension)
    agGraph.arc((*lcCurrentVariable).second->content().arc()).data().expected()=
    (*lcCurrentVariable).second->value();

   lcCurrentVariable++;
  }

  return (lcNbIteration);
 }
}

// B i n a r y S o l v e A l g o I I  Implementation //---------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------BuildLinearSystem
 /*METHOD clBinarySolveAlgoII */
 /* Builds a linear program equivalent to the minimum cost tension problem of a graph. */
 template <tdGraph>
 void clBinarySolveAlgoII<tuGraph>::buildLinearSystem(clTensionSystem & agSystem,
                                                      clGraph<tuGraph> & agGraph) const {
  method_name("binarySolveAlgoII::buildLinearSystem");

  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *            lcArc;
  clAssociation               lcAssociation;
  clTensionConstraint *       lcBoundaryConstraint;
  clTensionVariable *         lcPotentialVariable;
  clTensionVariable *         lcSelectionVariable;
  linearSystem::tyVariableKey lcSourceKey;
  linearSystem::tyVariableKey lcTargetKey;
  clTensionConstraint *       lcTensionConstraint;
  clTensionVariable *         lcTensionVariable;
  tyReal                      lcTempo;

  cpArcIterator lcCurrentArc = agGraph.arcs().begin();
  cpArcIterator lcLastArc    = agGraph.arcs().end();
  tyMark        lcMark       = ++(agGraph.mark());

  agSystem.objective().kind()=linearSystem::minimum;

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

   // Potential Variables //
   if (lcArc->sourceNode()->mark()!=lcMark) {
    lcArc->sourceNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->sourceNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->sourceNode()->key();
    lcSourceKey=lcPotentialVariable->key();
   }
   else lcSourceKey=lcAssociation[lcArc->sourceNode()->key()];

   if (lcArc->targetNode()->mark()!=lcMark) {
    lcArc->targetNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->targetNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->targetNode()->key();
    lcTargetKey=lcPotentialVariable->key();
   }
   else lcTargetKey=lcAssociation[lcArc->targetNode()->key()];

   // Tension Variable //
   lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
   lcTensionVariable->content().significance()=tension;
   lcTensionVariable->content().arc()=lcArc->key();

   // Selection Variable //
   lcSelectionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
   lcSelectionVariable->kind()=linearSystem::integralVariable;
   lcSelectionVariable->content().significance()=binary;
   lcSelectionVariable->content().arc()=lcArc->key();
   lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
   lcBoundaryConstraint->boundary()=1.0;
   lcBoundaryConstraint->setCoefficient(lcSelectionVariable->key(),+1.0);

   if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
    send_error(erNegativeTension);

   // Minimum //
   lcTempo=lcArc->data().optimum()-lcArc->data().minimum();
   lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::superiority));
   lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
   lcBoundaryConstraint->setCoefficient(lcSelectionVariable->key(),lcTempo);
   lcBoundaryConstraint->boundary()=lcArc->data().optimum();

   // Maximum //
   if (lcArc->data().maximum()!=lcArc->data().positiveInfinity()) {
    lcTempo=lcArc->data().maximum()-lcArc->data().optimum();
    lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
    lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
    lcBoundaryConstraint->setCoefficient(lcSelectionVariable->key(),-lcTempo);
    lcBoundaryConstraint->boundary()=lcArc->data().optimum();
   }

   // Tension Constraint //
   lcTensionConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcTensionConstraint->setCoefficient(lcTargetKey,+1.0);
   lcTensionConstraint->setCoefficient(lcSourceKey,-1.0);
   lcTensionConstraint->setCoefficient(lcTensionVariable->key(),-1.0);
   lcTensionConstraint->boundary()=0.0;

   // Objective //
   agSystem.objective().setCoefficient(lcSelectionVariable->key(),lcArc->data().weight());

   ++lcCurrentArc;
  }
 }
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clBinarySolveAlgoII */
 /* Solves the minimum cost tension problem of a graph using a given linear program solver. */
 template <tdGraph>
 tyInteger clBinarySolveAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                             ctTensionSystemSolver & agLinearSolver) const {
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clTensionSystem::cpVariableX::const_iterator      clVariableIterator;

  clArc<tuGraph> *   lcArc;
  cpArcIterator      lcCurrentArc;
  clVariableIterator lcCurrentVariable;
  cpArcIterator      lcLastArc;
  clVariableIterator lcLastVariable;
  tyInteger          lcNbIteration;
  clTensionSystem    lcSystem;

  // Linear System Resolution //
  buildLinearSystem(lcSystem,agGraph);
  lcNbIteration=agLinearSolver.run(lcSystem);
  agGraph.solved()=lcSystem.solved();
  if (not lcSystem.solved()) return (-1);

  // Potential Collecting //
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();

  while (lcCurrentVariable!=lcLastVariable) {
   if ((*lcCurrentVariable).second->content().significance()==potential)
    agGraph.node((*lcCurrentVariable).second->content().node()).data().potential()=
    (*lcCurrentVariable).second->value();

   ++lcCurrentVariable;
  }

  // Tension Building //
  lcCurrentArc=agGraph.arcs().begin();
  lcLastArc=agGraph.arcs().end();

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

   lcArc->data().tension()=lcArc->targetNode()->data().potential()
                           -lcArc->sourceNode()->data().potential();

   ++lcCurrentArc;
  }

  return (lcNbIteration);
 }
 //------------------------------------------------------------------------BuildLagrangeanRelaxation
 /*METHOD clBinarySolveAlgoII */
 /* Builds a Lagrangean relaxation of the linear program equivalent to the minimum binary cost
    tension problem of a graph. Lagrangean coefficients for the relaxed constraints must be
    given. */
 template <tdGraph>
 void clBinarySolveAlgoII<tuGraph>::buildLagrangeanRelaxation (clTensionSystem & agSystem,
                                    clGraph<tuGraph> & agGraph,
                                    std_map(clArc<tuGraph> *,tyPairReal) & agCoefficientX) const {
  method_name("binarySolveAlgoII::buildLagrangeanRelaxation");

  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *            lcArc;
  clAssociation               lcAssociation;
  clTensionConstraint *       lcBoundaryConstraint;
  clTensionVariable *         lcPotentialVariable;
  linearSystem::tyVariableKey lcSourceKey;
  linearSystem::tyVariableKey lcTargetKey;
  clTensionConstraint *       lcTensionConstraint;
  clTensionVariable *         lcTensionVariable;
  tyReal                      lcTempo;

  cpArcIterator lcCurrentArc = agGraph.arcs().begin();
  cpArcIterator lcLastArc    = agGraph.arcs().end();
  tyMark        lcMark       = ++(agGraph.mark());

  agSystem.objective().kind()=linearSystem::minimum;

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

   // Potential Variables //
   if (lcArc->sourceNode()->mark()!=lcMark) {
    lcArc->sourceNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->sourceNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->sourceNode()->key();
    lcSourceKey=lcPotentialVariable->key();
   }
   else lcSourceKey=lcAssociation[lcArc->sourceNode()->key()];

   if (lcArc->targetNode()->mark()!=lcMark) {
    lcArc->targetNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->targetNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->targetNode()->key();
    lcTargetKey=lcPotentialVariable->key();
   }
   else lcTargetKey=lcAssociation[lcArc->targetNode()->key()];

   // Tension Variable //
   lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
   lcTensionVariable->content().significance()=tension;
   lcTensionVariable->content().arc()=lcArc->key();

   if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
    send_error(erNegativeTension);

   // Minimum //
   lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::superiority));
   lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
   lcBoundaryConstraint->boundary()=lcArc->data().minimum();

   // Maximum //
   if (lcArc->data().maximum()!=lcArc->data().positiveInfinity()) {
    lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
    lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),+1.0);
    lcBoundaryConstraint->boundary()=lcArc->data().maximum();
   }

   // Tension Constraint //
   lcTensionConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcTensionConstraint->setCoefficient(lcTargetKey,+1.0);
   lcTensionConstraint->setCoefficient(lcSourceKey,-1.0);
   lcTensionConstraint->setCoefficient(lcTensionVariable->key(),-1.0);
   lcTensionConstraint->boundary()=0.0;

   // Objective //
   lcTempo=agCoefficientX[lcArc].second-agCoefficientX[lcArc].first;
   agSystem.objective().setCoefficient(lcTensionVariable->key(),lcTempo);

   ++lcCurrentArc;
  }
 }
}

// D i s c r e t e S o l v e A l g o I I  Implementation //-----------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------BuildLinearSystem
 /*METHOD clDiscreteSolveAlgoII */
 /* Builds a linear program equivalent to the minimum cost tension problem of a graph. */
 template <tdGraph>
 void clDiscreteSolveAlgoII<tuGraph>::buildLinearSystem(clTensionSystem & agSystem,
                                                        clGraph<tuGraph> & agGraph) const {
  method_name("discreteSolveAlgoII::buildLinearSystem");

  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *            lcArc;
  clAssociation               lcAssociation;
  clTensionConstraint *       lcBoundaryConstraint;
  tyCardinal                  lcCounter;
  clTensionConstraint *       lcExclusivityConstraint;
  clTensionVariable *         lcPotentialVariable;
  clTensionVariable *         lcShrinkVariable;
  linearSystem::tyVariableKey lcSourceKey;
  clTensionVariable *         lcStretchVariable;
  linearSystem::tyVariableKey lcTargetKey;
  clTensionConstraint *       lcTensionConstraint;
  clTensionVariable *         lcTensionVariable;
  tyReal                      lcTempo;

  cpArcIterator lcCurrentArc = agGraph.arcs().begin();
  cpArcIterator lcLastArc    = agGraph.arcs().end();
  tyMark        lcMark       = ++(agGraph.mark());

  agSystem.objective().kind()=linearSystem::minimum;

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

   // Potential Variables //
   if (lcArc->sourceNode()->mark()!=lcMark) {
    lcArc->sourceNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->sourceNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->sourceNode()->key();
    lcSourceKey=lcPotentialVariable->key();
   }
   else lcSourceKey=lcAssociation[lcArc->sourceNode()->key()];

   if (lcArc->targetNode()->mark()!=lcMark) {
    lcArc->targetNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->targetNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->targetNode()->key();
    lcTargetKey=lcPotentialVariable->key();
   }
   else lcTargetKey=lcAssociation[lcArc->targetNode()->key()];

   // Tension Variables //
   lcShrinkVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
   lcStretchVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));

   lcShrinkVariable->content().significance()=shrinking;
   lcShrinkVariable->content().arc()=lcArc->key();
   lcStretchVariable->content().significance()=stretching;
   lcStretchVariable->content().arc()=lcArc->key();

   if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
    send_error(erNegativeTension);

   // Feasible Tensions //
   lcCounter=0;
   lcTensionConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcTensionConstraint->boundary()=lcArc->data().optimum();
   lcTensionConstraint->setCoefficient(lcShrinkVariable->key(),1.0);
   lcTensionConstraint->setCoefficient(lcStretchVariable->key(),-1.0);
   lcExclusivityConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcExclusivityConstraint->boundary()=1.0;

   while (lcCounter<lcArc->data().feasibles().size()) {
    lcTensionVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcTensionVariable->content().significance()=binary;
    lcTensionVariable->content().arc()=lcArc->key();
    lcTensionVariable->kind()=linearSystem::integralVariable;
    lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
    lcBoundaryConstraint->boundary()=1.0;
    lcBoundaryConstraint->setCoefficient(lcTensionVariable->key(),1.0);
    lcTempo=lcArc->data().feasibles()[lcCounter];
    lcTensionConstraint->setCoefficient(lcTensionVariable->key(),lcTempo);
    lcExclusivityConstraint->setCoefficient(lcTensionVariable->key(),1.0);
    ++lcCounter;
   }

   // Tension Constraint //
   lcTensionConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcTensionConstraint->setCoefficient(lcTargetKey,+1.0);
   lcTensionConstraint->setCoefficient(lcSourceKey,-1.0);
   lcTensionConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
   lcTensionConstraint->setCoefficient(lcStretchVariable->key(),-1.0);
   lcTensionConstraint->boundary()=lcArc->data().optimum();

   // Objective //
   agSystem.objective().setCoefficient(lcShrinkVariable->key(),lcArc->data().shrinkingCost());
   agSystem.objective().setCoefficient(lcStretchVariable->key(),lcArc->data().stretchingCost());

   ++lcCurrentArc;
  }
 }
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clDiscreteSolveAlgoII */
 /* Solves the minimum cost tension problem of a graph using a given linear program solver. */
 template <tdGraph>
 tyInteger clDiscreteSolveAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                               ctTensionSystemSolver & agLinearSolver) const {
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clTensionSystem::cpVariableX::const_iterator      clVariableIterator;

  clArc<tuGraph> *   lcArc;
  cpArcIterator      lcCurrentArc;
  clVariableIterator lcCurrentVariable;
  cpArcIterator      lcLastArc;
  clVariableIterator lcLastVariable;
  tyInteger          lcNbIteration;
  clTensionSystem    lcSystem;

  // Linear System Resolution //
  buildLinearSystem(lcSystem,agGraph);
  lcNbIteration=agLinearSolver.run(lcSystem);
  agGraph.solved()=lcSystem.solved();
  if (not lcSystem.solved()) return (-1);

  // Potential Collecting //
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();

  while (lcCurrentVariable!=lcLastVariable) {
   if ((*lcCurrentVariable).second->content().significance()==potential)
    agGraph.node((*lcCurrentVariable).second->content().node()).data().potential()=
    (*lcCurrentVariable).second->value();

   ++lcCurrentVariable;
  }

  // Tension Building //
  lcCurrentArc=agGraph.arcs().begin();
  lcLastArc=agGraph.arcs().end();

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

   lcArc->data().tension()=lcArc->targetNode()->data().potential()
                           -lcArc->sourceNode()->data().potential();

   ++lcCurrentArc;
  }

  return (lcNbIteration);
 }
}

// L i n e a r S o l v e A l g o I I  Implementation //---------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------BuildLinearSystem
 /*METHOD clLinearSolveAlgoII */
 /* Builds a linear program equivalent to the minimum cost tension problem of a graph. */
 template <tdGraph>
 void clLinearSolveAlgoII<tuGraph>::buildLinearSystem(clTensionSystem & agSystem,
                                                      clGraph<tuGraph> & agGraph) const {
  method_name("linearSolveAlgoII::buildLinearSystem");

  typedef clCycle::const_iterator                           clArcIterator;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clCycleS::const_iterator                          clCycleIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *      lcArc;
  clAssociation         lcAssociation1;
  clAssociation         lcAssociation2;
  clTensionConstraint * lcBalanceConstraint;
  clTensionConstraint * lcBoundaryConstraint;
  clCycleS              lcCycleS;
  clTensionConstraint * lcMeetingConstraint;
  clTensionVariable *   lcShrinkVariable;
  clTensionVariable *   lcStretchVariable;
  tyReal                lcTempo;

  tyMark          lcArcsMark;
  clArcIterator   lcCurrentArc;
  cpArcIterator   lcCurrentArc2;
  clCycleIterator lcCurrentCycle;
  clArcIterator   lcLastArc;
  cpArcIterator   lcLastArc2;
  clCycleIterator lcLastCycle;

  agSystem.objective().kind()=linearSystem::minimum;
  private_area::findCycles(agGraph,lcCycleS,atShortCycles);
  lcCurrentCycle=lcCycleS.begin();
  lcLastCycle=lcCycleS.end();
  lcArcsMark=++(agGraph.mark());

  // Constrained Arcs //
  while (lcCurrentCycle!=lcLastCycle) {
   lcMeetingConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcCurrentArc=(*lcCurrentCycle).begin();
   lcLastArc=(*lcCurrentCycle).end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=&(agGraph.arc((*lcCurrentArc).first));

    // Associated Variables //
    if (lcArc->mark()!=lcArcsMark) {
     lcArc->mark()=lcArcsMark;
     lcShrinkVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcStretchVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
     lcAssociation1.insert(std_make_pair(lcArc->key(),lcShrinkVariable->key()));
     lcAssociation2.insert(std_make_pair(lcArc->key(),lcStretchVariable->key()));

     lcShrinkVariable->content().significance()=shrinking;
     lcShrinkVariable->content().arc()=lcArc->key();
     lcStretchVariable->content().significance()=stretching;
     lcStretchVariable->content().arc()=lcArc->key();

     if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
      send_error(erNegativeTension);

     // Minimum //
     lcTempo=lcArc->data().optimum()-lcArc->data().minimum();
     lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
     lcBoundaryConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
     lcBoundaryConstraint->boundary()=(lcTempo<0 ? 0 : lcTempo);

     // Maximum //
     if (lcArc->data().maximum()!=lcArc->data().positiveInfinity()) {
      lcTempo=lcArc->data().maximum()-lcArc->data().optimum();
      lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
      lcBoundaryConstraint->setCoefficient(lcStretchVariable->key(),+1.0);
      lcBoundaryConstraint->boundary()=(lcTempo<0 ? 0 : lcTempo);
     }

     // Objective //
     agSystem.objective().setCoefficient(lcShrinkVariable->key(),(lcArc->data().shrinkingCost()));
     agSystem.objective().setCoefficient(lcStretchVariable->key(),lcArc->data().stretchingCost());
    }

    // Direction In The Cycle //
    lcMeetingConstraint->setCoefficient(lcAssociation1[lcArc->key()],-(*lcCurrentArc).second);
    lcMeetingConstraint->setCoefficient(lcAssociation2[lcArc->key()],(*lcCurrentArc).second);
    ((*lcMeetingConstraint).boundary())-=(*lcCurrentArc).second*(lcArc->data().optimum());

    lcCurrentArc++;
   }

   lcCurrentCycle++;
  }

  // Unconstrained Arcs //
  lcCurrentArc2=agGraph.arcs().begin();
  lcLastArc2=agGraph.arcs().end();

  while (lcCurrentArc2!=lcLastArc2) {
   lcArc=(*lcCurrentArc2).second;

   // Associated Variables //
   if (lcArc->mark()!=lcArcsMark) {
    lcArc->mark()=lcArcsMark;
    lcShrinkVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcStretchVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcShrinkVariable->content().significance()=shrinking;
    lcShrinkVariable->content().arc()=lcArc->key();
    lcStretchVariable->content().significance()=stretching;
    lcStretchVariable->content().arc()=lcArc->key();

    if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
     send_error(erNegativeTension);

    // Shrink Variable Is Null //
    lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
    lcBalanceConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
    lcBalanceConstraint->boundary()=0.0;

    // Stretch Variable Is Null //
    lcBalanceConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
    lcBalanceConstraint->setCoefficient(lcStretchVariable->key(),+1.0);
    lcBalanceConstraint->boundary()=0.0;
   }

   lcCurrentArc2++;
  }
 }
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clLinearSolveAlgoII */
 /* Solves the minimum cost tension problem of a graph using a given linear program solver. */
 template <tdGraph>
 tyInteger clLinearSolveAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                             ctTensionSystemSolver & agLinearSolver) const {
  typedef clArc<tuGraph>                               cpArc;
  typedef clTensionSystem::cpVariableX::const_iterator clVariableIterator;

  typedef graphProblemMinCostTensionStructure::clVariableContent clVariableContent;

  cpArc *             lcArc;
  clVariableContent * lcContent;
  clVariableIterator  lcCurrentVariable;
  clVariableIterator  lcLastVariable;
  tyMark              lcMark;
  tyInteger           lcNbIteration;
  clTensionSystem     lcSystem;

  // Linear System Resolution //
  buildLinearSystem(lcSystem,agGraph);
  lcNbIteration=agLinearSolver.run(lcSystem);
  agGraph.solved()=lcSystem.solved();
  if (not lcSystem.solved()) return (-1);

  // Connection With The Graph //
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();
  lcMark=++(agGraph.mark());

  while (lcCurrentVariable!=lcLastVariable) {
   lcContent=&((*lcCurrentVariable).second->content());
   lcArc=&(agGraph.arc(lcContent->arc()));

   if (lcArc->mark()!=lcMark) {
    lcArc->data().expected()=lcArc->data().optimum();
    lcArc->mark()=lcMark;
   }

   if (lcContent->significance()==shrinking)
    lcArc->data().expected()-=(*lcCurrentVariable).second->value();
   else if (lcContent->significance()==stretching)
    lcArc->data().expected()+=(*lcCurrentVariable).second->value();

   lcCurrentVariable++;
  }

  return (lcNbIteration);
 }
}

// L i n e a r S o l v e A l g o I I I  Implementation //-------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------BuildLinearSystem
 /*METHOD clLinearSolveAlgoIII */
 /* Builds a linear program equivalent to the minimum cost tension problem of a graph. */
 template <tdGraph>
 void clLinearSolveAlgoIII<tuGraph>::buildLinearSystem(clTensionSystem & agSystem,
                                                       clGraph<tuGraph> & agGraph) const {
  method_name("linearSolveAlgoIII::buildLinearSystem");

  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef std_map(tyArcKey,linearSystem::tyVariableKey)     clAssociation;

  clArc<tuGraph> *            lcArc;
  clAssociation               lcAssociation;
  clTensionConstraint *       lcBoundaryConstraint;
  clTensionVariable *         lcPotentialVariable;
  clTensionVariable *         lcShrinkVariable;
  linearSystem::tyVariableKey lcSourceKey;
  clTensionVariable *         lcStretchVariable;
  linearSystem::tyVariableKey lcTargetKey;
  clTensionConstraint *       lcTensionConstraint;
  tyReal                      lcTempo;

  cpArcIterator lcCurrentArc = agGraph.arcs().begin();
  cpArcIterator lcLastArc    = agGraph.arcs().end();
  tyMark        lcMark       = ++(agGraph.mark());

  agSystem.objective().kind()=linearSystem::minimum;

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

   // Potential Variables //
   if (lcArc->sourceNode()->mark()!=lcMark) {
    lcArc->sourceNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->sourceNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->sourceNode()->key();
    lcSourceKey=lcPotentialVariable->key();
   }
   else lcSourceKey=lcAssociation[lcArc->sourceNode()->key()];

   if (lcArc->targetNode()->mark()!=lcMark) {
    lcArc->targetNode()->mark()=lcMark;
    lcPotentialVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
    lcAssociation.insert(std_make_pair(lcArc->targetNode()->key(),lcPotentialVariable->key()));
    lcPotentialVariable->content().significance()=potential;
    lcPotentialVariable->content().node()=lcArc->targetNode()->key();
    lcTargetKey=lcPotentialVariable->key();
   }
   else lcTargetKey=lcAssociation[lcArc->targetNode()->key()];

   // Tension Variables //
   lcShrinkVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));
   lcStretchVariable=new_object(clTensionVariable(agSystem,agSystem.getNewVariableKey()));

   lcShrinkVariable->content().significance()=shrinking;
   lcShrinkVariable->content().arc()=lcArc->key();
   lcStretchVariable->content().significance()=stretching;
   lcStretchVariable->content().arc()=lcArc->key();

   if (lcArc->data().maximum()<0 or lcArc->data().minimum()<0 or lcArc->data().optimum()<0)
    send_error(erNegativeTension);

   // Minimum //
   lcTempo=lcArc->data().optimum()-lcArc->data().minimum();
   lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
   lcBoundaryConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
   lcBoundaryConstraint->boundary()=(lcTempo<0 ? 0 : lcTempo);

   // Maximum //
   if (lcArc->data().maximum()!=lcArc->data().positiveInfinity()) {
    lcBoundaryConstraint=new_object(clTensionConstraint(agSystem,linearSystem::inferiority));
    lcBoundaryConstraint->setCoefficient(lcStretchVariable->key(),+1.0);
    lcTempo=lcArc->data().maximum()-lcArc->data().optimum();
    lcBoundaryConstraint->boundary()=(lcTempo<0 ? 0 : lcTempo);
   }

   // Tension Constraint //
   lcTensionConstraint=new_object(clTensionConstraint(agSystem,linearSystem::equality));
   lcTensionConstraint->setCoefficient(lcTargetKey,+1.0);
   lcTensionConstraint->setCoefficient(lcSourceKey,-1.0);
   lcTensionConstraint->setCoefficient(lcShrinkVariable->key(),+1.0);
   lcTensionConstraint->setCoefficient(lcStretchVariable->key(),-1.0);
   lcTensionConstraint->boundary()=lcArc->data().optimum();

   // Objective //
   agSystem.objective().setCoefficient(lcShrinkVariable->key(),lcArc->data().shrinkingCost());
   agSystem.objective().setCoefficient(lcStretchVariable->key(),lcArc->data().stretchingCost());

   ++lcCurrentArc;
  }
 }
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clLinearSolveAlgoIII */
 /* Solves the minimum cost tension problem of a graph using a given linear program solver. */
 template <tdGraph>
 tyInteger clLinearSolveAlgoIII<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                              ctTensionSystemSolver & agLinearSolver) const {
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clTensionSystem::cpVariableX::const_iterator      clVariableIterator;

  clArc<tuGraph> *   lcArc;
  cpArcIterator      lcCurrentArc;
  clVariableIterator lcCurrentVariable;
  cpArcIterator      lcLastArc;
  clVariableIterator lcLastVariable;
  tyInteger          lcNbIteration;
  clTensionSystem    lcSystem;

  // Linear System Resolution //
  buildLinearSystem(lcSystem,agGraph);
  lcNbIteration=agLinearSolver.run(lcSystem);
  agGraph.solved()=lcSystem.solved();
  if (not lcSystem.solved()) return (-1);

  // Potential Collecting //
  lcCurrentVariable=lcSystem.variables().begin();
  lcLastVariable=lcSystem.variables().end();

  while (lcCurrentVariable!=lcLastVariable) {
   if ((*lcCurrentVariable).second->content().significance()==potential)
    agGraph.node((*lcCurrentVariable).second->content().node()).data().potential()=
    (*lcCurrentVariable).second->value();

   ++lcCurrentVariable;
  }

  // Tension Building //
  lcCurrentArc=agGraph.arcs().begin();
  lcLastArc=agGraph.arcs().end();

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

   lcArc->data().tension()=lcArc->targetNode()->data().potential()
                           -lcArc->sourceNode()->data().potential();

   ++lcCurrentArc;
  }

  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 _ t e n s i o n
// L i n e a r _ s y s t e 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/linear_system.cpp"

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

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

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostTensionLinearSystem
#define private_area graphProblemMinCostTensionLinearSystem_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Min_cost_tension/Linear_system");

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