//==================================================================================================
// G r a p h _ p r o b l e m                                                              Interface
// M i n _ c o s t _ t e n s i o n
// A g g r e g a t i o n _ b i n a r y
//                                                                                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 implements an algorithm we call "aggregation" to solve the minimum cost tension
   problem in serial-parallel graphs. The cost functions of the arcs in the graph must be binary
   as defined by the <CODE>clBinaryArcData</CODE> class of the <CODE>Structure</CODE> module. */

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

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemMinCostTensionAggregationBinary
#define guGraphProblemMinCostTensionAggregationBinary

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph_problem/tension/algorithm.hpp> /*INCLUDE*/
#include <bpp/graph_problem/serial_parallel.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  graphProblemMinCostTensionAggregationBinary
#define private_area graphProblemMinCostTensionAggregationBinary_private

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

extern_module_name;

// Initialization //--------------------------------------------------------------------------------

// Macrocommands //---------------------------------------------------------------------------------
/*ALIAS*/
#define tdGraph class prArcData,class prNodeData //

/*ALIAS*/
#define tuGraph prArcData,prNodeData //

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 template <tdGraph> class clAggregationAlgo;
 template <tdGraph> class clAggregationAlgoI;
 template <tdGraph> class clAggregationAlgoII;

 template <tdGraph> class clOptimalCase;
 template <tdGraph> class clCaseFunction;
 template <tdGraph> class clCaseIterator;
}

namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 template <tdGraph>
 tyInteger findMinCostTension(clBinaryTree<clSerialParallelData<tuGraph> > &,
                              clCaseFunction<tuGraph> &,tyBoolean,tyCardinal &);
}

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

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

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

