//==================================================================================================
// G r a p h _ p r o b l e m                                                              Interface
// M i n _ c o s t _ f l o w
// 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 flow problem. */

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

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemMinCostFlowStructure
#define guGraphProblemMinCostFlowStructure

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

namespace bpp {

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

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostFlowStructure
#define private_area graphProblemMinCostFlowStructure_private

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

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniGraphProblemMinCostFlowStructure
has_initializer;

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

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 class clLinearArcData;
 class clNodeData;
 class clVariableContent;
 //-----------------------------------------------------------------------------------Variable Types
 /*TYPE*/ /* Arc of a graph with a minimum cost flow problem with linear costs. */
 typedef clArc<clLinearArcData,clNodeData> clLinearArc;

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

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

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

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

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

 /*TYPE*/ /* Variable of a linear program that models the minimum cost flow problem. */
 typedef linearSystemStructure::clVariable<clVariableContent> clFlowVariable;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const clLinearArcData   ctLinearArcData;
 typedef const clNodeData        ctNodeData;
 typedef const clVariableContent ctVariableContent;

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

 typedef const clFlowConstraint ctFlowConstraint;
 typedef const clFlowObjective  ctFlowObjective;
 typedef const clFlowSystem     ctFlowSystem;
 typedef const clFlowVariable   ctFlowVariable;
}

namespace private_area {}

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

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erInvalidFlowGraph; /* Invalid graph structure for a flow problem. */
}

// Constants & Variables //-------------------------------------------------------------------------
extern_dynamic_constant(private,clString,goDataLocation,?);

