//==================================================================================================
// G r a p h _ p r o b l e m                                                              Interface
// 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 to model tension problems in graphs. */

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

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemTensionStructure
#define guGraphProblemTensionStructure

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph.hpp> /*INCLUDE*/

namespace bpp {

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

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemTensionStructure
#define private_area graphProblemTensionStructure_private

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

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniGraphProblemTensionStructure
has_initializer;

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

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 class clArcDataI;
 class clArcDataII;
 class clNodeData;
 //-----------------------------------------------------------------------------------Variable Types
 /*TYPE*/ /* Arc of a graph that has a tension problem with no cost implied. */
 typedef clArc<clArcDataI,clNodeData> clTensionArcI;

 /*TYPE*/ /* Arc of a graph that has a tension problem with costs implied. */
 typedef clArc<clArcDataII,clNodeData> clTensionArcII;

 /*TYPE*/ /* Graph that has a tension problem with no cost implied. */
 typedef clGraph<clArcDataI,clNodeData> clTensionGraphI;

 /*TYPE*/ /* Graph that has a tension problem with costs implied. */
 typedef clGraph<clArcDataII,clNodeData> clTensionGraphII;

 /*TYPE*/ /* Node of a graph that has a tension problem with no cost implied. */
 typedef clNode<clArcDataI,clNodeData> clTensionNodeI;

 /*TYPE*/ /* Node of a graph that has a tension problem with costs implied. */
 typedef clNode<clArcDataII,clNodeData> clTensionNodeII;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const clArcDataI  ctArcDataI;
 typedef const clArcDataII ctArcDataII;
 typedef const clNodeData  ctNodeData;

 typedef const clTensionArcI    ctTensionArcI;
 typedef const clTensionArcII   ctTensionArcII;
 typedef const clTensionGraphI  ctTensionGraphI;
 typedef const clTensionGraphII ctTensionGraphII;
 typedef const clTensionNodeI   ctTensionNodeI;
 typedef const clTensionNodeII  ctTensionNodeII;
}

namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area  {}
namespace private_area { testing_mode ( function void test(void); ) }

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

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

// A r c D a t a I  Interface //--------------------------------------------------------------------
namespace public_area {
 /*CLASS clArcDataI */
 /* Represents the data carried by an arc in a graph that has a tension problem with no cost
    implied. */
 class clArcDataI {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clArcDataI */ /* Minimum tension of the arc. */
  read_write_attribute(tyReal,atMinimum,minimum);

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

  /*ATTRIBUTE clArcDataI */ /* Resolved tension of the arc. */
  read_write_attribute(tyReal,atTension,tension);

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

  public_property constructor clArcDataI(void);
  public_property constructor clArcDataI(ctArcDataI &);
  public_property constructor clArcDataI(tyReal,tyReal,tyReal);
  public_property constructor clArcDataI(clInStream &,tyBoolean);
  public_property destructor  clArcDataI(void);

  public_property clArcDataI & operator = (ctArcDataI &);

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

// A r c D a t a I I  Interface //------------------------------------------------------------------
namespace public_area {
 /*CLASS clArcDataII */
 /* Represents the data carried by an arc in a graph that has a tension problem with costs
    implied. */
 class clArcDataII {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clArcDataII */ /* Minimum tension of the arc. */
  read_write_attribute(tyReal,atMinimum,minimum);

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

  /*ATTRIBUTE clArcDataII */ /* Resolved tension of the arc. */
  read_write_attribute(tyReal,atTension,tension);

  /*ATTRIBUTE clArcDataII */ /* Cost of the arc. */
  read_write_attribute(tyReal,atCost,cost);

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

  public_property constructor clArcDataII(void);
  public_property constructor clArcDataII(ctArcDataII &);
  public_property constructor clArcDataII(tyReal,tyReal,tyReal,tyReal);
  public_property constructor clArcDataII(clInStream &,tyBoolean);
  public_property destructor  clArcDataII(void);

  public_property clArcDataII & operator = (ctArcDataII &);

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

// N o d e D a t a  Interface //--------------------------------------------------------------------
namespace public_area {
 /*CLASS clNodeData */
 /* Represents the data carried by a node in a graph that has a tension problem. */
 class clNodeData {
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clNodeData */ /* Resolved potential of the node. */
  read_write_attribute(tyReal,atPotential,potential);