// A g g r e g a t i o n A l g o  Interface //------------------------------------------------------
namespace public_area {
 /*CLASS clAggregationAlgo */
 /* Represents an algorithm to solve the minimum binary cost tension problem in a serial-parallel
    graph using the aggregation technique. It is an abstract class. */
 template <tdGraph> class clAggregationAlgo {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clAggregationAlgo(const clAggregationAlgo &);
  private_property clAggregationAlgo & operator = (const clAggregationAlgo &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clAggregationAlgo(void);
  public_property virtual destructor clAggregationAlgo(void);

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

  /*AMETHOD clAggregationAlgo */
  /* Solves the minimum cost tension problem of a cycle. The solution is the list of arcs that
     are scheduled to their optimal tension. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> &,const clCycle &,
                                        std_vector(clArc<tuGraph> *) &) const = 0;

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

// A g g r e g a t i o n A l g o I  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clAggregationAlgoI */
 /* Represents an algorithm to solve the minimum binary cost tension problem in a serial-parallel
    graph using the aggregation technique with a raw inf-convolution computation (approach I).
    <B>Not fully implemented yet.</B> */
 template <tdGraph> class clAggregationAlgoI : public clAggregationAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clAggregationAlgoI(const clAggregationAlgoI &);
  private_property clAggregationAlgoI & operator = (const clAggregationAlgoI &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clAggregationAlgoI(void);
  public_property destructor clAggregationAlgoI(void);

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

  public_property tyInteger run(clGraph<tuGraph> &,const clCycle &,
                                std_vector(clArc<tuGraph> *) &) const;
 };
}

// A g g r e g a t i o n A l g o I I  Interface //--------------------------------------------------
namespace public_area {
 /*CLASS clAggregationAlgoII */
 /* Represents an algorithm to solve the minimum binary cost tension problem in a serial-parallel
    graph using the aggregation technique with a case-oriented inf-convolution computation
    (approach II). */
 template <tdGraph> class clAggregationAlgoII : public clAggregationAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clAggregationAlgoII(const clAggregationAlgoII &);
  private_property clAggregationAlgoII & operator = (const clAggregationAlgoII &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clAggregationAlgoII(void);
  public_property destructor clAggregationAlgoII(void);

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

  public_property tyInteger run(clGraph<tuGraph> &,const clCycle &,
                                std_vector(clArc<tuGraph> *) &) const;
 };
}

// O p t i m a l C a s e  Interface //--------------------------------------------------------------
namespace public_area {
 /*CLASS clOptimalCase */
 /* Represents an optimal case of the minimum binary cost tension problem in a serial-parallel
    graph. */
 template <tdGraph> class clOptimalCase {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clOptimalCase */ /* Type of the list of arcs. */
  public_property typedef std_vector(clArc<tuGraph> *) cpArcS;
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clOptimalCase */
  /* List of the arcs set to their optimal tension in the actual case. */
  read_write_attribute(cpArcS,atArcS,arcs);

  /*ATTRIBUTE clOptimalCase */ /* Cost of the case. */
  read_write_attribute(tyReal,atCost,cost);

  /*ATTRIBUTE clOptimalCase */ /* Minimum main tension such that the case remains feasible. */
  read_write_attribute(tyReal,atMinimum,minimum);

  /*ATTRIBUTE clOptimalCase */ /* Maximum main tension such that the case remains feasible. */
  read_write_attribute(tyReal,atMaximum,maximum);

  public_property constructor clOptimalCase(void);
  public_property constructor clOptimalCase(const clOptimalCase &);
  public_property destructor clOptimalCase(void);

  public_property clOptimalCase & operator = (const clOptimalCase &);

  public_property clOptimalCase * combineParallel(const clOptimalCase &) const;
  public_property clOptimalCase * combineSerial(const clOptimalCase &) const;
  public_property tyBoolean       empty(void) const;
  public_property tyBoolean       include(const clOptimalCase &) const;
  public_property clOptimalCase * keepParallel(const clCaseFunction<tuGraph> &) const;
  public_property clOptimalCase * keepSerial(const clCaseFunction<tuGraph> &) const;
  public_property void            setInterval(tyReal,tyReal);
 };
}

// C a s e F u n c t i o n  Interface //------------------------------------------------------------
namespace public_area {
 /*CLASS clCaseFunction */
 /* Represents the minimum cost function of the minimum binary cost tension problem in a
    serial-parallel graph. */
 template <tdGraph> class clCaseFunction {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clCaseFunction */ /* Type of an optimal case. */
  public_property typedef clOptimalCase<tuGraph>  cpCase;

  /*TYPE clCaseFunction */ /* Type of a subset of cases. */
  public_property typedef std_vector(cpCase *) cpCaseS;

  /*TYPE clCaseFunction */ /* Type of an iterator on the whole list of cases. */
  public_property typedef clCaseIterator<tuGraph> cpCaseIterator;

  private_property typedef std_map(tyReal,cpCaseS) cpCaseX;
  //-----------------------------------------------------------------------------------------Private
  private_property cpCaseX atCaseX;

  private_property void clear(void);
  private_property void copy(const clCaseFunction &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clCaseFunction */ /* Minimum cost of the function. */
  read_write_attribute(tyReal,atCost,cost);

  /*ATTRIBUTE clCaseFunction */ /* Minimum main tension possible for the problem. */
  read_write_attribute(tyReal,atMinimum,minimum);

  /*ATTRIBUTE clCaseFunction */ /* Maximum main tension possible for the problem. */
  read_write_attribute(tyReal,atMaximum,maximum);

  public_property constructor clCaseFunction(void);
  public_property constructor clCaseFunction(const clCaseFunction &);
  public_property destructor clCaseFunction(void);

  public_property clCaseFunction & operator = (const clCaseFunction &);

  public_property void            add(cpCase *,tyBoolean);
  public_property cpCaseIterator  begin(void) const;
  public_property cpCaseS *       bestCases(void);
  public_property const cpCaseS * bestCases(void) const;
  public_property tyInteger       combineParallel(clCaseFunction &,clCaseFunction &,tyBoolean);

  public_property tyInteger combineSerial(const clCaseFunction &,clCaseFunction &,tyBoolean) const;

  public_property tyBoolean      empty(void) const;
  public_property cpCaseIterator end(void) const;
  public_property tyCardinal     size(void) const;
 };
}

// C a s e I t e r a t o r  Interface //------------------------------------------------------------
namespace public_area {
 /*CLASS clCaseIterator */
 /* Represents an iterator on the list of optimal cases of a minimum cost function. */
 template <tdGraph> class clCaseIterator {
  //-----------------------------------------------------------------------------------------Friends
  friend class clCaseFunction<tuGraph>;
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clCaseIterator */ /* Type of an optimal case. */
  public_property typedef clOptimalCase<tuGraph> cpCase;

  private_property typedef std_vector(cpCase *)             cpCaseS;
  private_property typedef std_map(tyReal,cpCaseS)          cpCaseX;
  private_property typedef typename cpCaseX::const_iterator cpCaseIterator;
  //-----------------------------------------------------------------------------------------Private
  private_property cpCaseIterator atIterator;
  private_property tyCardinal     atCounter;

  private_property constructor clCaseIterator(const cpCaseIterator &,tyCardinal);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clCaseIterator(void);
  public_property destructor clCaseIterator(void);

  public_property cpCase *         operator * (void) const;
  public_property clCaseIterator & operator ++ (void);
  public_property clCaseIterator   operator ++ (int);
  public_property tyBoolean        operator != (const clCaseIterator &);
 };
}

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

// A g g r e g a t i o n A l g o  Inline //---------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clAggregationAlgo */ /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clAggregationAlgo<tuGraph>::clAggregationAlgo(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clAggregationAlgo */ /* Destructs the algorithm. */
 template <tdGraph> inline clAggregationAlgo<tuGraph>::~clAggregationAlgo(void) {}
 //---------------------------------------------------------------------------------------DefaultRun
 /*METHOD clAggregationAlgo */
 /* Solves the minimum cost tension problem of a serial-parallel graph using the default version of
    the algorithm (case-oriented inf-convolution computation, approach II). */
 template <tdGraph> inline
 tyInteger clAggregationAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph) {
  clAggregationAlgoII<tuGraph> lcAggregationAlgo;

  return (lcAggregationAlgo.run(agGraph));
 }
}

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

// A g g r e g a t i o n A l g o I I  Inline //-----------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clAggregationAlgoII */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clAggregationAlgoII<tuGraph>::clAggregationAlgoII(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clAggregationAlgoII */ /* Destructs the algorithm. */
 template <tdGraph> inline clAggregationAlgoII<tuGraph>::~clAggregationAlgoII(void) {}
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clAggregationAlgoII */
 /* Solves the minimum cost tension problem of a graph, with default parameters. */
 template <tdGraph>
 inline tyInteger clAggregationAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph) const
 { return (run(agGraph,true,false)); }
}