// 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 flow problem. The arc has
    a minimum flow capacity and a maximum flow capacity. The cost associated with the flow
    is linear. */
 class clLinearArcData {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clLinearArcData */ /* Minimum flow of the arc. */
  read_write_attribute(tyReal,atMinimum,minimum);

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

  /*ATTRIBUTE clLinearArcData */ /* Unit cost of the arc. */
  read_write_attribute(tyReal,atUnitCost,unitCost);

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

  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);
  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 flow problem. */
 class clNodeData {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //-----------------------------------------------------------------------------------------Private
  private_property static tyReal atNegativeInfinity;
  private_property static tyReal atPositiveInfinity;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clNodeData */ /* Potential of the node. */
  read_write_attribute(tyReal,atPotential,potential);

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

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

// 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
    flow problem. */
 class clVariableContent {
  //-----------------------------------------------------------------------------------------Friends
  friend class private_area::clInitializer;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clVariableContent */ /* Key of the arc the variable is associated with. */
  read_write_attribute(tyArcKey,atArc,arc);

  public_property constructor clVariableContent(void);
  public_property constructor clVariableContent(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  {}
namespace private_area {}

// L i n e a r A r c D a t a  Inline //-------------------------------------------------------------
namespace public_area {
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clLinearArcData */
 /* Returns the value that represents the negative infinity of the flow. Static method. */
 inline tyReal clLinearArcData::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clLinearArcData */
 /* Returns the value that represents the positive infinity of the flow. Static method. */
 inline tyReal clLinearArcData::positiveInfinity(void) { return (atPositiveInfinity); }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds a default arc data. */
 inline clLinearArcData::clLinearArcData(void)
 : atMinimum(negativeInfinity()),atMaximum(positiveInfinity()),atUnitCost(0.0),atFlow(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds an arc data from another one. */
 inline clLinearArcData::clLinearArcData(ctLinearArcData & agData)
 : atMinimum(agData.atMinimum),atMaximum(agData.atMaximum),atUnitCost(agData.atUnitCost),
   atFlow(agData.atFlow) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds an arc data from separated data. */
 inline clLinearArcData::clLinearArcData(tyReal agMinimum,tyReal agMaximum,tyReal agUnitCost,
                                         tyReal agFlow)
 : atMinimum(agMinimum),atMaximum(agMaximum),atUnitCost(agUnitCost),atFlow(agFlow) {}
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clLinearArcData */ /* Returns the cost of the actual flow of the arc. */
 inline tyReal clLinearArcData::cost(void) const { return (atUnitCost*atFlow); }
 //---------------------------------------------------------------------------------------------Cost
 /*METHOD clLinearArcData */ /* Returns the cost of a given flow of the arc. */
 inline tyReal clLinearArcData::cost(tyReal agFlow) const { return (atUnitCost*agFlow); }
}

// N o d e D a t a  Inline //-----------------------------------------------------------------------
namespace public_area {
 //---------------------------------------------------------------------------------NegativeInfinity
 /*METHOD clNodeData */
 /* Returns the value that represents the negative infinity of the potential. Static method. */
 inline tyReal clNodeData::negativeInfinity(void) { return (atNegativeInfinity); }
 //---------------------------------------------------------------------------------PositiveInfinity
 /*METHOD clNodeData */
 /* Returns the value that represents the positive infinity of the potential. Static method. */
 inline tyReal clNodeData::positiveInfinity(void) { return (atPositiveInfinity); }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a default node data. */
 inline clNodeData::clNodeData(void) : atPotential(0.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from separated data. */
 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) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clNodeData */ /* Builds a node data from a stream. */
 inline clNodeData::clNodeData(clInStream & agStream,tyBoolean agSolved) : atPotential(0.0) {
  clString lcString;

  if (agSolved) agStream >> atPotential; else agStream >> lcString;
  if (agStream.fail()) send_inline_error(erStreamReading,"nodeData::constructor");
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clNodeData */ /* Copies a node data. */
 inline clNodeData & clNodeData::operator = (ctNodeData & agData) {
  atPotential=agData.atPotential;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clNodeData */ /* Writes a node data into a stream. */
 inline void clNodeData::out(clOutStream & agStream,tyBoolean agSolved) const {
  if (agSolved) agStream << atPotential; else agStream << unsolvedValueStreamFlag();
  if (agStream.fail()) send_inline_error(erStreamWriting,"nodeData::out");
 }
}

// 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) : atArc(0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVariableContent */ /* Builds a variable content with a given arc key. */
 inline clVariableContent::clVariableContent(tyArcKey agArc) : atArc(agArc) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVariableContent */ /* Builds a variable content from another one. */
 inline clVariableContent::clVariableContent(ctVariableContent & agContent)
 : atArc(agContent.atArc) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clVariableContent */ /* Builds a variable content from a stream. */
 inline clVariableContent::clVariableContent(clInStream & agStream) : atArc(0) {
  agStream >> atArc;
  if (agStream.fail()) send_inline_error(erStreamReading,"variableContent::constructor");
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clVariableContent */ /* Copies a variable content. */
 inline clVariableContent & clVariableContent::operator = (ctVariableContent & agContent) {
  atArc=agContent.atArc;
  return (*this);
 }
 //----------------------------------------------------------------------------------------------Out
 /*METHOD clVariableContent */ /* Writes the variable content into a stream. */
 inline void clVariableContent::out(clOutStream & agStream) const {
  agStream << 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 _ f l o w
// 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_flow/structure.cpp"

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

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

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostFlowStructure
#define private_area graphProblemMinCostFlowStructure_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Min_cost_flow/Structure");

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

// Errors //----------------------------------------------------------------------------------------
namespace public_area { static_error erInvalidFlowGraph; }

// Constants & Variables //-------------------------------------------------------------------------
dynamic_constant(clString,goDataLocation);

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

namespace private_area {}

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

// L i n e a r A r c D a t a  Implementation //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clLinearArcData */ /* Builds an arc data from a stream. */
 property clLinearArcData::clLinearArcData(clInStream & agStream,tyBoolean agSolved)
 : atMinimum(0.0),atMaximum(0.0),atUnitCost(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 >> atUnitCost;

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

  if (agStream.fail()) send_error(erStreamReading);
 }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clLinearArcData */ /* Copies an arc data. */
 property clLinearArcData & clLinearArcData::operator = (ctLinearArcData & agData) {
  atMinimum=agData.atMinimum;
  atMaximum=agData.atMaximum;
  atUnitCost=agData.atUnitCost;
  atFlow=agData.atFlow;
  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 << " ; " << atUnitCost;

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

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

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

    erInvalidFlowGraph.create("Min Cost Flow - Invalid graph structure for a flow problem.");

    clLinearArcData::atNegativeInfinity = realMin();
    clLinearArcData::atPositiveInfinity = realMax();

    goDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator()
                     +"graph_problem"+fileNameSeparator()+"min_cost_flow"));
   }

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

   delete_object(goDataLocation);
  }

  initializer_catch;
 }
}

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