//================================================================================================== // 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 // 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 or almost serial-parallel graphs. The cost functions of the arcs in the graph must be linear as defined by the <CODE>clLinearArcData</CODE> class of the <CODE>Structure</CODE> module. */
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph_problem/min_cost_tension/aggregation.hpp"
// Guardian //-------------------------------------------------------------------------------------- #ifndef guGraphProblemMinCostTensionAggregation #define guGraphProblemMinCostTensionAggregation
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph_problem/min_cost_tension/conforming_piecewise.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 graphProblemMinCostTensionAggregation #define private_area graphProblemMinCostTensionAggregation_private
namespace public_area { /*NAMESPACE*/ using namespace graphProblemMinCostTensionAlgorithm; /*NAMESPACE*/ using namespace graphProblemSerialParallel; }
namespace private_area { using namespace public_area; }
extern_module_name;
// Initialization //-------------------------------------------------------------------------------- #define iniGraphProblemMinCostTensionAggregation has_initializer;
// Macrocommands //--------------------------------------------------------------------------------- /*ALIAS*/ #define tdGraph class prArcData,class prNodeData //
/*ALIAS*/ #define tuGraph prArcData,prNodeData //
// Types & Classes //------------------------------------------------------------------------------- namespace public_area { //------------------------------------------------------------------------------------------Classes template <tdGraph> class clSolveAlgo; template <tdGraph> class clSolveAlgoI; template <tdGraph> class clSolveAlgoII; template <tdGraph> class clSolveSerialParallelAlgo; }
namespace private_area { template <tdGraph> struct clTreeInfo; template <tdGraph> class clVariation; }
// Functions Interface //--------------------------------------------------------------------------- namespace public_area {}
namespace private_area { testing_mode ( function void test(void); )
template <tdGraph> void clean(std_vector(clVariation<tuGraph>) &);
template <tdGraph> tyInteger findMinCostTension(clBinaryTree<clSerialParallelData<tuGraph> > &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &,tyReal &,tyReal * =nil, tyReal * =nil);
template <tdGraph,class prIterator> tyInteger improveBalance(prIterator &,const prIterator,prIterator &,const prIterator, std_deque(clVariation<tuGraph>) &,std_deque(clVariation<tuGraph>) &, tyReal &,tyReal &,tyReal &,tyReal &,tyBoolean);
template <tdGraph> tyBoolean mergeParallelArcs(clBinaryTree<clSerialParallelData<tuGraph> > &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, tyReal &,tyReal &,tyBoolean);
template <tdGraph> void mergeParallelVariations(std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &);
template <tdGraph,class prIterator1,class prIterator2> void mergeSerialVariations(std_deque(clVariation<tuGraph>) &,prIterator1,const prIterator1, prIterator2,const prIterator2);
template <tdGraph> clPiecewiseArc * createPiecewiseArc(clPiecewiseGraph &,clTreeInfo<tuGraph> &, clNode<tuGraph> &,clNode<tuGraph> &,tyReal,tyBoolean);
template <tdGraph> void disintegrateArc(clBinaryTree<clSerialParallelData<tuGraph> > &,clPiecewiseGraph &, clNode<tuGraph> **, clNode<tuGraph> **, std_map(clNode<tuGraph> *,clBinaryTree<clSerialParallelData<tuGraph> > *) &, tyBoolean);
template <tdGraph> void findFlow(clBinaryTree<clSerialParallelData<tuGraph> > &,tyReal &);
template <tdGraph> void increaseFlow(std_deque(clVariation<tuGraph>) &,tyReal &,tyReal);
template <class prConformity,class prDirectMintyColor,class prInverseMintyColor> tyInteger makeConform(clPiecewiseArc **,tyCardinal &,prConformity &, prDirectMintyColor &,prInverseMintyColor &);
template <tdGraph> tyReal maximumFlow(clArc<tuGraph> &);
template <tdGraph> void mergeParallelFlows(std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, tyReal,tyReal);
template <tdGraph> void mergeSerialFlows(std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &, std_deque(clVariation<tuGraph>) &);
template <tdGraph> tyReal minimumFlow(clArc<tuGraph> &); template <tdGraph> void updateCosts(clTreeInfo<tuGraph> &); template <tdGraph> void updateTension(clTreeInfo<tuGraph> &); }
// Errors //---------------------------------------------------------------------------------------- namespace public_area { /*ERROR*/ extern_error erEmptyArcList; /* The arc list is empty. */ /*ERROR*/ extern_error erNotEnoughAvailableFlow; /* Can not increase or decrease more a flow. */
/*ERROR*/ extern_error erNotEnoughAvailableTension; /* Can not increase or decrease more a tension. */ }
// Constants & Variables //------------------------------------------------------------------------- extern_dynamic_constant(private,clString,goDataLocation,?);
// S o l v e A l g o Interface //------------------------------------------------------------------ namespace public_area { /*CLASS clSolveAlgo */ /* Represents an algorithm to solve the minimum cost tension problem in a graph, using the reconstruction approach that combines the aggregation and the conforming methods. */ template <tdGraph> class clSolveAlgo : public clLinearSolver<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clSolveAlgo(const clSolveAlgo &); private_property clSolveAlgo & operator = (const clSolveAlgo &); //------------------------------------------------------------------------------------------Public public_property constructor clSolveAlgo(void); public_property virtual destructor clSolveAlgo(void);
/*AMETHOD clSolveAlgo */ /* Solves the minimum cost tension problem of a graph by decomposing the graph into serial-parallel components. Abstract method. */ public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;
/*AMETHOD clSolveAlgo */ /* Solves the minimum cost tension problem of a graph by decomposing the graph into serial-parallel components, using the method given as argument, or directly if serial-parallel components are given (default is not). The number of components obtained can be displayed (default is not). Abstract method. */ public_property virtual tyInteger run(clGraph<tuGraph> & agGraph, const clDecomposeAlgo<tuGraph> & agDecomposeAlgo, std_vector(clBinaryTree<clSerialParallelData<tuGraph> > *) * agComponentS=nil, tyBoolean agDisplayed=false) const = 0;
public_property static tyInteger defaultRun(clGraph<tuGraph> &); }; }
// S o l v e A l g o I Interface //---------------------------------------------------------------- namespace public_area { /*CLASS clSolveAlgoI */ /* Represents an algorithm to solve the minimum cost tension problem in a graph, using the reconstruction approach (version I) that combines the aggregation and the conforming methods. */ template <tdGraph> class clSolveAlgoI : public clSolveAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clSolveAlgoI(const clSolveAlgoI &); private_property clSolveAlgoI & operator = (const clSolveAlgoI &); //------------------------------------------------------------------------------------------Public public_property constructor clSolveAlgoI(void); public_property virtual destructor clSolveAlgoI(void);
public_property tyInteger run(clGraph<tuGraph> &) const;
public_property tyInteger run(clGraph<tuGraph> &,const clDecomposeAlgo<tuGraph> &, std_vector(clBinaryTree<clSerialParallelData<tuGraph> > *) * =nil, tyBoolean=false) const; }; }
// S o l v e A l g o I I Interface //-------------------------------------------------------------- namespace public_area { /*CLASS clSolveAlgoII */ /* Represents an algorithm to solve the minimum cost tension problem in a graph, using the reconstruction approach (version II, post-decomposition) that combines the aggregation and the conforming methods. */ template <tdGraph> class clSolveAlgoII : public clSolveAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clSolveAlgoII(const clSolveAlgoII &); private_property clSolveAlgoII & operator = (const clSolveAlgoII &); //------------------------------------------------------------------------------------------Public public_property constructor clSolveAlgoII(void); public_property virtual destructor clSolveAlgoII(void);
public_property tyInteger run(clGraph<tuGraph> &) const;
public_property tyInteger run(clGraph<tuGraph> &,const clDecomposeAlgo<tuGraph> &, std_vector(clBinaryTree<clSerialParallelData<tuGraph> > *) * =nil, tyBoolean=false) const; }; }
// S o l v e S e r i a l P a r a l l e l A l g o Interface //-------------------------------------- namespace public_area { /*CLASS clSolveSerialParallelAlgo */ /* Represents an algorithm to solve the minimum cost tension problem in a serial-parallel graph using the recursive aggregation method. */ template <tdGraph> class clSolveSerialParallelAlgo : public clLinearSolver<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clSolveSerialParallelAlgo(const clSolveSerialParallelAlgo &); private_property clSolveSerialParallelAlgo & operator = (const clSolveSerialParallelAlgo &); //------------------------------------------------------------------------------------------Public public_property constructor clSolveSerialParallelAlgo(void); public_property virtual destructor clSolveSerialParallelAlgo(void);
public_property tyInteger run(clGraph<tuGraph> &) const; }; }
// V a r i a t i o n Interface //------------------------------------------------------------------ namespace private_area { template <tdGraph> class clVariation { //-------------------------------------------------------------------------------------------Types public_property typedef std_vector(clArc<tuGraph> *) cpArcS; private_property typedef cpArcS * cpArcSP; //------------------------------------------------------------------------------------------Public read_write_attribute(tyReal,atCost,cost); read_write_attribute(tyReal,atAvailable,available); read_write_attribute(cpArcSP,atArcS,arcs); read_write_attribute(tyBoolean,atInfinity,infinity);
public_property constructor clVariation(void); public_property constructor clVariation(tyReal,tyReal,cpArcS *,tyBoolean=false); public_property constructor clVariation(const clVariation<tuGraph> &); public_property destructor clVariation(void) {}
public_property clVariation<tuGraph> & operator = (const clVariation<tuGraph> &);
public_property void addArcs(const clVariation<tuGraph> &); public_property void copyArcs(const clVariation<tuGraph> &); public_property void decreaseTension(tyReal,tyBoolean); public_property void increaseTension(tyReal,tyBoolean); }; }
// Types //----------------------------------------------------------------------------------------- namespace private_area { template <tdGraph> struct clTreeInfo { tyBoolean aggregated; clPiecewiseArc * arc; std_deque(private_area::clVariation<tuGraph>) shrinkCosts; std_deque(private_area::clVariation<tuGraph>) stretchCosts; tyReal tension; }; }
// Functions Inline //------------------------------------------------------------------------------ namespace public_area {}
namespace private_area { //--------------------------------------------------------------------------------------MaximumFlow template <tdGraph> inline tyReal maximumFlow(clArc<tuGraph> & agArc) { if (agArc.data().tension()<agArc.data().minimum() or agArc.data().tension()>=agArc.data().maximum()) return (realMax());
if (agArc.data().tension()>=agArc.data().optimum()) return (agArc.data().stretchingCost()); return (-agArc.data().shrinkingCost()); } //--------------------------------------------------------------------------------------MinimumFlow template <tdGraph> inline tyReal minimumFlow(clArc<tuGraph> & agArc) { if (agArc.data().tension()<=agArc.data().minimum() or agArc.data().tension()>agArc.data().maximum()) return (realMin());
if (agArc.data().tension()<=agArc.data().optimum()) return (-agArc.data().shrinkingCost()); return (agArc.data().stretchingCost()); } }
// S o l v e A l g o Inline //--------------------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clSolveAlgo */ /* Builds an algorithm to solve the minimum cost tension problem. */ template <tdGraph> inline clSolveAlgo<tuGraph>::clSolveAlgo(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clSolveAlgo */ /* Destructs the algorithm. */ template <tdGraph> inline clSolveAlgo<tuGraph>::~clSolveAlgo(void) {} //---------------------------------------------------------------------------------------DefaultRun /*METHOD clSolveAlgo */ /* Solves the minimum cost tension problem of a graph using the default version of the algorithm (version II). Static method. */ template <tdGraph> inline tyInteger clSolveAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph) { return (clSolveAlgoII<tuGraph>().run(agGraph)); } }
// S o l v e A l g o I Inline //------------------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clSolveAlgoI */ /* Builds an algorithm to solve the minimum cost tension problem. */ template <tdGraph> inline clSolveAlgoI<tuGraph>::clSolveAlgoI(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clSolveAlgoI */ /* Destructs the algorithm. */ template <tdGraph> inline clSolveAlgoI<tuGraph>::~clSolveAlgoI(void) {} //----------------------------------------------------------------------------------------------Run /*METHOD clSolveAlgoI */ /* Solves the minimum cost tension problem of a graph by decomposing the graph into serial-parallel components (using method I). */ template <tdGraph> inline tyInteger clSolveAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph) const { clDecomposeAlgoI<tuGraph> lcDecomposeAlgo;
return (run(agGraph,lcDecomposeAlgo,nil,false)); } }
// S o l v e A l g o I I Inline //----------------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clSolveAlgoII */ /* Builds an algorithm to solve the minimum cost tension problem. */ template <tdGraph> inline clSolveAlgoII<tuGraph>::clSolveAlgoII(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clSolveAlgoII */ /* Destructs the algorithm. */ template <tdGraph> inline clSolveAlgoII<tuGraph>::~clSolveAlgoII(void) {} //----------------------------------------------------------------------------------------------Run /*METHOD clSolveAlgoII */ /* Solves the minimum cost tension problem of a graph by decomposing the graph into serial-parallel components (using method I). */ template <tdGraph> inline tyInteger clSolveAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph) const { clDecomposeAlgoI<tuGraph> lcDecomposeAlgo;
return (run(agGraph,lcDecomposeAlgo,nil,false)); } }
// S o l v e S e r i a l P a r a l l e l A l g o Inline //----------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clSolveSerialParallelAlgo */ /* Builds an algorithm to solve the minimum cost tension problem. */ template <tdGraph> inline clSolveSerialParallelAlgo<tuGraph>::clSolveSerialParallelAlgo(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clSolveSerialParallelAlgo */ /* Destructs the algorithm. */ template <tdGraph> inline clSolveSerialParallelAlgo<tuGraph>::~clSolveSerialParallelAlgo(void) {} }
// V a r i a t i o n Inline //--------------------------------------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------Constructor template <tdGraph> inline clVariation<tuGraph>::clVariation(void) : atCost(0.0),atAvailable(0.0),atArcS(nil),atInfinity(false) {} //--------------------------------------------------------------------------------------Constructor template <tdGraph> inline clVariation<tuGraph>::clVariation(const clVariation<tuGraph> & agData) : atCost(agData.atCost),atAvailable(agData.atAvailable),atArcS(agData.atArcS), atInfinity(agData.atInfinity) {} //--------------------------------------------------------------------------------------Constructor template <tdGraph> inline clVariation<tuGraph>::clVariation(tyReal agCost,tyReal agAvailable,cpArcS * agArcS, tyBoolean agInfinity) : atCost(agCost),atAvailable(agAvailable),atArcS(agArcS),atInfinity(agInfinity) {} //---------------------------------------------------------------------------------------Operator = template <tdGraph> inline clVariation<tuGraph> & clVariation<tuGraph>::operator = (const clVariation<tuGraph> & agData) { atCost=agData.atCost; atAvailable=agData.atAvailable; atArcS=agData.atArcS; atInfinity=agData.atInfinity; return (*this); } }
// Functions Implementation //---------------------------------------------------------------------- namespace public_area {}
namespace private_area { //--------------------------------------------------------------------------------------------Clean template <tdGraph> void clean(std_deque(clVariation<tuGraph>) & agVariationS) { typedef typename std_deque(clVariation<tuGraph>)::const_iterator cpIterator;
cpIterator lcCurrentVariation = agVariationS.begin(); cpIterator lcLastVariation = agVariationS.end();
while (lcCurrentVariation!=lcLastVariation) { delete_object((*lcCurrentVariation).arcs()); lcCurrentVariation++; }
agVariationS.clear(); } //-------------------------------------------------------------------------------FindMinCostTension template <tdGraph> tyInteger findMinCostTension(clBinaryTree<clSerialParallelData<tuGraph> > & agTree, std_deque(clVariation<tuGraph>) & agShrinkS, std_deque(clVariation<tuGraph>) & agStretchS,tyReal & agOptimum, tyReal * agTension,tyReal * agFlow) { typedef clArc<tuGraph> cpArc; typedef std_vector(clArc<tuGraph> *) cpArcS; typedef clSerialParallelData<tuGraph> cpSerialParallelData; typedef clBinaryTree<cpSerialParallelData> cpTree; typedef std_vector(cpTree *) cpTreeS; typedef std_vector(tyCardinal) clCardinalS; typedef std_vector(tyReal) clRealS; typedef std_deque(clVariation<tuGraph>) cpVariationS; typedef std_vector(cpVariationS *) cpVariationD;
cpArc * lcArc; clRealS lcFlowS; clRealS lcOptimumS; cpVariationS * lcShrink1S; cpVariationS * lcShrink2S; cpVariationD lcShrinkD; clCardinalS lcStateS; cpVariationS * lcStretch1S; cpVariationS * lcStretch2S; cpVariationD lcStretchD; clRealS lcTensionS; cpTree * lcTree; cpTreeS lcTreeS;
tyReal lcFlow2; tyReal lcOptimum1; tyReal lcOptimum2; tyReal lcTension2;
tyReal lcFlow = 0.0; tyReal lcFlow1 = 0.0; tyInteger lcIteration = 0; tyReal lcOptimum = 0.0; cpVariationS * lcShrinkS = nil; cpVariationS * lcStretchS = nil; tyReal lcTension = 0.0; tyReal lcTension1 = 0.0;
// Empty Tree // if (agTree.empty()) { agOptimum=0.0; if (agTension!=nil) *agTension=0.0; if (agFlow!=nil) *agFlow=0.0; return (0); }
// Main Loop // lcTreeS.push_back(&agTree); lcStateS.push_back(0); lcShrinkD.push_back(nil); lcStretchD.push_back(nil); lcOptimumS.push_back(0.0); if (agTension!=nil) lcTensionS.push_back(0.0); if (agFlow!=nil) lcFlowS.push_back(0.0);
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(); lcOptimum=lcArc->data().optimum();
if (agTension==nil) lcArc->data().tension()=lcArc->data().optimum(); else lcTension=lcArc->data().tension();
if (agFlow!=nil) lcFlow=lcArc->data().flow();
if (lcTree==&agTree) { lcShrinkS=&agShrinkS; lcStretchS=&agStretchS; } else { lcShrinkS=new_object(cpVariationS()); lcStretchS=new_object(cpVariationS()); }
if (lcArc->data().optimum()!=lcArc->data().minimum()) { lcShrinkS->push_back(clVariation<tuGraph>()); lcShrinkS->back().arcs()=new_object(cpArcS()); lcShrinkS->back().arcs()->push_back(lcArc); lcShrinkS->back().cost()=lcArc->data().shrinkingCost(); lcShrinkS->back().available()=lcArc->data().optimum()-lcArc->data().minimum(); }
if (lcArc->data().optimum()!=lcArc->data().maximum()) { lcStretchS->push_back(clVariation<tuGraph>()); lcStretchS->back().arcs()=new_object(cpArcS()); lcStretchS->back().arcs()->push_back(lcArc); lcStretchS->back().cost()=lcArc->data().stretchingCost(); lcStretchS->back().available()=lcArc->data().maximum()-lcArc->data().optimum(); }
lcTreeS.pop_back(); lcStateS.pop_back(); lcShrinkD.pop_back(); lcStretchD.pop_back(); lcOptimumS.pop_back(); if (agTension!=nil) lcTensionS.pop_back(); if (agFlow!=nil) lcFlowS.pop_back(); }
// Left Member Of An SP-Operation // else { lcTreeS.push_back(&(lcTree->left())); lcStateS.push_back(0); lcShrinkD.push_back(nil); lcStretchD.push_back(nil); lcOptimumS.push_back(0.0); if (agTension!=nil) lcTensionS.push_back(0.0); if (agFlow!=nil) lcFlowS.push_back(0.0); }
break;
case 2: // Right Member Of An SP-Operation // lcShrinkD.back()=lcShrinkS; lcStretchD.back()=lcStretchS; lcOptimumS.back()=lcOptimum; if (agTension!=nil) lcTensionS.back()=lcTension; if (agFlow!=nil) lcFlowS.back()=lcFlow;
lcTreeS.push_back(&(lcTree->right())); lcStateS.push_back(0); lcShrinkD.push_back(nil); lcStretchD.push_back(nil); lcOptimumS.push_back(0.0); if (agTension!=nil) lcTensionS.push_back(0.0); if (agFlow!=nil) lcFlowS.push_back(0.0); break;
default: // Preparation To SP-Fusion // lcShrink1S=lcShrinkD.back(); lcStretch1S=lcStretchD.back(); lcOptimum1=lcOptimumS.back(); if (agTension!=nil) lcTension1=lcTensionS.back(); if (agFlow!=nil) lcFlow1=lcFlowS.back(); lcShrink2S=lcShrinkS; lcStretch2S=lcStretchS; lcOptimum2=lcOptimum; lcTension2=lcTension; lcFlow2=lcFlow;
if (lcTree==&agTree) { lcShrinkS=&agShrinkS; lcStretchS=&agStretchS; } else { lcShrinkS=new_object(cpVariationS()); lcStretchS=new_object(cpVariationS()); }
// Serial Fusion // if (lcTree->data().operation()==cpSerialParallelData::serial) { lcOptimum=lcOptimum1+lcOptimum2; lcTension=lcTension1+lcTension2; lcFlow=lcFlow1;
mergeSerialVariations(*lcShrinkS,lcShrink1S->begin(),lcShrink1S->end(), lcShrink2S->begin(),lcShrink2S->end());
mergeSerialVariations(*lcStretchS,lcStretch1S->begin(),lcStretch1S->end(), lcStretch2S->begin(),lcStretch2S->end());
lcIteration+=2; }
// Parallel Fusion // else { if (mergeParallelArcs(*lcShrinkS,*lcStretchS,*lcShrink1S,*lcStretch1S,*lcShrink2S, *lcStretch2S,lcOptimum1,lcOptimum2,(agTension==nil))) { lcIteration+=6; lcOptimum=lcOptimum1; lcTension=lcTension1; lcFlow=lcFlow1+lcFlow2; } else lcIteration=-1; }
// Cleaning And Stack Update // delete_object(lcShrink1S); delete_object(lcShrink2S); delete_object(lcStretch1S); delete_object(lcStretch2S); lcTreeS.pop_back(); lcStateS.pop_back(); lcShrinkD.pop_back(); lcStretchD.pop_back(); lcOptimumS.pop_back(); if (agTension!=nil) lcTensionS.pop_back(); if (agFlow!=nil) lcFlowS.pop_back(); } }
// Termination // if (lcIteration==-1) { delete_object(lcShrinkS); delete_object(lcStretchS); } else { agOptimum=lcOptimum; if (agTension!=nil) *agTension=lcTension; if (agFlow!=nil) *agFlow=lcFlow; }
return (lcIteration); } //-----------------------------------------------------------------------------------ImproveBalance template <tdGraph,class prIterator> inline tyInteger improveBalance(prIterator & agCurrentShrink,const prIterator agLastShrink, prIterator & agCurrentStretch,const prIterator agLastStretch, std_deque(clVariation<tuGraph>) & agNewShrinkS, std_deque(clVariation<tuGraph>) & agNewStretchS, tyReal & agLastDecrease,tyReal & agLastIncrease, tyReal & agOptimum1,tyReal & agOptimum2,tyBoolean agTensionAdjusted) { tyReal lcAvailable1; tyReal lcAvailable2; tyReal lcCost1; tyReal lcCost2; tyReal lcMax;
if (agCurrentStretch==agLastStretch) { lcCost1=realMax(); lcAvailable1=realMax(); } else { lcCost1=(*agCurrentStretch).cost(); lcAvailable1=(*agCurrentStretch).available(); }
if (agCurrentShrink==agLastShrink) { lcCost2=realMax(); lcAvailable2=realMax(); } else { lcCost2=(*agCurrentShrink).cost(); lcAvailable2=(*agCurrentShrink).available(); }
if (lcCost1==realMax() and lcCost2==realMax()) return (-1);
if (lcCost1<lcCost2) { lcMax=mini(lcAvailable1,agOptimum2-agOptimum1); agOptimum1+=lcMax; if (agLastIncrease==0.0) agLastIncrease=(*agCurrentStretch).available(); (*agCurrentStretch).increaseTension(lcMax,agTensionAdjusted);
if ((*agCurrentStretch).available()==0.0) { (*agCurrentStretch).available()=agLastIncrease; (*agCurrentStretch).cost()*=-1.0; agNewShrinkS.push_back(*agCurrentStretch); agCurrentStretch++; agLastIncrease=0.0; } } else { lcMax=mini(lcAvailable2,agOptimum2-agOptimum1); agOptimum2-=lcMax; if (agLastDecrease==0.0) agLastDecrease=(*agCurrentShrink).available(); (*agCurrentShrink).decreaseTension(lcMax,agTensionAdjusted);
if ((*agCurrentShrink).available()==0.0) { (*agCurrentShrink).available()=agLastDecrease; (*agCurrentShrink).cost()*=-1.0; agNewStretchS.push_back(*agCurrentShrink); agCurrentShrink++; agLastDecrease=0.0; } }
return (0); } //--------------------------------------------------------------------------------MergeParallelArcs template <tdGraph> tyBoolean mergeParallelArcs(std_deque(clVariation<tuGraph>) & agShrinkS, std_deque(clVariation<tuGraph>) & agStretchS, std_deque(clVariation<tuGraph>) & agShrink1S, std_deque(clVariation<tuGraph>) & agStretch1S, std_deque(clVariation<tuGraph>) & agShrink2S, std_deque(clVariation<tuGraph>) & agStretch2S, tyReal & agOptimum1,tyReal & agOptimum2,tyBoolean agTensionAdjusted) { typedef clVariation<tuGraph> cpVariation; typedef std_deque(cpVariation) cpVariationS; typedef typename cpVariationS::iterator cpIterator;
cpVariationS lcNewShrink1S; cpVariationS lcNewShrink2S; cpVariationS lcNewStretch1S; cpVariationS lcNewStretch2S; cpVariationS lcShrink1S; cpVariationS lcShrink2S; cpVariationS lcStretch1S; cpVariationS lcStretch2S; cpVariationS lcTempoShrink1S; cpVariationS lcTempoShrink2S; cpVariationS lcTempoStretch1S; cpVariationS lcTempoStretch2S; cpVariation lcVariation;
tyReal lcLastDecrease1 = 0.0; tyReal lcLastDecrease2 = 0.0; tyReal lcLastIncrease1 = 0.0; tyReal lcLastIncrease2 = 0.0;
cpIterator lcCurrentShrink1 = agShrink1S.begin(); cpIterator lcCurrentShrink2 = agShrink2S.begin(); cpIterator lcCurrentStretch1 = agStretch1S.begin(); cpIterator lcCurrentStretch2 = agStretch2S.begin();
while (agOptimum1!=agOptimum2) { if (agOptimum1<agOptimum2) { if (improveBalance(lcCurrentShrink2,agShrink2S.end(),lcCurrentStretch1,agStretch1S.end(), lcNewShrink1S,lcNewStretch2S,lcLastDecrease2,lcLastIncrease1,agOptimum1, agOptimum2,agTensionAdjusted)==-1) { clean(agShrink1S); clean(agShrink2S); clean(agStretch1S); clean(agStretch2S); return (false); } } else { if (improveBalance(lcCurrentShrink1,agShrink1S.end(),lcCurrentStretch2,agStretch2S.end(), lcNewShrink2S,lcNewStretch1S,lcLastDecrease1,lcLastIncrease2,agOptimum2, agOptimum1,agTensionAdjusted)==-1) { clean(agShrink1S); clean(agShrink2S); clean(agStretch1S); clean(agStretch2S); return (false); } } }
if (lcLastIncrease1!=0.0) { lcVariation=*lcCurrentStretch1; lcVariation.copyArcs(*lcCurrentStretch1); lcVariation.available()=lcLastIncrease1-(*lcCurrentStretch1).available(); lcVariation.cost()*=-1.0; lcNewShrink1S.push_back(lcVariation); }
if (lcLastIncrease2!=0.0) { lcVariation=*lcCurrentStretch2; lcVariation.copyArcs(*lcCurrentStretch2); lcVariation.available()=lcLastIncrease2-(*lcCurrentStretch2).available(); lcVariation.cost()*=-1.0; lcNewShrink2S.push_back(lcVariation); }
if (lcLastDecrease1!=0.0) { lcVariation=*lcCurrentShrink1; lcVariation.copyArcs(*lcCurrentShrink1); lcVariation.available()=lcLastDecrease1-(*lcCurrentShrink1).available(); lcVariation.cost()*=-1.0; lcNewStretch1S.push_back(lcVariation); }
if (lcLastDecrease2!=0.0) { lcVariation=*lcCurrentShrink2; lcVariation.copyArcs(*lcCurrentShrink2); lcVariation.available()=lcLastDecrease2-(*lcCurrentShrink2).available(); lcVariation.cost()*=-1.0; lcNewStretch2S.push_back(lcVariation); }
mergeSerialVariations(lcTempoShrink1S,lcNewShrink1S.rbegin(),lcNewShrink1S.rend(), lcCurrentShrink1,agShrink1S.end());
mergeSerialVariations(lcTempoShrink2S,lcNewShrink2S.rbegin(),lcNewShrink2S.rend(), lcCurrentShrink2,agShrink2S.end());
mergeSerialVariations(lcTempoStretch1S,lcNewStretch1S.rbegin(),lcNewStretch1S.rend(), lcCurrentStretch1,agStretch1S.end());
mergeSerialVariations(lcTempoStretch2S,lcNewStretch2S.rbegin(),lcNewStretch2S.rend(), lcCurrentStretch2,agStretch2S.end());
mergeParallelVariations(agShrinkS,lcTempoShrink1S,lcTempoShrink2S); mergeParallelVariations(agStretchS,lcTempoStretch1S,lcTempoStretch2S);
return (true); } //--------------------------------------------------------------------------MergeParallelVariations template <tdGraph> void mergeParallelVariations(std_deque(clVariation<tuGraph>) & agFusion, std_deque(clVariation<tuGraph>) & agList1, std_deque(clVariation<tuGraph>) & agList2) { typedef typename std_deque(clVariation<tuGraph>)::iterator cpIterator;
clVariation<tuGraph> lcVariation;
cpIterator lcCurrentVariation1 = agList1.begin(); cpIterator lcCurrentVariation2 = agList2.begin(); cpIterator lcLastVariation1 = agList1.end(); cpIterator lcLastVariation2 = agList2.end();
while (lcCurrentVariation1!=lcLastVariation1 and lcCurrentVariation2!=lcLastVariation2) { if ((*lcCurrentVariation1).available()<(*lcCurrentVariation2).available()) { lcVariation=*lcCurrentVariation1; lcVariation.addArcs(*lcCurrentVariation2); lcVariation.cost()+=(*lcCurrentVariation2).cost(); (*lcCurrentVariation2).available()-=lcVariation.available(); lcCurrentVariation1++; } else { lcVariation=*lcCurrentVariation2; lcVariation.addArcs(*lcCurrentVariation1); lcVariation.cost()+=(*lcCurrentVariation1).cost(); (*lcCurrentVariation1).available()-=lcVariation.available();
if ((*lcCurrentVariation1).available()==0.0) { delete_object((*lcCurrentVariation1).arcs()); lcCurrentVariation1++; }
lcCurrentVariation2++; }
agFusion.push_back(lcVariation); }
while (lcCurrentVariation1!=lcLastVariation1) { delete_object((*lcCurrentVariation1).arcs()); lcCurrentVariation1++; }
while (lcCurrentVariation2!=lcLastVariation2) { delete_object((*lcCurrentVariation2).arcs()); lcCurrentVariation2++; } } //----------------------------------------------------------------------------MergeSerialVariations template <tdGraph,class prIterator1,class prIterator2> void mergeSerialVariations(std_deque(clVariation<tuGraph>) & agFusion, prIterator1 agCurrentVariation1,const prIterator1 agLastVariation1, prIterator2 agCurrentVariation2,const prIterator2 agLastVariation2) { while (agCurrentVariation1!=agLastVariation1 and agCurrentVariation2!=agLastVariation2) { if ((*agCurrentVariation1).cost()<(*agCurrentVariation2).cost()) { agFusion.push_back(*agCurrentVariation1); agCurrentVariation1++; } else { agFusion.push_back(*agCurrentVariation2); agCurrentVariation2++; } }
while (agCurrentVariation1!=agLastVariation1) { agFusion.push_back(*agCurrentVariation1); agCurrentVariation1++; }
while (agCurrentVariation2!=agLastVariation2) { agFusion.push_back(*agCurrentVariation2); agCurrentVariation2++; } } //-------------------------------------------------------------------------------CreatePiecewiseArc template <tdGraph> clPiecewiseArc * createPiecewiseArc(clPiecewiseGraph & agGraph,clTreeInfo<tuGraph> & agTreeInfo, clNode<tuGraph> & agSource,clNode<tuGraph> & agTarget, tyReal agOptimum,tyBoolean agTensionAdjusted) { typedef std_map(clPiecewiseArc *,tyInteger) clCycle; typedef clCycle::const_iterator clArcIterator;
clArcIterator lcCurrentArc; clCycle lcCycle; clArcIterator lcLastArc;
clPiecewiseArc * lcArc = new_object(clPiecewiseArc(agGraph,agGraph.getNewArcKey(), clPiecewiseArcData(),agSource.key(),agTarget.key()));
tyCardinal lcCounter = agTreeInfo.shrinkCosts.size(); tyReal lcTension = agOptimum;
// Shrinking Cost // lcArc->data().optimum()=agOptimum; lcArc->data().expected()=agOptimum; lcArc->data().update();
while (lcCounter>0) { --lcCounter; lcTension-=agTreeInfo.shrinkCosts[lcCounter].available();
lcArc->data().shrinkingCosts().push_back( standard::make_pair(agTreeInfo.shrinkCosts[lcCounter].available(), agTreeInfo.shrinkCosts[lcCounter].cost())); }
// Stretching Cost // lcArc->data().minimum()=lcTension; lcTension=agOptimum; lcCounter=agTreeInfo.stretchCosts.size();
while (lcCounter>0) { --lcCounter; lcTension+=agTreeInfo.stretchCosts[lcCounter].available();
lcArc->data().stretchingCosts().push_back( standard::make_pair(agTreeInfo.stretchCosts[lcCounter].available(), agTreeInfo.stretchCosts[lcCounter].cost())); }
lcArc->data().maximum()=lcTension; lcArc->data().flow()=0.0;
// Tension Adjusting // if (agTensionAdjusted and findCycle(*lcArc,lcCycle)) { lcCurrentArc=lcCycle.begin(); lcLastArc=lcCycle.end(); lcTension=0.0;
while (lcCurrentArc!=lcLastArc) { if ((*lcCurrentArc).second==+1) { if ((*lcCurrentArc).first!=lcArc) lcTension-=(*lcCurrentArc).first->data().tension(); } else lcTension+=(*lcCurrentArc).first->data().tension();
++lcCurrentArc; }
lcArc->data().tension()=lcTension; lcArc->data().update(); }
return (lcArc); } //----------------------------------------------------------------------------------DisintegrateArc template <tdGraph> void disintegrateArc(clBinaryTree<clSerialParallelData<tuGraph> > & agTree, clPiecewiseGraph & agGraph, clNode<tuGraph> ** agSource,clNode<tuGraph> ** agTarget, std_map(clNode<tuGraph> *, clBinaryTree<clSerialParallelData<tuGraph> > *) & agTreeX, tyBoolean agBackToOriginalGraph) { clPiecewiseArc * lcArc; clNode<tuGraph> * lcMiddle;
if (agTree.data().operation()==clSerialParallelData<tuGraph>::none) { lcArc=&(agGraph.arc(agTree.data().arc()->key()));
if (agBackToOriginalGraph) { lcArc->setSourceNode(&(agGraph.node(agTree.data().arc()->sourceNode()->key()))); lcArc->setTargetNode(&(agGraph.node(agTree.data().arc()->targetNode()->key()))); }
lcArc->data().tension()=agTree.data().arc()->data().tension(); lcArc->data().flow()=agTree.data().arc()->data().flow(); } else { disintegrateArc(agTree.left(),agGraph,agSource,&lcMiddle,agTreeX,agBackToOriginalGraph); agTreeX.erase(lcMiddle); disintegrateArc(agTree.right(),agGraph,&lcMiddle,agTarget,agTreeX,agBackToOriginalGraph); } } //-----------------------------------------------------------------------------------------FindFlow template <tdGraph> void findFlow(clBinaryTree<clSerialParallelData<tuGraph> > & agTree, tyReal & agMainFlow) { typedef std_vector(clArc<tuGraph> *) cpArcS; typedef clSerialParallelData<tuGraph> cpSerialParallelData; typedef clBinaryTree<cpSerialParallelData> cpTree; typedef std_vector(cpTree *) cpTreeS; typedef std_vector(tyCardinal) clCardinalS; typedef std_vector(tyReal) clRealS; typedef std_deque(clVariation<tuGraph>) cpVariationS; typedef std_vector(cpVariationS *) cpVariationD;
tyReal lcFlow1; tyReal lcFlow2; clRealS lcFlowS; clCardinalS lcStateS; cpTree * lcTree; cpTreeS lcTreeS; cpVariationS * lcVariation1S; cpVariationS * lcVariation2S; cpVariationD lcVariationD;
tyReal lcFlow = 0.0; cpVariationS * lcVariationS = nil;
if (not agTree.empty()) { lcTreeS.push_back(&agTree); lcStateS.push_back(0); lcFlowS.push_back(0.0); lcVariationD.push_back(nil);
while (lcTreeS.size()>0) { lcTree=lcTreeS.back();
switch(++(lcStateS.back())) { case 1: // Single Arc // if (lcTree->data().operation()==cpSerialParallelData::none) { lcFlow=minimumFlow(*(lcTree->data().arc())); lcFlow2=maximumFlow(*(lcTree->data().arc())); lcTree->data().arc()->data().flow()=lcFlow; lcVariationS=new_object(cpVariationS());
if (lcFlow==realMin()) { lcVariationS->push_back(clVariation<tuGraph>()); lcVariationS->back().arcs()=new_object(cpArcS()); lcVariationS->back().arcs()->push_back(lcTree->data().arc()); lcVariationS->back().infinity()=true;
if (lcFlow2==realMax()) lcVariationS->back().available()=0.0; else { lcVariationS->back().available()=lcFlow2; lcFlow2=0.0; }
lcTree->data().arc()->data().flow()=lcVariationS->back().available(); } else lcFlow2-=lcFlow;
if (lcFlow2>0.0) { lcVariationS->push_back(clVariation<tuGraph>()); lcVariationS->back().arcs()=new_object(cpArcS()); lcVariationS->back().arcs()->push_back(lcTree->data().arc()); lcVariationS->back().available()=lcFlow2; }
lcTreeS.pop_back(); lcStateS.pop_back(); lcFlowS.pop_back(); lcVariationD.pop_back(); }
// Left Member Of An SP-Operation // else { lcTreeS.push_back(&(lcTree->left())); lcStateS.push_back(0); lcFlowS.push_back(0.0); lcVariationD.push_back(nil); }
break;
case 2: // Right Member Of An SP-Operation // lcVariationD.back()=lcVariationS; lcFlowS.back()=lcFlow; lcTreeS.push_back(&(lcTree->right())); lcStateS.push_back(0); lcFlowS.push_back(0.0); lcVariationD.push_back(nil); break;
default: // Preparation To SP-Fusion // lcFlow1=lcFlowS.back(); lcFlow2=lcFlow; lcVariation1S=lcVariationD.back(); lcVariation2S=lcVariationS; lcVariationS=new_object(cpVariationS());
// Serial Fusion // if (lcTree->data().operation()==cpSerialParallelData::serial) { if (lcFlow1<lcFlow2) increaseFlow(*lcVariation1S,lcFlow1,lcFlow2); else if (lcFlow1>lcFlow2) increaseFlow(*lcVariation2S,lcFlow2,lcFlow1);
mergeSerialFlows(*lcVariationS,*lcVariation1S,*lcVariation2S); lcFlow=lcFlow1; }
// Parallel Fusion // else { mergeParallelFlows(*lcVariationS,*lcVariation1S,*lcVariation2S,lcFlow1,lcFlow2); lcFlow=(lcFlow1==realMin() or lcFlow2==realMin() ? realMin() : lcFlow1+lcFlow2); }
// Cleaning And Stack Update // delete_object(lcVariation1S); delete_object(lcVariation2S); lcTreeS.pop_back(); lcStateS.pop_back(); lcFlowS.pop_back(); lcVariationD.pop_back(); } }
// Adjusting To Main Flow // increaseFlow(*lcVariationS,lcFlow,agMainFlow); clean(*lcVariationS); delete_object(lcVariationS); } } //-------------------------------------------------------------------------------------IncreaseFlow template <tdGraph> void increaseFlow(std_deque(clVariation<tuGraph>) & agVariationS, tyReal & agOldFlow,tyReal agNewFlow) { method_name("increaseFlow");
tyCardinal lcCounter; tyReal lcIncrement; tyReal lcMaximum;
if (agNewFlow!=realMin() and agOldFlow<agNewFlow) { if (agOldFlow==realMin()) { if (agVariationS.size()==0 or not agVariationS.front().infinity()) send_error(erNotEnoughAvailableFlow);
lcMaximum=agVariationS.front().available(); lcIncrement=mini(lcMaximum,agNewFlow); lcIncrement=lcMaximum-lcIncrement; lcCounter=agVariationS.front().arcs()->size();
while (lcCounter>0) { --lcCounter; (*(agVariationS.front().arcs()))[lcCounter]->data().flow()-=lcIncrement; }
agVariationS.front().available()=lcIncrement; agVariationS.front().infinity()=false; agOldFlow=lcMaximum-lcIncrement;
if (agVariationS.front().available()==0.0) { delete_object(agVariationS.front().arcs()); agVariationS.pop_front(); } }
while (agOldFlow<agNewFlow) { if (agVariationS.size()==0) send_error(erNotEnoughAvailableFlow); lcIncrement=mini(agNewFlow-agOldFlow,agVariationS.front().available()); lcCounter=agVariationS.front().arcs()->size();
while (lcCounter>0) { --lcCounter; (*(agVariationS.front().arcs()))[lcCounter]->data().flow()+=lcIncrement; }
agVariationS.front().available()-=lcIncrement;
if (agVariationS.front().available()==0.0) { delete_object(agVariationS.front().arcs()); agVariationS.pop_front(); }
agOldFlow+=lcIncrement; } } } //--------------------------------------------------------------------------------------MakeConform template <class prConformity,class prDirectMintyColor,class prInverseMintyColor> tyInteger makeConform(clPiecewiseArc ** agArcS,tyCardinal & agCounter,prConformity & agConformity, prDirectMintyColor & agDirectMintyColor, prInverseMintyColor & agInverseMintyColor) { clPiecewiseArc * lcArc;
clPiecewiseArc ** lcArcS = new_array(clPiecewiseArc *,agCounter); clPiecewiseArc ** lcArc2S = lcArcS; tyCardinal lcCounter = 0; tyInteger lcIteration = 0;
try { while (agCounter>0) { standard::swap(agArcS,lcArcS); standard::swap(lcCounter,agCounter);
while (lcCounter>0) { --lcCounter; lcArc=lcArcS[lcCounter];
if (not agConformity.conformedArc(*lcArc)) { ++lcIteration;
graphProblemMinCostTensionConforming_private:: improveArc(*lcArc,agDirectMintyColor,agInverseMintyColor,agConformity);
agArcS[agCounter]=lcArc; ++agCounter; } } } }
catch (ctError &) { delete_array(lcArc2S); return (-1); }
delete_array(lcArc2S); return (lcIteration); } //-------------------------------------------------------------------------------MergeParallelFlows template <tdGraph> void mergeParallelFlows(std_deque(clVariation<tuGraph>) & agFusion, std_deque(clVariation<tuGraph>) & agVariation1S, std_deque(clVariation<tuGraph>) & agVariation2S, tyReal agFlow1,tyReal agFlow2) { typedef typename std_deque(clVariation<tuGraph>)::const_iterator cpIterator;
cpIterator lcCurrentVariation1 = agVariation1S.begin(); cpIterator lcCurrentVariation2 = agVariation2S.begin(); cpIterator lcLastVariation1 = agVariation1S.end(); cpIterator lcLastVariation2 = agVariation2S.end();
tyBoolean lcInfinity1 = false; tyBoolean lcInfinity2 = false;
if (lcCurrentVariation1!=lcLastVariation1) lcInfinity1=(*lcCurrentVariation1).infinity(); if (lcCurrentVariation2!=lcLastVariation2) lcInfinity2=(*lcCurrentVariation2).infinity();
if (lcInfinity1) { agFusion.push_back(*lcCurrentVariation1); ++lcCurrentVariation1;
if (lcInfinity2) { agFusion.back().available()+=(*lcCurrentVariation2).available(); delete_object((*lcCurrentVariation2).arcs()); ++lcCurrentVariation2; } else agFusion.back().available()+=agFlow2; } else if (lcInfinity2) { agFusion.push_back(*lcCurrentVariation2); ++lcCurrentVariation2; agFusion.back().available()+=agFlow1; }
while (lcCurrentVariation1!=lcLastVariation1) { agFusion.push_back(*lcCurrentVariation1); ++lcCurrentVariation1; }
while (lcCurrentVariation2!=lcLastVariation2) { agFusion.push_back(*lcCurrentVariation2); ++lcCurrentVariation2; } } //---------------------------------------------------------------------------------MergeSerialFlows template <tdGraph> void mergeSerialFlows(std_deque(clVariation<tuGraph>) & agFusion, std_deque(clVariation<tuGraph>) & agVariation1S, std_deque(clVariation<tuGraph>) & agVariation2S) { method_name("mergeSerialFlows");
typedef typename std_deque(clVariation<tuGraph>)::iterator cpIterator;
tyCardinal lcCounter; tyReal lcIncrement; clVariation<tuGraph> lcVariation;
cpIterator lcCurrentVariation1 = agVariation1S.begin(); cpIterator lcCurrentVariation2 = agVariation2S.begin(); cpIterator lcLastVariation1 = agVariation1S.end(); cpIterator lcLastVariation2 = agVariation2S.end();
tyBoolean lcInfinity1 = false; tyBoolean lcInfinity2 = false;
if (lcCurrentVariation1!=lcLastVariation1) lcInfinity1=(*lcCurrentVariation1).infinity(); if (lcCurrentVariation2!=lcLastVariation2) lcInfinity2=(*lcCurrentVariation2).infinity();
if ((lcInfinity1 and not lcInfinity2) or (not lcInfinity1 and lcInfinity2)) send_error(erNotEnoughAvailableFlow);
if (lcInfinity1) { lcIncrement=(*lcCurrentVariation1).available()-(*lcCurrentVariation2).available();
if (lcIncrement<0.0) { agFusion.push_back(*lcCurrentVariation1); agFusion.back().addArcs(*lcCurrentVariation2); lcCounter=(*lcCurrentVariation2).arcs()->size();
while (lcCounter>0) { --lcCounter; (*((*lcCurrentVariation2).arcs()))[lcCounter]->data().flow()+=lcIncrement; }
(*lcCurrentVariation2).available()=-lcIncrement; (*lcCurrentVariation2).infinity()=false; ++lcCurrentVariation1; } else { agFusion.push_back(*lcCurrentVariation2); agFusion.back().addArcs(*lcCurrentVariation1);
if (lcIncrement==0.0) { delete_object((*lcCurrentVariation1).arcs()); ++lcCurrentVariation1; } else { lcCounter=(*lcCurrentVariation1).arcs()->size();
while (lcCounter>0) { --lcCounter; (*((*lcCurrentVariation1).arcs()))[lcCounter]->data().flow()-=lcIncrement; }
(*lcCurrentVariation1).available()=lcIncrement; (*lcCurrentVariation1).infinity()=false; }
++lcCurrentVariation2; } }
while (lcCurrentVariation1!=lcLastVariation1 and lcCurrentVariation2!=lcLastVariation2) { if ((*lcCurrentVariation1).available()<0.0) send_error(erNotEnoughAvailableFlow); if ((*lcCurrentVariation2).available()<0.0) send_error(erNotEnoughAvailableFlow);
if ((*lcCurrentVariation1).available()<(*lcCurrentVariation2).available()) { agFusion.push_back(*lcCurrentVariation1); agFusion.back().addArcs(*lcCurrentVariation2); (*lcCurrentVariation2).available()-=(*lcCurrentVariation1).available(); ++lcCurrentVariation1; } else { agFusion.push_back(*lcCurrentVariation2); agFusion.back().addArcs(*lcCurrentVariation1); (*lcCurrentVariation1).available()-=(*lcCurrentVariation2).available(); ++lcCurrentVariation2;
if ((*lcCurrentVariation1).available()==0.0) { delete_object((*lcCurrentVariation1).arcs()); ++lcCurrentVariation1; } } }
while (lcCurrentVariation1!=lcLastVariation1) { delete_object((*lcCurrentVariation1).arcs()); ++lcCurrentVariation1; }
while (lcCurrentVariation2!=lcLastVariation2) { delete_object((*lcCurrentVariation2).arcs()); ++lcCurrentVariation2; } } //--------------------------------------------------------------------------------------UpdateCosts template <tdGraph> void updateCosts(clTreeInfo<tuGraph> & agTreeInfo) { tyReal lcIncrement;
tyReal lcNewTension = agTreeInfo.arc->data().tension(); tyReal lcOldTension = agTreeInfo.arc->data().optimum();
// Increase Tension // if (lcOldTension<lcNewTension) { while (lcOldTension<lcNewTension) { lcIncrement=mini(lcNewTension-lcOldTension,agTreeInfo.stretchCosts.front().available()); lcOldTension+=lcIncrement; agTreeInfo.shrinkCosts.push_front(agTreeInfo.stretchCosts.front()); agTreeInfo.shrinkCosts.front().cost()*=-1;
if (lcIncrement<agTreeInfo.stretchCosts.front().available()) { agTreeInfo.shrinkCosts.front().available()=lcIncrement; agTreeInfo.shrinkCosts.front().copyArcs(agTreeInfo.stretchCosts.front()); agTreeInfo.stretchCosts.front().available()-=lcIncrement; } else agTreeInfo.stretchCosts.pop_front(); } }
// Decrease Tension // else { while (lcOldTension>lcNewTension) { lcIncrement=mini(lcOldTension-lcNewTension,agTreeInfo.shrinkCosts.front().available()); lcOldTension-=lcIncrement; agTreeInfo.stretchCosts.push_front(agTreeInfo.shrinkCosts.front()); agTreeInfo.stretchCosts.front().cost()*=-1;
if (lcIncrement<agTreeInfo.shrinkCosts.front().available()) { agTreeInfo.stretchCosts.front().available()=lcIncrement; agTreeInfo.stretchCosts.front().copyArcs(agTreeInfo.shrinkCosts.front()); agTreeInfo.shrinkCosts.front().available()-=lcIncrement; } else agTreeInfo.shrinkCosts.pop_front(); } } } //------------------------------------------------------------------------------------UpdateTension template <tdGraph> void updateTension(clTreeInfo<tuGraph> & agTreeInfo) { method_name("updateTension");
std_vector(clArc<tuGraph> *) * lcArcS; tyCardinal lcCounter2; tyReal lcIncrement; tyCardinal lcSize;
tyCardinal lcCounter1 = 0; tyReal lcNewTension = agTreeInfo.arc->data().tension(); tyReal lcOldTension = agTreeInfo.tension;
// Increase Tension // if (lcOldTension<lcNewTension) { while (lcOldTension<lcNewTension) { if (lcCounter1==agTreeInfo.stretchCosts.size()) send_error(erNotEnoughAvailableTension); lcIncrement=mini(lcNewTension-lcOldTension,agTreeInfo.stretchCosts[lcCounter1].available()); lcArcS=agTreeInfo.stretchCosts[lcCounter1].arcs(); lcSize=(lcArcS==nil ? 0 : lcArcS->size()); lcCounter2=0;
while (lcCounter2<lcSize) { (*lcArcS)[lcCounter2]->data().tension()+=lcIncrement; ++lcCounter2; }
++lcCounter1; lcOldTension+=lcIncrement; } }
// Decrease Tension // else { while (lcOldTension>lcNewTension) { if (lcCounter1==agTreeInfo.shrinkCosts.size()) send_error(erNotEnoughAvailableTension); lcIncrement=mini(lcOldTension-lcNewTension,agTreeInfo.shrinkCosts[lcCounter1].available()); lcArcS=agTreeInfo.shrinkCosts[lcCounter1].arcs(); lcSize=(lcArcS==nil ? 0 : lcArcS->size()); lcCounter2=0;
while (lcCounter2<lcSize) { (*lcArcS)[lcCounter2]->data().tension()-=lcIncrement; ++lcCounter2; }
++lcCounter1; lcOldTension-=lcIncrement; } } } }
// S o l v e A l g o I Implementation //----------------------------------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clSolveAlgoI */ /* Solves the minimum cost tension problem of a graph by decomposing the graph into serial-parallel components, using the method given as argument, or directly if serial-parallel components are given (default is not). The number of components obtained can be displayed (default is not). */ template <tdGraph> tyInteger clSolveAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph, const clDecomposeAlgo<tuGraph> & agDecomposeAlgo, std_vector(clBinaryTree<clSerialParallelData<tuGraph> > *) * agComponentS, tyBoolean agDisplayed) const { typedef clNode<tuGraph> cpNode; typedef graphProblemMinCostTensionStructure::clNodeData clNodeData; typedef clBinaryTree<clSerialParallelData<tuGraph> > cpTree; typedef private_area::clTreeInfo<tuGraph> cpTreeInfo;
typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator; typedef typename std_map(cpTree *,cpTreeInfo *)::const_iterator cpInfoIterator; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
clPiecewiseArc * lcArc; tyInteger lcClock; tyReal lcCost; tyCardinal lcCounter1; tyCardinal lcCounter3; cpInfoIterator lcCurrentInfo; cpNode * lcDummyNode; clPiecewiseGraph lcGraph; cpInfoIterator lcLastInfo; tyReal lcLength; std_vector(cpNode *) lcNodeS; tyReal lcOptimum; tyInteger lcReturn; cpNode * lcSourceNode; cpNode * lcTargetNode; cpTree * lcTree1; cpTree * lcTree2; cpTreeInfo * lcTreeInfo; std_map(cpTree *,cpTreeInfo *) lcTreeInfoX; std_vector(cpTree *) lcTreeS; std_map(cpNode *,cpTree *) lcTreeX;
typedef graphProblemMinCostTensionConformingPiecewise_private:: clConformity<clPiecewiseArcData,clNodeData> clConformity;
typedef graphProblemMinCostTensionConforming_private:: clDirectMintyColor<clPiecewiseArcData,clNodeData,clConformity > clDirectMintyColor;
typedef graphProblemMinCostTensionConforming_private:: clInverseMintyColor<clPiecewiseArcData,clNodeData,clConformity > clInverseMintyColor;
clConformity lcConformity; clDirectMintyColor lcDirectMintyColor(lcConformity); clInverseMintyColor lcInverseMintyColor(lcConformity);
tyInteger lcAggregationTime = 0; clPiecewiseArc ** lcArcS = new_array(clPiecewiseArc *,agGraph.arcs().size()); tyInteger lcConformingTime = 0; tyCardinal lcCounter2 = 0; cpArcIterator lcCurrentArc = agGraph.arcs().begin(); cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); tyInteger lcDisintegrationTime = 0; tyInteger lcIteration = 0; cpArcIterator lcLastArc = agGraph.arcs().end(); cpNodeIterator lcLastNode = agGraph.nodes().end();
// Serial-Parallel Decomposition // lcClock=environment::currentClock();
if (agComponentS==nil) agDecomposeAlgo.run(agGraph,lcTreeS); else { lcCounter1=agComponentS->size();
while (lcCounter1>0) { --lcCounter1; lcTreeS.push_back((*agComponentS)[lcCounter1]); } }
lcClock=environment::currentClock()-lcClock;
if (agDisplayed) { environment::out("Components = ",false,true); environment::out(tyCardinal(lcTreeS.size()),true); environment::out("Decomposition Time = ",false,true); environment::out(lcClock,true); }
// Nodes Copy // while (lcCurrentNode!=lcLastNode) { new_object(clPiecewiseNode(lcGraph,(*lcCurrentNode).first,clNodeData())); ++lcCurrentNode; }
// Arcs Copy (With Nil Extremities) // while (lcCurrentArc!=lcLastArc) { lcArc=new_object(clPiecewiseArc(lcGraph,(*lcCurrentArc).first,clPiecewiseArcData(), nilNode(),nilNode()));
lcArc->data().optimum()=(*lcCurrentArc).second->data().optimum(); lcArc->data().tension()=(*lcCurrentArc).second->data().optimum(); lcArc->data().update(); lcArc->data().minimum()=(*lcCurrentArc).second->data().minimum(); lcArc->data().maximum()=(*lcCurrentArc).second->data().maximum(); lcLength=lcArc->data().optimum()-lcArc->data().minimum(); lcCost=(*lcCurrentArc).second->data().shrinkingCost(); lcArc->data().shrinkingCosts().push_back(standard::make_pair(lcLength,lcCost)); lcLength=lcArc->data().maximum()-lcArc->data().optimum(); lcCost=(*lcCurrentArc).second->data().stretchingCost(); lcArc->data().stretchingCosts().push_back(standard::make_pair(lcLength,lcCost)); lcArc->data().flow()=0.0; ++lcCurrentArc; }
// Components Gathering // lcCounter1=lcTreeS.size();
while (lcCounter1>0) { --lcCounter1; lcTree1=lcTreeS[lcCounter1]; lcNodeS.erase(lcNodeS.begin(),lcNodeS.end()); findNodes(*lcTree1,lcNodeS,&lcSourceNode,&lcTargetNode); lcCounter3=lcNodeS.size();
while (lcCounter3>0) { --lcCounter3; lcTreeX.insert(std_make_pair(lcNodeS[lcCounter3],lcTree1)); }
// Arc Disintegration // if (lcTreeX.count(lcSourceNode)>0) { lcTree2=lcTreeX[lcSourceNode]; lcTreeInfo=lcTreeInfoX[lcTree2];
if (lcTreeInfo->aggregated) { if (lcCounter2>0) { lcClock=environment::currentClock();
lcReturn=private_area::makeConform(lcArcS,lcCounter2,lcConformity, lcDirectMintyColor,lcInverseMintyColor);
if (lcReturn==-1) { lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcIteration+=lcReturn; lcConformingTime+=environment::currentClock()-lcClock; }
lcTreeInfo->aggregated=false; lcClock=environment::currentClock(); private_area::updateTension(*lcTreeInfo); private_area::findFlow(*lcTree2,lcTreeInfo->arc->data().flow()); private_area::disintegrateArc(*lcTree2,lcGraph,&lcDummyNode,&lcDummyNode,lcTreeX,true); delete_object(lcTreeInfo->arc); lcDisintegrationTime+=environment::currentClock()-lcClock; } }
if (lcTreeX.count(lcTargetNode)>0) { lcTree2=lcTreeX[lcTargetNode]; lcTreeInfo=lcTreeInfoX[lcTree2];
if (lcTreeInfo->aggregated) { if (lcCounter2>0) { lcClock=environment::currentClock();
lcReturn=private_area::makeConform(lcArcS,lcCounter2,lcConformity, lcDirectMintyColor,lcInverseMintyColor);
if (lcReturn==-1) { lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcIteration+=lcReturn; lcConformingTime+=environment::currentClock()-lcClock; }
lcClock=environment::currentClock(); lcTreeInfo->aggregated=false; private_area::updateTension(*lcTreeInfo); private_area::findFlow(*lcTree2,lcTreeInfo->arc->data().flow()); private_area::disintegrateArc(*lcTree2,lcGraph,&lcDummyNode,&lcDummyNode,lcTreeX,true); delete_object(lcTreeInfo->arc); lcDisintegrationTime+=environment::currentClock()-lcClock; } }
// Aggregated Arc Creation // lcClock=environment::currentClock(); lcTreeInfo=new_object(cpTreeInfo()); lcTreeInfoX.insert(std_make_pair(lcTree1,lcTreeInfo)); lcTreeInfo->aggregated=true;
if (private_area::findMinCostTension(*lcTree1,lcTreeInfo->shrinkCosts, lcTreeInfo->stretchCosts,lcOptimum)==-1) { lcTreeInfoX.erase(lcTree1); delete_object(lcTreeInfo); lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcTreeInfo->arc=private_area::createPiecewiseArc(lcGraph,*lcTreeInfo,*lcSourceNode, *lcTargetNode,lcOptimum,true);
lcTreeInfo->tension=lcOptimum; lcAggregationTime+=environment::currentClock()-lcClock;
// Non-Conform Arcs Listing // lcArcS[lcCounter2]=lcTreeInfo->arc; ++lcCounter2; }
if (lcCounter2>0) { lcClock=environment::currentClock();
lcReturn=private_area::makeConform(lcArcS,lcCounter2,lcConformity, lcDirectMintyColor,lcInverseMintyColor);
if (lcReturn==-1) { lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcIteration+=lcReturn; lcConformingTime+=environment::currentClock()-lcClock; }
lcGraph.solved()=true; lbEnd:
// Remaining Aggregated Arcs Disintegration // lcCurrentInfo=lcTreeInfoX.begin(); lcLastInfo=lcTreeInfoX.end();
while (lcCurrentInfo!=lcLastInfo) { lcTreeInfo=(*lcCurrentInfo).second;
if (lcTreeInfo->aggregated) { if (lcGraph.solved()) { lcTree2=(*lcCurrentInfo).first; lcClock=environment::currentClock(); private_area::updateTension(*lcTreeInfo); private_area::disintegrateArc(*lcTree2,lcGraph,&lcDummyNode,&lcDummyNode,lcTreeX,true); lcDisintegrationTime+=environment::currentClock()-lcClock; }
delete_object(lcTreeInfo->arc); }
private_area::clean(lcTreeInfo->shrinkCosts); private_area::clean(lcTreeInfo->stretchCosts); delete_object(lcTreeInfo); ++lcCurrentInfo; }
// Tension Update In Original Graph // if (lcGraph.solved()) { lcCurrentArc=agGraph.arcs().begin();
while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc).second->data().tension()=lcGraph.arc((*lcCurrentArc).first).data().tension(); ++lcCurrentArc; }
if (agDisplayed) { environment::out("Aggregation Time = ",false,true); environment::out(lcAggregationTime,true); environment::out("Conforming Time = ",false,true); environment::out(lcConformingTime,true); environment::out("Disintegration Time = ",false,true); environment::out(lcDisintegrationTime,true); } }
// Memory Deallocation // delete_array(lcArcS);
if (agComponentS==nil) { lcCounter1=lcTreeS.size();
while (lcCounter1>0) { --lcCounter1; delete_object(lcTreeS[lcCounter1]); } }
agGraph.solved()=lcGraph.solved(); return (lcIteration); } }
// S o l v e A l g o I I Implementation //--------------------------------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clSolveAlgoII */ /* Solves the minimum cost tension problem of a graph by decomposing the graph into serial-parallel components, using the method given as argument, or directly if serial-parallel components are given (default is not). The number of components obtained can be displayed (default is not). */ template <tdGraph> tyInteger clSolveAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph, const clDecomposeAlgo<tuGraph> & agDecomposeAlgo, std_vector(clBinaryTree<clSerialParallelData<tuGraph> > *) * agComponentS, tyBoolean agDisplayed) const { typedef clNode<tuGraph> cpNode; typedef graphProblemMinCostTensionStructure::clNodeData clNodeData; typedef clBinaryTree<clSerialParallelData<tuGraph> > cpTree; typedef private_area::clTreeInfo<tuGraph> cpTreeInfo; typedef std_map(cpTree *,cpTreeInfo *) cpTreeInfoX; typedef std_deque(cpTree *) cpTreeS; typedef std_deque(cpTreeS *) cpTreeD;
typedef typename std_map(cpTree *,cpTreeInfo *)::const_iterator cpInfoIterator; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
tyInteger lcClock; tyCardinal lcCounter1; tyCardinal lcCounter2; tyReal lcFlow; tyReal lcOptimum; tyInteger lcReturn; tyReal lcTension;
cpTreeS lcBreakerS; cpTreeD lcBrokenD; cpTreeS * lcBrokenS; cpTreeS lcComponentS; cpInfoIterator lcCurrentInfo; clPiecewiseGraph lcGraph; cpInfoIterator lcLastInfo; cpTreeD lcPieceD; cpTreeS * lcPieceS; cpNode * lcSourceNode; cpNode * lcTargetNode; cpTree * lcTree1; cpTree * lcTree2; cpTreeInfo * lcTreeInfo; cpTreeInfoX lcTreeInfoX; std_vector(cpTree *) lcTreeS;
typedef graphProblemMinCostTensionConformingPiecewise_private:: clConformity<clPiecewiseArcData,clNodeData> clConformity;
typedef graphProblemMinCostTensionConforming_private:: clDirectMintyColor<clPiecewiseArcData,clNodeData,clConformity > clDirectMintyColor;
typedef graphProblemMinCostTensionConforming_private:: clInverseMintyColor<clPiecewiseArcData,clNodeData,clConformity > clInverseMintyColor;
clConformity lcConformity; clDirectMintyColor lcDirectMintyColor(lcConformity); clInverseMintyColor lcInverseMintyColor(lcConformity);
tyInteger lcAggregationTime = 0; clPiecewiseArc ** lcArcS = new_array(clPiecewiseArc *,agGraph.arcs().size()); tyInteger lcConformingTime = 0; cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); tyCardinal lcCurrentPiece = 0; tyInteger lcDisintegrationTime = 0; tyInteger lcIteration = 0; cpNodeIterator lcLastNode = agGraph.nodes().end(); tyCardinal lcNbArc = 0;
// Serial-Parallel Decomposition // lcClock=environment::currentClock();
if (agComponentS==nil) agDecomposeAlgo.run(agGraph,lcTreeS); else { lcCounter1=agComponentS->size();
while (lcCounter1>0) { --lcCounter1; lcTreeS.push_back((*agComponentS)[lcCounter1]); } }
postDecompose(lcTreeS,lcBreakerS,lcPieceD,lcBrokenD); lcClock=environment::currentClock()-lcClock;
if (agDisplayed) { environment::out("Components = ",false,true); environment::out(tyCardinal(lcTreeS.size()),true); environment::out("Decomposition Time = ",false,true); environment::out(lcClock,true); }
// Nodes Copy // while (lcCurrentNode!=lcLastNode) { new_object(clPiecewiseNode(lcGraph,(*lcCurrentNode).first,clNodeData())); ++lcCurrentNode; }
// Components Gathering // lcCounter1=lcTreeS.size();
while (lcCounter1>0) { --lcCounter1; lcTree1=lcTreeS[lcCounter1];
if (lcBreakerS.size()>0 and lcBreakerS.front()==lcTree1) { // Conforming // if (lcNbArc>0) { lcClock=environment::currentClock();
lcReturn=private_area::makeConform(lcArcS,lcNbArc,lcConformity, lcDirectMintyColor,lcInverseMintyColor);
if (lcReturn==-1) { lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcIteration+=lcReturn; lcConformingTime+=environment::currentClock()-lcClock; }
// Arcs Disintegration // lcBreakerS.pop_front(); lcClock=environment::currentClock(); lcBrokenS=lcBrokenD.front(); lcBrokenD.pop_front();
while (lcBrokenS->size()>0) { lcTree2=lcBrokenS->front(); lcBrokenS->pop_front(); lcTreeInfo=lcTreeInfoX[lcTree2]; private_area::updateTension(*lcTreeInfo); private_area::findFlow(*lcTree2,lcTreeInfo->arc->data().flow()); delete_object(lcTreeInfo->arc); lcTreeInfo->aggregated=false; }
delete_object(lcBrokenS); lcDisintegrationTime+=environment::currentClock()-lcClock;
// Replacement Arcs Creation // lcClock=environment::currentClock(); lcPieceS=lcPieceD[lcCurrentPiece++]; lcCounter2=lcPieceS->size();
while (lcCounter2>0) { --lcCounter2; lcTree2=(*lcPieceS)[lcCounter2]; lcTreeInfo=new_object(cpTreeInfo()); lcTreeInfoX.insert(std_make_pair(lcTree2,lcTreeInfo)); lcTreeInfo->aggregated=true; lcSourceNode=getTreeSourceNode(*lcTree2); lcTargetNode=getTreeTargetNode(*lcTree2);
if (private_area::findMinCostTension(*lcTree2,lcTreeInfo->shrinkCosts, lcTreeInfo->stretchCosts,lcOptimum, &lcTension,&lcFlow)==-1) { lcTreeInfoX.erase(lcTree2); delete_object(lcTreeInfo); lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcTreeInfo->arc=private_area::createPiecewiseArc(lcGraph,*lcTreeInfo,*lcSourceNode, *lcTargetNode,lcOptimum,false);
lcTreeInfo->tension=lcTension; lcTreeInfo->arc->data().expected()=lcTension; lcTreeInfo->arc->data().flow()=lcFlow; lcTreeInfo->arc->data().update(); private_area::updateCosts(*lcTreeInfo); }
lcAggregationTime+=environment::currentClock()-lcClock; }
// Aggregated Arc Creation // lcClock=environment::currentClock(); lcTreeInfo=new_object(cpTreeInfo()); lcTreeInfoX.insert(std_make_pair(lcTree1,lcTreeInfo)); lcTreeInfo->aggregated=true; lcSourceNode=getTreeSourceNode(*lcTree1); lcTargetNode=getTreeTargetNode(*lcTree1);
if (private_area::findMinCostTension(*lcTree1,lcTreeInfo->shrinkCosts, lcTreeInfo->stretchCosts,lcOptimum)==-1) { lcTreeInfoX.erase(lcTree1); delete_object(lcTreeInfo); lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcTreeInfo->arc=private_area::createPiecewiseArc(lcGraph,*lcTreeInfo,*lcSourceNode, *lcTargetNode,lcOptimum,true);
lcTreeInfo->tension=lcOptimum; lcAggregationTime+=environment::currentClock()-lcClock;
// Non-Conform Arcs Listing // lcArcS[lcNbArc]=lcTreeInfo->arc; ++lcNbArc; }
// Conforming // if (lcNbArc>0) { lcClock=environment::currentClock();
lcReturn=private_area::makeConform(lcArcS,lcNbArc,lcConformity, lcDirectMintyColor,lcInverseMintyColor);
if (lcReturn==-1) { lcGraph.solved()=false; lcIteration=-1; goto lbEnd; }
lcIteration+=lcReturn; lcConformingTime+=environment::currentClock()-lcClock; }
lcGraph.solved()=true; lbEnd:
// Remaining Aggregated Arcs Disintegration // lcCurrentInfo=lcTreeInfoX.begin(); lcLastInfo=lcTreeInfoX.end();
while (lcCurrentInfo!=lcLastInfo) { lcTreeInfo=(*lcCurrentInfo).second;
if (lcTreeInfo->aggregated) { if (lcGraph.solved()) { lcTree2=(*lcCurrentInfo).first; lcClock=environment::currentClock(); private_area::updateTension(*lcTreeInfo); lcDisintegrationTime+=environment::currentClock()-lcClock; }
delete_object(lcTreeInfo->arc); }
private_area::clean(lcTreeInfo->shrinkCosts); private_area::clean(lcTreeInfo->stretchCosts); delete_object(lcTreeInfo); ++lcCurrentInfo; }
if (lcGraph.solved()) { if (agDisplayed) { environment::out("Aggregation Time = ",false,true); environment::out(lcAggregationTime,true); environment::out("Conforming Time = ",false,true); environment::out(lcConformingTime,true); environment::out("Disintegration Time = ",false,true); environment::out(lcDisintegrationTime,true); } }
// Memory Deallocation // delete_array(lcArcS);
if (agComponentS==nil) { lcCounter1=lcTreeS.size();
while (lcCounter1>0) { --lcCounter1; delete_object(lcTreeS[lcCounter1]); } }
lcCounter1=lcPieceD.size();
while (lcCounter1>0) { --lcCounter1; lcPieceS=lcPieceD[lcCounter1]; lcCounter2=lcPieceS->size();
while (lcCounter2>0) { --lcCounter2; delete_object((*lcPieceS)[lcCounter2]); }
delete_object(lcPieceS); }
agGraph.solved()=lcGraph.solved(); return (lcIteration); } }
// S o l v e S e r i a l P a r a l l e l A l g o Implementation //--------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clSolveSerialParallelAlgo */ /* Solves the minimum cost tension problem of a graph. */ template <tdGraph> tyInteger clSolveSerialParallelAlgo<tuGraph>::run(clGraph<tuGraph> & agGraph) const { method_name("solveSerialParallelAlgo::run");
typedef std_vector(clBinaryTree<clSerialParallelData<tuGraph> > *) cpTreeS; typedef std_deque(private_area::clVariation<tuGraph>) cpVariationS;
tyInteger lcIteration; tyReal lcOptimum; cpVariationS lcShrinkS; cpVariationS lcStretchS; cpTreeS lcTreeS;
agGraph.solved()=false; graphProblemSerialParallel::clDecomposeAlgo<tuGraph>::defaultRun(agGraph,lcTreeS); if (lcTreeS.size()!=1) send_error(erNotSerialParallel);
lcIteration=private_area::findMinCostTension(*(lcTreeS[0]),lcShrinkS,lcStretchS,lcOptimum); delete_object(lcTreeS[0]); private_area::clean(lcShrinkS); private_area::clean(lcStretchS); if (lcIteration!=-1) agGraph.solved()=true; return (lcIteration); } }
// V a r i a t i o n Implementation //------------------------------------------------------------- namespace private_area { //------------------------------------------------------------------------------------------AddArcs template <tdGraph> void clVariation<tuGraph>::addArcs(const clVariation<tuGraph> & agVariation) { typedef typename cpArcS::const_iterator cpIterator;
cpIterator lcCurrentArc = agVariation.atArcS->begin(); cpIterator lcLastArc = agVariation.atArcS->end();
if (atArcS==nil) atArcS=new_object(cpArcS());
while (lcCurrentArc!=lcLastArc) { atArcS->push_back(*lcCurrentArc); lcCurrentArc++; } } //-----------------------------------------------------------------------------------------CopyArcs template <tdGraph> void clVariation<tuGraph>::copyArcs(const clVariation<tuGraph> & agVariation) { typedef typename cpArcS::const_iterator cpIterator;
cpIterator lcCurrentArc = agVariation.atArcS->begin(); cpIterator lcLastArc = agVariation.atArcS->end();
atArcS=new_object(cpArcS());
while (lcCurrentArc!=lcLastArc) { atArcS->push_back(*lcCurrentArc); lcCurrentArc++; } } //----------------------------------------------------------------------------------DecreaseTension template <tdGraph> void clVariation<tuGraph>::decreaseTension(tyReal agDecrease,tyBoolean agTensionAdjusted) { method_name("variation::decreaseTension");
typedef typename cpArcS::const_iterator cpIterator;
cpIterator lcCurrentArc; cpIterator lcLastArc;
if (atArcS==nil) send_error(erEmptyArcList);
atAvailable-=agDecrease; if (atAvailable<0.0) send_error(erNotEnoughAvailableTension);
if (agTensionAdjusted) { lcCurrentArc=atArcS->begin(); lcLastArc=atArcS->end();
while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc)->data().tension()-=agDecrease; lcCurrentArc++; } } } //----------------------------------------------------------------------------------IncreaseTension template <tdGraph> void clVariation<tuGraph>::increaseTension(tyReal agIncrease,tyBoolean agTensionAdjusted) { method_name("variation::increaseTension");
typedef typename std_vector(clArc<tuGraph> *)::const_iterator cpIterator;
cpIterator lcCurrentArc; cpIterator lcLastArc;
if (atArcS==nil) send_error(erEmptyArcList);
atAvailable-=agIncrease; if (atAvailable<0.0) send_error(erNotEnoughAvailableTension);
if (agTensionAdjusted) { lcCurrentArc=atArcS->begin(); lcLastArc=atArcS->end();
while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc)->data().tension()+=agIncrease; lcCurrentArc++; } } } }
// 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 // 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.cpp"
// DLL Belonging //--------------------------------------------------------------------------------- #define GRAPH_PROBLEM_MIN_COST_TENSION_DLL
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph_problem/min_cost_tension/aggregation.hpp> /*INTERFACE*/
namespace bpp {
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphProblemMinCostTensionAggregation #define private_area graphProblemMinCostTensionAggregation_private #define dll_export DLL_EXPORT
namespace public_area {} namespace private_area {}
static_module_name("Graph_problem/Min_cost_tension/Aggregation");
// Initialization //-------------------------------------------------------------------------------- #undef iniGraphProblemMinCostTensionAggregation static_constant(private_area::clInitializer,goInitializer);
// Errors //---------------------------------------------------------------------------------------- namespace public_area { static_error erEmptyArcList; static_error erNotEnoughAvailableTension; static_error erNotEnoughAvailableFlow; }
// Constants & Variables //------------------------------------------------------------------------- dynamic_constant(clString,goDataLocation);
// Static Members //-------------------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// Functions Implementation //---------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// X X X Implementation //------------------------------------------------------------------------- namespace {}
// I n i t i a l i z e r Implementation //--------------------------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------------Start property void clInitializer::start(void) { if (atCounter++ == 0) { try { #include <bpp/modules.hpp> /*NEED*/ registerStop(this); environment::informInitialization(goModuleName);
erEmptyArcList.create("Min Cost Tension - The arc list is empty."); erNotEnoughAvailableFlow.create("Min Cost Tension - Can't increase / decrease more a flow."); erNotEnoughAvailableTension.create("Min Cost Tension - Can't increase / decrease more a tension.");
goDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator() +"graph_problem"+fileNameSeparator()+"min_cost_tension" +fileNameSeparator()+"serial_parallel")); }
initializer_catch; } } //---------------------------------------------------------------------------------------------Stop property void clInitializer::stop(void) { try { environment::informTermination(goModuleName);
delete_object(goDataLocation); }
initializer_catch; } }
// End //------------------------------------------------------------------------------------------- } |
|