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