//==================================================================================================
// 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
// S t r u c t u r e
//                                                                                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 structures for the minimum cost tension problem in graphs. */

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

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemMinCostTensionStructure
#define guGraphProblemMinCostTensionStructure

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph.hpp> /*INCLUDE*/
#include <bpp/linear_system.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  graphProblemMinCostTensionStructure
#define private_area graphProblemMinCostTensionStructure_private

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

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniGraphProblemMinCostTensionStructure
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 class clBinaryArcData;
 class clConvexArcData1;
 class clConvexArcData2;
 class clDiscreteArcData;
 class clLinearArcData;
 class clNodeData;
 class clPiecewiseArcData;
 class clVariableContent;
 //-----------------------------------------------------------------------------------Variable Types
 /*TYPE*/ /* Arc of a graph with a minimum cost tension problem with binary costs. */
 typedef clArc<clBinaryArcData,clNodeData> clBinaryArc;

 /*TYPE*/ /* Graph with a minimum cost tension problem with binary costs. */
 typedef clGraph<clBinaryArcData,clNodeData> clBinaryGraph;

 /*TYPE*/ /* Node of a graph with a minimum cost tension problem with binary costs. */
 typedef clNode<clBinaryArcData,clNodeData> clBinaryNode;

 /*TYPE*/ /* Arc of a graph with a minimum cost tension problem with convex quadratic costs. */
 typedef clArc<clConvexArcData1,clNodeData> clConvexArc1;

 /*TYPE*/ /* Graph with a minimum cost tension problem with convex quadratic costs. */
 typedef clGraph<clConvexArcData1,clNodeData> clConvexGraph1;

 /*TYPE*/ /* Node of a graph with a minimum cost tension problem with convex quadratic costs. */
 typedef clNode<clConvexArcData1,clNodeData> clConvexNode1;

 /*TYPE*/ /* Arc of a graph with a minimum cost tension problem with convex exponential costs. */
 typedef clArc<clConvexArcData2,clNodeData> clConvexArc2;

 /*TYPE*/ /* Graph with a minimum cost tension problem with convex exponential costs. */
 typedef clGraph<clConvexArcData2,clNodeData> clConvexGraph2;

 /*TYPE*/ /* Node of a graph with a minimum cost tension problem with convex exponential costs. */
 typedef clNode<clConvexArcData2,clNodeData> clConvexNode2;

 /*TYPE*/
 /* Arc of a graph with a minimum cost tension problem with discrete tensions and linear costs. */
 typedef clArc<clDiscreteArcData,clNodeData> clDiscreteArc;

 /*TYPE*/
 /* Graph with a minimum cost tension problem with discrete tensions and linear costs. */
 typedef clGraph<clDiscreteArcData,clNodeData> clDiscreteGraph;

 /*TYPE*/
 /* Node of a graph with a minimum cost tension problem with discrete tensions and linear costs. */
 typedef clNode<clDiscreteArcData,clNodeData> clDiscreteNode;

 /*TYPE*/ /* Arc of a graph with a minimum cost tension problem with linear costs. */
 typedef clArc<clLinearArcData,clNodeData> clLinearArc;

 /*TYPE*/ /* Graph with a minimum cost tension problem with linear costs. */
 typedef clGraph<clLinearArcData,clNodeData> clLinearGraph;

 /*TYPE*/ /* Node of a graph with a minimum cost tension problem with linear costs. */
 typedef clNode<clLinearArcData,clNodeData> clLinearNode;

 /*TYPE*/ /* Arc of a graph with a minimum cost tension problem with piecewise linear costs. */
 typedef clArc<clPiecewiseArcData,clNodeData> clPiecewiseArc;

 /*TYPE*/ /* Graph with a minimum cost tension problem with piecewise linear costs. */
 typedef clGraph<clPiecewiseArcData,clNodeData> clPiecewiseGraph;

 /*TYPE*/ /* Node of a graph with a minimum cost tension problem with piecewise linear costs. */
 typedef clNode<clPiecewiseArcData,clNodeData> clPiecewiseNode;

 /*TYPE*/ /* Constraint of a linear program that models the minimum cost tension problem. */
 typedef linearSystemStructure::clConstraint<public_area::clVariableContent> clTensionConstraint;

 /*TYPE*/ /* Objective of a linear program that models the minimum cost tension problem. */
 typedef linearSystemStructure::clObjective<public_area::clVariableContent> clTensionObjective;

 /*TYPE*/ /* Linear program that models the minimum cost tension problem. */
 typedef linearSystemStructure::clLinearSystem<public_area::clVariableContent> clTensionSystem;

 /*TYPE*/ /* Variable of a linear program that models the minimum cost tension problem. */
 typedef linearSystemStructure::clVariable<public_area::clVariableContent> clTensionVariable;

 /*TYPE*/ /* Solver of linear programs that model the minimum cost tension problem. */
 typedef linearSystemSolver::clSolver<public_area::clVariableContent> clTensionSystemSolver;

 /*TYPE*/
 /* Symbolic constants to associate a significance with each variable of a linear program modeling
    the minimum cost tension problem. */
 enumeration { tension, shrinking, stretching, potential, binary } tyVariableSignificance;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const clBinaryArcData    ctBinaryArcData;
 typedef const clConvexArcData1   ctConvexArcData1;
 typedef const clConvexArcData2   ctConvexArcData2;
 typedef const clDiscreteArcData  ctDiscreteArcData;
 typedef const clLinearArcData    ctLinearArcData;
 typedef const clNodeData         ctNodeData;
 typedef const clPiecewiseArcData ctPiecewiseArcData;
 typedef const clVariableContent  ctVariableContent;

 typedef const clBinaryArc   ctBinaryArc;
 typedef const clBinaryGraph ctBinaryGraph;
 typedef const clBinaryNode  ctBinaryNode;

 typedef const clConvexArc1   ctConvexArc1;
 typedef const clConvexGraph1 ctConvexGraph1;
 typedef const clConvexNode1  ctConvexNode1;

 typedef const clConvexArc2   ctConvexArc2;
 typedef const clConvexGraph2 ctConvexGraph2;
 typedef const clConvexNode2  ctConvexNode2;

 typedef const clDiscreteArc   ctDiscreteArc;
 typedef const clDiscreteGraph ctDiscreteGraph;
 typedef const clDiscreteNode  ctDiscreteNode;

 typedef const clLinearArc   ctLinearArc;
 typedef const clLinearGraph ctLinearGraph;
 typedef const clLinearNode  ctLinearNode;

 typedef const clPiecewiseArc   ctPiecewiseArc;
 typedef const clPiecewiseGraph ctPiecewiseGraph;
 typedef const clPiecewiseNode  ctPiecewiseNode;

 typedef const clTensionConstraint   ctTensionConstraint;
 typedef const clTensionObjective    ctTensionObjective;
 typedef const clTensionSystem       ctTensionSystem;
 typedef const clTensionVariable     ctTensionVariable;
 typedef const clTensionSystemSolver ctTensionSystemSolver;

 typedef const tyVariableSignificance tcVariableSignificance;
}

namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 function tyVariableSignificance variableSignificance(ctString &);
 inline   clString               variableSignificanceToString(tyVariableSignificance);
}

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

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erInconsistentPiecewiseCost; /* The piecewise cost is inconsistent. */

 /*ERROR*/ extern_error erInvalidVariableSignificanceString;
 /* Invalid variable significance string. */

 /*ERROR*/ extern_error erNegativeTension; /* A tension can not be negative. */

 /*ERROR*/ extern_error erOptimalTensionOutOfBound;
 /* The optimal tension of an arc is out of the feasible bounds. */
}

// Constants & Variables //-------------------------------------------------------------------------
extern_dynamic_constant(private,clString,goBinaryDataLocation,?);
extern_dynamic_constant(private,clString,goDiscreteDataLocation,?);
extern_dynamic_constant(private,clString,goLinearDataLocation,?);
extern_dynamic_constant(private,clString,goPiecewiseDataLocation,?);

// B i n a r y A r c D a t a  Interface //----------------------------------------------------------
namespace public_area {
 /*CLASS clBinaryArcData */
 /* Represents the data carried by an arc of a graph with a minimum cost tension problem.
    The arc has a minimum tension, a maximum tension and a wanted, optimum, tension. The cost
    associated with the tension of an arc is a binary function equal to
    <CODE>0</CODE> if <CODE>tension = optimum</CODE> or <CODE>weight</CODE> else. */
 class clBinaryArcData {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clBinaryArcData */ /* Minimum tension of the arc. */
  read_write_attribute(tyReal,atMinimum,minimum);

  /*ATTRIBUTE clBinaryArcData */ /* Maximum tension of the arc. */
  read_write_attribute(tyReal,atMaximum,maximum);

  /*ATTRIBUTE clBinaryArcData */ /* Optimum tension of the arc. */
  read_write_attribute(tyReal,atOptimum,optimum);

  /*ATTRIBUTE clBinaryArcData */ /* Cost weight of the arc. */
  read_write_attribute(tyReal,atWeight,weight);

  /*ATTRIBUTE clBinaryArcData */
  /* Resolved tension of the arc (also called the expected tension). */
  read_write_attribute(tyReal,atExpected,expected);

  /*ATTRIBUTE clBinaryArcData */ /* Flow that goes through the arc. */
  read_write_attribute(tyReal,atFlow,flow);