// O p t i m a l C a s e  Inline //-----------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clOptimalCase */ /* Builds an empty case. */
 template <tdGraph> inline clOptimalCase<tuGraph>::clOptimalCase(void)
 : atArcS(),atCost(0.0),atMinimum(1.0),atMaximum(-1.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clOptimalCase */ /* Builds and copies a case. */
 template <tdGraph> inline clOptimalCase<tuGraph>::clOptimalCase(const clOptimalCase & agCase)
 : atArcS(agCase.atArcS),atCost(agCase.atCost),atMinimum(agCase.atMinimum),
   atMaximum(agCase.atMaximum) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clOptimalCase */ /* Destructs the case. */
 template <tdGraph> inline clOptimalCase<tuGraph>::~clOptimalCase(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clOptimalCase */ /* Copies a case. */
 template <tdGraph> inline
 clOptimalCase<tuGraph> & clOptimalCase<tuGraph>::operator = (const clOptimalCase & agCase) {
  atArcS=agCase.atArcS;
  atCost=agCase.atCost;
  atMinimum=agCase.atMinimum;
  atMaximum=agCase.atMaximum;

  return (*this);
 }
 //--------------------------------------------------------------------------------------------Empty
 /*METHOD clOptimalCase */
 /* Indicates if the case is empty (i.e. the feasibility interval is empty). */
 template <tdGraph> inline tyBoolean clOptimalCase<tuGraph>::empty(void) const
 { return (minimum()>maximum()); }
 //------------------------------------------------------------------------------------------Include
 /*METHOD clOptimalCase */ /* Indicates if the case is including another one. */
 template <tdGraph>
 inline tyBoolean clOptimalCase<tuGraph>::include(const clOptimalCase & agCase) const
 { return (minimum()<=agCase.minimum() and maximum()>=agCase.maximum()); }
 //-------------------------------------------------------------------------------------KeepParallel
 /*METHOD clOptimalCase */ /* Keeps the parallel association of this case with another one. */
 template <tdGraph> inline clOptimalCase<tuGraph> *
 clOptimalCase<tuGraph>::keepParallel(const clCaseFunction<tuGraph> & agFunction) const {
  typedef clOptimalCase<tuGraph> cpCase;

  cpCase * lcCase = new_object(cpCase());

  lcCase->arcs()=arcs();
  lcCase->cost()=cost()+agFunction.cost();
  lcCase->minimum()=maxi(minimum(),agFunction.minimum());
  lcCase->maximum()=mini(maximum(),agFunction.maximum());

  return (lcCase);
 }
 //---------------------------------------------------------------------------------------KeepSerial
 /*METHOD clOptimalCase */ /* Keeps the serial association of this case with another one. */
 template <tdGraph> inline clOptimalCase<tuGraph> *
 clOptimalCase<tuGraph>::keepSerial(const clCaseFunction<tuGraph> & agFunction) const {
  typedef clOptimalCase<tuGraph> cpCase;

  cpCase * lcCase = new_object(cpCase());

  lcCase->arcs()=arcs();
  lcCase->cost()=cost()+agFunction.cost();
  lcCase->minimum()=minimum()+agFunction.minimum();
  lcCase->maximum()=maximum()+agFunction.maximum();

  return (lcCase);
 }
 //--------------------------------------------------------------------------------------SetInterval
 /*METHOD clOptimalCase */ /* Sets the feasibility interval of the case. */
 template <tdGraph>
 inline void clOptimalCase<tuGraph>::setInterval(tyReal agMinimum,tyReal agMaximum) {
  atMinimum=maxi(agMinimum,atMinimum);
  atMaximum=mini(agMaximum,atMaximum);
 }
}

// C a s e F u n c t i o n  Inline //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clCaseFunction */ /* Builds an empty case function. */
 template <tdGraph> inline clCaseFunction<tuGraph>::clCaseFunction(void)
 : atCaseX(),atCost(0.0),atMinimum(1.0),atMaximum(-1.0) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clCaseFunction */ /* Builds and copies a case function. */
 template <tdGraph>
 inline clCaseFunction<tuGraph>::clCaseFunction(const clCaseFunction & agFunction)
 : atCaseX(),atCost(agFunction.atCost),atMinimum(agFunction.atMinimum),
   atMaximum(agFunction.atMaximum) { copy(agFunction); }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clCaseFunction */ /* Destructs the case function. */
 template <tdGraph> inline clCaseFunction<tuGraph>::~clCaseFunction(void) { clear(); }
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clCaseFunction */ /* Copies a case function. */
 template <tdGraph> inline clCaseFunction<tuGraph> &
 clCaseFunction<tuGraph>::operator = (const clCaseFunction & agFunction) {
  cost()=agFunction.cost();
  maximum()=agFunction.maximum();
  minimum()=agFunction.minimum();
  clear();
  copy(agFunction);

  return (*this);
 }
 //--------------------------------------------------------------------------------------------Begin
 /*METHOD clCaseFunction */
 /* Returns an iterator on the first case of the function (the cases are sorted from the best to
    the worst). */
 template <tdGraph> inline clCaseIterator<tuGraph> clCaseFunction<tuGraph>::begin(void) const
 { return (clCaseIterator<tuGraph>(atCaseX.begin(),0)); }
 //----------------------------------------------------------------------------------------BestCases
 /*METHOD clCaseFunction */
 /* Returns the list of best cases of the function. Read-write version. */
 template <tdGraph>
 inline typename clCaseFunction<tuGraph>::cpCaseS * clCaseFunction<tuGraph>::bestCases(void)
 { return (atCaseX.size()==0 ? nil : &((*(atCaseX.begin())).second)); }
 //----------------------------------------------------------------------------------------BestCases
 /*METHOD clCaseFunction */
 /* Returns the list of best cases of the function. Read-only version. */
 template <tdGraph> inline
 const typename clCaseFunction<tuGraph>::cpCaseS * clCaseFunction<tuGraph>::bestCases(void) const
 { return (atCaseX.size()==0 ? nil : &((*(atCaseX.begin())).second)); }
 //--------------------------------------------------------------------------------------------Empty
 /*METHOD clCaseFunction */
 /* Indicates if the case function is empty (i.e. the feasibility interval is empty). */
 template <tdGraph> inline tyBoolean clCaseFunction<tuGraph>::empty(void) const
 { return (minimum()>maximum()); }
 //----------------------------------------------------------------------------------------------End
 /*METHOD clCaseFunction */
 /* Returns an iterator on the last case of the function (the cases are sorted from the best to
    the worst). */
 template <tdGraph> inline clCaseIterator<tuGraph> clCaseFunction<tuGraph>::end(void) const
 { return (clCaseIterator<tuGraph>(atCaseX.end(),0)); }
}