  public_property constructor clNodeData(void);
  public_property constructor clNodeData(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;
 };
}

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

// A r c D a t a I  Inline //-----------------------------------------------------------------------
namespace public_area {
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clArcDataI */
 /* Returns the value that represents the negative infinity for the tension of the arc. Static
    method. */
 inline tyReal clArcDataI::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clArcDataI */
 /* Returns the value that represents the positive infinity for the tension of the arc. Static
    method. */
 inline tyReal clArcDataI::positiveInfinity(void) { return (atPositiveInfinity); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clArcDataI */ /* Destructs the arc data. */
 inline clArcDataI::~clArcDataI(void) {}
}

// A r c D a t a I I  Inline //---------------------------------------------------------------------
namespace public_area {
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clArcDataII */
 /* Returns the value that represents the negative infinity for the tension of the arc. Static
    method. */
 inline tyReal clArcDataII::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clArcDataII */
 /* Returns the value that represents the positive infinity for the tension of the arc. Static
    method. */
 inline tyReal clArcDataII::positiveInfinity(void) { return (atPositiveInfinity); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clArcDataII */ /* Destructs the arc data. */
 inline clArcDataII::~clArcDataII(void) {}
}

// N o d e D a t a  Inline //-----------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a default node data. */
 inline clNodeData::clNodeData(void) : atPotential(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from a given potential. */
 inline clNodeData::clNodeData(tyReal agPotential) : atPotential(agPotential) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from another one. */
 inline clNodeData::clNodeData(const clNodeData & agData)
 : atPotential(agData.atPotential) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clNodeData */ /* Destructs the node data. */
 inline clNodeData::~clNodeData(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clNodeData */ /* Copies a node data. */
 inline clNodeData & clNodeData::operator = (ctNodeData & agData) {
  atPotential=agData.atPotential;
  return (*this);
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// G r a p h _ p r o b l e m                                                         Implementation
// 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/tension/structure.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define GRAPH_PROBLEM_TENSION_DLL

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

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemTensionStructure
#define private_area graphProblemTensionStructure_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Tension/Structure");

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

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

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

// Static Members //--------------------------------------------------------------------------------
namespace public_area {
 property tyReal clArcDataI::atNegativeInfinity;
 property tyReal clArcDataI::atPositiveInfinity;
 property tyReal clArcDataII::atNegativeInfinity;
 property tyReal clArcDataII::atPositiveInfinity;
}

namespace private_area {}

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

// A r c D a t a I  Implementation //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataI */ /* Builds a default arc data. */
 property clArcDataI::clArcDataI(void)
 : atMinimum(0.0),atMaximum(positiveInfinity()),atTension(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataI */ /* Builds an arc data from another one. */
 property clArcDataI::clArcDataI(ctArcDataI & agData)
 : atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),atTension(agData.atTension) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataI */ /* Builds an arc data from separated data. */
 clArcDataI::clArcDataI(tyReal agMinimum,tyReal agMaximum,tyReal agTension)
 : atMinimum(agMinimum),atMaximum(agMaximum),atTension(agTension) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataI */ /* Builds an arc data from a stream. */
 property clArcDataI::clArcDataI(clInStream & agStream,tyBoolean agSolved) {
  method_name("arcDataI::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());

  if (agSolved) agStream >> lcString >> atTension;
  else {
   agStream >> lcString >> lcString;
   atTension=0.0;
  }

  if (agStream.fail()) send_error(erStreamWriting);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clArcDataI */ /* Copies an arc data. */
 property clArcDataI & clArcDataI::operator = (ctArcDataI & agData) {
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atTension=agData.atTension;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clArcDataI */ /* Writes the arc data into a stream. */
 property void clArcDataI::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("arcDataI::out");

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

  agStream << " , ";

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

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

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

// A r c D a t a I I  Implementation //-------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataII */ /* Builds a default arc data. */
 property clArcDataII::clArcDataII(void)
 : atMinimum(0.0),atMaximum(positiveInfinity()),atTension(0.0),atCost(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataII */ /* Builds an arc data from another one. */
 property clArcDataII::clArcDataII(ctArcDataII & agData)
 : atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),atTension(agData.atTension),
   atCost(agData.atCost) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataII */ /* Builds an arc data from separated data. */
 clArcDataII::clArcDataII(tyReal agMinimum,tyReal agMaximum,tyReal agTension,tyReal agCost)
 : atMinimum(agMinimum),atMaximum(agMaximum),atTension(agTension),atCost(agCost) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcDataII */ /* Builds an arc data from a stream. */
 property clArcDataII::clArcDataII(clInStream & agStream,tyBoolean agSolved) {
  method_name("arcDataII::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 >> atCost;

  if (agSolved) agStream >> lcString >> atTension;
  else {
   agStream >> lcString >> lcString;
   atTension=0.0;
  }

  if (agStream.fail()) send_error(erStreamWriting);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clArcDataII */ /* Copies an arc data. */
 property clArcDataII & clArcDataII::operator = (ctArcDataII & agData) {
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atTension=agData.atTension;
  atCost=agData.atCost;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clArcDataII */ /* Writes the arc data into a stream. */
 property void clArcDataII::out(clOutStream & agStream,tyBoolean agSolved) const {
  method_name("arcDataII::out");

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

  agStream << " , ";

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

  agStream << " ; " << atCost;

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

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

// N o d e D a t a //-------------------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from a stream. */
 property clNodeData::clNodeData(clInStream & agStream,tyBoolean agSolved) : atPotential() {
  clString lcString;

  if (agSolved) agStream >> atPotential;
  else {
   agStream >> lcString;
   atPotential=0.0;
  }

  if (agStream.fail()) send_inline_error(erStreamReading,"nodeData::constructor");
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clNodeData */ /* Writes the node data into a stream. */
 property void clNodeData::out(clOutStream & agStream,tyBoolean agSolved) const {
  if (agSolved) agStream << atPotential;
  else agStream << graphStructure_private::unsolvedValueStreamFlag();

  if (agStream.fail()) send_inline_error(erStreamWriting,"nodeData::out");
 }
}

// 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);

    clArcDataI::atNegativeInfinity = realMin();
    clArcDataI::atPositiveInfinity = realMax();
    clArcDataII::atNegativeInfinity = realMin();
    clArcDataII::atPositiveInfinity = realMax();
   }

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

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