  public_property tyReal & tension(void);
  public_property tyReal   tension(void) const;

  public_property static tyReal negativeInfinity(void);
  public_property static tyReal positiveInfinity(void);

  public_property constructor clBinaryArcData(void);
  public_property constructor clBinaryArcData(ctBinaryArcData &);
  public_property constructor clBinaryArcData(tyReal,tyReal,tyReal,tyReal,tyReal);
  public_property constructor clBinaryArcData(clInStream &,tyBoolean);
  public_property destructor  clBinaryArcData(void);

  public_property clBinaryArcData & operator = (ctBinaryArcData &);

  public_property void   out(clOutStream &,tyBoolean) const;
  public_property tyReal cost(void) const;
  public_property tyReal cost(tyReal) const;
 };
}

// C o n v e x A r c D a t a 1  Interface //--------------------------------------------------------
namespace public_area {
 /*CLASS clConvexArcData1 */
 /* Represents the data carried by an arc of a graph with a minimum cost tension problem.
    The arc has a minimum tension, a maximum tension and a wanted, optimum, tension. The cost
    associated with the tension of an arc is a quadratic function of the form
    <CODE>costAcceleration*(tension-optimum)*(tension-optimum)</CODE>. */
 class clConvexArcData1 {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clConvexArcData1 */ /* Minimum tension of the arc. */
  read_write_attribute(tyReal,atMinimum,minimum);

  /*ATTRIBUTE clConvexArcData1 */ /* Maximum tension of the arc. */
  read_write_attribute(tyReal,atMaximum,maximum);

  /*ATTRIBUTE clConvexArcData1 */ /* Optimum tension of the arc. */
  read_write_attribute(tyReal,atOptimum,optimum);

  /*ATTRIBUTE clConvexArcData1 */
  /* It is a parameter of the cost function of the arc. We call it "cost acceleration". */
  read_write_attribute(tyReal,atCostAcceleration,costAcceleration);

  /*ATTRIBUTE clConvexArcData1 */
  /* Resolved tension of the arc (also called the expected tension). */
  read_write_attribute(tyReal,atExpected,expected);

  /*ATTRIBUTE clConvexArcData1 */ /* Flow that goes through the arc. */
  read_write_attribute(tyReal,atFlow,flow);

  public_property tyReal & tension(void);
  public_property tyReal   tension(void) const;

  public_property static tyReal negativeInfinity(void);
  public_property static tyReal positiveInfinity(void);

  public_property constructor clConvexArcData1(void);
  public_property constructor clConvexArcData1(ctConvexArcData1 &);
  public_property constructor clConvexArcData1(tyReal,tyReal,tyReal,tyReal,tyReal);
  public_property constructor clConvexArcData1(clInStream &,tyBoolean);
  public_property destructor  clConvexArcData1(void);

  public_property clConvexArcData1 & operator = (ctConvexArcData1 &);

  public_property void   out(clOutStream &,tyBoolean) const;
  public_property tyReal cost(void) const;
  public_property tyReal cost(tyReal) const;
 };
}

// C o n v e x A r c D a t a 2  Interface //--------------------------------------------------------
namespace public_area {
 /*CLASS clConvexArcData2 */
 /* Represents the data carried by an arc of a graph with a minimum cost tension problem.
    The arc has a wanted, optimum, tension and a given tolerance <CODE>t</CODE> is accepted
    around it. The cost associated with the tension of an arc is a function of the form:
    <CODE>log(t*t/(tension-(optimum-t))*((optimum+t)-tension))</CODE>. */
 class clConvexArcData2 {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clConvexArcData2 */ /* Optimum tension of the arc. */
  read_write_attribute(tyReal,atOptimum,optimum);

  /*ATTRIBUTE clConvexArcData2 */ /* Tolerance around the optimum tension of the arc. */
  read_write_attribute(tyReal,atTolerance,tolerance);

  /*ATTRIBUTE clConvexArcData2 */
  /* Resolved tension of the arc (also called the expected tension). */
  read_write_attribute(tyReal,atExpected,expected);

  /*ATTRIBUTE clConvexArcData2 */ /* Flow that goes through the arc. */
  read_write_attribute(tyReal,atFlow,flow);

  public_property tyReal   minimum(void) const;
  public_property tyReal   maximum(void) const;
  public_property tyReal & tension(void);
  public_property tyReal   tension(void) const;

  public_property static tyReal negativeInfinity(void);
  public_property static tyReal positiveInfinity(void);

  public_property constructor clConvexArcData2(void);
  public_property constructor clConvexArcData2(ctConvexArcData2 &);
  public_property constructor clConvexArcData2(tyReal,tyReal,tyReal);
  public_property constructor clConvexArcData2(clInStream &,tyBoolean);
  public_property destructor  clConvexArcData2(void);

  public_property clConvexArcData2 & operator = (ctConvexArcData2 &);

  public_property void   out(clOutStream &,tyBoolean) const;
  public_property tyReal cost(void) const;
  public_property tyReal cost(tyReal) const;
 };
}

// D i s c r e t e A r c D a t a  Interface //------------------------------------------------------
namespace public_area {
 /*CLASS clDiscreteArcData */
 /* Represents the data carried by an arc of a graph with a minimum cost tension problem. The arc
    has a set of feasible tensions and a wanted, optimum, tension. The cost associated with the
    tension of an arc is a two-part linear function of the form
    <CODE>stretchingCost*(tension-optimum)</CODE> if <CODE>tension > optimum</CODE> or
    <CODE>shrinkingCost*(optimum-tension)</CODE> else. */
 class clDiscreteArcData {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clDiscreteArcData */ /* Type of the list of feasible tensions. */
  public_property typedef std_vector(tyReal) clFeasibleS;
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clDiscreteArcData */ /* Feasible tensions of the arc. */
  read_only_attribute(clFeasibleS,atFeasibleS,feasibles);

  /*ATTRIBUTE clDiscreteArcData */ /* Optimum tension of the arc. */
  read_write_attribute(tyReal,atOptimum,optimum);

  /*ATTRIBUTE clDiscreteArcData */ /* Shrinking cost of the arc. */
  read_write_attribute(tyReal,atShrinkingCost,shrinkingCost);

  /*ATTRIBUTE clDiscreteArcData */ /* Stretching cost of the arc. */
  read_write_attribute(tyReal,atStretchingCost,stretchingCost);

  /*ATTRIBUTE clDiscreteArcData */
  /* Resolved tension of the arc (also called the expected tension). */
  read_write_attribute(tyReal,atExpected,expected);

  /*ATTRIBUTE clDiscreteArcData */ /* Flow that goes through the arc. */
  read_write_attribute(tyReal,atFlow,flow);

  public_property tyReal & minimum(void); // Trick to allow dummy assignment.
  public_property tyReal & maximum(void); // Trick to allow dummy assignment.

  public_property tyReal   minimum(void) const;
  public_property tyReal   maximum(void) const;
  public_property tyReal & tension(void);
  public_property tyReal   tension(void) const;

  public_property static tyReal negativeInfinity(void);
  public_property static tyReal positiveInfinity(void);

  public_property constructor clDiscreteArcData(void);
  public_property constructor clDiscreteArcData(ctDiscreteArcData &);
  public_property constructor clDiscreteArcData(tyReal,tyReal,tyReal,tyReal);
  public_property constructor clDiscreteArcData(clInStream &,tyBoolean);
  public_property destructor  clDiscreteArcData(void);

  public_property clDiscreteArcData & operator = (ctDiscreteArcData &);

  public_property void out(clOutStream &,tyBoolean) const;

  public_property tyReal cost(void) const;
  public_property tyReal cost(tyReal) const;

  public_property void addFeasible(tyReal);
 };
}

// L i n e a r A r c D a t a  Interface //----------------------------------------------------------
namespace public_area {
 /*CLASS clLinearArcData */
 /* Represents the data carried by an arc of a graph with a minimum cost tension problem.
    The arc has a minimum tension, a maximum tension and a wanted, optimum, tension. The cost
    associated with the tension of an arc is a two-part linear function of the form
    <CODE>stretchingCost*(tension-optimum)</CODE> if <CODE>tension > optimum</CODE> or
    <CODE>shrinkingCost*(optimum-tension)</CODE> else. */
 class clLinearArcData {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clLinearArcData */ /* Minimum tension of the arc. */
  read_write_attribute(tyReal,atMinimum,minimum);

  /*ATTRIBUTE clLinearArcData */ /* Maximum tension of the arc. */
  read_write_attribute(tyReal,atMaximum,maximum);

  /*ATTRIBUTE clLinearArcData */ /* Optimum tension of the arc. */
  read_write_attribute(tyReal,atOptimum,optimum);

  /*ATTRIBUTE clLinearArcData */ /* Shrinking cost of the arc. */
  read_write_attribute(tyReal,atShrinkingCost,shrinkingCost);

  /*ATTRIBUTE clLinearArcData */ /* Stretching cost of the arc. */
  read_write_attribute(tyReal,atStretchingCost,stretchingCost);

  /*ATTRIBUTE clLinearArcData */
  /* Resolved tension of the arc (also called the expected tension). */
  read_write_attribute(tyReal,atExpected,expected);