// C a s e I t e r a t o r  Inline //---------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 template <tdGraph>
 inline clCaseIterator<tuGraph>::clCaseIterator(const cpCaseIterator & agIterator,
                                                tyCardinal agCounter)
 : atIterator(agIterator),atCounter(agCounter) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clCaseIterator */ /* Builds an iterator. */
 template <tdGraph> inline clCaseIterator<tuGraph>::clCaseIterator(void)
 : atIterator(),atCounter(0) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clCaseIterator */ /* Destructs the iterator. */
 template <tdGraph> inline clCaseIterator<tuGraph>::~clCaseIterator(void) {}
 //---------------------------------------------------------------------------------------Operator *
 /*METHOD clCaseIterator */ /* Returns a pointer to the case referenced by the iterator. */
 template <tdGraph>
 inline clOptimalCase<tuGraph> * clCaseIterator<tuGraph>::operator * (void) const
 { return ((*atIterator).second)[atCounter]; }
 //--------------------------------------------------------------------------------------Operator ++
 /*METHOD clCaseIterator */ /* Moves the iterator to the next case. */
 template <tdGraph> inline clCaseIterator<tuGraph> & clCaseIterator<tuGraph>::operator ++ (void) {
  if (++atCounter==(*atIterator).second.size()) {
   atCounter=0;
   ++atIterator;
  }

  return (*this);
 }
 //--------------------------------------------------------------------------------------Operator ++
 /*METHOD clCaseIterator */ /* Moves the iterator to the next case. */
 template <tdGraph> inline clCaseIterator<tuGraph> clCaseIterator<tuGraph>::operator ++ (int) {
  clCaseIterator<tuGraph> lcIterator(atIterator,atCounter);

  if (++atCounter==(*atIterator).second.size()) {
   atCounter=0;
   ++atIterator;
  }

  return (lcIterator);
 }
 //--------------------------------------------------------------------------------------Operator !=
 /*METHOD clCaseIterator */ /* Indicates if the iterator is different from another one. */
 template <tdGraph>
 inline tyBoolean clCaseIterator<tuGraph>::operator != (const clCaseIterator<tuGraph> & agIterator)
 { return (atIterator!=agIterator.atIterator or atCounter!=agIterator.atCounter); }
}

// A g g r e g a t i o n A l g o I  Implementation //-----------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Run (Graph)
 /*METHOD clAggregationAlgoI */
 /* Solves the minimum cost tension problem of a graph. <B>Not implemented yet.</B> */
 template <tdGraph> tyInteger clAggregationAlgoI<tuGraph>::run(clGraph<tuGraph> &) const
 { return (-1); }
 //--------------------------------------------------------------------------------------Run (Cycle)
 /*METHOD clAggregationAlgoI */
 /* Solves the minimum cost tension problem of a cycle. The solution is the list of arcs that
    are scheduled to their optimal tension. <B>Not implemented yet.</B> */
 template <tdGraph>
 tyInteger clAggregationAlgoI<tuGraph>::run(clGraph<tuGraph> &,const clCycle &,
                                            std_vector(clArc<tuGraph> *) &) const
 { return (-1); }
}

