//================================================================================================== // G r a p h _ p r o b l e m Interface // T e n s i o n // A l g o r i t h m // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU Library General Public License for more details (http://www.gnu.org).
/*DESCRIPTION*/ /* This module provides algorithms to solve tension problems in graphs. */
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph_problem/tension/algorithm.hpp"
// Guardian //-------------------------------------------------------------------------------------- #ifndef guGraphProblemTensionAlgorithm #define guGraphProblemTensionAlgorithm
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph.hpp> /*INCLUDE*/ #include <bpp/graph_problem/shortest_path.hpp> /*INCLUDE*/
namespace bpp {
// Importation/Exportation //----------------------------------------------------------------------- #ifdef GRAPH_PROBLEM_TENSION_DLL #define dll_export DLL_EXPORT #else #define dll_export DLL_IMPORT #endif
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphProblemTensionAlgorithm #define private_area graphProblemTensionAlgorithm_private
namespace public_area { /*NAMESPACE*/ using namespace graph; }
namespace private_area { using namespace public_area; using namespace graphProblemShortestPath; }
extern_module_name;
// Initialization //-------------------------------------------------------------------------------- #define iniGraphProblemTensionAlgorithm has_initializer;
// Macrocommands //--------------------------------------------------------------------------------- #define tdGraph class prArcData,class prNodeData #define tuGraph prArcData,prNodeData
// Types & Classes //------------------------------------------------------------------------------- namespace public_area { //------------------------------------------------------------------------------------------Classes template <tdGraph> class clCompatibleTensionAlgo; template <tdGraph> class clCompatibleTensionAlgoI; template <tdGraph> class clCompatibleTensionAlgoII; template <tdGraph> class clCompatibleTensionAlgoIII; template <tdGraph> class clCompatibleTensionAlgoIV; }
namespace private_area { template <tdGraph> class clConditionForCompatibility; template <tdGraph> class clConditionForMaximum; template <tdGraph> class clMintyColorForCompatibility; template <tdGraph> class clMintyColorForIncrease;
structure { tyCardinal cycle; tyInteger direction; } tyArcInfo; }
// Functions Interface //--------------------------------------------------------------------------- namespace public_area { template <tdGraph> tyBoolean checkCompatibility(const clGraph<tuGraph> &); template <tdGraph> tyBoolean computePotential(clGraph<tuGraph> &); template <tdGraph> void increaseTension(clGraph<tuGraph> &,ctCocycle &,tyReal); template <tdGraph> void increaseTension(const std_map(clArc<tuGraph> *,tyInteger) &,tyReal); template <tdGraph> tyInteger makeTensionCompatible(clArc<tuGraph> &,tyReal,tyReal); template <tdGraph> tyInteger maximizeTension(clArc<tuGraph> &); }
namespace private_area { template <tdGraph> void buildResidualGraph(clLengthGraph &,clGraph<tuGraph> &,std_vector(clLengthArc *) &);
template <tdGraph,class prCondition> tyInteger increaseTension(clArc<tuGraph> &,const prCondition &);
testing_mode ( function void test(void); ) }
// Errors //---------------------------------------------------------------------------------------- namespace public_area {}
// Constants & Variables //------------------------------------------------------------------------- extern_dynamic_constant(private,clString,goDataLocation,?);
// C o m p a t i b l e T e n s i o n A l g o Interface //------------------------------------------ namespace public_area { /*CLASS clCompatibleTensionAlgo */ /* Represents an algorithm to find a compatible tension in a graph. It is an abstract class. */ template <tdGraph> class clCompatibleTensionAlgo { //-----------------------------------------------------------------------------------------Private private_property constructor clCompatibleTensionAlgo(const clCompatibleTensionAlgo &); private_property clCompatibleTensionAlgo & operator = (const clCompatibleTensionAlgo &); //------------------------------------------------------------------------------------------Public public_property constructor clCompatibleTensionAlgo(void); public_property virtual destructor clCompatibleTensionAlgo(void);
/*AMETHOD clCompatibleTensionAlgo */ /* Finds a compatible tension in a graph. Abstract method. */ public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;
/*AMETHOD clCompatibleTensionAlgo */ /* Finds a compatible tension in a graph. The second argument is set to <CODE>true</CODE> if the algorithm has to consider the current tension of the graph, which is supposed to help it. Abstract method. */ public_property virtual tyInteger run(clGraph<tuGraph> & agGraph, tyBoolean agKeepTension) const = 0;
public_property static tyInteger defaultRun(clGraph<tuGraph> &); public_property static tyInteger defaultRun(clGraph<tuGraph> &,tyBoolean); }; }
// C o m p a t i b l e T e n s i o n A l g o I Interface //---------------------------------------- namespace public_area { /*CLASS clCompatibleTensionAlgoI */ /* Represents an algorithm to find a compatible tension in a graph (method I: increasing cocycle). */ template <tdGraph> class clCompatibleTensionAlgoI : public clCompatibleTensionAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clCompatibleTensionAlgoI(const clCompatibleTensionAlgoI &); private_property clCompatibleTensionAlgoI & operator = (const clCompatibleTensionAlgoI &); //------------------------------------------------------------------------------------------Public public_property constructor clCompatibleTensionAlgoI(void); public_property destructor clCompatibleTensionAlgoI(void);
public_property tyInteger run(clGraph<tuGraph> &) const; public_property tyInteger run(clGraph<tuGraph> &,tyBoolean) const; }; }
// C o m p a t i b l e T e n s i o n A l g o I I Interface //-------------------------------------- namespace public_area { /*CLASS clCompatibleTensionAlgoII */ /* Represents an algorithm to find a compatible tension in a graph (method II: increasing cocycle). */ template <tdGraph> class clCompatibleTensionAlgoII : public clCompatibleTensionAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clCompatibleTensionAlgoII(const clCompatibleTensionAlgoII &); private_property clCompatibleTensionAlgoII & operator = (const clCompatibleTensionAlgoII &); //------------------------------------------------------------------------------------------Public public_property constructor clCompatibleTensionAlgoII(void); public_property destructor clCompatibleTensionAlgoII(void);
public_property tyInteger run(clGraph<tuGraph> &) const; public_property tyInteger run(clGraph<tuGraph> &,tyBoolean) const; }; }
// C o m p a t i b l e T e n s i o n A l g o I I I Interface //------------------------------------- namespace public_area { /*CLASS clCompatibleTensionAlgoIII */ /* Represents an algorithm to find a compatible tension in a graph (method III: use of a shortest path algorithm). */ template <tdGraph> class clCompatibleTensionAlgoIII : public clCompatibleTensionAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clCompatibleTensionAlgoIII(const clCompatibleTensionAlgoIII &); private_property clCompatibleTensionAlgoIII & operator = (const clCompatibleTensionAlgoIII &); //------------------------------------------------------------------------------------------Public public_property constructor clCompatibleTensionAlgoIII(void); public_property destructor clCompatibleTensionAlgoIII(void);
public_property tyInteger run(clGraph<tuGraph> &) const; public_property tyInteger run(clGraph<tuGraph> &,tyBoolean) const; }; }
// C o m p a t i b l e T e n s i o n A l g o I V Interface //--------------------------------------- namespace public_area { /*CLASS clCompatibleTensionAlgoIV */ /* Represents an algorithm to find a compatible tension in a graph (method IV: use of a shortest path algorithm). */ template <tdGraph> class clCompatibleTensionAlgoIV : public clCompatibleTensionAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clCompatibleTensionAlgoIV(const clCompatibleTensionAlgoIV &); private_property clCompatibleTensionAlgoIV & operator = (const clCompatibleTensionAlgoIV &); //------------------------------------------------------------------------------------------Public public_property constructor clCompatibleTensionAlgoIV(void); public_property destructor clCompatibleTensionAlgoIV(void);
public_property tyInteger run(clGraph<tuGraph> &) const; public_property tyInteger run(clGraph<tuGraph> &,tyBoolean) const; }; }
// C o n d i t i o n F o r M a x i m u m Interface //---------------------------------------------- namespace private_area { template <tdGraph> class clConditionForMaximum { //-----------------------------------------------------------------------------------------Private private_property const clArc<tuGraph> & atArc;
private_property constructor clConditionForMaximum(const clConditionForMaximum &); private_property clConditionForMaximum & operator = (const clConditionForMaximum &); //------------------------------------------------------------------------------------------Public public_property constructor clConditionForMaximum(const clArc<tuGraph> &); public_property destructor clConditionForMaximum(void) {}
public_property tyBoolean evaluate(void) const; }; }
// C o n d i t i o n F o r C o m p a t i b i l i t y Interface //---------------------------------- namespace private_area { template <tdGraph> class clConditionForCompatibility { //-----------------------------------------------------------------------------------------Private private_property const clArc<tuGraph> & atArc; private_property tyReal atMinimum; private_property tyReal atMaximum;
private_property constructor clConditionForCompatibility(const clConditionForCompatibility &); private_property clConditionForCompatibility & operator = (const clConditionForCompatibility &); //------------------------------------------------------------------------------------------Public public_property constructor clConditionForCompatibility(const clArc<tuGraph> &,tyReal,tyReal); public_property destructor clConditionForCompatibility(void) {}
public_property tyBoolean evaluate(void) const; }; }
// M i n t y C o l o r F o r C o m p a t i b i l i t y Interface //-------------------------------- namespace private_area { template <tdGraph> class clMintyColorForCompatibility { //-------------------------------------------------------------------------------------------Types public_property typedef clArc<tuGraph> cpArc; //-----------------------------------------------------------------------------------------Private private_property constructor clMintyColorForCompatibility(const clMintyColorForCompatibility &);
private_property clMintyColorForCompatibility & operator = (const clMintyColorForCompatibility &); //------------------------------------------------------------------------------------------Public public_property constructor clMintyColorForCompatibility(void) {} public_property destructor clMintyColorForCompatibility(void) {}
public_property tyBoolean red(const cpArc &) const; public_property tyBoolean black(const cpArc &) const; public_property tyBoolean blue(const cpArc &) const; public_property tyBoolean green(const cpArc &) const;
public_property tcString color(const cpArc &) const; }; }
// M i n t y C o l o r F o r I n c r e a s e Interface //------------------------------------------ namespace private_area { template <tdGraph> class clMintyColorForIncrease { //-------------------------------------------------------------------------------------------Types public_property typedef clArc<tuGraph> cpArc; //-----------------------------------------------------------------------------------------Private private_property constructor clMintyColorForIncrease(const clMintyColorForIncrease &); private_property clMintyColorForIncrease & operator = (const clMintyColorForIncrease &); //------------------------------------------------------------------------------------------Public public_property constructor clMintyColorForIncrease(void) {} public_property destructor clMintyColorForIncrease(void) {}
public_property tyBoolean red(const cpArc &) const; public_property tyBoolean black(const cpArc &) const; public_property tyBoolean blue(const cpArc &) const; public_property tyBoolean green(const cpArc &) const;
public_property tcString color(const cpArc &) const; }; }
// Functions Inline //------------------------------------------------------------------------------ namespace public_area { //----------------------------------------------------------------------------MakeTensionCompatible /*FUNCTION*/ /* Makes the tension of an arc compatible. */ template <tdGraph> inline tyInteger makeTensionCompatible(clArc<tuGraph> & agArc,tyReal agMinimum,tyReal agMaximum) { return (private_area::increaseTension (agArc,private_area::clConditionForCompatibility<tuGraph>(agArc,agMinimum,agMaximum))); } //----------------------------------------------------------------------------------MaximizeTension /*FUNCTION*/ /* Maximizes the tension of an arc. */ template <tdGraph> inline tyInteger maximizeTension(clArc<tuGraph> & agArc) { return (private_area::increaseTension(agArc, private_area::clConditionForMaximum<tuGraph>(agArc))); } }
namespace private_area {}
// C o m p a t i b l e T e n s i o n A l g o Inline //--------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clCompatibleTensionAlgo */ /* Builds an algorithm to find a compatible tension in a graph. */ template <tdGraph> inline clCompatibleTensionAlgo<tuGraph>::clCompatibleTensionAlgo(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clCompatibleTensionAlgo */ /* Destructs the algorithm. */ template <tdGraph> inline clCompatibleTensionAlgo<tuGraph>::~clCompatibleTensionAlgo(void) {} }
// C o m p a t i b l e T e n s i o n A l g o I Inline //------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clCompatibleTensionAlgoI */ /* Builds an algorithm to find a compatible tension in a graph. */ template <tdGraph> inline clCompatibleTensionAlgoI<tuGraph>::clCompatibleTensionAlgoI(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clCompatibleTensionAlgoI */ /* Destructs the algorithm. */ template <tdGraph> inline clCompatibleTensionAlgoI<tuGraph>::~clCompatibleTensionAlgoI(void) {} //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoI */ /* Finds a compatible tension in a graph. */ template <tdGraph> inline tyInteger clCompatibleTensionAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph) const { return (run(agGraph,false)); } }
// C o m p a t i b l e T e n s i o n A l g o I I Inline //----------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clCompatibleTensionAlgoII */ /* Builds an algorithm to find a compatible tension in a graph. */ template <tdGraph> inline clCompatibleTensionAlgoII<tuGraph>::clCompatibleTensionAlgoII(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clCompatibleTensionAlgoII */ /* Destructs the algorithm. */ template <tdGraph> inline clCompatibleTensionAlgoII<tuGraph>::~clCompatibleTensionAlgoII(void) {} //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoII */ /* Finds a compatible tension in a graph. */ template <tdGraph> inline tyInteger clCompatibleTensionAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph) const { return (run(agGraph,false)); } }
// C o m p a t i b l e T e n s i o n A l g o I I I Inline //--------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clCompatibleTensionAlgoIII */ /* Builds an algorithm to find a compatible tension in a graph. */ template <tdGraph> inline clCompatibleTensionAlgoIII<tuGraph>::clCompatibleTensionAlgoIII(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clCompatibleTensionAlgoIII */ /* Destructs the algorithm. */ template <tdGraph> inline clCompatibleTensionAlgoIII<tuGraph>::~clCompatibleTensionAlgoIII(void) {} //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoIII */ /* Finds a compatible tension in a graph. The second argument is not used. */ template <tdGraph> inline tyInteger clCompatibleTensionAlgoIII<tuGraph>::run(clGraph<tuGraph> & agGraph,tyBoolean) const { return (run(agGraph)); } }
// C o m p a t i b l e T e n s i o n A l g o I V Inline //----------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clCompatibleTensionAlgoIV */ /* Builds an algorithm to find a compatible tension in a graph. */ template <tdGraph> inline clCompatibleTensionAlgoIV<tuGraph>::clCompatibleTensionAlgoIV(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clCompatibleTensionAlgoIV */ /* Destructs the algorithm. */ template <tdGraph> inline clCompatibleTensionAlgoIV<tuGraph>::~clCompatibleTensionAlgoIV(void) {} //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoIV */ /* Finds a compatible tension in a graph. The second argument is not used. */ template <tdGraph> inline tyInteger clCompatibleTensionAlgoIV<tuGraph>::run(clGraph<tuGraph> & agGraph,tyBoolean) const { return (run(agGraph)); } }
// C o n d i t i o n F o r C o m p a t i b i l i t y Inline //------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------Constructor template <tdGraph> inline clConditionForCompatibility<tuGraph>:: clConditionForCompatibility(const clArc<tuGraph> & agArc,tyReal agMinimum,tyReal agMaximum) : atArc(agArc),atMinimum(agMinimum),atMaximum(agMaximum) {} //-----------------------------------------------------------------------------------------Evaluate template <tdGraph> inline tyBoolean clConditionForCompatibility<tuGraph>::evaluate(void) const { return (atArc.data().tension()>=atMinimum and atArc.data().tension()<=atMaximum); } }
// C o n d i t i o n F o r M a x i m u m Inline //------------------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------Constructor template <tdGraph> inline clConditionForMaximum<tuGraph>::clConditionForMaximum(const clArc<tuGraph> & agArc) : atArc(agArc) {} //-----------------------------------------------------------------------------------------Evaluate template <tdGraph> inline tyBoolean clConditionForMaximum<tuGraph>::evaluate(void) const { return (atArc.data().tension()==atArc.data().maximum()); } }
// M i n t y C o l o r F o r C o m p a t i b i l i t y Inline //----------------------------------- namespace private_area { //----------------------------------------------------------------------------------------------Red template <tdGraph> inline tyBoolean clMintyColorForCompatibility<tuGraph>::red(const cpArc & agArc) const { return (agArc.data().tension()>agArc.data().minimum() and agArc.data().tension()<agArc.data().maximum()); } //--------------------------------------------------------------------------------------------Black template <tdGraph> inline tyBoolean clMintyColorForCompatibility<tuGraph>::black(const cpArc & agArc) const { return (agArc.data().tension()<=agArc.data().minimum() and agArc.data().tension()<agArc.data().maximum()); } //---------------------------------------------------------------------------------------------Blue template <tdGraph> inline tyBoolean clMintyColorForCompatibility<tuGraph>::blue(const cpArc & agArc) const { return (agArc.data().tension()>=agArc.data().maximum() and agArc.data().tension()>agArc.data().minimum()); } //--------------------------------------------------------------------------------------------Green template <tdGraph> inline tyBoolean clMintyColorForCompatibility<tuGraph>::green(const cpArc & agArc) const { return (agArc.data().tension()==agArc.data().minimum() and agArc.data().tension()==agArc.data().maximum()); } }
// M i n t y C o l o r F o r I n c r e a s e Inline //--------------------------------------------- namespace private_area { //----------------------------------------------------------------------------------------------Red template <tdGraph> inline tyBoolean clMintyColorForIncrease<tuGraph>::red(const cpArc & agArc) const { return (agArc.data().minimum()<agArc.data().tension() and agArc.data().tension()<agArc.data().maximum()); } //--------------------------------------------------------------------------------------------Black template <tdGraph> inline tyBoolean clMintyColorForIncrease<tuGraph>::black(const cpArc & agArc) const { return (agArc.data().minimum()==agArc.data().tension() and agArc.data().tension()<agArc.data().maximum()); } //---------------------------------------------------------------------------------------------Blue template <tdGraph> inline tyBoolean clMintyColorForIncrease<tuGraph>::blue(const cpArc & agArc) const { return (agArc.data().minimum()<agArc.data().tension() and agArc.data().tension()==agArc.data().maximum()); } //--------------------------------------------------------------------------------------------Green template <tdGraph> inline tyBoolean clMintyColorForIncrease<tuGraph>::green(const cpArc & agArc) const { return (agArc.data().minimum()==agArc.data().tension() and agArc.data().tension()==agArc.data().maximum()); } }
// Functions Implementation //---------------------------------------------------------------------- namespace public_area { //-------------------------------------------------------------------------------CheckCompatibility /*FUNCTION*/ /* Verifies that the tension in a graph is compatible (<CODE>true</CODE> = compatible). */ template <tdGraph> tyBoolean checkCompatibility(const clGraph<tuGraph> & agGraph) { typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpIterator;
cpIterator lcCurrentArc = agGraph.arcs().begin(); cpIterator lcLastArc = agGraph.arcs().end();
clArc<tuGraph> * lcArc;
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcArc->data().tension()<lcArc->data().minimum() or lcArc->data().tension()>lcArc->data().maximum()) return (false);
lcCurrentArc++; }
return (true); } //---------------------------------------------------------------------------------ComputePotential /*FUNCTION*/ /* Computes the potential of each node according to the tension of the arcs. Returns <CODE>false</CODE> if the tension is not feasible. */ template <tdGraph> tyBoolean computePotential(clGraph<tuGraph> & agGraph) { typedef typename clNode<tuGraph>::cpArcX::const_iterator cpArcIterator; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator; typedef std_vector(clNode<tuGraph> *) clNodeS;
tyMark lcMark = ++(agGraph.mark());
clArc<tuGraph> * lcArc; cpArcIterator lcCurrentArc; cpNodeIterator lcCurrentNode; cpArcIterator lcLastArc; cpNodeIterator lcLastNode; clNode<tuGraph> * lcNode; clNodeS lcNodeS; clNode<tuGraph> * lcSourceNode; clNode<tuGraph> * lcTargetNode; tyReal lcTension;
lcCurrentNode=agGraph.nodes().begin(); lcLastNode=agGraph.nodes().end();
while (lcCurrentNode!=lcLastNode) { lcNode=(*lcCurrentNode).second;
if (lcNode->mark()!=lcMark) { lcNode->data().potential()=0.0; lcNode->mark()=lcMark; lcNodeS.push_back(lcNode); }
while (not lcNodeS.empty()) { lcNode=lcNodeS.back(); lcNodeS.pop_back(); lcCurrentArc=lcNode->outgoingArcs().begin(); lcLastArc=lcNode->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcTargetNode=lcArc->targetNode();
if (lcTargetNode->mark()==lcMark) { lcTension=lcTargetNode->data().potential()-lcNode->data().potential(); if (lcTension!=lcArc->data().tension()) return (false); } else { lcTargetNode->data().potential()=lcNode->data().potential()+lcArc->data().tension(); lcTargetNode->mark()=lcMark; lcNodeS.push_back(lcTargetNode); }
lcCurrentArc++; }
lcCurrentArc=lcNode->incomingArcs().begin(); lcLastArc=lcNode->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcSourceNode=lcArc->sourceNode();
if (lcSourceNode->mark()==lcMark) { lcTension=lcNode->data().potential()-lcSourceNode->data().potential(); if (lcTension!=lcArc->data().tension()) return (false); } else { lcSourceNode->data().potential()=lcNode->data().potential()-lcArc->data().tension(); lcSourceNode->mark()=lcMark; lcNodeS.push_back(lcSourceNode); }
lcCurrentArc++; } }
lcCurrentNode++; }
return (true); } //----------------------------------------------------------------------------------IncreaseTension /*FUNCTION*/ /* Increases the tension in a cocycle of a given value. */ template <tdGraph> void increaseTension(clGraph<tuGraph> & agGraph,ctCocycle & agCocycle,tyReal agValue) { clCocycle::const_iterator lcCurrentArc = agCocycle.begin(); clCocycle::const_iterator lcLastArc = agCocycle.end();
while (lcCurrentArc!=lcLastArc) { if ((*lcCurrentArc).second==+1) agGraph.arc((*lcCurrentArc).first).data().tension()+=agValue; else agGraph.arc((*lcCurrentArc).first).data().tension()-=agValue;
lcCurrentArc++; } } //----------------------------------------------------------------------------------IncreaseTension /*FUNCTION*/ /* Increases the tension in a cocycle of a given value. */ template <tdGraph> void increaseTension(const std_map(clArc<tuGraph> *,tyInteger) & agCocycle,tyReal agValue) { typedef typename std_map(clArc<tuGraph> *,tyInteger)::const_iterator cpIterator;
cpIterator lcCurrentArc = agCocycle.begin(); cpIterator lcLastArc = agCocycle.end();
while (lcCurrentArc!=lcLastArc) { if ((*lcCurrentArc).second==+1) (*lcCurrentArc).first->data().tension()+=agValue; else (*lcCurrentArc).first->data().tension()-=agValue;
lcCurrentArc++; } } }
namespace private_area { //-------------------------------------------------------------------------------BuildResidualGraph template <tdGraph> void buildResidualGraph(clLengthGraph & agResidualGraph,clGraph<tuGraph> & agGraph, std_vector(clLengthArc *) & agArcS) { typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
clArc<tuGraph> * lcArc1; clLengthArc * lcArc2;
cpArcIterator lcCurrentArc = agGraph.arcs().begin(); cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpArcIterator lcLastArc = agGraph.arcs().end(); cpNodeIterator lcLastNode = agGraph.nodes().end();
// Nodes Duplication // while (lcCurrentNode!=lcLastNode) { new_object(clLengthNode(agResidualGraph,(*lcCurrentNode).first,dataStructure::clNoData())); ++lcCurrentNode; }
// Arcs Duplication // agArcS.reserve(agGraph.arcs().size()); lcCurrentArc=agGraph.arcs().begin();
while (lcCurrentArc!=lcLastArc) { lcArc1=(*lcCurrentArc).second;
lcArc2=new_object(clLengthArc(agResidualGraph,agResidualGraph.getNewArcKey(), dataStructure::clLengthData(),lcArc1->sourceNode()->key(), lcArc1->targetNode()->key()));
lcArc2->data().length()=lcArc1->data().maximum(); agArcS.push_back(lcArc2);
lcArc2=new_object(clLengthArc(agResidualGraph,agResidualGraph.getNewArcKey(), dataStructure::clLengthData(),lcArc1->targetNode()->key(), lcArc1->sourceNode()->key()));
lcArc2->data().length()=-(lcArc1->data().minimum()); ++lcCurrentArc; } } //----------------------------------------------------------------------------------IncreaseTension template <tdGraph,class prCondition> tyInteger increaseTension(clArc<tuGraph> & agArc,const prCondition & agCondition) { typedef std_map(clArc<tuGraph> *,tyInteger) cpCocycle; typedef std_map(clArc<tuGraph> *,tyInteger) cpCycle; typedef typename cpCycle::iterator cpIterator;
clMintyColorForIncrease<tuGraph> lcMintyColor;
tyInteger lcNbIteration = 0;
clArc<tuGraph> * lcArc; cpCocycle lcCocycle; cpIterator lcCurrentArc; cpCycle lcCycle; cpIterator lcLastArc; tyReal lcIncrement;
while (not agCondition.evaluate() and not findMintyCycle(agArc,lcMintyColor,lcCycle,lcCocycle)) { lcNbIteration++; lcCurrentArc=lcCocycle.begin(); lcLastArc=lcCocycle.end(); lcIncrement=realMax();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).first;
if ((*lcCurrentArc).second==+1) lcIncrement=mini(lcArc->data().maximum()-lcArc->data().tension(),lcIncrement); else lcIncrement=mini(lcArc->data().tension()-lcArc->data().minimum(),lcIncrement);
lcCurrentArc++; }
public_area::increaseTension(lcCocycle,lcIncrement); }
return (lcNbIteration); } }
// C o m p a t i b l e T e n s i o n A l g o Implementation //------------------------------------- namespace public_area { //---------------------------------------------------------------------------------------DefaultRun /*METHOD clCompatibleTensionAlgo */ /* Finds a compatible tension in a graph using the default version of the algorithm (method III). Static method. */ template <tdGraph> inline tyInteger clCompatibleTensionAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph) { return (clCompatibleTensionAlgoIII<tuGraph>().run(agGraph)); } //---------------------------------------------------------------------------------------DefaultRun /*METHOD clCompatibleTensionAlgo */ /* Finds a compatible tension in a graph using the default version of the algorithm (method III). The second argument is set to <CODE>true</CODE> if the algorithm has to consider the current tension of the graph, which is supposed to help it. Static method. */ template <tdGraph> inline tyInteger clCompatibleTensionAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph, tyBoolean agKeepTension) { return (clCompatibleTensionAlgoIII<tuGraph>().run(agGraph,agKeepTension)); } }
// C o m p a t i b l e T e n s i o n A l g o I Implementation //----------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoI */ /* Finds a compatible tension in a graph. The second argument is set to <CODE>true</CODE> if the algorithm has to consider the current tension of the graph, which is supposed to help it. */ template <tdGraph> tyInteger clCompatibleTensionAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph, tyBoolean agKeepTension) const { typedef std_map(clArc<tuGraph> *,tyInteger) cpCocycle; typedef std_map(clArc<tuGraph> *,tyInteger) cpCycle; typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpIterator1; typedef typename cpCocycle::const_iterator cpIterator2;
cpIterator1 lcCurrentArc = agGraph.arcs().begin(); cpIterator1 lcLastArc = agGraph.arcs().end(); tyCardinal lcNbIteration = 0;
clArc<tuGraph> * lcArc; clArc<tuGraph> * lcArc2; cpCocycle lcCocycle; cpIterator2 lcCurrentArc2; cpCycle lcCycle; tyReal lcIncrement; cpIterator2 lcLastArc2;
private_area::clMintyColorForCompatibility<tuGraph> lcMintyColor;
agGraph.solved()=false;
if (not agKeepTension) { while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc).second->data().tension()=0; lcCurrentArc++; }
lcCurrentArc=agGraph.arcs().begin(); }
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcArc->data().tension()<lcArc->data().minimum()) { while (lcArc->data().tension()<lcArc->data().minimum() and (not findMintyCycle(*lcArc,lcMintyColor,lcCycle,lcCocycle))) { lcNbIteration++; lcCurrentArc2=lcCocycle.begin(); lcLastArc2=lcCocycle.end(); lcIncrement=realMax();
while (lcCurrentArc2!=lcLastArc2) { lcArc2=(*lcCurrentArc2).first;
if ((*lcCurrentArc2).second==+1) lcIncrement=mini(lcArc2->data().maximum()-lcArc2->data().tension(),lcIncrement); else lcIncrement=mini(lcArc2->data().tension()-lcArc2->data().minimum(),lcIncrement);
lcCurrentArc2++; }
increaseTension(lcCocycle,lcIncrement); }
if (lcArc->data().tension()<lcArc->data().minimum()) return (-1); }
lcCurrentArc++; }
agGraph.solved()=true; return (lcNbIteration); } }
// C o m p a t i b l e T e n s i o n A l g o I I Implementation //--------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoII */ /* Finds a compatible tension in a graph. The second argument is set to <CODE>true</CODE> if the algorithm has to consider the current tension of the graph, which is supposed to help it. */ template <tdGraph> tyInteger clCompatibleTensionAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph, tyBoolean agKeepTension) const { typedef std_map(clArc<tuGraph> *,tyInteger) cpCocycle; typedef std_map(clArc<tuGraph> *,tyInteger) cpCycle; typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpIterator1; typedef typename cpCocycle::const_iterator cpIterator2;
cpIterator1 lcCurrentArc = agGraph.arcs().begin(); cpIterator1 lcLastArc = agGraph.arcs().end(); tyCardinal lcNbIteration = 0;
tyBoolean lcAgain; clArc<tuGraph> * lcArc; clArc<tuGraph> * lcArc2; cpCocycle lcCocycle; cpIterator2 lcCurrentArc2; cpCycle lcCycle; tyReal lcIncrement; cpIterator2 lcLastArc2;
private_area::clMintyColorForCompatibility<tuGraph> lcMintyColor;
agGraph.solved()=false;
if (not agKeepTension) { while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc).second->data().tension()=0; lcCurrentArc++; } }
do { lcAgain=false; lcCurrentArc=agGraph.arcs().begin();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcArc->data().tension()<lcArc->data().minimum()) { lcAgain=true;
if (not findMintyCycle(*lcArc,lcMintyColor,lcCycle,lcCocycle)) { lcNbIteration++; lcCurrentArc2=lcCocycle.begin(); lcLastArc2=lcCocycle.end(); lcIncrement=realMax();
while (lcCurrentArc2!=lcLastArc2) { lcArc2=(*lcCurrentArc2).first;
if ((*lcCurrentArc2).second==+1) lcIncrement=mini(lcArc2->data().maximum()-lcArc2->data().tension(),lcIncrement); else lcIncrement=mini(lcArc2->data().tension()-lcArc2->data().minimum(),lcIncrement);
lcCurrentArc2++; }
increaseTension(lcCocycle,lcIncrement); } else return (0); }
lcCurrentArc++; } } while (lcAgain);
agGraph.solved()=true; return (lcNbIteration); } }
// C o m p a t i b l e T e n s i o n A l g o I I I Implementation //------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoIII */ /* Finds a compatible tension in a graph. */ template <tdGraph> tyInteger clCompatibleTensionAlgoIII<tuGraph>::run(clGraph<tuGraph> & agGraph) const { typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator1; typedef std_vector(private_area::clLengthArc *) clArcS; typedef clArcS::const_iterator clArcIterator2;
typedef graphProblemShortestPath::clFordAlgo<dataStructure::clLengthData,dataStructure::clNoData> clShortestPathAlgo;
typedef clShortestPathAlgo::cpWorkspace clWorkspace;
clArc<tuGraph> * lcArc1; private_area::clLengthArc * lcArc2; clArcS lcAssociation; clArcIterator2 lcCurrentArc2; clArcS lcPath; private_area::clLengthGraph lcResidualGraph;
cpArcIterator1 lcCurrentArc1 = agGraph.arcs().begin(); cpArcIterator1 lcLastArc1 = agGraph.arcs().end();
// Compatible Tension Search // agGraph.solved()=false; private_area::buildResidualGraph(lcResidualGraph,agGraph,lcAssociation);
try { clShortestPathAlgo(true).run(lcResidualGraph,(*(lcResidualGraph.nodes().begin())).first, (*(lcResidualGraph.nodes().begin())).first,lcPath); }
// Inconsistent Constraints // catch (ctError &) { deleteNodeWorkspace(lcResidualGraph,clWorkspace()); clearError(); return (-1); }
// Tension Computation // lcCurrentArc2=lcAssociation.begin();
while (lcCurrentArc1!=lcLastArc1) { lcArc1=(*lcCurrentArc1).second; lcArc2=*lcCurrentArc2;
if (lcArc2->sourceNode()!=nil and lcArc2->targetNode()!=nil) lcArc1->data().tension()=static_cast<clWorkspace *>(lcArc2->targetNode()->work())->potential() -static_cast<clWorkspace *>(lcArc2->sourceNode()->work())->potential(); else lcArc1->data().tension()=0.0;
++lcCurrentArc1; ++lcCurrentArc2; }
deleteNodeWorkspace(lcResidualGraph,clWorkspace()); agGraph.solved()=true; return (0); } }
// C o m p a t i b l e T e n s i o n A l g o I V Implementation //--------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clCompatibleTensionAlgoIV */ /* Finds a compatible tension in a graph. */ template <tdGraph> tyInteger clCompatibleTensionAlgoIV<tuGraph>::run(clGraph<tuGraph> & agGraph) const { typedef std_vector(private_area::clLengthArc *) clArcS; typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator1; typedef clArcS::const_iterator clArcIterator2; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator clNodeIterator;
typedef graphProblemShortestPath::clFordAlgo<dataStructure::clLengthData,dataStructure::clNoData> clShortestPathAlgo;
clArc<tuGraph> * lcArc1; private_area::clLengthArc * lcArc2; private_area::clLengthArc * lcArc3; private_area::clLengthArc * lcArc4; private_area::clLengthArc * lcArc5; clArcS lcArcS; clArcIterator2 lcCurrentArc2; clArcIterator2 lcCurrentArc3; private_area::clLengthGraph lcGraph; clArcIterator2 lcLastArc2; clArcIterator2 lcLastArc3; clArcS lcPath; clShortestPathAlgo lcShortestPathAlgo(false); tyReal lcTension;
cpArcIterator1 lcCurrentArc1 = agGraph.arcs().begin(); clNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpArcIterator1 lcLastArc1 = agGraph.arcs().end(); clNodeIterator lcLastNode = agGraph.nodes().end();
agGraph.solved()=false;
// Shortest Path Problem Conversion // while (lcCurrentNode!=lcLastNode) { new_object(private_area::clLengthNode(lcGraph,(*lcCurrentNode).first,clNoData())); ++lcCurrentNode; }
while (lcCurrentArc1!=lcLastArc1) { lcArc1=(*lcCurrentArc1).second;
lcArc2=new_object(private_area::clLengthArc(lcGraph,lcArc1->key(), clLengthData(lcArc1->data().maximum()),lcArc1->sourceNode()->key(), lcArc1->targetNode()->key()));
lcArcS.push_back(lcArc2); ++lcCurrentArc1; }
lcCurrentArc1=agGraph.arcs().begin();
while (lcCurrentArc1!=lcLastArc1) { lcArc1=(*lcCurrentArc1).second;
lcArc2=new_object(private_area::clLengthArc(lcGraph,lcGraph.getNewArcKey(), clLengthData(-(lcArc1->data().minimum())),lcArc1->targetNode()->key(), lcArc1->sourceNode()->key()));
lcArc3=&(lcGraph.arc(lcArc1->key())); lcArc3->work()=lcArc2; lcArc2->work()=lcArc3; ++lcCurrentArc1; }
// Compatible Tension Search // lcCurrentArc2=lcArcS.begin(); lcLastArc2=lcArcS.end();
while (lcCurrentArc2!=lcLastArc2) { lcArc2=*lcCurrentArc2; lcArc3=(private_area::clLengthArc *)(lcArc2->work());
if (lcArc2->data().length()!=-(lcArc3->data().length())) { try { lcShortestPathAlgo.run(lcGraph,lcArc2->sourceNode()->key(), lcArc2->targetNode()->key(),lcPath); }
catch (ctError &) { clearError(); return (-1); } lcTension=0.0; lcCurrentArc3=lcPath.begin(); lcLastArc3=lcPath.end();
while (lcCurrentArc3!=lcLastArc3) { lcArc4=*lcCurrentArc3; lcArc5=(private_area::clLengthArc *)(lcArc4->work()); lcArc5->data().length()=-lcArc4->data().length(); lcTension+=lcArc4->data().length(); ++lcCurrentArc3; }
lcArc2->data().length()=lcTension; lcArc3->data().length()=-lcTension; }
++lcCurrentArc2; }
// Compatible Tension Building // lcCurrentArc1=agGraph.arcs().begin(); lcCurrentArc2=lcArcS.begin();
while (lcCurrentArc1!=lcLastArc1) { (*lcCurrentArc1).second->data().tension()=(*lcCurrentArc2)->data().length(); ++lcCurrentArc1; ++lcCurrentArc2; }
agGraph.solved()=true; return (0); } }
// M i n t y C o l o r F o r C o m p a t i b i l i t y Implementation //--------------------------- namespace private_area { //--------------------------------------------------------------------------------------------Color template <tdGraph> tcString clMintyColorForCompatibility<tuGraph>::color(const cpArc & agArc) const { if (red(agArc)) return ("red"); if (black(agArc)) return ("black"); if (blue(agArc)) return ("blue"); return ("green"); } }
// M i n t y C o l o r F o r I n c r e a s e Implementation //------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------------Color template <tdGraph> tcString clMintyColorForIncrease<tuGraph>::color(const cpArc & agArc) const { if (red(agArc)) return ("red"); if (black(agArc)) return ("black"); if (blue(agArc)) return ("blue"); return ("green"); } }
// 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 // T e n s i o n // A l g o r i t h m // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU Library General Public License for more details (http://www.gnu.org).
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph_problem/tension/algorithm.cpp"
// DLL Belonging //--------------------------------------------------------------------------------- #define GRAPH_PROBLEM_TENSION_DLL
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph_problem/tension/algorithm.hpp> /*INTERFACE*/
namespace bpp {
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphProblemTensionAlgorithm #define private_area graphProblemTensionAlgorithm_private #define dll_export DLL_EXPORT
namespace public_area {} namespace private_area {}
static_module_name("Graph_problem/Tension/Algorithm");
// Initialization //-------------------------------------------------------------------------------- #undef iniGraphProblemTensionAlgorithm static_constant(private_area::clInitializer,goInitializer);
// Errors //---------------------------------------------------------------------------------------- namespace public_area {}
// 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);
goDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator() +"graph_problem"+fileNameSeparator()+"tension" +fileNameSeparator()+"algorithm")); }
initializer_catch; } } //---------------------------------------------------------------------------------------------Stop property void clInitializer::stop(void) { try { environment::informTermination(goModuleName);
delete_object(goDataLocation); }
initializer_catch; } }
// End //------------------------------------------------------------------------------------------- } |
|