  /*ATTRIBUTE clLinearArcData */ /* Flow that goes through the arc. */
  read_write_attribute(tyReal,atFlow,flow);

  public_property tyReal & tension(void);
  public_property tyReal   tension(void) const;

  public_property static tyReal negativeInfinity(void);
  public_property static tyReal positiveInfinity(void);

  public_property constructor clLinearArcData(void);
  public_property constructor clLinearArcData(ctLinearArcData &);
  public_property constructor clLinearArcData(tyReal,tyReal,tyReal,tyReal,tyReal,tyReal);
  public_property constructor clLinearArcData(clInStream &,tyBoolean);
  public_property destructor  clLinearArcData(void);

  public_property clLinearArcData & operator = (ctLinearArcData &);

  public_property void   out(clOutStream &,tyBoolean) const;
  public_property tyReal cost(void) const;
  public_property tyReal cost(tyReal) const;
 };
}

// N o d e D a t a  Interface //--------------------------------------------------------------------
namespace public_area {
 /*CLASS clNodeData */
 /* Represents the data carried by a node of a graph with a minimum cost tension problem. */
 class clNodeData {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clNodeData */ /* Minimum potential of the node. */
  read_write_attribute(tyReal,atMinimum,minimum);

  /*ATTRIBUTE clNodeData */ /* Maximum potential of the node. */
  read_write_attribute(tyReal,atMaximum,maximum);

  /*ATTRIBUTE clNodeData */ /* Resolved potential of the node. */
  read_write_attribute(tyReal,atValue,value);

  public_property tyReal & potential(void);
  public_property tyReal   potential(void) const;

  public_property static tyReal negativeInfinity(void);
  public_property static tyReal positiveInfinity(void);

  public_property constructor clNodeData(void);
  public_property constructor clNodeData(tyReal,tyReal,tyReal);
  public_property constructor clNodeData(ctNodeData &);
  public_property constructor clNodeData(clInStream &,tyBoolean);
  public_property destructor  clNodeData(void);

  public_property clNodeData & operator = (ctNodeData &);

  public_property void out(clOutStream &,tyBoolean) const;
 };
}

// P i e c e w i s e A r c D a t a  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clPiecewiseArcData */
 /* Represents the data carried by an arc of a graph with a minimum cost tension problem.
    The arc has a minimum tension, a maximum tension and a wanted, optimum, tension. The cost
    associated with the tension of an arc is a convex piecewise linear function. Two vectors
    of pairs <CODE>(length;cost)</CODE> represent the pieces of the cost to decrease or increase
    the tension from the optimum value. */
 class clPiecewiseArcData {
  //-------------------------------------------------------------------------------------------Types
  public_property typedef std_pair(tyReal,tyReal) clCost;
  public_property typedef std_vector(clCost)      clCostS;
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;

  private_property tyReal atReference;

  private_property void readCosts(clInStream &,clCostS &) const;
  private_property void restoreShrinkingCosts(clCostS &) const;
  private_property void restoreStretchingCosts(clCostS &) const;
  private_property void writeCosts(clOutStream &,const clCostS &) const;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clPiecewiseArcData */ /* Minimum tension of the arc. */
  read_write_attribute(tyReal,atMinimum,minimum);

  /*ATTRIBUTE clPiecewiseArcData */ /* Maximum tension of the arc. */
  read_write_attribute(tyReal,atMaximum,maximum);

  /*ATTRIBUTE clPiecewiseArcData */ /* Optimum tension of the arc. */
  read_write_attribute(tyReal,atOptimum,optimum);

  /*ATTRIBUTE clPiecewiseArcData */
  /* Shrinking costs of the arc (vector representing the pieces of the cost function at the left
     of the expected tension). */
  read_write_attribute(clCostS,atShrinkingCostS,shrinkingCosts);

  /*ATTRIBUTE clPiecewiseArcData */
  /* Stretching costs of the arc (vector representing the pieces of the cost function at the right
     of the expected tension). */
  read_write_attribute(clCostS,atStretchingCostS,stretchingCosts);

  /*ATTRIBUTE clPiecewiseArcData */
  /* Resolved tension of the arc (also called the expected tension). */
  read_write_attribute(tyReal,atExpected,expected);

  /*ATTRIBUTE clPiecewiseArcData */ /* Flow that goes through the arc. */
  read_write_attribute(tyReal,atFlow,flow);

  public_property tyReal & tension(void);
  public_property tyReal   tension(void) const;
  public_property tyReal   nextShrinkingCost(void) const;
  public_property tyReal   nextShrinkingBoundary(void) const;
  public_property tyReal   nextStretchingCost(void) const;
  public_property tyReal   nextStretchingBoundary(void) const;

  public_property static tyReal negativeInfinity(void);
  public_property static tyReal positiveInfinity(void);

  public_property constructor clPiecewiseArcData(void);
  public_property constructor clPiecewiseArcData(ctPiecewiseArcData &);
  public_property constructor clPiecewiseArcData(tyReal,tyReal,tyReal);
  public_property constructor clPiecewiseArcData(clInStream &,tyBoolean);
  public_property destructor  clPiecewiseArcData(void);

  public_property clPiecewiseArcData & operator = (ctPiecewiseArcData &);

  public_property void   out(clOutStream &,tyBoolean) const;
  public_property tyReal cost(void);

  public_property tyBoolean needUpdate(void) const;
  public_property void      update(void);
 };
}

// V a r i a b l e C o n t e n t  Interface //------------------------------------------------------
namespace public_area {
 /*CLASS clVariableContent */
 /* Represents the data carried by a variable of a linear program that models the minimum cost
    tension problem. */
 class clVariableContent {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clVariableContent */
  /* Significance of the variable according to the minimum cost tension problem. */
  read_write_attribute(tyVariableSignificance,atSignificance,significance);

  /*ATTRIBUTE clVariableContent */
  /* Key of the arc the variable is associated with. */
  read_write_attribute(tyArcKey,atArc,arc);

  /*ATTRIBUTE clVariableContent */
  /* Key of the node the variable is associated with. */
  read_write_attribute(tyArcKey,atNode,node);

  public_property constructor clVariableContent(void);
  public_property constructor clVariableContent(tyVariableSignificance,tyArcKey);
  public_property constructor clVariableContent(ctVariableContent &);
  public_property constructor clVariableContent(clInStream &);
  public_property destructor  clVariableContent(void);

  public_property clVariableContent & operator = (ctVariableContent &);