// A g g r e g a t i o n A l g o I I  Implementation //---------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Run (Graph)
 /*METHOD clAggregationAlgoII */
 /* Solves the minimum cost tension problem of a graph. The elimination of redundant cases can
    be activated (default is yes). Information during the process can be displayed (default is
    not). */
 template <tdGraph>
 tyInteger clAggregationAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph,
                                             tyBoolean agRedundanceElimination,
                                             tyBoolean agDisplayed) const {
  method_name("aggregationAlgoII::run");

  typedef clArc<tuGraph>                               cpArc;
  typedef clOptimalCase<tuGraph>                       cpCase;
  typedef clCaseFunction<tuGraph>                      cpFunction;
  typedef typename cpFunction::cpCaseS                 cpCaseS;
  typedef clGraph<tuGraph>                             cpGraph;
  typedef clBinaryTree<clSerialParallelData<tuGraph> > cpTree;
  typedef std_vector(cpTree *)                         cpTreeS;

  typedef typename cpCase::cpArcS::const_iterator  cpArcIterator1;
  typedef typename cpGraph::cpArcX::const_iterator cpArcIterator2;

  cpArc *        lcArc;
  cpCaseS *      lcCaseS;
  cpArcIterator1 lcCurrentArc1;
  cpArcIterator2 lcCurrentArc2;
  cpArcIterator2 lcCurrentArc3;
  cpFunction     lcFunction;
  tyInteger      lcIteration;
  cpArcIterator1 lcLastArc1;
  cpArcIterator2 lcLastArc2;
  tyCardinal     lcMaximumNbCase;
  tyInteger      lcTotalIteration;
  cpTreeS        lcTreeS;

  cpGraph lcGraph(agGraph);

  agGraph.solved()=false;

  // Serial-Parallel Decomposition //
  graphProblemSerialParallel::clDecomposeAlgo<tuGraph>::defaultRun(lcGraph,lcTreeS);
  if (lcTreeS.size()!=1) send_error(erNotSerialParallel);

  // Aggregation Phase //
  lcTotalIteration=findMinCostTension(*(lcTreeS[0]),lcFunction,
                                      agRedundanceElimination,lcMaximumNbCase);

  delete_object(lcTreeS[0]);

  // If Feasible Problem //
  if (lcTotalIteration!=-1) {
   // Capacity Restriction //
   lcCaseS=lcFunction.bestCases();

   if (lcCaseS!=nil) {
    lcCurrentArc1=(*(lcCaseS->begin()))->arcs().begin();
    lcLastArc1=(*(lcCaseS->begin()))->arcs().end();

    while (lcCurrentArc1!=lcLastArc1) {
     lcArc=*lcCurrentArc1;
     lcArc->data().minimum()=lcArc->data().optimum();
     lcArc->data().maximum()=lcArc->data().optimum();
     ++lcCurrentArc1;
    }
   }

   // Compatible Tension Computation //
   lcIteration=graphProblemTensionAlgorithm::clCompatibleTensionAlgo<tuGraph>::defaultRun(lcGraph);

   // Solution Storage Into Original Graph //
   if (lcIteration!=-1) {
    lcCurrentArc2=lcGraph.arcs().begin();
    lcCurrentArc3=agGraph.arcs().begin();
    lcLastArc2=lcGraph.arcs().end();

    while (lcCurrentArc2!=lcLastArc2) {
     (*lcCurrentArc3).second->data().tension()=(*lcCurrentArc2).second->data().tension();
     ++lcCurrentArc2;
     ++lcCurrentArc3;
    }

    agGraph.solved()=true;

    // Information Display //
    if (agDisplayed) {
     environment::out("Maximum Cases = ",false,true);
     environment::out(lcMaximumNbCase,true);
     environment::out("Final Cases = ",false,true);
     environment::out(lcFunction.size(),true);
    }
   }
  }

  return (lcTotalIteration);
 }
 //--------------------------------------------------------------------------------------Run (Cycle)
 /*METHOD clAggregationAlgoII */
 /* Solves the minimum cost tension problem of a cycle. The solution is the list of arcs that
    are scheduled to their optimal tension. */
 template <tdGraph>
 tyInteger clAggregationAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph,const clCycle & agCycle,
                                             std_vector(clArc<tuGraph> *) & agSolution) const {
  typedef clArc<tuGraph>                        cpArc;
  typedef clCycle::const_iterator               clArcIterator;
  typedef clOptimalCase<tuGraph>                cpCase;
  typedef clCaseFunction<tuGraph>               cpFunction;
  typedef typename cpFunction::cpCaseS          cpCaseS;

  cpArc *       lcArc;
  cpCase *      lcCase;
  cpCaseS *     lcCaseS;
  clArcIterator lcCurrentArc;
  cpFunction *  lcFunction;
  cpFunction *  lcFunction1;
  cpFunction *  lcFunction2;

  tyCardinal lcCounter1;
  tyCardinal lcCounter2;
  tyReal     lcSign;

  cpFunction * lcFunctionS[2];
  tyCardinal   lcSizeS[2];

  tyReal    lcDirection = -1.0;
  tyInteger lcIteration = 0;

  // Initialization //
  if (agCycle.size()<2) return (-1);
  lcSizeS[0]=agCycle.size();
  lcSizeS[1]=agCycle.size()/2;
  lcCounter1=2;
  lcCounter2=0;
  lcCurrentArc=agCycle.begin();

  // Serial Combinations //
  while (lcCounter1>0) {
   --lcCounter1;
   lcDirection*=-1.0;
   lcFunction=new_object(cpFunction());
   lcFunction->minimum()=0.0;
   lcFunction->maximum()=0.0;

   while (lcCounter2<lcSizeS[lcCounter1]) {
    lcFunction1=lcFunction;
    lcFunction2=new_object(cpFunction());
    lcArc=&(agGraph.arc((*lcCurrentArc).first));
    lcSign=lcDirection*(*lcCurrentArc).second;

    if (lcSign<0.0) {
     lcFunction2->minimum()=-1.0*lcArc->data().maximum();
     lcFunction2->maximum()=-1.0*lcArc->data().minimum();
    }
    else {
     lcFunction2->minimum()=lcArc->data().minimum();
     lcFunction2->maximum()=lcArc->data().maximum();
    }

    lcFunction2->cost()=lcArc->data().weight();

    lcCase=new_object(cpCase());
    lcCase->arcs().push_back(lcArc);
    lcCase->cost()=0.0;
    lcCase->minimum()=lcSign*lcArc->data().optimum();
    lcCase->maximum()=lcCase->minimum();
    lcFunction2->add(lcCase,false);

    lcFunction=new_object(cpFunction());
    lcIteration+=lcFunction1->combineSerial(*lcFunction2,*lcFunction,true);

    delete_object(lcFunction1);
    delete_object(lcFunction2);
    ++lcCounter2;
    ++lcCurrentArc;
   }

   lcFunctionS[lcCounter1]=lcFunction;
  }

  // Parallel Combination //
  lcFunction=new_object(cpFunction());
  lcIteration+=lcFunctionS[0]->combineParallel(*(lcFunctionS[1]),*lcFunction,true);
  if (lcFunction->empty()) lcIteration=-1;
  delete_object(lcFunctionS[0]);
  delete_object(lcFunctionS[1]);

  // Objective Value //
  if (lcIteration!=-1) {
   lcCaseS=lcFunction->bestCases();
   agSolution.erase(agSolution.begin(),agSolution.end());
   if (lcCaseS!=nil) agSolution=(*(lcCaseS->begin()))->arcs();
  }

  // Termination //
  delete_object(lcFunction);
  return (lcIteration);
 }
}

