//================================================================================================== // G r a p h Interface // 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 basic algorithms for graphs. */
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph/algorithm.hpp"
// Guardian //-------------------------------------------------------------------------------------- #ifndef guGraphAlgorithm #define guGraphAlgorithm
// Headers //--------------------------------------------------------------------------------------- #include <algorithm> /*INCLUDE*/ #include <bpp/graph/structure.hpp> /*INCLUDE*/
namespace bpp {
// Importation/Exportation //----------------------------------------------------------------------- #ifdef GRAPH_DLL #define dll_export DLL_EXPORT #else #define dll_export DLL_IMPORT #endif
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphAlgorithm #define private_area graphAlgorithm_private
namespace public_area { /*NAMESPACE*/ using namespace graphStructure; } namespace private_area { using namespace public_area; }
extern_module_name;
// Initialization //-------------------------------------------------------------------------------- #define iniGraphAlgorithm has_initializer;
// Macrocommands //--------------------------------------------------------------------------------- /*ALIAS*/ #define tdGraph class prArcData,class prNodeData //
/*ALIAS*/ #define tuGraph prArcData,prNodeData //
// Types & Classes //------------------------------------------------------------------------------- namespace public_area { //------------------------------------------------------------------------------------------Classes template <tdGraph> class clArcAdmissibility; template <tdGraph> class clDecreaseDegreeNodeOrder; template <tdGraph> class clIncreaseDegreeNodeOrder; template <tdGraph> class clMintyColor; //-----------------------------------------------------------------------------------Variable Types /*TYPE*/ /* Cocycle of a graph (association of arc keys with their direction in the cocycle). */ typedef std_map(tyArcKey,tyInteger) clCocycle;
/*TYPE*/ /* Cycle of a graph (association of arc keys with their direction in the cycle). */ typedef std_map(tyArcKey,tyInteger) clCycle;
/*TYPE*/ /* List of cocycles. */ typedef std_vector(clCocycle) clCocycleS;
/*TYPE*/ /* List of cycles. */ typedef std_vector(clCycle) clCycleS;
/*TYPE*/ /* Symbolic constants for the colors used by a Minty coloration. */ enumeration { green, black, blue, red } tyMintyColor; //-----------------------------------------------------------------------------------Constant Types typedef const clCocycle ctCocycle; typedef const clCocycleS ctCocycleS; typedef const clCycle ctCycle; typedef const clCycleS ctCycleS;
typedef const tyMintyColor tcMintyColor; }
namespace private_area { template <tdGraph> class clMintyColorForCircuitDetection; template <tdGraph> class clMintyColorForCycleDetection; template <tdGraph> class clStandardArcAdmissibility; }
// Functions Interface //--------------------------------------------------------------------------- namespace public_area { template <tdGraph> void eliminateNonCycles(clGraph<tuGraph> &);
template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) &, std_vector(clArc<tuGraph> *) &,std_vector(clArc<tuGraph> *) &);
template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) &, std_map(clArc<tuGraph> *,tyInteger) &);
template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) &,clCocycle &); template <tdGraph> void findCycles(clGraph<tuGraph> &,clCycleS &,tyBoolean=false);
template <tdGraph> void findCycles(clGraph<tuGraph> &, std_vector(std_map(clArc<tuGraph> *,tyInteger)) &, tyBoolean=false);
template <tdGraph> void findFirstNodes(const clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &); template <tdGraph> void findLastNodes(const clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &);
template <tdGraph> clNode<tuGraph> * firstNode(const clGraph<tuGraph> &); template <tdGraph> clNode<tuGraph> * lastNode(const clGraph<tuGraph> &);
template <tdGraph> tyNodeKey addSourceNode(clGraph<tuGraph> &,const prArcData &,const prNodeData &);
template <tdGraph> tyNodeKey addTargetNode(clGraph<tuGraph> &,const prArcData &,const prNodeData &);
template <tdGraph,class prMintyColor> tyBoolean findMintyCycle(clGraph<tuGraph> &,tyArcKey,const prMintyColor &,clCycle &,clCocycle &);
template <tdGraph,class prMintyColor> tyBoolean findMintyCycle(clArc<tuGraph> &,const prMintyColor &, std_map(clArc<tuGraph> *,tyInteger) &, std_map(clArc<tuGraph> *,tyInteger) &);
template <tdGraph> tyBoolean findCircuit(clGraph<tuGraph> &,tyArcKey,clCycle &); template <tdGraph> tyBoolean findCycle(clGraph<tuGraph> &,tyArcKey,clCycle &); template <tdGraph> tyBoolean findCircuit(clArc<tuGraph> &,std_map(clArc<tuGraph> *,tyInteger) &); template <tdGraph> tyBoolean findCycle(clArc<tuGraph> &,std_map(clArc<tuGraph> *,tyInteger) &);
template <tdGraph> void findCoveringTree(clGraph<tuGraph> &,clGraph<tuGraph> &);
function clOutStream & operator << (clOutStream &,ctCycle &);
template <tdGraph> function clOutStream & operator << (clOutStream &,const std_map(clArc<tuGraph> *,tyInteger) &);
template <tdGraph,class prArcAdmissibility> tyBoolean findTopologicalOrdering(clGraph<tuGraph> &,const prArcAdmissibility &, std_vector(clNode<tuGraph> *) &);
template <tdGraph> tyBoolean findTopologicalOrdering(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &); }
namespace private_area { template <tdGraph> void destructCycle(const std_vector(clArc<tuGraph> *) &,std_vector(clNode<tuGraph> *) &);
template <tdGraph,class prMintyColor> tyBoolean findMintyCycle(clArc<tuGraph> &,const prMintyColor &, std_vector(clNode<tuGraph> *) &,std_vector(clArc<tuGraph> *) &, std_vector(tyCardinal) &,tyCardinal &);
template <tdGraph> void makeCycleDeepTree(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &, std_vector(clArc<tuGraph> *) &,std_vector(tyCardinal) &);
template <tdGraph> void makeCycleBroadTree(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &, std_vector(clArc<tuGraph> *) &,std_vector(tyCardinal) &);
template <tdGraph> void makeCycle(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &,std_vector(clArc<tuGraph> *) &, std_vector(tyCardinal) &,clCycle &,const clArc<tuGraph> &);
template <tdGraph> void makeCycle(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &,std_vector(clArc<tuGraph> *) &, std_vector(tyCardinal) &,std_map(clArc<tuGraph> *,tyInteger) &,clArc<tuGraph> &);
testing_mode ( function void test(void); ) }
// Errors //---------------------------------------------------------------------------------------- namespace public_area { /*ERROR*/ extern_error erGraphNotConnex; /* The graph is not connex. */ }
// Constants & Variables //------------------------------------------------------------------------- extern_dynamic_constant(private,clString,goDataLocation,?);
// A r c A d m i s s i b i l i t y Interface //---------------------------------------------------- namespace public_area { /*CLASS clArcAdmissibility */ /* This class represents arc admissibility. It is used to know if an arc is admissible or not, using it in the direct or indirect direction. This object is given as argument to functions that search nodes in a graph where only admissible arcs are used (in the direction(s) they are admissible for). This class is abstract. */ template <tdGraph> class clArcAdmissibility { //-------------------------------------------------------------------------------------------Types /*TYPE clArcAdmissibility */ /* Type of arc this object checks. */ public_property typedef clArc<tuGraph> cpArc; //-----------------------------------------------------------------------------------------Private private_property constructor clArcAdmissibility(const clArcAdmissibility &); private_property clArcAdmissibility & operator = (const clArcAdmissibility &); //------------------------------------------------------------------------------------------Public public_property constructor clArcAdmissibility(void); public_property virtual destructor clArcAdmissibility(void);
/*AMETHOD clArcAdmissibility */ /* Indicates if an arc is admissible in the direct direction. Abstract method. */ public_property virtual tyBoolean direct(const cpArc &) const = 0;
/*AMETHOD clArcAdmissibility */ /* Indicates if an arc is admissible in the indirect direction. Abstract method. */ public_property virtual tyBoolean indirect(const cpArc &) const = 0; }; }
// D e c r e a s e D e g r e e N o d e O r d e r i n g Interface //-------------------------------- namespace public_area { /*CLASS clDecreaseDegreeNodeOrder */ /* This class represents an ordering between two nodes, based on their degree. <I>x</I> is before <I>y</I> if its degree is greater than <I>y</I>'s one. It is a functor that can be used by STL functions to sort nodes. */ template <tdGraph> class clDecreaseDegreeNodeOrder { //-------------------------------------------------------------------------------------------Types /*TYPE clDecreaseDegreeNodeOrder */ /* Type of node this object compares. */ public_property typedef clNode<tuGraph> cpNode; //------------------------------------------------------------------------------------------Public public_property constructor clDecreaseDegreeNodeOrder(void); public_property constructor clDecreaseDegreeNodeOrder(const clDecreaseDegreeNodeOrder &); public_property destructor clDecreaseDegreeNodeOrder(void);
public_property clDecreaseDegreeNodeOrder & operator = (const clDecreaseDegreeNodeOrder &); public_property tyBoolean operator () (cpNode *,cpNode *) const; }; }
// I n c r e a s e D e g r e e N o d e O r d e r i n g Interface //-------------------------------- namespace public_area { /*CLASS clIncreaseDegreeNodeOrder */ /* This class represents an ordering between two nodes, based on their degree. <I>x</I> is before <I>y</I> if its degree is lower than <I>y</I>'s one. It is a functor that can be used by STL functions to sort nodes. */ template <tdGraph> class clIncreaseDegreeNodeOrder { //-------------------------------------------------------------------------------------------Types /*TYPE clIncreaseDegreeNodeOrder */ /* Type of node this object compares. */ public_property typedef clNode<tuGraph> cpNode; //------------------------------------------------------------------------------------------Public public_property constructor clIncreaseDegreeNodeOrder(void); public_property constructor clIncreaseDegreeNodeOrder(const clIncreaseDegreeNodeOrder &); public_property destructor clIncreaseDegreeNodeOrder(void);
public_property clIncreaseDegreeNodeOrder & operator = (const clIncreaseDegreeNodeOrder &); public_property tyBoolean operator () (cpNode *,cpNode *) const; }; }
// M i n t y C o l o r Interface //---------------------------------------------------------------- namespace public_area { /*CLASS clMintyColor */ /* This class represents a Minty coloration. It is used to define the color wanted for the arcs of a graph. This object is given as argument to the Minty cycle search function. This class is abstract. */ template <tdGraph> class clMintyColor { //-------------------------------------------------------------------------------------------Types /*TYPE clMintyColor */ /* Type of arc this object colors. */ public_property typedef clArc<tuGraph> cpArc; //-----------------------------------------------------------------------------------------Private private_property constructor clMintyColor(const clMintyColor &); private_property clMintyColor & operator = (const clMintyColor &); //------------------------------------------------------------------------------------------Public public_property constructor clMintyColor(void); public_property virtual destructor clMintyColor(void);
/*AMETHOD clMintyColor */ /* Indicates if an arc is red. Abstract method. */ public_property virtual tyBoolean red(const cpArc &) const = 0;
/*AMETHOD clMintyColor */ /* Indicates if an arc is black. Abstract method. */ public_property virtual tyBoolean black(const cpArc &) const = 0;
/*AMETHOD clMintyColor */ /* Indicates if an arc is black. Abstract method. */ public_property virtual tyBoolean blue(const cpArc &) const = 0;
/*AMETHOD clMintyColor */ /* Indicates if an arc is green. Abstract method. */ public_property virtual tyBoolean green(const cpArc &) const = 0;
public_property tcString color(const cpArc &) const; }; }
// M i n t y C o l o r F o r C i r c u i t D e t e c t i o n Interface //-------------------------- namespace private_area { template <tdGraph> class clMintyColorForCircuitDetection { //-------------------------------------------------------------------------------------------Types public_property typedef clArc<tuGraph> cpArc; //-----------------------------------------------------------------------------------------Private private_property constructor clMintyColorForCircuitDetection(const clMintyColorForCircuitDetection &);
private_property clMintyColorForCircuitDetection & operator = (const clMintyColorForCircuitDetection &); //------------------------------------------------------------------------------------------Public public_property constructor clMintyColorForCircuitDetection(void) {} public_property destructor clMintyColorForCircuitDetection(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 C y c l e D e t e c t i o n Interface //------------------------------ namespace private_area { template <tdGraph> class clMintyColorForCycleDetection { //-------------------------------------------------------------------------------------------Types public_property typedef clArc<tuGraph> cpArc; //-----------------------------------------------------------------------------------------Private private_property constructor clMintyColorForCycleDetection(const clMintyColorForCycleDetection &);
private_property clMintyColorForCycleDetection & operator = (const clMintyColorForCycleDetection &); //------------------------------------------------------------------------------------------Public public_property constructor clMintyColorForCycleDetection(void) {} public_property destructor clMintyColorForCycleDetection(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; }; }
// S t a n d a r d A r c A d m i s s i b i l i t y Interface //------------------------------------ namespace private_area { template <tdGraph> class clStandardArcAdmissibility { //-------------------------------------------------------------------------------------------Types public_property typedef clArc<tuGraph> cpArc; //-----------------------------------------------------------------------------------------Private private_property constructor clStandardArcAdmissibility(const clStandardArcAdmissibility &); private_property clStandardArcAdmissibility & operator = (const clStandardArcAdmissibility &); //------------------------------------------------------------------------------------------Public public_property constructor clStandardArcAdmissibility(void) {} public_property destructor clStandardArcAdmissibility(void) {}
public_property tyBoolean direct(const cpArc &) const { return (true); } public_property tyBoolean indirect(const cpArc &) const { return (false); } }; }
// Functions Inline //------------------------------------------------------------------------------ namespace public_area { //----------------------------------------------------------------------------------------FirstNode /*FUNCTION*/ /* Returns the node of a graph that has no predecessor. If no such node exists or if more than one such node exist, then <CODE>nil</CODE> is returned. */ template <tdGraph> inline clNode<tuGraph> * firstNode(const clGraph<tuGraph> & agGraph) { std_vector(clNode<tuGraph> *) lcNodeS;
findFirstNodes(agGraph,lcNodeS); if (lcNodeS.size()!=1) return (nil); return (*(lcNodeS.begin())); } //-----------------------------------------------------------------------------------------LastNode /*FUNCTION*/ /* Returns the node of a graph that has no successor. If no such node exists or if more than one such node exist, then <CODE>nil</CODE> is returned. */ template <tdGraph> inline clNode<tuGraph> * lastNode(const clGraph<tuGraph> & agGraph) { std_vector(clNode<tuGraph> *) lcNodeS;
findLastNodes(agGraph,lcNodeS); if (lcNodeS.size()!=1) return (nil); return (*(lcNodeS.begin())); } //--------------------------------------------------------------------------------------FindCircuit /*FUNCTION*/ /* Finds a circuit containing a given arc. Returns <CODE>false</CODE> if there is no such circuit. The result is a list containing the arc keys of the circuit with their direction (always +1). */ template <tdGraph> inline tyBoolean findCircuit(clGraph<tuGraph> & agGraph,tyArcKey agArcKey,clCycle & agCircuit) { clCocycle lcCocycle; private_area::clMintyColorForCircuitDetection<tuGraph> lcMintyColor;
return (findMintyCycle(agGraph,agArcKey,lcMintyColor,agCircuit,lcCocycle)); } //----------------------------------------------------------------------------------------FindCycle /*FUNCTION*/ /* Finds a cycle containing a given arc. Returns <CODE>false</CODE> if there is no such cycle. The result is a list containing the arc keys of the cycle with their direction. */ template <tdGraph> inline tyBoolean findCycle(clGraph<tuGraph> & agGraph,tyArcKey agArcKey,clCycle & agCycle) { clCocycle lcCocycle; private_area::clMintyColorForCycleDetection<tuGraph> lcMintyColor;
return (findMintyCycle(agGraph,agArcKey,lcMintyColor,agCycle,lcCocycle)); } //--------------------------------------------------------------------------------------FindCircuit /*FUNCTION*/ /* Finds a circuit containing a given arc. Returns <CODE>false</CODE> if there is no such circuit. The result is a list containing the arc memory pointers of the circuit with their direction (always +1). */ template <tdGraph> inline tyBoolean findCircuit(clArc<tuGraph> & agArc,std_map(clArc<tuGraph> *,tyInteger) & agCircuit) { std_map(clArc<tuGraph> *,tyInteger) lcCocycle; private_area::clMintyColorForCircuitDetection<tuGraph> lcMintyColor;
return (findMintyCycle(agArc,lcMintyColor,agCircuit,lcCocycle)); } //----------------------------------------------------------------------------------------FindCycle /*FUNCTION*/ /* Finds a cycle containing a given arc. Returns <CODE>false</CODE> if there is no such cycle. The result is a list containing the arc memory pointers of the cycle with their direction. */ template <tdGraph> inline tyBoolean findCycle(clArc<tuGraph> & agArc,std_map(clArc<tuGraph> *,tyInteger) & agCycle) { std_map(clArc<tuGraph> *,tyInteger) lcCocycle; private_area::clMintyColorForCycleDetection<tuGraph> lcMintyColor;
return (findMintyCycle(agArc,lcMintyColor,agCycle,lcCocycle)); } //--------------------------------------------------------------------------FindTopologicalOrdering /*FUNCTION*/ /* Finds a topological ordering of the nodes of a graph. There must be no circuit. Returns <CODE>true</CODE> if an ordering is found. The result is an ordered list containing the node memory pointers. */ template <tdGraph> inline tyBoolean findTopologicalOrdering(clGraph<tuGraph> & agGraph, std_vector(clNode<tuGraph> *) & agNodeS) { private_area::clStandardArcAdmissibility<tuGraph> lcAdmissibility;
return (findTopologicalOrdering(agGraph,lcAdmissibility,agNodeS)); } }
namespace private_area {}
// A r c A d m i s s i b i l i t y Inline //------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clArcAdmissibility */ /* Builds an arc admissibility. */ template <tdGraph> inline clArcAdmissibility<tuGraph>::clArcAdmissibility(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clArcAdmissibility */ /* Destructs the arc admissibility. */ template <tdGraph> inline clArcAdmissibility<tuGraph>::~clArcAdmissibility(void) {} }
// D e c r e a s e D e g r e e N o d e O r d e r i n g Inline //----------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clDecreaseDegreeNodeOrder */ /* Builds a node ordering. */ template <tdGraph> inline clDecreaseDegreeNodeOrder<tuGraph>::clDecreaseDegreeNodeOrder(void) {} //--------------------------------------------------------------------------------------Constructor /*METHOD clDecreaseDegreeNodeOrder */ /* Builds a node ordering by copying another one. */ template <tdGraph> inline clDecreaseDegreeNodeOrder<tuGraph>:: clDecreaseDegreeNodeOrder(const clDecreaseDegreeNodeOrder &) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clDecreaseDegreeNodeOrder */ /* Destructs the ordering. */ template <tdGraph> inline clDecreaseDegreeNodeOrder<tuGraph>::~clDecreaseDegreeNodeOrder(void) {} //---------------------------------------------------------------------------------------Operator = /*METHOD clDecreaseDegreeNodeOrder */ /* Copies an ordering. */ template <tdGraph> inline clDecreaseDegreeNodeOrder<tuGraph> & clDecreaseDegreeNodeOrder<tuGraph>::operator = (const clDecreaseDegreeNodeOrder &) { return (*this); } //--------------------------------------------------------------------------------------Operator () /*METHOD clDecreaseDegreeNodeOrder */ /* Compares two nodes. */ template <tdGraph> inline tyBoolean clDecreaseDegreeNodeOrder<tuGraph>::operator () (cpNode * agNode1,cpNode * agNode2) const { tyCardinal lcDegree1 = agNode1->incomingArcs().size()+agNode1->outgoingArcs().size(); tyCardinal lcDegree2 = agNode2->incomingArcs().size()+agNode2->outgoingArcs().size();
return (lcDegree1>lcDegree2); } }
// I n c r e a s e D e g r e e N o d e O r d e r i n g Inline //----------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clIncreaseDegreeNodeOrder */ /* Builds a node ordering. */ template <tdGraph> inline clIncreaseDegreeNodeOrder<tuGraph>::clIncreaseDegreeNodeOrder(void) {} //--------------------------------------------------------------------------------------Constructor /*METHOD clIncreaseDegreeNodeOrder */ /* Builds a node ordering by copying another one. */ template <tdGraph> inline clIncreaseDegreeNodeOrder<tuGraph>:: clIncreaseDegreeNodeOrder(const clIncreaseDegreeNodeOrder &) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clIncreaseDegreeNodeOrder */ /* Destructs the ordering. */ template <tdGraph> inline clIncreaseDegreeNodeOrder<tuGraph>::~clIncreaseDegreeNodeOrder(void) {} //---------------------------------------------------------------------------------------Operator = /*METHOD clIncreaseDegreeNodeOrder */ /* Copies an ordering. */ template <tdGraph> inline clIncreaseDegreeNodeOrder<tuGraph> & clIncreaseDegreeNodeOrder<tuGraph>::operator = (const clIncreaseDegreeNodeOrder &) { return (*this); } //--------------------------------------------------------------------------------------Operator () /*METHOD clIncreaseDegreeNodeOrder */ /* Compares two nodes. */ template <tdGraph> inline tyBoolean clIncreaseDegreeNodeOrder<tuGraph>::operator () (cpNode * agNode1,cpNode * agNode2) const { tyCardinal lcDegree1 = agNode1->incomingArcs().size()+agNode1->outgoingArcs().size(); tyCardinal lcDegree2 = agNode2->incomingArcs().size()+agNode2->outgoingArcs().size();
return (lcDegree1<lcDegree2); } }
// M i n t y C o l o r Inline //------------------------------------------------------------------ namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clMintyColor */ /* Builds the Minty coloration. */ template <tdGraph> inline clMintyColor<tuGraph>::clMintyColor(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clMintyColor */ /* Destructs the Minty coloration. */ template <tdGraph> inline clMintyColor<tuGraph>::~clMintyColor(void) {} }
// M i n t y C o l o r F o r C i r c u i t D e t e c t i o n Inline //----------------------------- namespace private_area { //----------------------------------------------------------------------------------------------Red template <tdGraph> inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::red(const cpArc &) const { return (false); } //--------------------------------------------------------------------------------------------Black template <tdGraph> inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::black(const cpArc &) const { return (true); } //---------------------------------------------------------------------------------------------Blue template <tdGraph> inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::blue(const cpArc &) const { return (false); } //--------------------------------------------------------------------------------------------Green template <tdGraph> inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::green(const cpArc &) const { return (false); } }
// M i n t y C o l o r F o r C y c l e D e t e c t i o n Inline //--------------------------------- namespace private_area { //----------------------------------------------------------------------------------------------Red template <tdGraph> inline tyBoolean clMintyColorForCycleDetection<tuGraph>::red(const cpArc &) const { return (false); } //--------------------------------------------------------------------------------------------Black template <tdGraph> inline tyBoolean clMintyColorForCycleDetection<tuGraph>::black(const cpArc &) const { return (false); } //---------------------------------------------------------------------------------------------Blue template <tdGraph> inline tyBoolean clMintyColorForCycleDetection<tuGraph>::blue(const cpArc &) const { return (false); } //--------------------------------------------------------------------------------------------Green template <tdGraph> inline tyBoolean clMintyColorForCycleDetection<tuGraph>::green(const cpArc &) const { return (true); } }
// Functions Implementation //---------------------------------------------------------------------- namespace public_area { //-------------------------------------------------------------------------------EliminateNonCycles /*FUNCTION*/ /* Eliminates the arcs and the nodes of a graph that do not belong to any cycle. */ template <tdGraph> void eliminateNonCycles(clGraph<tuGraph> & agGraph) { typedef clGraph<tuGraph> cpGraph; typedef clNode<tuGraph> cpNode; typedef typename cpGraph::cpNodeX::const_iterator cpNodeIterator;
cpNode * lcNode;
cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpNodeIterator lcLastNode = agGraph.nodes().end();
while (lcCurrentNode!=lcLastNode) { lcNode=(*lcCurrentNode).second; if (lcNode->outgoingArcs().size()+lcNode->incomingArcs().size() < 2) { delete_object(lcNode); lcCurrentNode=agGraph.nodes().begin(); } else lcCurrentNode++; } } //--------------------------------------------------------------------------------------FindCocycle /*FUNCTION*/ /* Finds the cocycle that separates a group of nodes from the rest of a graph. The result is the list of the incoming arcs and the list of the outgoing arcs. */ template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) & agNodeS, std_vector(clArc<tuGraph> *) & agIncomingArcS, std_vector(clArc<tuGraph> *) & agOutgoingArcS) { typedef typename clNode<tuGraph>::cpArcX::const_iterator clArcIterator; typedef typename std_vector(clNode<tuGraph> *)::const_iterator clNodeIterator;
clArc<tuGraph> * lcArc; clArcIterator lcCurrentArc; clArcIterator lcLastArc;
if (agNodeS.empty()) return;
clNodeIterator lcCurrentNode = agNodeS.begin(); clNodeIterator lcLastNode = agNodeS.end(); clGraph<tuGraph> & lcGraph = (*(lcCurrentNode))->graph(); tyMark lcBothMark = ++(lcGraph.mark()); tyMark lcSourceMark = ++(lcGraph.mark()); tyMark lcTargetMark = ++(lcGraph.mark()); tyCardinal lcNbIncoming = 0; tyCardinal lcNbOutgoing = 0;
while (lcCurrentNode!=lcLastNode) { lcCurrentArc=(*lcCurrentNode)->incomingArcs().begin(); lcLastArc=(*lcCurrentNode)->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcCurrentArc++;
if (lcArc->mark()==lcSourceMark) { lcArc->mark()=lcBothMark; lcNbOutgoing--; } else { lcArc->mark()=lcTargetMark; lcNbIncoming++; } }
lcCurrentArc=(*lcCurrentNode)->outgoingArcs().begin(); lcLastArc=(*lcCurrentNode)->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcCurrentArc++;
if (lcArc->mark()==lcTargetMark) { lcArc->mark()=lcBothMark; lcNbIncoming--; } else { lcArc->mark()=lcSourceMark; lcNbOutgoing++; } }
lcCurrentNode++; }
agOutgoingArcS.reserve(agOutgoingArcS.size()+lcNbOutgoing); agIncomingArcS.reserve(agIncomingArcS.size()+lcNbIncoming);
lcCurrentArc=lcGraph.arcs().begin(); lcLastArc=lcGraph.arcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcArc->mark()==lcSourceMark) agOutgoingArcS.push_back(lcArc); else if (lcArc->mark()==lcTargetMark) agIncomingArcS.push_back(lcArc);
lcCurrentArc++; } } //--------------------------------------------------------------------------------------FindCocycle /*FUNCTION*/ /* Finds the cocycle that separates a group of nodes from the rest of a graph. The result is a list containing the arc keys and their direction in the cocycle. */ template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) & agNodeS, clCocycle & agCocycle) { typedef typename clNode<tuGraph>::cpArcX::const_iterator clArcIterator; typedef typename std_vector(clNode<tuGraph> *)::const_iterator clNodeIterator;
clArc<tuGraph>* lcArc; clArcIterator lcCurrentArc; clArcIterator lcLastArc;
if (agNodeS.empty()) return;
clNodeIterator lcCurrentNode = agNodeS.begin(); clNodeIterator lcLastNode = agNodeS.end(); clGraph<tuGraph> & lcGraph = (*(lcCurrentNode))->graph(); tyMark lcBothMark = ++(lcGraph.mark()); tyMark lcSourceMark = ++(lcGraph.mark()); tyMark lcTargetMark = ++(lcGraph.mark());
while (lcCurrentNode!=lcLastNode) { lcCurrentArc=(*lcCurrentNode)->incomingArcs().begin(); lcLastArc=(*lcCurrentNode)->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcCurrentArc++;
if (lcArc->mark()==lcSourceMark) lcArc->mark()=lcBothMark; else lcArc->mark()=lcTargetMark; }
lcCurrentArc=(*lcCurrentNode)->outgoingArcs().begin(); lcLastArc=(*lcCurrentNode)->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcCurrentArc++;
if (lcArc->mark()==lcTargetMark) lcArc->mark()=lcBothMark; else lcArc->mark()=lcSourceMark; }
lcCurrentNode++; }
lcCurrentArc=lcGraph.arcs().begin(); lcLastArc=lcGraph.arcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcArc->mark()==lcSourceMark) agCocycle.insert(clCocycle::value_type(lcArc->key(),+1)); else if (lcArc->mark()==lcTargetMark) agCocycle.insert(clCocycle::value_type(lcArc->key(),-1));
lcCurrentArc++; } } //--------------------------------------------------------------------------------------FindCocycle /*FUNCTION*/ /* Finds the cocycle that separates a group of nodes from the rest of a graph. The result is a list containing the arc memory pointers and their direction in the cocycle. */ template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) & agNodeS, std_map(clArc<tuGraph> *,tyInteger) & agCocycle) { typedef typename clNode<tuGraph>::cpArcX::const_iterator clArcIterator; typedef typename std_vector(clNode<tuGraph> *)::const_iterator clNodeIterator;
clArc<tuGraph>* lcArc; clArcIterator lcCurrentArc; clArcIterator lcLastArc;
if (agNodeS.empty()) return;
clNodeIterator lcCurrentNode = agNodeS.begin(); clNodeIterator lcLastNode = agNodeS.end(); clGraph<tuGraph> & lcGraph = (*(lcCurrentNode))->graph(); tyMark lcBothMark = ++(lcGraph.mark()); tyMark lcSourceMark = ++(lcGraph.mark()); tyMark lcTargetMark = ++(lcGraph.mark());
while (lcCurrentNode!=lcLastNode) { lcCurrentArc=(*lcCurrentNode)->incomingArcs().begin(); lcLastArc=(*lcCurrentNode)->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcCurrentArc++;
if (lcArc->mark()==lcSourceMark) lcArc->mark()=lcBothMark; else lcArc->mark()=lcTargetMark; }
lcCurrentArc=(*lcCurrentNode)->outgoingArcs().begin(); lcLastArc=(*lcCurrentNode)->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcCurrentArc++;
if (lcArc->mark()==lcTargetMark) lcArc->mark()=lcBothMark; else lcArc->mark()=lcSourceMark; }
lcCurrentNode++; }
lcCurrentArc=lcGraph.arcs().begin(); lcLastArc=lcGraph.arcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcArc->mark()==lcSourceMark) agCocycle.insert(std_make_pair(lcArc,+1)); else if (lcArc->mark()==lcTargetMark) agCocycle.insert(std_make_pair(lcArc,-1));
lcCurrentArc++; } } //---------------------------------------------------------------------------------------FindCycles /*FUNCTION*/ /* Finds as independent cycles as possible in the graph. Any cycle in the graph is a linear combination of these cycles. In other word, any cycle in the graph can be recomposed from those cycles. The result is a list of cycles, each cycle is a list containing the arc keys and their direction in the cycle. The algorithm can be forced to find short cycles (default is not). */ template <tdGraph> void findCycles(clGraph<tuGraph> & agGraph,clCycleS & agCycleS, tyBoolean agShort) { typedef clArc<tuGraph> cpArc; typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator; typedef std_vector(clArc<tuGraph> *) cpArcS; typedef std_vector(tyCardinal) cpIndexS; typedef std_vector(clNode<tuGraph> *) cpNodeS;
cpArc * lcArc; cpArcS lcArcS(agGraph.nodes().size()); tyMark lcMark; cpNodeS lcNodeS(agGraph.nodes().size()); cpIndexS lcPreviousS(agGraph.nodes().size());
cpArcIterator lcCurrentArc = agGraph.arcs().begin(); cpArcIterator lcLastArc = agGraph.arcs().end();
if (agShort) private_area::makeCycleBroadTree(agGraph,lcNodeS,lcArcS,lcPreviousS); else private_area::makeCycleDeepTree(agGraph,lcNodeS,lcArcS,lcPreviousS);
agCycleS.erase(agCycleS.begin(),agCycleS.end()); lcMark=agGraph.mark();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcArc->mark()!=lcMark) { agCycleS.push_back(clCycle()); private_area::makeCycle(agGraph,lcNodeS,lcArcS,lcPreviousS,agCycleS.back(),*lcArc); }
++lcCurrentArc; } } //---------------------------------------------------------------------------------------FindCycles /*FUNCTION*/ /* Finds as independent cycles as possible in the graph. Any cycle in the graph is a linear combination of these cycles. In other word, any cycle in the graph can be recomposed from those cycles. The result is a list of cycles, each cycle is a list containing the arc memory pointers and their direction in the cycle. The algorithm can be forced to find short cycles (default is not). */ template <tdGraph> void findCycles(clGraph<tuGraph> & agGraph, std_vector(std_map(clArc<tuGraph> *,tyInteger)) & agCycleS, tyBoolean agShort) { typedef clArc<tuGraph> cpArc; typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator; typedef std_vector(clArc<tuGraph> *) cpArcS; typedef std_map(clArc<tuGraph> *,tyInteger) cpCycle; typedef std_vector(tyCardinal) cpIndexS; typedef std_vector(clNode<tuGraph> *) cpNodeS;
cpArc * lcArc; cpArcS lcArcS(agGraph.nodes().size()); tyMark lcMark; cpNodeS lcNodeS(agGraph.nodes().size()); cpIndexS lcPreviousS(agGraph.nodes().size());
cpArcIterator lcCurrentArc = agGraph.arcs().begin(); cpArcIterator lcLastArc = agGraph.arcs().end();
if (agShort) private_area::makeCycleBroadTree(agGraph,lcNodeS,lcArcS,lcPreviousS); else private_area::makeCycleDeepTree(agGraph,lcNodeS,lcArcS,lcPreviousS);
agCycleS.erase(agCycleS.begin(),agCycleS.end()); lcMark=agGraph.mark();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; if (lcArc->mark()!=lcMark) { agCycleS.push_back(cpCycle()); private_area::makeCycle(agGraph,lcNodeS,lcArcS,lcPreviousS,agCycleS.back(),*lcArc); }
++lcCurrentArc; } } //-----------------------------------------------------------------------------------FindFirstNodes /*FUNCTION*/ /* Finds in a graph the nodes that have no predecessor. */ template <tdGraph> void findFirstNodes(const clGraph<tuGraph> & agGraph, std_vector(clNode<tuGraph> *) & agNodeS) { typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpNodeIterator lcLastNode = agGraph.nodes().end();
while (lcCurrentNode!=lcLastNode) { if ((*lcCurrentNode).second->incomingArcs().size()==0) agNodeS.push_back((*lcCurrentNode).second);
lcCurrentNode++; } } //------------------------------------------------------------------------------------FindLastNodes /*FUNCTION*/ /* Finds in a graph the nodes that have no successor. */ template <tdGraph> void findLastNodes(const clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS) { typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpNodeIterator lcLastNode = agGraph.nodes().end();
while (lcCurrentNode!=lcLastNode) { if ((*lcCurrentNode).second->outgoingArcs().size()==0) agNodeS.push_back((*lcCurrentNode).second);
lcCurrentNode++; } } //------------------------------------------------------------------------------------AddSourceNode /*FUNCTION*/ /* Adds a node to a graph. This node becomes the predecessor of all the nodes that had not one. */ template <tdGraph> tyNodeKey addSourceNode(clGraph<tuGraph> & agGraph, const prArcData & agArcData, const prNodeData & agNodeData) { typedef clArc<tuGraph> cpArc; typedef clNode<tuGraph> cpNode; typedef std_vector(cpNode *) cpNodeS;
typedef typename cpNodeS::const_iterator cpNodeIterator1; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator2; typedef typename clGraph<tuGraph>::cpNodeX::difference_type cpNodeDistance;
cpNodeIterator1 lcCurrentNode; cpNodeIterator1 lcLastNode; cpNodeS lcNodeS; cpNodeIterator2 lcRandomNode; cpNode * lcSourceNode;
findFirstNodes(agGraph,lcNodeS); lcCurrentNode=lcNodeS.begin(); lcLastNode=lcNodeS.end(); if (lcNodeS.size()==1) return ((*lcCurrentNode)->key()); lcSourceNode=new_object(cpNode(agGraph,agGraph.getNewNodeKey(),agNodeData));
if (lcNodeS.size()==0) { do { lcRandomNode=agGraph.nodes().begin(); std_advance(lcRandomNode,cpNodeDistance(randomCardinal(agGraph.nodes().size()))); } while (lcSourceNode->key()==(*lcRandomNode).second->key());
new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData, lcSourceNode->key(),(*lcRandomNode).second->key())); } else { while (lcCurrentNode!=lcLastNode) { new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData, lcSourceNode->key(),(*lcCurrentNode)->key()));
lcCurrentNode++; } }
return (lcSourceNode->key()); } //------------------------------------------------------------------------------------AddTargetNode /*FUNCTION*/ /* Adds a node to a graph. This node becomes the successor of all the nodes that had not one. */ template <tdGraph> tyNodeKey addTargetNode(clGraph<tuGraph> & agGraph, const prArcData & agArcData, const prNodeData & agNodeData) { typedef clArc<tuGraph> cpArc; typedef clNode<tuGraph> cpNode; typedef std_vector(cpNode *) cpNodeS;
typedef typename cpNodeS::const_iterator cpNodeIterator1; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator2; typedef typename clGraph<tuGraph>::cpNodeX::difference_type cpNodeDistance;
cpNodeIterator1 lcCurrentNode; cpNodeIterator1 lcLastNode; cpNodeS lcNodeS; cpNodeIterator2 lcRandomNode; cpNode * lcTargetNode;
findLastNodes(agGraph,lcNodeS); lcCurrentNode=lcNodeS.begin(); lcLastNode=lcNodeS.end(); if (lcNodeS.size()==1) return ((*lcCurrentNode)->key()); lcTargetNode=new_object(cpNode(agGraph,agGraph.getNewNodeKey(),agNodeData));
if (lcNodeS.size()==0) { do { lcRandomNode=agGraph.nodes().begin(); std_advance(lcRandomNode,cpNodeDistance(randomCardinal(agGraph.nodes().size()))); } while ((*lcRandomNode).second->key()==lcTargetNode->key());
new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData, (*lcRandomNode).second->key(),lcTargetNode->key())); } else { while (lcCurrentNode!=lcLastNode) { new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData, (*lcCurrentNode)->key(),lcTargetNode->key()));
lcCurrentNode++; } }
return (lcTargetNode->key()); } //-----------------------------------------------------------------------------------FindMintyCycle /*FUNCTION*/ /* Finds a cycle or a cocycle according to a Minty coloration. It searchs a cycle that contains a given arc <I>x</I>. Moreover any other arc in the cycle must be green, blue or black. Green arcs can be in the same direction as <I>x</I> or in the opposite direction, blue arcs must be in the opposite direction and black ones in the same direction. If no such cycle exists, there must be a cocycle containing <I>x</I> that have only red, blue and black arcs. Red arcs can be in the same direction as <I>x</I> or in the opposite direction, blue arcs must be in the opposite direction and black ones in the same direction. The result is a list containing the arc keys with their direction. */ template <tdGraph,class prMintyColor> tyBoolean findMintyCycle(clGraph<tuGraph> & agGraph,tyArcKey agKey,const prMintyColor & agTest, clCycle & agCycle,clCocycle & agCocycle) { typedef std_vector(clArc<tuGraph> *) cpArcS; typedef std_vector(clNode<tuGraph> *) cpNodeS; typedef std_vector(tyCardinal) cpIndexS;
cpArcS lcArcS(agGraph.nodes().size()); tyCardinal lcNbMark; cpNodeS lcNodeS(agGraph.nodes().size()); cpIndexS lcPreviousS(agGraph.nodes().size());
clCocycle::iterator lcCurrentArc; tyCardinal lcIndex; clCocycle::iterator lcLastArc;
agCycle.erase(agCycle.begin(),agCycle.end()); agCocycle.erase(agCocycle.begin(),agCocycle.end());
// Cycle Construction // if (private_area::findMintyCycle(agGraph.arc(agKey),agTest,lcNodeS, lcArcS,lcPreviousS,lcNbMark)) { if (lcNbMark>0) { lcIndex=lcNbMark-1;
while (lcArcS[lcIndex]!=nil) { if (lcArcS[lcIndex]->targetNode()==lcNodeS[lcIndex]) agCycle.insert(clCycle::value_type(lcArcS[lcIndex]->key(),+1)); else agCycle.insert(clCycle::value_type(lcArcS[lcIndex]->key(),-1));
lcIndex=lcPreviousS[lcIndex]; } }
agCycle.insert(clCycle::value_type(agKey,+1)); return (true); }
// Cocycle Construction // else { lcNodeS.resize(lcNbMark); findCocycle(lcNodeS,agCocycle); lcCurrentArc=agCocycle.begin(); lcLastArc=agCocycle.end();
while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc).second*=-1; lcCurrentArc++; }
return (false); } } //-----------------------------------------------------------------------------------FindMintyCycle /*FUNCTION*/ /* Finds a cycle or a cocycle according to a Minty coloration. It searchs a cycle that contains a given arc <I>x</I>. Moreover any other arc in the cycle must be green, blue or black. Green arcs can be in the same direction as <I>x</I> or in the opposite direction, blue arcs must be in the opposite direction and black ones in the same direction. If no such cycle exists, there must be a cocycle containing <I>x</I> that have only red, blue and black arcs. Red arcs can be in the same direction as <I>x</I> or in the opposite direction, blue arcs must be in the opposite direction and black ones in the same direction. The result is a list containing the arc memory pointers with their direction. */ template <tdGraph,class prMintyColor> tyBoolean findMintyCycle(clArc<tuGraph> & agArc,const prMintyColor & agTest, std_map(clArc<tuGraph> *,tyInteger) & agCycle, std_map(clArc<tuGraph> *,tyInteger) & agCocycle) { typedef std_vector(clArc<tuGraph> *) cpArcS; typedef std_map(clArc<tuGraph> *,tyInteger) cpCocycle; typedef std_vector(tyCardinal) cpIndexS; typedef typename cpCocycle::iterator cpIterator; typedef std_vector(clNode<tuGraph> *) cpNodeS;
clGraph<tuGraph> & lcGraph = agArc.graph();
cpArcS lcArcS(lcGraph.nodes().size()); tyCardinal lcNbMark; cpNodeS lcNodeS(lcGraph.nodes().size()); cpIndexS lcPreviousS(lcGraph.nodes().size());
cpIterator lcCurrentArc; cpIterator lcLastArc; tyCardinal lcIndex;
agCycle.erase(agCycle.begin(),agCycle.end()); agCocycle.erase(agCocycle.begin(),agCocycle.end());
// Cycle Construction // if (private_area::findMintyCycle(agArc,agTest,lcNodeS,lcArcS,lcPreviousS,lcNbMark)) { if (lcNbMark>0) { lcIndex=lcNbMark-1;
while (lcArcS[lcIndex]!=nil) { if (lcArcS[lcIndex]->targetNode()==lcNodeS[lcIndex]) agCycle.insert(std_make_pair(lcArcS[lcIndex],+1)); else agCycle.insert(std_make_pair(lcArcS[lcIndex],-1));
lcIndex=lcPreviousS[lcIndex]; } }
agCycle.insert(std_make_pair(&agArc,+1)); return (true); }
// Cocycle Construction // else { lcNodeS.resize(lcNbMark); findCocycle(lcNodeS,(std_map(clArc<tuGraph> *,tyInteger) &)agCocycle); lcCurrentArc=agCocycle.begin(); lcLastArc=agCocycle.end();
while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc).second*=-1; lcCurrentArc++; }
return (false); } } //---------------------------------------------------------------------------------FindCoveringTree /*FUNCTION*/ /* Finds a covering tree in a graph. */ template <tdGraph> void findCoveringTree(clGraph<tuGraph> & agGraph,clGraph<tuGraph> & agTree) { method_name("findCoveringTree");
typedef clArc<tuGraph> cpArc; typedef clNode<tuGraph> cpNode; typedef typename cpNode::cpArcX::const_iterator cpArcIterator;
tyMark lcMark = ++(agGraph.mark());
cpArc * lcArc; cpArcIterator lcCurrentArc; cpArcIterator lcLastArc; cpNode * lcNode1; cpNode * lcNode2; std_vector(cpNode *) lcNodeS;
agTree.clear(); lcNode1=(*agGraph.nodes().begin()).second; lcNodeS.push_back(lcNode1); lcNode1->mark()=lcMark; new_object(cpNode(agTree,*lcNode1));
while (lcNodeS.size()!=0) { lcNode1=lcNodeS.back(); lcNodeS.pop_back();
// Outgoing Arcs // lcCurrentArc=lcNode1->outgoingArcs().begin(); lcLastArc=lcNode1->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcNode2=lcArc->targetNode();
if (lcNode2->mark()!=lcMark) { lcNodeS.push_back(lcNode2); lcNode2->mark()=lcMark; new_object(cpNode(agTree,*lcNode2)); new_object(cpArc(agTree,*lcArc)); }
lcCurrentArc++; }
// Incoming Arcs // lcCurrentArc=lcNode1->incomingArcs().begin(); lcLastArc=lcNode1->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcNode2=lcArc->sourceNode();
if (lcNode2->mark()!=lcMark) { lcNodeS.push_back(lcNode2); lcNode2->mark()=lcMark; new_object(cpNode(agTree,*lcNode2)); new_object(cpArc(agTree,*lcArc)); }
lcCurrentArc++; } }
if (agTree.nodes().size()!=agGraph.nodes().size()) send_error(erGraphNotConnex); } //----------------------------------------------------------------------Operator << (Cycle/Cocycle) /*FUNCTION*/ /* Writes a cycle or a cocycle into a stream. */ template <tdGraph> clOutStream & operator << (clOutStream & agStream, const std_map(clArc<tuGraph> *,tyInteger) & agCycle) { typedef typename std_map(clArc<tuGraph> *,tyInteger)::const_iterator cpIterator;
clCycle lcCycle;
cpIterator lcCurrentArc = agCycle.begin(); cpIterator lcLastArc = agCycle.end();
while (lcCurrentArc!=lcLastArc) { lcCycle.insert(std_make_pair(lcCurrentArc->first->key(),lcCurrentArc->second)); ++lcCurrentArc; }
agStream << lcCycle;
return (agStream); } //--------------------------------------------------------------------------FindTopologicalOrdering /*FUNCTION*/ /* Finds a topological ordering of the nodes of a graph. There must be no circuit. Returns <CODE>true</CODE> if an ordering is found. The result is an ordered list containing the node memory pointers. An object with the <CODE>clArcAdmissibility</CODE> interface is given to indicate if an arc must be used (in the direct or indirect direction) during the search. Check the <CODE>clArcAdmissibility</CODE> class for more details. */ template <tdGraph,class prArcAdmissibility> tyBoolean findTopologicalOrdering(clGraph<tuGraph> & agGraph,const prArcAdmissibility & agTest, std_vector(clNode<tuGraph> *) & agNodeS) { typedef typename clNode<tuGraph>::cpArcX::const_iterator cpArcIterator; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
clArc<tuGraph> * lcArc; tyCardinal lcCounter; cpArcIterator lcCurrentArc; tyBoolean lcError; cpArcIterator lcLastArc; std_vector(tyPointer) lcWorkS; clNode<tuGraph> * lcNode; tyCardinal * lcNumber;
cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpNodeIterator lcLastNode = agGraph.nodes().end();
// Workspace Saving & Initialization // while (lcCurrentNode!=lcLastNode) { lcNode=(*lcCurrentNode).second; lcWorkS.push_back(lcNode->work()); lcNode->work()=new_object(tyCardinal); ++lcCurrentNode; }
agNodeS.erase(agNodeS.begin(),agNodeS.end());
// First Nodes Search // lcCurrentNode=agGraph.nodes().begin(); lcLastNode=agGraph.nodes().end();
while (lcCurrentNode!=lcLastNode) { lcNode=(*lcCurrentNode).second; lcNumber=(tyCardinal *)lcNode->work(); *lcNumber=0; lcCurrentArc=lcNode->incomingArcs().begin(); lcLastArc=lcNode->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { if (agTest.direct(*((*lcCurrentArc).second))) ++(*lcNumber); ++lcCurrentArc; }
lcCurrentArc=lcNode->outgoingArcs().begin(); lcLastArc=lcNode->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { if (agTest.indirect(*((*lcCurrentArc).second))) ++(*lcNumber); ++lcCurrentArc; }
if (*lcNumber==0) agNodeS.push_back(lcNode); ++lcCurrentNode; }
// Graph Search // lcCounter=0;
while (lcCounter<agNodeS.size()) { lcNode=agNodeS[lcCounter]; lcCurrentArc=lcNode->outgoingArcs().begin(); lcLastArc=lcNode->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (agTest.direct(*lcArc)) { lcNumber=(tyCardinal *)lcArc->targetNode()->work();
if (*lcNumber==0) { lcError=true; goto lbEnd; }
--(*lcNumber); if (*lcNumber==0) agNodeS.push_back(lcArc->targetNode()); }
++lcCurrentArc; }
lcCurrentArc=lcNode->incomingArcs().begin(); lcLastArc=lcNode->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) {
if (agTest.indirect(*((*lcCurrentArc).second))) { lcArc=(*lcCurrentArc).second; lcNumber=(tyCardinal *)lcArc->sourceNode()->work();
if (*lcNumber==0) { lcError=true; goto lbEnd; }
--(*lcNumber); if (*lcNumber==0) agNodeS.push_back(lcArc->sourceNode()); }
++lcCurrentArc; }
++lcCounter; }
lcError=(agNodeS.size()!=agGraph.nodes().size());
// Workspace Restoring // lbEnd: lcCurrentNode=agGraph.nodes().begin(); lcLastNode=agGraph.nodes().end(); lcCounter=0;
while (lcCurrentNode!=lcLastNode) { lcNode=(*lcCurrentNode).second; delete_object((tyCardinal *)lcNode->work()); lcNode->work()=lcWorkS[lcCounter]; ++lcCounter; ++lcCurrentNode; }
return (not lcError); } }
namespace private_area { //-----------------------------------------------------------------------------------FindMintyCycle template <tdGraph,class prMintyColor> tyBoolean findMintyCycle(clArc<tuGraph> & agArc,const prMintyColor & agTest, std_vector(clNode<tuGraph> *) & agNodeS, std_vector(clArc<tuGraph> *) & agArcS, std_vector(tyCardinal) & agPreviousS,tyCardinal & agNbMark) { typedef clArc<tuGraph> cpArc; typedef std_vector(tyCardinal) cpIndexS; typedef clNode<tuGraph> cpNode; typedef std_vector(clNode<tuGraph> *) cpNodeS; typedef typename clNode<tuGraph>::cpArcX::const_iterator cpArcIterator;
cpArc * lcArc; tyCardinal lcCounter; cpArcIterator lcCurrentArc; tyCardinal lcCurrentCounter; cpArcIterator lcLastArc; tyCardinal lcNextCounter; cpNode * lcNode;
clGraph<tuGraph> & lcGraph = agArc.graph(); tyBoolean lcCycleFound = false; tyMark lcMark = ++(lcGraph.mark()); cpNode * lcSourceNode = agArc.sourceNode(); cpNode * lcTargetNode = agArc.targetNode();
cpIndexS * lcCurrentIndexS = new_object(cpIndexS(lcGraph.nodes().size())); cpNodeS * lcCurrentNodeS = new_object(cpNodeS(lcGraph.nodes().size())); cpIndexS * lcNextIndexS = new_object(cpIndexS(lcGraph.nodes().size())); cpNodeS * lcNextNodeS = new_object(cpNodeS(lcGraph.nodes().size()));
lcTargetNode->mark()=lcMark; (*lcNextNodeS)[0]=lcTargetNode; (*lcNextIndexS)[0]=0; lcNextCounter=1; agNodeS[0]=lcTargetNode; agArcS[0]=nil; agPreviousS[0]=0; agNbMark=1;
while ((not lcCycleFound) and lcNextCounter>0) { standard::swap(lcCurrentNodeS,lcNextNodeS); standard::swap(lcCurrentIndexS,lcNextIndexS); lcCurrentCounter=lcNextCounter; lcNextCounter=0; lcCounter=0;
while ((not lcCycleFound) and lcCounter<lcCurrentCounter) {
// Incoming Arcs // lcCurrentArc=(*lcCurrentNodeS)[lcCounter]->incomingArcs().begin(); lcLastArc=(*lcCurrentNodeS)[lcCounter]->incomingArcs().end();
while ((not lcCycleFound) and lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcNode=lcArc->sourceNode();
if (lcArc->key()!=agArc.key() and lcNode->mark()!=lcMark) { if (agTest.green(*lcArc) or agTest.blue(*lcArc)) { lcNode->mark()=lcMark; (*lcNextNodeS)[lcNextCounter]=lcNode; (*lcNextIndexS)[lcNextCounter++]=agNbMark; agNodeS[agNbMark]=lcNode; agArcS[agNbMark]=lcArc; agPreviousS[agNbMark++]=(*lcCurrentIndexS)[lcCounter]; lcCycleFound=(lcNode==lcSourceNode); } }
lcCurrentArc++; }
// Outgoing Arcs // lcCurrentArc=(*lcCurrentNodeS)[lcCounter]->outgoingArcs().begin(); lcLastArc=(*lcCurrentNodeS)[lcCounter]->outgoingArcs().end();
while ((not lcCycleFound) and lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second; lcNode=lcArc->targetNode();
if (lcArc->key()!=agArc.key() and lcNode->mark()!=lcMark) { if (agTest.green(*lcArc) or agTest.black(*lcArc)) { lcNode->mark()=lcMark; (*lcNextNodeS)[lcNextCounter]=lcNode; (*lcNextIndexS)[lcNextCounter++]=agNbMark; agNodeS[agNbMark]=lcNode; agArcS[agNbMark]=lcArc; agPreviousS[agNbMark++]=(*lcCurrentIndexS)[lcCounter]; lcCycleFound=(lcNode==lcSourceNode); } }
lcCurrentArc++; }
lcCounter++; } }
delete_object(lcCurrentIndexS); delete_object(lcCurrentNodeS); delete_object(lcNextIndexS); delete_object(lcNextNodeS); return (lcCycleFound); } //----------------------------------------------------------------------------------------MakeCycle template <tdGraph> void makeCycle(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS, std_vector(clArc<tuGraph> *) & agArcS,std_vector(tyCardinal) & agPreviousS, clCycle & agCycle,const clArc<tuGraph> & agArc) { clArc<tuGraph> * lcArc; tyCardinal lcCommonIndex; tyCardinal lcIndex;
tyMark lcMark = ++(agGraph.mark()); tyCardinal lcSourceIndex = 0; tyCardinal lcTargetIndex = 0;
while (agNodeS[lcSourceIndex]!=agArc.sourceNode()) lcSourceIndex++; while (agNodeS[lcTargetIndex]!=agArc.targetNode()) lcTargetIndex++; lcIndex=lcTargetIndex; agNodeS[lcIndex]->mark()=lcMark;
while (agArcS[lcIndex]!=nil) { lcIndex=agPreviousS[lcIndex]; agNodeS[lcIndex]->mark()=lcMark; }
lcCommonIndex=lcSourceIndex; agCycle.insert(clCycle::value_type(agArc.key(),+1));
while (agNodeS[lcCommonIndex]->mark()!=lcMark and agArcS[lcCommonIndex]!=nil) { lcArc=agArcS[lcCommonIndex];
if (lcArc->sourceNode()==agNodeS[lcCommonIndex]) agCycle.insert(clCycle::value_type(lcArc->key(),-1)); else agCycle.insert(clCycle::value_type(lcArc->key(),+1));
lcCommonIndex=agPreviousS[lcCommonIndex]; }
lcIndex=lcTargetIndex;
while (lcIndex!=lcCommonIndex) { lcArc=agArcS[lcIndex];
if (lcArc->sourceNode()==agNodeS[lcIndex]) agCycle.insert(clCycle::value_type(lcArc->key(),+1)); else agCycle.insert(clCycle::value_type(lcArc->key(),-1));
lcIndex=agPreviousS[lcIndex]; } } //----------------------------------------------------------------------------------------MakeCycle template <tdGraph> void makeCycle(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS, std_vector(clArc<tuGraph> *) & agArcS,std_vector(tyCardinal) & agPreviousS, std_map(clArc<tuGraph> *,tyInteger) & agCycle,clArc<tuGraph> & agArc) { clArc<tuGraph> * lcArc; tyCardinal lcCommonIndex; tyCardinal lcIndex;
tyMark lcMark = ++(agGraph.mark()); tyCardinal lcSourceIndex = 0; tyCardinal lcTargetIndex = 0;
while (agNodeS[lcSourceIndex]!=agArc.sourceNode()) lcSourceIndex++; while (agNodeS[lcTargetIndex]!=agArc.targetNode()) lcTargetIndex++; lcIndex=lcTargetIndex; agNodeS[lcIndex]->mark()=lcMark;
while (agArcS[lcIndex]!=nil) { lcIndex=agPreviousS[lcIndex]; agNodeS[lcIndex]->mark()=lcMark; }
lcCommonIndex=lcSourceIndex; agCycle.insert(std_make_pair(&agArc,+1));
while (agNodeS[lcCommonIndex]->mark()!=lcMark and agArcS[lcCommonIndex]!=nil) { lcArc=agArcS[lcCommonIndex];
if (lcArc->sourceNode()==agNodeS[lcCommonIndex]) agCycle.insert(std_make_pair(lcArc,-1)); else agCycle.insert(std_make_pair(lcArc,+1));
lcCommonIndex=agPreviousS[lcCommonIndex]; }
lcIndex=lcTargetIndex;
while (lcIndex!=lcCommonIndex) { lcArc=agArcS[lcIndex];
if (lcArc->sourceNode()==agNodeS[lcIndex]) agCycle.insert(std_make_pair(lcArc,+1)); else agCycle.insert(std_make_pair(lcArc,-1));
lcIndex=agPreviousS[lcIndex]; } } //--------------------------------------------------------------------------------MakeCycleDeepTree template <tdGraph> void makeCycleDeepTree(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS, std_vector(clArc<tuGraph> *) & agArcS, std_vector(tyCardinal) & agPreviousS) { typedef clGraph<tuGraph> cpGraph; typedef typename cpGraph::cpArcX::const_iterator cpArcIterator; typedef std_vector(tyCardinal) cpIndexS; typedef clNode<tuGraph> cpNode; typedef typename cpGraph::cpNodeX::const_iterator cpNodeIterator; typedef std_vector(clNode<tuGraph> *) cpNodeS;
cpArcIterator lcCurrentArc; tyCardinal lcCurrentCounter; tyCardinal lcIndex; cpIndexS lcIndexS(agGraph.nodes().size()); cpArcIterator lcLastArc; tyCardinal lcNbMark; cpNode * lcNextNode; cpNode * lcNode; tyCardinal lcNodeCounter; cpNodeS lcNodeS(agGraph.nodes().size());
cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpNodeIterator lcLastNode = agGraph.nodes().end(); tyMark lcMark = ++(agGraph.mark());
lcNbMark=0; lcNodeCounter=0;
while (lcCurrentNode!=lcLastNode) { lcNode=(*lcCurrentNode).second;
if (lcNode->mark()!=lcMark) { lcNode->mark()=lcMark; lcNodeS[lcNodeCounter]=lcNode; lcIndexS[lcNodeCounter++]=lcNbMark; agNodeS[lcNbMark]=lcNode; agArcS[lcNbMark]=nil; agPreviousS[lcNbMark++]=0;
while (lcNodeCounter>0) { lcCurrentCounter=--lcNodeCounter; lcNode=lcNodeS[lcCurrentCounter]; lcIndex=lcIndexS[lcCurrentCounter];
lcCurrentArc=lcNode->outgoingArcs().begin(); lcLastArc=lcNode->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcNextNode=(*lcCurrentArc).second->targetNode();
if (lcNextNode->mark()!=lcMark) { lcNextNode->mark()=lcMark; (*lcCurrentArc).second->mark()=lcMark; lcNodeS[lcNodeCounter]=lcNextNode; lcIndexS[lcNodeCounter++]=lcNbMark; agNodeS[lcNbMark]=lcNextNode; agArcS[lcNbMark]=(*lcCurrentArc).second; agPreviousS[lcNbMark++]=lcIndex; }
lcCurrentArc++; }
lcCurrentArc=lcNode->incomingArcs().begin(); lcLastArc=lcNode->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcNextNode=(*lcCurrentArc).second->sourceNode();
if (lcNextNode->mark()!=lcMark) { lcNextNode->mark()=lcMark; (*lcCurrentArc).second->mark()=lcMark; lcNodeS[lcNodeCounter]=lcNextNode; lcIndexS[lcNodeCounter++]=lcNbMark; agNodeS[lcNbMark]=lcNextNode; agArcS[lcNbMark]=(*lcCurrentArc).second; agPreviousS[lcNbMark++]=lcIndex; }
lcCurrentArc++; } } }
lcCurrentNode++; } } //-------------------------------------------------------------------------------MakeCycleBroadTree template <tdGraph> void makeCycleBroadTree(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS, std_vector(clArc<tuGraph> *) & agArcS, std_vector(tyCardinal) & agPreviousS) { typedef clGraph<tuGraph> cpGraph; typedef typename cpGraph::cpArcX::const_iterator cpArcIterator; typedef typename cpGraph::cpNodeX::const_iterator cpNodeIterator; typedef std_vector(tyCardinal) cpIndexS; typedef clNode<tuGraph> cpNode; typedef std_vector(clNode<tuGraph> *) cpNodeS; typedef clIncreaseDegreeNodeOrder<tuGraph> cpOrdering;
cpArcIterator lcCurrentArc; tyCardinal lcCurrentCounter; tyCardinal lcIndex; cpArcIterator lcLastArc; tyCardinal lcNbMark; cpNode * lcNextNode; cpNode * lcNode; tyCardinal lcNodeCounter1; tyCardinal lcNodeCounter2; cpNodeS lcSortedNodeS;
cpNodeIterator lcCurrentNode = agGraph.nodes().begin(); cpIndexS * lcIndex1S = new_object(cpIndexS(agGraph.nodes().size())); cpIndexS * lcIndex2S = new_object(cpIndexS(agGraph.nodes().size())); cpNodeIterator lcLastNode = agGraph.nodes().end(); tyMark lcMark = ++(agGraph.mark()); cpNodeS * lcNode1S = new_object(cpNodeS(agGraph.nodes().size())); cpNodeS * lcNode2S = new_object(cpNodeS(agGraph.nodes().size()));
// Nodes Sorting // lcSortedNodeS.reserve(agGraph.nodes().size());
while (lcCurrentNode!=lcLastNode) { lcSortedNodeS.push_back((*lcCurrentNode).second); ++lcCurrentNode; }
std_sort(lcSortedNodeS.begin(),lcSortedNodeS.end(),cpOrdering());
// Broad Parsing // lcNbMark=0; lcNodeCounter1=0; lcNodeCounter2=0;
while (lcSortedNodeS.size()>0) { lcNode=lcSortedNodeS.back(); lcSortedNodeS.pop_back();
if (lcNode->mark()!=lcMark) { lcNode->mark()=lcMark; (*lcNode1S)[lcNodeCounter1]=lcNode; (*lcIndex1S)[lcNodeCounter1++]=lcNbMark; agNodeS[lcNbMark]=lcNode; agArcS[lcNbMark]=nil; agPreviousS[lcNbMark++]=0;
while (lcNodeCounter1>0) { standard::swap(lcNodeCounter1,lcNodeCounter2); standard::swap(lcNode1S,lcNode2S); standard::swap(lcIndex1S,lcIndex2S);
while (lcNodeCounter2>0) { lcCurrentCounter=--lcNodeCounter2; lcNode=(*lcNode2S)[lcCurrentCounter]; lcIndex=(*lcIndex2S)[lcCurrentCounter];
lcCurrentArc=lcNode->outgoingArcs().begin(); lcLastArc=lcNode->outgoingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcNextNode=(*lcCurrentArc).second->targetNode();
if (lcNextNode->mark()!=lcMark) { lcNextNode->mark()=lcMark; (*lcCurrentArc).second->mark()=lcMark; (*lcNode1S)[lcNodeCounter1]=lcNextNode; (*lcIndex1S)[lcNodeCounter1++]=lcNbMark; agNodeS[lcNbMark]=lcNextNode; agArcS[lcNbMark]=(*lcCurrentArc).second; agPreviousS[lcNbMark++]=lcIndex; }
lcCurrentArc++; }
lcCurrentArc=lcNode->incomingArcs().begin(); lcLastArc=lcNode->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcNextNode=(*lcCurrentArc).second->sourceNode();
if (lcNextNode->mark()!=lcMark) { lcNextNode->mark()=lcMark; (*lcCurrentArc).second->mark()=lcMark; (*lcNode1S)[lcNodeCounter1]=lcNextNode; (*lcIndex1S)[lcNodeCounter1++]=lcNbMark; agNodeS[lcNbMark]=lcNextNode; agArcS[lcNbMark]=(*lcCurrentArc).second; agPreviousS[lcNbMark++]=lcIndex; }
lcCurrentArc++; } } } } }
delete_object(lcIndex1S); delete_object(lcIndex2S); delete_object(lcNode1S); delete_object(lcNode2S); } }
// M i n t y C o l o r Implementation //----------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------------Color /*METHOD clMintyColor */ /* Returns a string that indicates the color of an arc. */ template <tdGraph> tcString clMintyColor<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 public_area #undef private_area #undef tdGraph #undef tuGraph #endif |
//================================================================================================== // G r a p h Implementation // 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/algorithm.cpp"
// DLL Belonging //--------------------------------------------------------------------------------- #define GRAPH_DLL
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph/algorithm.hpp> /*INTERFACE*/
namespace bpp {
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphAlgorithm #define private_area graphAlgorithm_private #define dll_export DLL_EXPORT
namespace public_area {} namespace private_area {}
static_module_name("Graph/Algorithm");
// Initialization //-------------------------------------------------------------------------------- #undef iniGraphAlgorithm static_constant(private_area::clInitializer,goInitializer);
// Errors //---------------------------------------------------------------------------------------- namespace public_area { static_error erGraphNotConnex; }
// Constants & Variables //------------------------------------------------------------------------- dynamic_constant(clString,goDataLocation);
// Static Members //-------------------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// Functions Implementation //---------------------------------------------------------------------- namespace public_area { //----------------------------------------------------------------------Operator << (Cycle/Cocycle) /*FUNCTION*/ /* Writes a cycle or a cocycle into a stream. */ function clOutStream & operator << (clOutStream & agStream,ctCycle & agCycle) { clCycle::const_iterator lcCurrentArc = agCycle.begin(); clCycle::const_iterator lcLastArc = agCycle.end();
if (agCycle.size()==0) agStream << "empty"; else { while (lcCurrentArc!=lcLastArc) { if ((*lcCurrentArc).second==+1) agStream << '+'; else if ((*lcCurrentArc).second==-1) agStream << '-'; else agStream << '?';
agStream << (*lcCurrentArc).first; lcCurrentArc++; if (lcCurrentArc!=lcLastArc) agStream << ' '; } }
return (agStream); } }
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);
erGraphNotConnex.create("Graph - The graph isn't connex.");
goDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator()+"graph" +fileNameSeparator()+"algorithm")); }
initializer_catch; } } //---------------------------------------------------------------------------------------------Stop property void clInitializer::stop(void) { try { environment::informTermination(goModuleName);
delete_object(goDataLocation); }
initializer_catch; } }
// End //------------------------------------------------------------------------------------------- } |
|