  public_property void out(clOutStream &) const;
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area {
 //-------------------------------------------------------------------VariableSignificance To String
 /*FUNCTION*/ /* Converts a string into a variable significance. */
 inline clString variableSignificanceToString(tyVariableSignificance agSignificance) {
  if (agSignificance==shrinking) return (clString("<->"));
  if (agSignificance==stretching) return (clString("<+>"));
  if (agSignificance==tension) return (clString("<T>"));
  if (agSignificance==potential) return (clString("<P>"));
  if (agSignificance==binary) return (clString("<B>"));
  return (clString("<?>"));
 }
}

namespace private_area {}

// B i n a r y A r c D a t a  Inline //-------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clBinaryArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-write
    version. */
 inline tyReal & clBinaryArcData::tension(void) { return (atExpected); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clBinaryArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-only
    version. */
 inline tyReal clBinaryArcData::tension(void) const { return (atExpected); }
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clBinaryArcData */
 /* Returns the value that represents the negative infinity of the tension. Static method. */
 inline tyReal clBinaryArcData::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clBinaryArcData */
 /* Returns the value that represents the positive infinity of the tension. Static method. */
 inline tyReal clBinaryArcData::positiveInfinity(void) { return (atPositiveInfinity); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clBinaryArcData */ /* Destructs the arc data. */
 inline clBinaryArcData::~clBinaryArcData(void) {}
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clBinaryArcData */ /* Returns the cost of the actual tension of the arc. */
 inline tyReal clBinaryArcData::cost(void) const {
  if (isEqual(atExpected,atOptimum)) return (0.0);
  else return (atWeight);
 }
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clBinaryArcData */ /* Returns the cost of a given tension of the arc. */
 inline tyReal clBinaryArcData::cost(tyReal agTension) const {
  if (isEqual(agTension,atOptimum)) return (0.0);
  else return (atWeight);
 }
}

// C o n v e x A r c D a t a 1  Inline //-----------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clConvexArcData1 */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-write
    version. */
 inline tyReal & clConvexArcData1::tension(void) { return (atExpected); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clConvexArcData1 */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-only
    version. */
 inline tyReal clConvexArcData1::tension(void) const { return (atExpected); }
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clConvexArcData1 */
 /* Returns the value that represents the negative infinity of the tension. Static method. */
 inline tyReal clConvexArcData1::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clConvexArcData1 */
 /* Returns the value that represents the positive infinity of the tension. Static method. */
 inline tyReal clConvexArcData1::positiveInfinity(void) { return (atPositiveInfinity); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clConvexArcData1 */ /* Destructs the arc data. */
 inline clConvexArcData1::~clConvexArcData1(void) {}
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clConvexArcData1 */ /* Returns the cost of the actual tension of the arc. */
 inline tyReal clConvexArcData1::cost(void) const
 { return (atCostAcceleration*(atExpected-atOptimum)*0.1*(atExpected-atOptimum)*0.1); }
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clConvexArcData1 */ /* Returns the cost of a given tension of the arc. */
 inline tyReal clConvexArcData1::cost(tyReal agTension) const
 { return (atCostAcceleration*(agTension-atOptimum)*0.1*(agTension-atOptimum)*0.1); }
}

// C o n v e x A r c D a t a 2  Inline //-----------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Minimum
 /*METHOD clConvexArcData2 */ /* Returns the minimum tension of the arc. */
 inline tyReal clConvexArcData2::minimum(void) const { return (atOptimum-atTolerance); }
 //------------------------------------------------------------------------------------------Maximum
 /*METHOD clConvexArcData2 */ /* Returns the maximum tension of the arc. */
 inline tyReal clConvexArcData2::maximum(void) const { return (atOptimum+atTolerance); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clConvexArcData2 */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-write
    version. */
 inline tyReal & clConvexArcData2::tension(void) { return (atExpected); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clConvexArcData2 */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-only
    version. */
 inline tyReal clConvexArcData2::tension(void) const { return (atExpected); }
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clConvexArcData2 */
 /* Returns the value that represents the negative infinity of the tension. Static method. */
 inline tyReal clConvexArcData2::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clConvexArcData2 */
 /* Returns the value that represents the positive infinity of the tension. Static method. */
 inline tyReal clConvexArcData2::positiveInfinity(void) { return (atPositiveInfinity); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clConvexArcData2 */ /* Destructs the arc data. */
 inline clConvexArcData2::~clConvexArcData2(void) {}
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clConvexArcData2 */ /* Returns the cost of the actual tension of the arc. */
 inline tyReal clConvexArcData2::cost(void) const {
  if (atExpected<atOptimum-atTolerance) return (1e6);
  else if (atExpected>atOptimum+atTolerance) return (1e6);
  return (std::log(((atTolerance+epsilon())*(atTolerance+epsilon()))
          /((atExpected-atOptimum+atTolerance+epsilon())
            *(atOptimum+atTolerance+epsilon()-atExpected))));
 }
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clConvexArcData2 */ /* Returns the cost of a given tension of the arc. */
 inline tyReal clConvexArcData2::cost(tyReal agTension) const {
  if (agTension<atOptimum-atTolerance) return (1e6);
  else if (agTension>atOptimum+atTolerance) return (1e6);
  return (std::log(((atTolerance+epsilon())*(atTolerance+epsilon()))
          /((agTension-atOptimum+atTolerance+epsilon())
            *(atOptimum+atTolerance+epsilon()-agTension))));
 }
}

// D i s c r e t e A r c D a t a  Inline //---------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Minimum
 /*METHOD clDiscreteArcData */ /* Returns the minimum tension of the arc. */
 inline tyReal clDiscreteArcData::minimum(void) const { return (atFeasibleS[0]); }
 //------------------------------------------------------------------------------------------Maximum
 /*METHOD clDiscreteArcData */ /* Returns the maximum tension of the arc. */
 inline tyReal clDiscreteArcData::maximum(void) const
 { return (atFeasibleS[atFeasibleS.size()-1]); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clDiscreteArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-write
    version. */
 inline tyReal & clDiscreteArcData::tension(void) { return (atExpected); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clDiscreteArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-only
    version. */
 inline tyReal clDiscreteArcData::tension(void) const { return (atExpected); }
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clDiscreteArcData */
 /* Returns the value that represents the negative infinity of the tension. Static method. */
 inline tyReal clDiscreteArcData::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clDiscreteArcData */
 /* Returns the value that represents the positive infinity of the tension. Static method. */
 inline tyReal clDiscreteArcData::positiveInfinity(void) { return (atPositiveInfinity); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clDiscreteArcData */ /* Destructs the arc data. */
 inline clDiscreteArcData::~clDiscreteArcData(void) {}
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clDiscreteArcData */ /* Returns the cost of the actual tension of the arc. */
 inline tyReal clDiscreteArcData::cost(void) const {
  if (atExpected<atOptimum) return (atShrinkingCost*(atOptimum-atExpected));
  else return (atStretchingCost*(atExpected-atOptimum));
 }
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clDiscreteArcData */ /* Returns the cost of a given tension of the arc. */
 inline tyReal clDiscreteArcData::cost(tyReal agTension) const {
  if (agTension<atOptimum) return (atShrinkingCost*(atOptimum-agTension));
  else return (atStretchingCost*(agTension-atOptimum));
 }
}

// L i n e a r A r c D a t a  Inline //-------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clLinearArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-write
    version. */
 inline tyReal & clLinearArcData::tension(void) { return (atExpected); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clLinearArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-only
    version. */
 inline tyReal clLinearArcData::tension(void) const { return (atExpected); }
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clLinearArcData */
 /* Returns the value that represents the negative infinity of the tension. Static method. */
 inline tyReal clLinearArcData::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clLinearArcData */
 /* Returns the value that represents the positive infinity of the tension. Static method. */
 inline tyReal clLinearArcData::positiveInfinity(void) { return (atPositiveInfinity); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clLinearArcData */ /* Destructs the arc data. */
 inline clLinearArcData::~clLinearArcData(void) {}
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clLinearArcData */ /* Returns the cost of the actual tension of the arc. */
 inline tyReal clLinearArcData::cost(void) const {
  if (atExpected<atOptimum) return (atShrinkingCost*(atOptimum-atExpected));
  else return (atStretchingCost*(atExpected-atOptimum));
 }
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clLinearArcData */ /* Returns the cost of a given tension of the arc. */
 inline tyReal clLinearArcData::cost(tyReal agTension) const {
  if (agTension<atOptimum) return (atShrinkingCost*(atOptimum-agTension));
  else return (atStretchingCost*(agTension-atOptimum));
 }
}

// N o d e D a t a  Inline //-----------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------Potential
 /*METHOD clNodeData */
 /* Returns the actual potential of the node (i.e. the <CODE>value</CODE> attribute). Read-write
    version. */
 inline tyReal & clNodeData::potential(void) { return (atValue); }
 //----------------------------------------------------------------------------------------Potential
 /*METHOD clNodeData */
 /* Returns the actual potential of the node (i.e. the <CODE>value</CODE> attribute). Read-only
    version. */
 inline tyReal clNodeData::potential(void) const { return (atValue); }
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clNodeData */
 /* Returns the value that represents the negative infinity of the tension. Static method. */
 inline tyReal clNodeData::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clNodeData */
 /* Returns the value that represents the positive infinity of the tension. Static method. */
 inline tyReal clNodeData::positiveInfinity(void) { return (atPositiveInfinity); }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a default node data. */
 inline clNodeData::clNodeData(void)
 : atMinimum(negativeInfinity()),atMaximum(positiveInfinity()),atValue(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from separated data. */
 inline clNodeData::clNodeData(tyReal agMinimum,tyReal agMaximum,tyReal agValue)
 : atMinimum(agMinimum),atMaximum(agMaximum),atValue(agValue) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from another one. */
 inline clNodeData::clNodeData(const clNodeData & agData)
 : atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),atValue(agData.atValue) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clNodeData */ /* Destructs the node data. */
 inline clNodeData::~clNodeData(void) {}
}

// P i e c e w i s e A r c D a t a  Inline //-------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clPiecewiseArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-write
    version. */
 inline tyReal & clPiecewiseArcData::tension(void) { return (atExpected); }
 //------------------------------------------------------------------------------------------Tension
 /*METHOD clPiecewiseArcData */
 /* Returns the actual tension of the arc (i.e. the <CODE>expected</CODE> attribute). Read-only
    version. */
 inline tyReal clPiecewiseArcData::tension(void) const { return (atExpected); }
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clPiecewiseArcData */
 /* Returns the value that represents the negative infinity of the tension. Static method. */
 inline tyReal clPiecewiseArcData::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clPiecewiseArcData */
 /* Returns the value that represents the positive infinity of the tension. Static method. */
 inline tyReal clPiecewiseArcData::positiveInfinity(void) { return (atPositiveInfinity); }
 //--------------------------------------------------------------------------------NextShrinkingCost
 /*METHOD clPiecewiseArcData */
 /* Returns the next shrinking cost (according to the expected tension). */
 inline tyReal clPiecewiseArcData::nextShrinkingCost(void) const {
  if (atShrinkingCostS.size()>0) return (atShrinkingCostS.back().second);
  if (atStretchingCostS.size()>0) return (-atStretchingCostS.back().second);
  return (0.0);
 }
 //----------------------------------------------------------------------------NextShrinkingBoundary
 /*METHOD clPiecewiseArcData */
 /* Returns the next shrinking boundary (according to the expected tension). */
 inline tyReal clPiecewiseArcData::nextShrinkingBoundary(void) const {
  if (atShrinkingCostS.size()>0) return (atExpected-atShrinkingCostS.back().first);
  return (atMinimum);
 }
 //-------------------------------------------------------------------------------NextStretchingCost
 /*METHOD clPiecewiseArcData */
 /* Returns the next stretching cost (according to the expected tension). */
 inline tyReal clPiecewiseArcData::nextStretchingCost(void) const {
  if (atStretchingCostS.size()>0) return (atStretchingCostS.back().second);
  if (atShrinkingCostS.size()>0) return (-atShrinkingCostS.back().second);
  return (0.0);
 }
 //---------------------------------------------------------------------------NextStretchingBoundary
 /*METHOD clPiecewiseArcData */
 /* Returns the next stretching boundary (according to the expected tension). */
 inline tyReal clPiecewiseArcData::nextStretchingBoundary(void) const {
  if (atStretchingCostS.size()>0) return (atExpected+atStretchingCostS.back().first);
  return (atMaximum);
 }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clPiecewiseArcData */ /* Destructs the arc data. */
 inline clPiecewiseArcData::~clPiecewiseArcData(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clPiecewiseArcData */ /* Copies an arc data. */
 inline clPiecewiseArcData & clPiecewiseArcData::operator = (ctPiecewiseArcData & agData) {
  atReference=agData.atReference;
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atOptimum=agData.atOptimum;
  atShrinkingCostS=agData.atShrinkingCostS;
  atStretchingCostS=agData.atStretchingCostS;
  atExpected=agData.atExpected;
  return (*this);
 }
 //---------------------------------------------------------------------------------------NeedUpdate
 /*METHOD clPiecewiseArcData */
 /* Returns if the expected tension has been modified, which means the vectors representing
    the cost function must be centered on the new value. */
 inline tyBoolean clPiecewiseArcData::needUpdate(void) const
 { return (atReference!=atExpected); }
}

// V a r i a b l e C o n t e n t  Inline //---------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVariableContent */ /* Builds a default variable content. */
 inline clVariableContent::clVariableContent(void) : atSignificance(tension),atArc(0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVariableContent */ /* Builds a variable content from separated data. */
 inline clVariableContent::clVariableContent(tyVariableSignificance agSignificance,tyArcKey agArc)
 : atSignificance(agSignificance),atArc(agArc) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVariableContent */ /* Builds a variable content from another one. */
 inline clVariableContent::clVariableContent(ctVariableContent & agContent)
 : atSignificance(agContent.atSignificance),atArc(agContent.atArc) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clVariableContent */ /* Destructs the variable. */
 inline clVariableContent::~clVariableContent(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clVariableContent */ /* Copies a variable content. */
 inline clVariableContent & clVariableContent::operator = (ctVariableContent & agContent) {
  atSignificance=agContent.atSignificance;
  atArc=agContent.atArc;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clVariableContent */ /* Writes the variable content into a stream. */
 inline void clVariableContent::out(clOutStream & agStream) const {
  agStream << variableSignificanceToString(atSignificance) << " , " << atArc;
  if (agStream.fail()) send_inline_error(erStreamWriting,"variableContent::out");
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#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
// S t r u c t u r e
//                                                                                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/structure.cpp"

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

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

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostTensionStructure
#define private_area graphProblemMinCostTensionStructure_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Min_cost_tension/Structure");

// Initialization //--------------------------------------------------------------------------------
#undef iniGraphProblemMinCostTensionStructure
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 static_error erInconsistentPiecewiseCost;
 static_error erInvalidVariableSignificanceString;
 static_error erNegativeTension;
 static_error erOptimalTensionOutOfBound;
}

// Constants & Variables //-------------------------------------------------------------------------
dynamic_constant(clString,goBinaryDataLocation);
dynamic_constant(clString,goDiscreteDataLocation);
dynamic_constant(clString,goLinearDataLocation);
dynamic_constant(clString,goPiecewiseDataLocation);

// Static Members //--------------------------------------------------------------------------------
namespace public_area {
 property tyReal clBinaryArcData::atNegativeInfinity;
 property tyReal clBinaryArcData::atPositiveInfinity;
 property tyReal clConvexArcData1::atNegativeInfinity;
 property tyReal clConvexArcData1::atPositiveInfinity;
 property tyReal clConvexArcData2::atNegativeInfinity;
 property tyReal clConvexArcData2::atPositiveInfinity;
 property tyReal clDiscreteArcData::atNegativeInfinity;
 property tyReal clDiscreteArcData::atPositiveInfinity;
 property tyReal clLinearArcData::atNegativeInfinity;
 property tyReal clLinearArcData::atPositiveInfinity;
 property tyReal clNodeData::atNegativeInfinity;
 property tyReal clNodeData::atPositiveInfinity;
 property tyReal clPiecewiseArcData::atNegativeInfinity;
 property tyReal clPiecewiseArcData::atPositiveInfinity;
}

namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //-------------------------------------------------------------------String To VariableSignificance
 /*FUNCTION*/ /* Converts a variable significance into a string. */
 function tyVariableSignificance variableSignificance(ctString & agString) {
  method_name("variableSignificance");

  if (agString=="<->") return (shrinking);
  if (agString=="<+>") return (stretching);
  if (agString=="<T>") return (tension);
  if (agString=="<P>") return (potential);
  if (agString=="<B>") return (binary);
  send_error(erInvalidVariableSignificanceString);
  return (tension);
 }
}

namespace private_area {}

// B i n a r y A r c D a t a  Implementation //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinaryArcData */ /* Builds a default arc data. */
 property clBinaryArcData::clBinaryArcData(void)
 : atMinimum(0.0),atMaximum(positiveInfinity()),atOptimum(0.0),atWeight(0.0),
   atExpected(0.0),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinaryArcData */ /* Builds an arc data from another one. */
 property clBinaryArcData::clBinaryArcData(ctBinaryArcData & agData)
 : atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),atOptimum(agData.atOptimum),
   atWeight(agData.atWeight),atExpected(agData.atExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinaryArcData */ /* Builds an arc data from separated data. */
 property clBinaryArcData::clBinaryArcData(tyReal agMinimum,tyReal agMaximum,tyReal agOptimum,
                                           tyReal agWeight,tyReal agExpected)
 : atMinimum(agMinimum),atMaximum(agMaximum),atOptimum(agOptimum),
   atWeight(agWeight),atExpected(agExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clBinaryArcData */ /* Builds an arc data from a stream. */
 property clBinaryArcData::clBinaryArcData(clInStream & agStream,tyBoolean agSolved)
 : atMinimum(0.0),atMaximum(0.0),atOptimum(0.0),atWeight(0.0),atExpected(0.0),atFlow(0.0) {
  method_name("binaryArcData::constructor");

  clString lcString;

  agStream >> lcString;

  if (lcString==negativeInfinityStreamFlag()) atMinimum=atNegativeInfinity;
  else atMinimum=standardMaths::real(lcString.data());

  agStream >> lcString >> lcString;

  if (lcString==positiveInfinityStreamFlag()) atMaximum=atPositiveInfinity;
  else atMaximum=standardMaths::real(lcString.data());

  agStream >> lcString >> atOptimum;
  agStream >> lcString >> atWeight;

  if (agSolved) agStream >> lcString >> atExpected;
  else agStream >> lcString >> lcString;

  if (agStream.fail()) send_error(erStreamReading);
  if (atOptimum<atMinimum or atOptimum>atMaximum) send_error(erOptimalTensionOutOfBound);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clBinaryArcData */ /* Copies an arc data. */
 property clBinaryArcData & clBinaryArcData::operator = (ctBinaryArcData & agData) {
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atOptimum=agData.atOptimum;
  atWeight=agData.atWeight;
  atExpected=agData.atExpected;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clBinaryArcData */ /* Writes the arc data into a stream. */
 property void clBinaryArcData::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("binaryArcData::out");

  if (atMinimum==negativeInfinity()) agStream << negativeInfinityStreamFlag();
  else agStream << atMinimum;

  agStream << " , ";

  if (atMaximum==positiveInfinity()) agStream << positiveInfinityStreamFlag();
  else agStream << atMaximum;

  agStream << " , " << atOptimum;
  agStream << " ; " << atWeight;

  if (agSolved) agStream << " ; " << atExpected;
  else agStream << " ; " << graphStructure_private::unsolvedValueStreamFlag();

  if (agStream.fail()) send_error(erStreamWriting);
 }
}

// C o n v e x A r c D a t a 1  Implementation //---------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData1 */ /* Builds a default arc data. */
 property clConvexArcData1::clConvexArcData1(void)
 : atMinimum(0.0),atMaximum(positiveInfinity()),atOptimum(0.0),atCostAcceleration(0.0),
   atExpected(0.0),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData1 */ /* Builds an arc data from another one. */
 property clConvexArcData1::clConvexArcData1(ctConvexArcData1 & agData)
 : atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),atOptimum(agData.atOptimum),
   atCostAcceleration(agData.atCostAcceleration),atExpected(agData.atExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData1 */ /* Builds an arc data from separated data. */
 clConvexArcData1::clConvexArcData1(tyReal agMinimum,tyReal agMaximum,tyReal agOptimum,
                                    tyReal agCostAcceleration,tyReal agExpected)
 : atMinimum(agMinimum),atMaximum(agMaximum),atOptimum(agOptimum),
   atCostAcceleration(agCostAcceleration),atExpected(agExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData1 */ /* Builds an arc data from a stream. */
 property clConvexArcData1::clConvexArcData1(clInStream & agStream,tyBoolean agSolved)
 : atMinimum(0.0),atMaximum(0.0),atOptimum(0.0),atCostAcceleration(0.0),atExpected(0.0),
   atFlow(0.0) {
  method_name("convexArcData1::constructor");

  clString lcString;

  agStream >> lcString;

  if (lcString==negativeInfinityStreamFlag()) atMinimum=atNegativeInfinity;
  else atMinimum=standardMaths::real(lcString.data());

  agStream >> lcString >> lcString;

  if (lcString==positiveInfinityStreamFlag()) atMaximum=atPositiveInfinity;
  else atMaximum=standardMaths::real(lcString.data());

  agStream >> lcString >> atOptimum;
  agStream >> lcString >> atCostAcceleration;

  if (agSolved) agStream >> lcString >> atExpected;
  else agStream >> lcString >> lcString;

  if (agStream.fail()) send_error(erStreamReading);
  if (atOptimum<atMinimum or atOptimum>atMaximum) send_error(erOptimalTensionOutOfBound);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clConvexArcData1 */ /* Copies an arc data. */
 property clConvexArcData1 & clConvexArcData1::operator = (ctConvexArcData1 & agData) {
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atOptimum=agData.atOptimum;
  atCostAcceleration=agData.atCostAcceleration;
  atExpected=agData.atExpected;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clConvexArcData1 */ /* Writes the arc data into a stream. */
 property void clConvexArcData1::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("convexArcData1::out");

  if (atMinimum==negativeInfinity()) agStream << negativeInfinityStreamFlag();
  else agStream << atMinimum;

  agStream << " , ";

  if (atMaximum==positiveInfinity()) agStream << positiveInfinityStreamFlag();
  else agStream << atMaximum;

  agStream << " , " << atOptimum;
  agStream << " ; " << atCostAcceleration;

  if (agSolved) agStream << " ; " << atExpected;
  else agStream << " ; " << unsolvedValueStreamFlag();

  if (agStream.fail()) send_error(erStreamWriting);
 }
}

// C o n v e x A r c D a t a 2  Implementation //---------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData2 */ /* Builds a default arc data. */
 property clConvexArcData2::clConvexArcData2(void)
 : atOptimum(0.0),atTolerance(0.0),atExpected(0.0),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData2 */ /* Builds an arc data from another one. */
 property clConvexArcData2::clConvexArcData2(ctConvexArcData2 & agData)
 : atOptimum(agData.atOptimum),atTolerance(agData.atTolerance),atExpected(agData.atExpected),
   atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData2 */ /* Builds an arc data from separated data. */
 clConvexArcData2::clConvexArcData2(tyReal agOptimum,tyReal agTolerance,tyReal agExpected)
 : atOptimum(agOptimum),atTolerance(agTolerance),atExpected(agExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clConvexArcData2 */ /* Builds an arc data from a stream. */
 property clConvexArcData2::clConvexArcData2(clInStream & agStream,tyBoolean agSolved)
 : atOptimum(0.0),atTolerance(0.0),atExpected(0.0),atFlow(0.0) {
  method_name("convexArcData2::constructor");

  clString lcString;

  agStream >> atOptimum >> lcString >> atTolerance;

  if (agSolved) agStream >> lcString >> atExpected;
  else agStream >> lcString >> lcString;

  if (agStream.fail()) send_error(erStreamReading);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clConvexArcData2 */ /* Copies an arc data. */
 property clConvexArcData2 & clConvexArcData2::operator = (ctConvexArcData2 & agData) {
  atOptimum=agData.atOptimum;
  atTolerance=agData.atTolerance;
  atExpected=agData.atExpected;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clConvexArcData2 */ /* Writes the arc data into a stream. */
 property void clConvexArcData2::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("convexArcData2::out");

  agStream << atOptimum << " , " << atTolerance;

  if (agSolved) agStream << " ; " << atExpected;
  else agStream << " ; " << unsolvedValueStreamFlag();

  if (agStream.fail()) send_error(erStreamWriting);
 }
}

// D i s c r e t e A r c D a t a  Implementation //-------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Minimum
 property tyReal & clDiscreteArcData::minimum(void) { static tyReal lcDummy; return (lcDummy); }
 //------------------------------------------------------------------------------------------Maximum
 property tyReal & clDiscreteArcData::maximum(void) { static tyReal lcDummy; return (lcDummy); }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteArcData */ /* Builds a default arc data. */
 property clDiscreteArcData::clDiscreteArcData(void)
 : atFeasibleS(),atOptimum(0.0),atShrinkingCost(0.0),atStretchingCost(0.0),atExpected(0.0),
   atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteArcData */ /* Builds an arc data from another one. */
 property clDiscreteArcData::clDiscreteArcData(ctDiscreteArcData & agData)
 : atFeasibleS(agData.atFeasibleS),atOptimum(agData.atOptimum),
   atShrinkingCost(agData.atShrinkingCost),atStretchingCost(agData.atStretchingCost),
   atExpected(agData.atExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteArcData */ /* Builds an arc data from separated data. */
 clDiscreteArcData::clDiscreteArcData(tyReal agOptimum,tyReal agStretchingCost,
                                      tyReal agShrinkingCost,tyReal agExpected)
 : atFeasibleS(),atOptimum(agOptimum),atShrinkingCost(agShrinkingCost),
   atStretchingCost(agStretchingCost),atExpected(agExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDiscreteArcData */ /* Builds an arc data from a stream. */
 property clDiscreteArcData::clDiscreteArcData(clInStream & agStream,tyBoolean agSolved)
 : atFeasibleS(),atOptimum(0.0),atShrinkingCost(0.0),atStretchingCost(0.0),atExpected(0.0),
   atFlow(0.0) {
  method_name("discreteArcData::constructor");

  clString lcString("");

  while (lcString!=",") {
   agStream >> lcString;
   if (lcString!=noDataStreamFlag()) addFeasible(real(lcString.data()));
   agStream >> lcString ;
  }

  agStream >> atOptimum;
  agStream >> lcString >> atShrinkingCost >> lcString >> atStretchingCost;

  if (agSolved) agStream >> lcString >> atExpected;
  else agStream >> lcString >> lcString;

  if (agStream.fail()) send_error(erStreamReading);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clDiscreteArcData */ /* Copies an arc data. */
 property clDiscreteArcData & clDiscreteArcData::operator = (ctDiscreteArcData & agData) {
  atFeasibleS=agData.atFeasibleS;
  atOptimum=agData.atOptimum;
  atShrinkingCost=agData.atShrinkingCost;
  atStretchingCost=agData.atStretchingCost;
  atExpected=agData.atExpected;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clDiscreteArcData */ /* Writes the arc data into a stream. */
 property void clDiscreteArcData::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("discreteArcData::out");

  clFeasibleS::const_iterator lcCurrentFeasible = atFeasibleS.begin();
  clFeasibleS::const_iterator lcLastFeasible    = atFeasibleS.end();

  if (lcCurrentFeasible==lcLastFeasible) agStream << noDataStreamFlag();
  else
   while (lcCurrentFeasible!=lcLastFeasible) {
    agStream << (*lcCurrentFeasible);
    ++lcCurrentFeasible;
    if (lcCurrentFeasible!=lcLastFeasible) agStream << " - ";
   }

  agStream << " , " << atOptimum;
  agStream << " ; " << atShrinkingCost << " , " << atStretchingCost;

  if (agSolved) agStream << " ; " << atExpected;
  else agStream << " ; " << unsolvedValueStreamFlag();

  if (agStream.fail()) send_error(erStreamWriting);
 }
 //--------------------------------------------------------------------------------------AddFeasible
 /*METHOD clDiscreteArcData */
 /* Adds a feasible tension to the arc data. It manages to keep sorted the list
    of feasible tensions. */
 property void clDiscreteArcData::addFeasible(tyReal agValue) {
  tyCardinal lcBegin;
  tyCardinal lcEnd;
  tyCardinal lcIndex;

  if (atFeasibleS.size()==0) atFeasibleS.push_back(agValue);
  else {
   lcBegin=0;
   lcEnd=atFeasibleS.size()-1;

   if (agValue<=atFeasibleS[lcBegin]) lcIndex=lcBegin;
   else if (agValue>=atFeasibleS[lcEnd]) lcIndex=lcEnd;
   else {
    lcIndex=(lcBegin+lcEnd)/2;

    while (lcIndex!=lcBegin and lcIndex!=lcEnd) {
     if (atFeasibleS[lcIndex]==agValue) lcBegin=lcEnd=lcIndex;
     else if (atFeasibleS[lcIndex]<agValue) lcBegin=lcIndex;
     else lcEnd=lcIndex;

     lcIndex=(lcBegin+lcEnd)/2;
    }
   }

   if (atFeasibleS[lcIndex]!=agValue) {
    lcEnd=lcIndex+(agValue<atFeasibleS[lcIndex] ? 0 : 1);
    lcIndex=atFeasibleS.size();
    atFeasibleS.push_back(0.0);

    while (lcIndex>lcEnd) {
     atFeasibleS[lcIndex]=atFeasibleS[lcIndex-1];
     --lcIndex;
    }

    atFeasibleS[lcIndex]=agValue;
   }
  }
 }
}

// L i n e a r A r c D a t a  Implementation //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds a default arc data. */
 property clLinearArcData::clLinearArcData(void)
 : atMinimum(0.0),atMaximum(positiveInfinity()),atOptimum(0.0),atShrinkingCost(0.0),
   atStretchingCost(0.0),atExpected(0.0),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds an arc data from another one. */
 property clLinearArcData::clLinearArcData(ctLinearArcData & agData)
 : atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),atOptimum(agData.atOptimum),
   atShrinkingCost(agData.atShrinkingCost),atStretchingCost(agData.atStretchingCost),
   atExpected(agData.atExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds an arc data from separated data. */
 property clLinearArcData::clLinearArcData(tyReal agMinimum,tyReal agMaximum,tyReal agOptimum,
                                           tyReal agShrinkingCost,tyReal agStretchingCost,
                                           tyReal agExpected)
 : atMinimum(agMinimum),atMaximum(agMaximum),atOptimum(agOptimum),
   atShrinkingCost(agShrinkingCost),atStretchingCost(agStretchingCost),atExpected(agExpected),
   atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds an arc data from a stream. */
 property clLinearArcData::clLinearArcData(clInStream & agStream,tyBoolean agSolved)
 : atMinimum(0.0),atMaximum(0.0),atOptimum(0.0),atShrinkingCost(0.0),atStretchingCost(0.0),
   atExpected(0.0),atFlow(0.0) {
  method_name("linearArcData::constructor");

  clString lcString;

  agStream >> lcString;

  if (lcString==negativeInfinityStreamFlag()) atMinimum=atNegativeInfinity;
  else atMinimum=standardMaths::real(lcString.data());

  agStream >> lcString >> lcString;

  if (lcString==positiveInfinityStreamFlag()) atMaximum=atPositiveInfinity;
  else atMaximum=standardMaths::real(lcString.data());

  agStream >> lcString >> atOptimum;
  agStream >> lcString >> atShrinkingCost >> lcString >> atStretchingCost;

  if (agSolved) agStream >> lcString >> atExpected;
  else agStream >> lcString >> lcString;

  if (agStream.fail()) send_error(erStreamReading);
  if (atOptimum<atMinimum or atOptimum>atMaximum) send_error(erOptimalTensionOutOfBound);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clLinearArcData */ /* Copies an arc data. */
 property clLinearArcData & clLinearArcData::operator = (ctLinearArcData & agData) {
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atOptimum=agData.atOptimum;
  atShrinkingCost=agData.atShrinkingCost;
  atStretchingCost=agData.atStretchingCost;
  atExpected=agData.atExpected;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clLinearArcData */ /* Writes the arc data into a stream. */
 property void clLinearArcData::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("linearArcData::out");

  if (atMinimum==negativeInfinity()) agStream << negativeInfinityStreamFlag();
  else agStream << atMinimum;

  agStream << " , ";

  if (atMaximum==positiveInfinity()) agStream << positiveInfinityStreamFlag();
  else agStream << atMaximum;

  agStream << " , " << atOptimum;
  agStream << " ; " << atShrinkingCost << " , " << atStretchingCost;

  if (agSolved) agStream << " ; " << atExpected;
  else agStream << " ; " << graphStructure_private::unsolvedValueStreamFlag();

  if (agStream.fail()) send_error(erStreamWriting);
 }
}

// N o d e D a t a  Implementation //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from a stream. */
 property clNodeData::clNodeData(clInStream & agStream,tyBoolean agSolved)
 : atMinimum(),atMaximum(),atValue() {
  method_name("nodeData::constructor");

  clString lcString;

  if (agSolved) {
   agStream >> lcString;

   if (lcString==negativeInfinityStreamFlag()) atMinimum=negativeInfinity();
   else atMinimum=standardMaths::real(lcString.data());

   agStream >> lcString >> lcString;

   if (lcString==positiveInfinityStreamFlag()) atMaximum=positiveInfinity();
   else atMaximum=standardMaths::real(lcString.data());

   agStream >> lcString >> atValue;
  }
  else {
   agStream >> lcString;
   atMinimum=negativeInfinity();
   atMaximum=positiveInfinity();
   atValue=0.0;
  }

  if (agStream.fail()) send_error(erStreamReading);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clNodeData */ /* Copies a node data. */
 property clNodeData & clNodeData::operator = (ctNodeData & agData) {
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atValue=agData.atValue;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clNodeData */ /* Writes a node data into a stream. */
 property void clNodeData::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("nodeData::out");

  if (agSolved) {
   if (atMinimum==negativeInfinity()) agStream << negativeInfinityStreamFlag();
   else agStream << atMinimum;

   agStream << " , ";

   if (atMaximum==positiveInfinity()) agStream << positiveInfinityStreamFlag();
   else agStream << atMaximum;

   agStream << " ; " << atValue;
  }
  else agStream << unsolvedValueStreamFlag();

  if (agStream.fail()) send_error(erStreamWriting);
 }
}

// P i e c e w i s e A r c D a t a  Implementation //-----------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------ReadCosts
 property void clPiecewiseArcData::readCosts(clInStream & agStream,clCostS & agCostS) const {
  tyReal   lcCost;
  tyReal   lcLength;
  clString lcString;

  agCostS.erase(agCostS.begin(),agCostS.end());

  do {
   agStream >> lcString;

   if (lcString==noDataStreamFlag()) agStream >> lcString;
   else {
    if (lcString==positiveInfinityStreamFlag()) lcLength=atPositiveInfinity;
    else lcLength=standardMaths::real(lcString.data());

    agStream >> lcString >> lcCost >> lcString;
    agCostS.push_back(standard::make_pair(lcLength,lcCost));
   }
  }
  while (lcString!=";");
 }
 //----------------------------------------------------------------------------RestoreShrinkingCosts
 property void clPiecewiseArcData::restoreShrinkingCosts(clCostS & agCostS) const {
  method_name("piecewiseArcData::restoreShrinkingCosts");

  tyCardinal lcCounter;
  tyReal     lcIncrement;
  tyReal     lcTension;

  if (atReference<=atOptimum) {
   agCostS=atShrinkingCostS;
   lcTension=maxi(atReference,atMinimum);
   lcCounter=atStretchingCostS.size();

   while (lcTension<atOptimum and lcCounter>0) {
    --lcCounter;
    lcIncrement=mini(atOptimum-lcTension,atStretchingCostS[lcCounter].first);

    if (agCostS.size()>0 and agCostS.back().second==-atStretchingCostS[lcCounter].second)
     agCostS.back().first+=lcIncrement;
    else agCostS.push_back(standard::make_pair(lcIncrement,-atStretchingCostS[lcCounter].second));

    lcTension+=lcIncrement;
   }
  }
  else {
   agCostS=atShrinkingCostS;
   lcTension=mini(atReference,atMaximum);

   while (lcTension>atOptimum and agCostS.size()>0) {
    lcIncrement=lcTension-atOptimum;

    if (lcIncrement>=agCostS.back().first) {
     lcIncrement=agCostS.back().first;
     agCostS.pop_back();
    }
    else agCostS.back().first-=lcIncrement;

    lcTension-=lcIncrement;
   }
  }

  if (lcTension!=atOptimum) send_error(erInconsistentPiecewiseCost);
 }
 //---------------------------------------------------------------------------RestoreStretchingCosts
 property void clPiecewiseArcData::restoreStretchingCosts(clCostS & agCostS) const {
  method_name("piecewiseArcData::restoreStretchingCosts");

  tyCardinal lcCounter;
  tyReal     lcIncrement;
  tyReal     lcTension;

  if (atReference>=atOptimum) {
   agCostS=atStretchingCostS;
   lcTension=mini(atReference,atMaximum);
   lcCounter=atShrinkingCostS.size();

   while (lcTension>atOptimum and lcCounter>0) {
    --lcCounter;
    lcIncrement=mini(lcTension-atOptimum,atShrinkingCostS[lcCounter].first);

    if (agCostS.size()>0 and agCostS.back().second==-atShrinkingCostS[lcCounter].second)
     agCostS.back().first+=lcIncrement;
    else agCostS.push_back(standard::make_pair(lcIncrement,-atShrinkingCostS[lcCounter].second));

    lcTension-=lcIncrement;
   }
  }
  else {
   agCostS=atStretchingCostS;
   lcTension=maxi(atReference,atMinimum);

   while (lcTension<atOptimum and agCostS.size()>0) {
    lcIncrement=atOptimum-lcTension;

    if (lcIncrement>=agCostS.back().first) {
     lcIncrement=agCostS.back().first;
     agCostS.pop_back();
    }
    else agCostS.back().first-=lcIncrement;

    lcTension+=lcIncrement;
   }
  }

  if (lcTension!=atOptimum) send_error(erInconsistentPiecewiseCost);
  std_reverse(agCostS.begin(),agCostS.end());
 }
 //---------------------------------------------------------------------------------------WriteCosts
 property void clPiecewiseArcData::writeCosts(clOutStream & agStream,
                                              const clCostS & agCostS) const {
  tyCardinal lcCounter = 0;

  while (lcCounter<agCostS.size()) {
   if (agCostS[lcCounter].first==positiveInfinity())
    agStream << positiveInfinityStreamFlag() << " - " << agCostS[lcCounter].second;
   else agStream << agCostS[lcCounter].first << " - " << agCostS[lcCounter].second;

   ++lcCounter;
   if (lcCounter<agCostS.size()) agStream << " , ";
  }
 }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clPiecewiseArcData */ /* Builds a default arc data. */
 property clPiecewiseArcData::clPiecewiseArcData(void)
 : atReference(0.0),atMinimum(0.0),atMaximum(positiveInfinity()),atOptimum(0.0),
   atShrinkingCostS(),atStretchingCostS(),atExpected(0.0),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clPiecewiseArcData */ /* Builds an arc data from another one. */
 property clPiecewiseArcData::clPiecewiseArcData(ctPiecewiseArcData & agData)
 : atReference(agData.atReference),atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),
   atOptimum(agData.atOptimum),atShrinkingCostS(agData.atShrinkingCostS),
   atStretchingCostS(agData.atStretchingCostS),atExpected(agData.atExpected),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clPiecewiseArcData */ /* Builds an arc data from separated data. */
 property clPiecewiseArcData::clPiecewiseArcData(tyReal agMinimum,tyReal agMaximum,
                                                 tyReal agOptimum)
 : atReference(agOptimum),atMinimum(agMinimum),atMaximum(agMaximum),atOptimum(agOptimum),
   atShrinkingCostS(),atStretchingCostS(),atExpected(agOptimum),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clPiecewiseArcData */ /* Builds an arc data from a stream. */
 property clPiecewiseArcData::clPiecewiseArcData(clInStream & agStream,tyBoolean agSolved)
 : atReference(0.0),atMinimum(0.0),atMaximum(0.0),atOptimum(0.0),atShrinkingCostS(),
   atStretchingCostS(),atExpected(0.0),atFlow(0.0) {
  method_name("piecewiseArcData::constructor");

  clString lcString;

  agStream >> lcString;

  if (lcString==negativeInfinityStreamFlag()) atMinimum=atNegativeInfinity;
  else atMinimum=standardMaths::real(lcString.data());

  agStream >> lcString >> lcString;

  if (lcString==positiveInfinityStreamFlag()) atMaximum=atPositiveInfinity;
  else atMaximum=standardMaths::real(lcString.data());

  agStream >> lcString >> atOptimum >> lcString;
  atReference=atOptimum;
  readCosts(agStream,atShrinkingCostS);
  readCosts(agStream,atStretchingCostS);
  std_reverse(atStretchingCostS.begin(),atStretchingCostS.end());

  if (agSolved) agStream >> atExpected;
  else agStream >> lcString;

  if (agStream.fail()) send_error(erStreamReading);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clPiecewiseArcData */ /* Writes the arc data into a stream. */
 property void clPiecewiseArcData::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("piecewiseArcData::out");

  clCostS lcCostS;

  if (atMinimum==negativeInfinity()) agStream << negativeInfinityStreamFlag();
  else agStream << atMinimum;

  agStream << " , ";

  if (atMaximum==positiveInfinity()) agStream << positiveInfinityStreamFlag();
  else agStream << atMaximum;

  agStream << " , " << atOptimum;
  agStream << " ; ";
  restoreShrinkingCosts(lcCostS);

  if (lcCostS.size()==0) agStream << graphStructure_private::noDataStreamFlag();
  else writeCosts(agStream,lcCostS);

  agStream << " ; ";
  restoreStretchingCosts(lcCostS);

  if (lcCostS.size()==0) agStream << graphStructure_private::noDataStreamFlag();
  else writeCosts(agStream,lcCostS);

  if (agSolved) agStream << " ; " << atExpected;
  else agStream << " ; " << graphStructure_private::unsolvedValueStreamFlag();

  if (agStream.fail()) send_error(erStreamWriting);
 }
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clPiecewiseArcData */ /* Returns the cost of the actual tension of the arc. */
 property tyReal clPiecewiseArcData::cost(void) {
  method_name("piecewiseArcData::cost");

  tyCardinal lcCounter;
  tyReal     lcIncrement;

  tyReal lcCost    = 0.0;
  tyReal lcTension = atExpected;

  if (needUpdate()) update();

  if (lcTension<atOptimum) {
   lcCounter=atStretchingCostS.size();

   while (lcTension<atOptimum and lcCounter>0) {
    --lcCounter;
    lcIncrement=mini(atOptimum-lcTension,atStretchingCostS[lcCounter].first);
    lcCost+=-atStretchingCostS[lcCounter].second*lcIncrement;
    lcTension+=lcIncrement;
   }
  }
  else {
   lcCounter=atShrinkingCostS.size();

   while (lcTension>atOptimum and lcCounter>0) {
    --lcCounter;
    lcIncrement=mini(lcTension-atOptimum,atShrinkingCostS[lcCounter].first);
    lcCost+=-atShrinkingCostS[lcCounter].second*lcIncrement;
    lcTension-=lcIncrement;
   }
  }

  if (lcTension!=atOptimum) send_error(erInconsistentPiecewiseCost);
  return (lcCost);
 }
 //-------------------------------------------------------------------------------------------Update
 /*METHOD clPiecewiseArcData */
 /* Centers on the expected tension the vectors representing the cost function. */
 property void clPiecewiseArcData::update(void) {
  method_name("piecewiseArcData::update");

  tyReal lcIncrement;

  if (atReference<atMinimum) atReference=atMinimum;
  else if (atReference>atMaximum) atReference=atMaximum;

  if (atStretchingCostS.size()==0 and atShrinkingCostS.size()==0)
   atReference=atExpected;
  else {
   if (atReference<atExpected) {
    while (atReference<atExpected and atStretchingCostS.size()>0) {
     lcIncrement=mini(atExpected-atReference,atStretchingCostS.back().first);

     if (atShrinkingCostS.size()>0
         and -atShrinkingCostS.back().second==atStretchingCostS.back().second)
      atShrinkingCostS.back().first+=lcIncrement;
     else
      atShrinkingCostS.push_back(standard::make_pair(lcIncrement,
                                                     -atStretchingCostS.back().second));

     if (atStretchingCostS.back().first==lcIncrement) atStretchingCostS.pop_back();
     else atStretchingCostS.back().first-=lcIncrement;

     atReference+=lcIncrement;
    }

    if (atExpected>atMaximum) atReference=atExpected;
   }
   else {
    while (atReference>atExpected and atShrinkingCostS.size()>0) {
     lcIncrement=mini(atReference-atExpected,atShrinkingCostS.back().first);

     if (atStretchingCostS.size()>0
         and -atShrinkingCostS.back().second==atStretchingCostS.back().second)
      atStretchingCostS.back().first+=lcIncrement;
     else
      atStretchingCostS.push_back(standard::make_pair(lcIncrement,
                                                      -atShrinkingCostS.back().second));

     if (atShrinkingCostS.back().first==lcIncrement) atShrinkingCostS.pop_back();
     else atShrinkingCostS.back().first-=lcIncrement;

     atReference-=lcIncrement;
    }

    if (atExpected<atMinimum) atReference=atExpected;
   }

   if (atReference!=atExpected) send_error(erInconsistentPiecewiseCost);
  }
 }
}

// V a r i a b l e C o n t e n t  Implementation //-------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVariableContent */ /* Builds a variable content from a stream. */
 property clVariableContent::clVariableContent(clInStream & agStream)
 : atSignificance(tension),atArc(0) {
  method_name("variableContent::constructor");

  clString lcString;
  agStream >> lcString;
  atSignificance=variableSignificance(lcString);
  agStream >> lcString >> atArc;

  if (agStream.fail()) send_error(erStreamReading);
 }
}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erInconsistentPiecewiseCost.create("Min Cost Tension - The piecewise cost is inconsistent.");
    erInvalidVariableSignificanceString.create("Min Cost Tension - Invalid variable significance string.");
    erNegativeTension.create("Min Cost Tension - A tension can't be negative.");
    erOptimalTensionOutOfBound.create("Min Cost Tension - The optimal tension is out of bounds.");

    clBinaryArcData::atNegativeInfinity    = realMin();
    clBinaryArcData::atPositiveInfinity    = realMax();
    clConvexArcData1::atNegativeInfinity   = realMin();
    clConvexArcData1::atPositiveInfinity   = realMax();
    clConvexArcData2::atNegativeInfinity   = realMin();
    clConvexArcData2::atPositiveInfinity   = realMax();
    clDiscreteArcData::atNegativeInfinity  = realMin();
    clDiscreteArcData::atPositiveInfinity  = realMax();
    clLinearArcData::atNegativeInfinity    = realMin();
    clLinearArcData::atPositiveInfinity    = realMax();
    clNodeData::atNegativeInfinity         = realMin();
    clNodeData::atPositiveInfinity         = realMax();
    clPiecewiseArcData::atNegativeInfinity = realMin();
    clPiecewiseArcData::atPositiveInfinity = realMax();

    goBinaryDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator()
                           +"graph_problem"+fileNameSeparator()+"min_cost_tension"
                           +fileNameSeparator()+"binary"));

    goDiscreteDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator()
                             +"graph_problem"+fileNameSeparator()+"min_cost_tension"
                             +fileNameSeparator()+"discrete"));

    goLinearDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator()
                           +"graph_problem"+fileNameSeparator()+"min_cost_tension"
                           +fileNameSeparator()+"linear"));

    goPiecewiseDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator()
                              +"graph_problem"+fileNameSeparator()+"min_cost_tension"
                              +fileNameSeparator()+"piecewise"));
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) {
  try {
   environment::informTermination(goModuleName);

   delete_object(goBinaryDataLocation);
   delete_object(goDiscreteDataLocation);
   delete_object(goLinearDataLocation);
   delete_object(goPiecewiseDataLocation);
  }

  initializer_catch;
 }
}

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