// C a s e F u n c t i o n  Implementation //-------------------------------------------------------
namespace public_area {
 //---------------------------------------------------------------------------------------------Copy
 template <tdGraph> void clCaseFunction<tuGraph>::copy(const clCaseFunction & agFunction) {
  typedef typename cpCaseX::const_iterator cpCasesIterator;

  cpCaseS *  lcCase1S;
  cpCaseS *  lcCase2S;
  tyCardinal lcCounter;

  cpCasesIterator lcCurrentCases = agFunction.atCaseX.begin();
  cpCasesIterator lcLastCases    = agFunction.atCaseX.end();

  while (lcCurrentCases!=lcLastCases) {
   lcCase1S=&((*lcCurrentCases).second);
   lcCase2S=&(atCaseX[(*lcCurrentCases).first]);
   lcCounter=lcCase1S->size();
   lcCase2S->reserve(lcCounter);

   while (lcCounter>0) {
    --lcCounter;
    (*lcCase2S).push_back(new_object(cpCase(*((*lcCase1S)[lcCounter]))));
   }

   ++lcCurrentCases;
  }
 }
 //--------------------------------------------------------------------------------------------Clear
 template <tdGraph> void clCaseFunction<tuGraph>::clear(void) {
  typedef typename cpCaseX::iterator cpCasesIterator;

  cpCaseS *  lcCaseS;
  tyCardinal lcCounter;

  cpCasesIterator lcCurrentCases = atCaseX.begin();
  cpCasesIterator lcLastCases    = atCaseX.end();

  while (lcCurrentCases!=lcLastCases) {
   lcCaseS=&((*lcCurrentCases).second);
   lcCounter=lcCaseS->size();

   while (lcCounter>0) {
    --lcCounter;
    delete_object((*lcCaseS)[lcCounter]);
   }

   ++lcCurrentCases;
  }

  atCaseX.erase(atCaseX.begin(),atCaseX.end());
 }
 //----------------------------------------------------------------------------------------------Add
 /*METHOD clCaseFunction */
 /* Adds a case to the function. The elimination of redundant cases can be activated. */
 template <tdGraph>
 void clCaseFunction<tuGraph>::add(cpCase * agCase,tyBoolean agRedundanceElimination) {
  typedef typename cpCaseX::iterator cpCasesIterator;

  cpCaseS *          lcCaseS;
  std_vector(tyReal) lcCostS;
  tyCardinal         lcCounter;

  cpCasesIterator lcCurrentCases = atCaseX.begin();
  cpCasesIterator lcLastCases    = atCaseX.end();

  if (agRedundanceElimination) {
   // Lower Cost Inclusions Search //
   while (lcCurrentCases!=lcLastCases and (*lcCurrentCases).first<agCase->cost()) {
    lcCaseS=&((*lcCurrentCases).second);
    lcCounter=lcCaseS->size();

    while (lcCounter>0) {
     --lcCounter;

     if ((*lcCaseS)[lcCounter]->include(*agCase)) {
      delete_object(agCase);
      return;
     }
    }

    ++lcCurrentCases;
   }

   // Equal Cost Inclusions Search //
   if (lcCurrentCases!=lcLastCases and (*lcCurrentCases).first==agCase->cost()) {
    lcCaseS=&((*lcCurrentCases).second);
    lcCounter=lcCaseS->size();

    while (lcCounter>0) {
     --lcCounter;

     if ((*lcCaseS)[lcCounter]->include(*agCase)) {
      delete_object(agCase);
      return;
     }
    }
   }

   // Higher Cost Inclusions Search //
   while (lcCurrentCases!=lcLastCases) {
    lcCaseS=&((*lcCurrentCases).second);
    lcCounter=lcCaseS->size();

    while (lcCounter>0) {
     --lcCounter;

     if (agCase->include(*((*lcCaseS)[lcCounter]))) {
      delete_object((*lcCaseS)[lcCounter]);
      (*lcCaseS)[lcCounter]=lcCaseS->back();
      lcCaseS->pop_back();
     }
    }

    if (lcCaseS->size()==0 and (*lcCurrentCases).first>agCase->cost())
     lcCostS.push_back((*lcCurrentCases).first);

    ++lcCurrentCases;
   }

   // Empty Cost Entries Removal //
   lcCounter=lcCostS.size();

   while (lcCounter>0) {
    --lcCounter;
    atCaseX.erase(lcCostS[lcCounter]);
   }
  }

  atCaseX[agCase->cost()].push_back(agCase);
 }
 //----------------------------------------------------------------------------------CombineParallel
 /*METHOD clCaseFunction */ /* Combines, by parallel composition, the function with another one. */
 template <tdGraph>
 tyInteger clCaseFunction<tuGraph>::combineParallel(clCaseFunction & agFunction,
                                                    clCaseFunction & agResult,
                                                    tyBoolean agRedundanceElimination) {
  typedef clCaseIterator<tuGraph> cpCaseIterator;

  cpCase *             lcCase;
  std_vector(cpCase *) lcCase1S;
  std_vector(cpCase *) lcCase2S;
  tyCardinal           lcCounter1;
  tyCardinal           lcCounter2;
  cpCaseIterator       lcCurrentCase;
  cpCaseIterator       lcLastCase;

  tyCardinal lcIteration = 0;

  agResult.cost()=cost()+agFunction.cost();
  agResult.minimum()=maxi(minimum(),agFunction.minimum());
  agResult.maximum()=mini(maximum(),agFunction.maximum());

  if (not agResult.empty()) {
   // Isolated Cases (Function 1) //
   lcCurrentCase=begin();
   lcLastCase=end();

   while (lcCurrentCase!=lcLastCase) {
    lcCase=*lcCurrentCase;
    lcCase->setInterval(agResult.minimum(),agResult.maximum());

    if (not lcCase->empty()) {
     lcCase1S.push_back(lcCase);
     agResult.add(lcCase->keepParallel(agFunction),agRedundanceElimination);
     ++lcIteration;
    }

    ++lcCurrentCase;
   }

   // Isolated Cases (Function 2) //
   lcCurrentCase=agFunction.begin();
   lcLastCase=agFunction.end();

   while (lcCurrentCase!=lcLastCase) {
    lcCase=*lcCurrentCase;
    lcCase->setInterval(agResult.minimum(),agResult.maximum());

    if (not lcCase->empty()) {
     lcCase2S.push_back(lcCase);
     agResult.add(lcCase->keepParallel(*this),agRedundanceElimination);
     ++lcIteration;
    }

    ++lcCurrentCase;
   }

   // Cases Combination //
   lcCounter1=0;

   while (lcCounter1!=lcCase1S.size()) {
    lcCounter2=0;

    while (lcCounter2<lcCase2S.size()) {
     lcCase=lcCase1S[lcCounter1]->combineParallel(*(lcCase2S[lcCounter2]));

     if (lcCase->empty()) delete_object(lcCase);
     else agResult.add(lcCase,agRedundanceElimination);

     ++lcCounter2;
     ++lcIteration;
    }

    ++lcCounter1;
   }
  }

  return (lcIteration);
 }
 //------------------------------------------------------------------------------------CombineSerial
 /*METHOD clCaseFunction */ /* Combines, by serial composition, the function with another one. */
 template <tdGraph>
 tyInteger clCaseFunction<tuGraph>::combineSerial(const clCaseFunction & agFunction,
                                                  clCaseFunction & agResult,
                                                  tyBoolean agRedundanceElimination) const {
  typedef clCaseIterator<tuGraph> cpCaseIterator;

  cpCaseIterator lcCurrentCase1;
  cpCaseIterator lcCurrentCase2;
  cpCaseIterator lcLastCase1;
  cpCaseIterator lcLastCase2;

  tyInteger lcIteration = 0;

  agResult.cost()=cost()+agFunction.cost();
  agResult.minimum()=minimum()+agFunction.minimum();
  agResult.maximum()=maximum()+agFunction.maximum();

  if (not agResult.empty()) {
   // Isolated Cases (Function 1) //
   lcCurrentCase1=begin();
   lcLastCase1=end();

   while (lcCurrentCase1!=lcLastCase1) {
    agResult.add((*lcCurrentCase1)->keepSerial(agFunction),agRedundanceElimination);
    ++lcCurrentCase1;
    ++lcIteration;
   }

   // Isolated Cases (Function 2) //
   lcCurrentCase2=agFunction.begin();
   lcLastCase2=agFunction.end();

   while (lcCurrentCase2!=lcLastCase2) {
    agResult.add((*lcCurrentCase2)->keepSerial(*this),agRedundanceElimination);
    ++lcCurrentCase2;
    ++lcIteration;
   }

   // Cases Combination //
   lcCurrentCase1=begin();

   while (lcCurrentCase1!=lcLastCase1) {
    lcCurrentCase2=agFunction.begin();

    while (lcCurrentCase2!=lcLastCase2) {
     agResult.add((*lcCurrentCase2)->combineSerial(**lcCurrentCase1),agRedundanceElimination);
     ++lcCurrentCase2;
     ++lcIteration;
    }

    ++lcCurrentCase1;
   }
  }

  return (lcIteration);
 }
 //---------------------------------------------------------------------------------------------Size
 /*METHOD clCaseFunction */ /* Returns the number of cases in the function. */
 template <tdGraph> tyCardinal clCaseFunction<tuGraph>::size(void) const {
  typedef typename cpCaseX::const_iterator cpCasesIterator;

  cpCasesIterator lcCurrentCases = atCaseX.begin();
  cpCasesIterator lcLastCases    = atCaseX.end();
  tyCardinal      lcSize         = 0;

  while (lcCurrentCases!=lcLastCases) {
   lcSize+=(*lcCurrentCases).second.size();
   ++lcCurrentCases;
  }

  return (lcSize);
 }
}

// O p t i m a l C a s e  Implementation //---------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------CombineParallel
 /*METHOD clOptimalCase */ /* Combines, by parallel composition, the case with another one. */
 template <tdGraph> clOptimalCase<tuGraph> *
 clOptimalCase<tuGraph>::combineParallel(const clOptimalCase & agCase) const {
  typedef clOptimalCase<tuGraph> cpCase;

  cpCase *   lcCase    = new_object(cpCase());
  tyCardinal lcCounter = agCase.arcs().size();
  tyCardinal lcSize    = arcs().size()+lcCounter;

  lcCase->arcs()=arcs();
  lcCase->arcs().reserve(lcSize);

  while (lcCounter>0) {
   --lcCounter;
   lcCase->arcs().push_back(agCase.arcs()[lcCounter]);
  }

  lcCase->cost()=cost()+agCase.cost();
  lcCase->minimum()=maxi(minimum(),agCase.minimum());
  lcCase->maximum()=mini(maximum(),agCase.maximum());

  return (lcCase);
 }
 //------------------------------------------------------------------------------------CombineSerial
 /*METHOD clOptimalCase */ /* Combines, by serial composition, the case with another one. */
 template <tdGraph> clOptimalCase<tuGraph> *
 clOptimalCase<tuGraph>::combineSerial(const clOptimalCase & agCase) const {
  typedef clOptimalCase<tuGraph> cpCase;

  cpCase *   lcCase    = new_object(cpCase());
  tyCardinal lcCounter = agCase.arcs().size();
  tyCardinal lcSize    = arcs().size()+lcCounter;

  lcCase->arcs()=arcs();
  lcCase->arcs().reserve(lcSize);

  while (lcCounter>0) {
   --lcCounter;
   lcCase->arcs().push_back(agCase.arcs()[lcCounter]);
  }

  lcCase->cost()=cost()+agCase.cost();
  lcCase->minimum()=minimum()+agCase.minimum();
  lcCase->maximum()=maximum()+agCase.maximum();

  return (lcCase);
 }
}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //-------------------------------------------------------------------------------FindMinCostTension
 /*FUNCTION*/
 /* Builds the minimum cost function of the minimum binary cost tension problem in a
    serial-parallel graph (represented by its SP-tree). The elimination of redundant cases can be
    activated. The maximum number of cases that have been generated during an iteration of the
    algorithm is also stored. */
 template <tdGraph>
 tyInteger findMinCostTension(clBinaryTree<clSerialParallelData<tuGraph> > & agTree,
                              clCaseFunction<tuGraph> & agFunction,
                              tyBoolean agRedundanceElimination,tyCardinal & agMaximumNbCase) {
  typedef clArc<tuGraph>                     cpArc;
  typedef clOptimalCase<tuGraph>             cpCase;
  typedef clSerialParallelData<tuGraph>      cpSerialParallelData;
  typedef clBinaryTree<cpSerialParallelData> cpTree;
  typedef std_vector(cpTree *)               cpTreeS;
  typedef std_vector(tyCardinal)             clCardinalS;
  typedef clCaseFunction<tuGraph>            cpFunction;
  typedef std_vector(cpFunction *)           cpFunctionS;

  cpArc *      lcArc;
  cpCase *     lcCase;
  cpFunction * lcFunction1;
  cpFunction * lcFunction2;
  cpFunctionS  lcFunctionS;
  clCardinalS  lcStateS;
  cpTree *     lcTree;
  cpTreeS      lcTreeS;

  cpFunction * lcFunction  = nil;
  tyInteger    lcIteration = 0;

  // Empty Tree //
  if (agTree.empty()) return (0);
  agMaximumNbCase=0;

  // Main Loop //
  lcTreeS.push_back(&agTree);
  lcStateS.push_back(0);
  lcFunctionS.push_back(nil);

  while (lcTreeS.size()>0 and lcIteration!=-1) {
   lcTree=lcTreeS.back();

   switch(++(lcStateS.back())) {
    case 1:
     // Single Arc //
     if (lcTree->data().operation()==cpSerialParallelData::none) {
      lcArc=lcTree->data().arc();

      lcFunction=(lcTree==&agTree ? &agFunction : new_object(cpFunction()));
      lcFunction->minimum()=lcArc->data().minimum();
      lcFunction->maximum()=lcArc->data().maximum();
      lcFunction->cost()=lcArc->data().weight();

      lcCase=new_object(cpCase());
      lcCase->arcs().push_back(lcArc);
      lcCase->cost()=0.0;
      lcCase->minimum()=lcArc->data().optimum();
      lcCase->maximum()=lcArc->data().optimum();
      lcFunction->add(lcCase,false);

      lcTreeS.pop_back();
      lcStateS.pop_back();
      lcFunctionS.pop_back();
     }

     // Left Member Of An SP-Operation //
     else {
      lcTreeS.push_back(&(lcTree->left()));
      lcStateS.push_back(0);
      lcFunctionS.push_back(nil);
     }

     break;

    case 2: // Right Member Of An SP-Operation //
     lcFunctionS.back()=lcFunction;
     lcTreeS.push_back(&(lcTree->right()));
     lcStateS.push_back(0);
     lcFunctionS.push_back(nil);
     break;

    default:
     // Preparation To SP-Fusion //
     lcFunction1=lcFunctionS.back();
     lcFunction2=lcFunction;

     if (lcTree==&agTree) lcFunction=&agFunction;
     else lcFunction=new_object(cpFunction());

     // Serial Fusion //
     if (lcTree->data().operation()==cpSerialParallelData::serial)
      lcIteration+=lcFunction1->combineSerial(*lcFunction2,*lcFunction,agRedundanceElimination);

     // Parallel Fusion //
     else lcIteration+=lcFunction1->combineParallel(*lcFunction2,*lcFunction,
                                                    agRedundanceElimination);

     // Cleaning And Stack Update //
     delete_object(lcFunction1);
     delete_object(lcFunction2);
     lcTreeS.pop_back();
     lcStateS.pop_back();
     lcFunctionS.pop_back();
     agMaximumNbCase=maxi(agMaximumNbCase,agFunction.size());
   }
  }

  // Termination //
  if (agFunction.empty()) lcIteration=-1;
  return (lcIteration);
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef tdGraph
#undef tuGraph
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// G r a p h _ p r o b l e m                                                         Implementation
// M i n _ c o s t _ t e n s i o n
// A g g r e g a t i o n _ b i n a r y
//                                                                                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/aggregation_binary.cpp"

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

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

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostTensionAggregationBinary
#define private_area graphProblemMinCostTensionAggregationBinary_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Min_cost_tension/Aggregation_binary");

// Initialization //--------------------------------------------------------------------------------

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

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

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

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

// X X X  Implementation //-------------------------------------------------------------------------
namespace {}

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