//================================================================================================== // G r a p h Interface // R a n d o m _ g e n e r a t i o n // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU Library General Public License for more details (http://www.gnu.org).
/*DESCRIPTION*/ /* This module provides facilities to generate random graphs. */
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph/random_generation.hpp"
// Guardian //-------------------------------------------------------------------------------------- #ifndef guGraphRandomGeneration #define guGraphRandomGeneration
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph/algorithm.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 graphRandomGeneration #define private_area graphRandomGeneration_private
namespace public_area { /*NAMESPACE*/ using namespace graphAlgorithm; } namespace private_area { using namespace public_area; }
extern_module_name;
// Initialization //-------------------------------------------------------------------------------- #define iniGraphRandomGeneration has_initializer;
// Macrocommands //--------------------------------------------------------------------------------- /*ALIAS*/ #define tdGraph class prArcData,class prNodeData //
/*ALIAS*/ #define tuGraph prArcData,prNodeData //
// Types & Classes //------------------------------------------------------------------------------- namespace public_area { //-----------------------------------------------------------------------------------Variable Types /*TYPE*/ /* List of node keys. */ typedef std_vector(tyNodeKey) clNodeKeyS; //-----------------------------------------------------------------------------------Constant Types typedef const clNodeKeyS ctNodeKeyS; }
namespace private_area { typedef std_vector(tyArcKey) clArcKeyS; }
// Functions Interface //--------------------------------------------------------------------------- namespace public_area { template <tdGraph> void generateConnexGraph(clGraph<tuGraph> &,tyCardinal,tyCardinal,tyBoolean);
template <tdGraph> void generateConnexGraphWithArcValue(clGraph<tuGraph> &,tyCardinal,tyCardinal,tyInteger,tyBoolean);
template <tdGraph> void generateNonConnexGraph(clGraph<tuGraph> &,tyCardinal,tyCardinal,tyBoolean);
template <tdGraph> void generateSerialParallelGraph(clGraph<tuGraph> &,tyCardinal,tyCardinal); template <tdGraph> void generateTree(clGraph<tuGraph> &,tyCardinal); }
namespace private_area { template <tdGraph> void addArcs(clGraph<tuGraph> &,tyCardinal,ctNodeKeyS &); template <tdGraph> void addArcsWithoutCircuit(clGraph<tuGraph> &,tyCardinal,ctNodeKeyS &);
template <tdGraph> void generateConnexGraph(clGraph<tuGraph> &,tyCardinal,tyCardinal,clNodeKeyS &,tyBoolean);
template <tdGraph> void generateNonConnexGraph(clGraph<tuGraph> &,tyCardinal,tyCardinal,clNodeKeyS &,tyBoolean);
template <tdGraph> void generateSerialParallelGraph(clGraph<tuGraph> &,tyCardinal,tyCardinal,clNodeKeyS &);
template <tdGraph> void generateTree(clGraph<tuGraph> &,tyCardinal,clNodeKeyS &);
template <tdGraph> void parallelize(clGraph<tuGraph> &,tyArcKey,clArcKeyS &); template <tdGraph> void serialize(clGraph<tuGraph> &,tyArcKey,clArcKeyS &,clNodeKeyS &); }
// Errors //---------------------------------------------------------------------------------------- namespace public_area { /*ERROR*/ extern_error erEmptyKeyList; /* The key list is empty. */
/*ERROR*/ extern_error erNotEnoughArcsForConnexity; /* Not enough arcs to obtain a connex graph. */ }
// Constants & Variables //------------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// X X X Interface //------------------------------------------------------------------------------ namespace {}
// Functions Inline //------------------------------------------------------------------------------ namespace public_area { //------------------------------------------------------------------------------GenerateConnexGraph /*FUNCTION*/ /* Generates randomly a connex graph with given numbers of arcs and nodes. */ template <tdGraph> inline void generateConnexGraph(clGraph<tuGraph> & agGraph,tyCardinal agNbNode,tyCardinal agNbArc, tyBoolean agNoCircuit) { clNodeKeyS lcNodeKeyS; private_area::generateConnexGraph(agGraph,agNbNode,agNbArc,lcNodeKeyS,agNoCircuit); } //---------------------------------------------------------------------------GenerateNonConnexGraph /*FUNCTION*/ /* Generates randomly a graph (connex or not) with given numbers of arcs and nodes. */ template <tdGraph> inline void generateNonConnexGraph(clGraph<tuGraph> & agGraph,tyCardinal agNbNode,tyCardinal agNbArc, tyBoolean agNoCircuit) { clNodeKeyS lcNodeKeyS; private_area::generateNonConnexGraph(agGraph,agNbNode,agNbArc,lcNodeKeyS,agNoCircuit); } //----------------------------------------------------------------------GenerateSerialParallelGraph /*FUNCTION*/ /* Generates randomly a connex serial-parallel graph with given numbers of arcs and nodes. */ template <tdGraph> inline void generateSerialParallelGraph(clGraph<tuGraph> & agGraph,tyCardinal agNbNode, tyCardinal agNbArc) { clNodeKeyS lcNodeKeyS; private_area::generateSerialParallelGraph(agGraph,agNbNode,agNbArc,lcNodeKeyS); } //-------------------------------------------------------------------------------------GenerateTree /*FUNCTION*/ /* Generates randomly a tree with a given number of nodes. */ template <tdGraph> inline void generateTree(clGraph<tuGraph> & agGraph,tyCardinal agNbNode) { clNodeKeyS lcNodeKeyS; private_area::generateTree(agGraph,agNbNode,lcNodeKeyS); } }
namespace private_area {}
// X X X Inline //--------------------------------------------------------------------------------- namespace {}
// Functions Implementation //---------------------------------------------------------------------- namespace public_area { //------------------------------------------------------------------GenerateConnexGraphWithArcValue /*FUNCTION*/ /* Generates randomly a connex graph with given numbers of arcs and nodes. A value between 0 and a given number is randomly chosen for each arc. */ template <tdGraph> void generateConnexGraphWithArcValue(clGraph<tuGraph> & agGraph,tyCardinal agNbNode, tyCardinal agNbArc,tyInteger agValueScale, tyBoolean agNoCircuit) { typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpIterator;
cpIterator lcCurrentArc; cpIterator lcLastArc; clNodeKeyS lcNodeKeyS;
private_area::generateConnexGraph(agGraph,agNbNode,agNbArc,lcNodeKeyS,agNoCircuit); lcCurrentArc=agGraph.arcs().begin(); lcLastArc=agGraph.arcs().end();
while (lcCurrentArc!=lcLastArc) { (*lcCurrentArc).second->data().value()=(agValueScale==0 ? 1 : randomCardinal(agValueScale+1)); lcCurrentArc++; } } }
namespace private_area { //------------------------------------------------------------------------------------------AddArcs template <tdGraph> void addArcs(clGraph<tuGraph> & agGraph,tyCardinal agNbArc,ctNodeKeyS & agNodeKeyS) { method_name("addArcs");
typedef clArc<tuGraph> cpArc;
tyNodeKey lcSourceKey; tyNodeKey lcTargetKey;
if (agNodeKeyS.size()==0) send_error(erEmptyKeyList);
// Arcs Generation // while (agNbArc>0) { do { lcSourceKey=agNodeKeyS[randomCardinal(agNodeKeyS.size())]; lcTargetKey=agNodeKeyS[randomCardinal(agNodeKeyS.size())]; } while (lcSourceKey==lcTargetKey);
new_object(cpArc(agGraph,agGraph.getNewArcKey(),prArcData(),lcSourceKey,lcTargetKey)); agNbArc--; } } //----------------------------------------------------------------------------AddArcsWithoutCircuit template <tdGraph> void addArcsWithoutCircuit(clGraph<tuGraph> & agGraph,tyCardinal agNbArc,ctNodeKeyS & agNodeKeyS) { method_name("addArcsWithoutCircuit");
typedef clArc<tuGraph> cpArc;
clCycle lcCircuit; cpArc * lcNewArc; tyNodeKey lcSourceKey; tyNodeKey lcTargetKey;
if (agNodeKeyS.size()==0) send_error(erEmptyKeyList);
// Arcs Generation // while (agNbArc>0) { do { lcSourceKey=agNodeKeyS[randomCardinal(agNodeKeyS.size())]; lcTargetKey=agNodeKeyS[randomCardinal(agNodeKeyS.size())]; } while (lcSourceKey==lcTargetKey);
lcNewArc=new_object(cpArc(agGraph,agGraph.getNewArcKey(),prArcData(),lcSourceKey,lcTargetKey));
if (findCircuit(agGraph,lcNewArc->key(),lcCircuit)) delete_object(lcNewArc); else agNbArc--; } } //------------------------------------------------------------------------------GenerateConnexGraph template <tdGraph> void generateConnexGraph(clGraph<tuGraph> & agGraph,tyCardinal agNbNode,tyCardinal agNbArc, clNodeKeyS & agNodeKeyS,tyBoolean agNoCircuit) { method_name("generateConnexGraph");
if (agNbArc<agNbNode-1) send_error(erNotEnoughArcsForConnexity); generateTree(agGraph,agNbNode,agNodeKeyS);
if (agNoCircuit) private_area::addArcsWithoutCircuit(agGraph,agNbArc-agNbNode+1,agNodeKeyS); else private_area::addArcs(agGraph,agNbArc-agNbNode+1,agNodeKeyS); } //---------------------------------------------------------------------------GenerateNonConnexGraph template <tdGraph> void generateNonConnexGraph(clGraph<tuGraph> & agGraph,tyCardinal agNbNode,tyCardinal agNbArc, clNodeKeyS & agNodeKeyS,tyBoolean agNoCircuit) { typedef clNode<tuGraph> cpNode;
tyCardinal lcCurrentNode = 0;
tyNodeKey lcKey;
agNodeKeyS.erase(agNodeKeyS.begin(),agNodeKeyS.end()); agNodeKeyS.reserve(agNbNode);
// Nodes Generation // while (lcCurrentNode<agNbNode) { lcKey=agGraph.getNewNodeKey(); agNodeKeyS.push_back(lcKey); new_object(cpNode(agGraph,lcKey,prNodeData())); lcCurrentNode++; }
// Arcs Generation // if (agNoCircuit) private_area::addArcsWithoutCircuit(agGraph,agNbArc,agNodeKeyS); else private_area::addArcs(agGraph,agNbArc,agNodeKeyS); } //----------------------------------------------------------------------GenerateSerialParallelGraph template <tdGraph> void generateSerialParallelGraph(clGraph<tuGraph> & agGraph,tyCardinal agNbNode, tyCardinal agNbArc,clNodeKeyS & agNodeKeyS) { typedef clArc<tuGraph> cpArc; typedef clNode<tuGraph> cpNode;
tyCardinal lcNbArc = 0; tyCardinal lcNbNode = 0;
tyArcKey lcArcKey; clArcKeyS lcArcKeyS; tyNodeKey lcNodeKey1; tyNodeKey lcNodeKey2;
agNodeKeyS.erase(agNodeKeyS.begin(),agNodeKeyS.end()); agNodeKeyS.reserve(agNbNode); lcArcKeyS.reserve(agNbArc);
// First Arc and Nodes // lcNodeKey1=agGraph.getNewNodeKey(); agNodeKeyS.push_back(lcNodeKey1); new_object(cpNode(agGraph,lcNodeKey1,prNodeData())); lcNbNode++;
lcNodeKey2=agGraph.getNewNodeKey(); agNodeKeyS.push_back(lcNodeKey2); new_object(cpNode(agGraph,lcNodeKey2,prNodeData())); lcNbNode++;
lcArcKey=agGraph.getNewArcKey(); lcArcKeyS.push_back(lcArcKey); new_object(cpArc(agGraph,lcArcKey,prArcData(),lcNodeKey1,lcNodeKey2)); lcNbArc++;
// Serial-Parallel Generation // while (lcNbArc<agNbArc) { lcArcKey=lcArcKeyS[randomCardinal(lcNbArc)];
if (randomCardinal(2)) { if (agNbNode-lcNbNode < agNbArc-lcNbArc) parallelize(agGraph,lcArcKey,lcArcKeyS); else { serialize(agGraph,lcArcKey,lcArcKeyS,agNodeKeyS); lcNbNode++; } } else { if (lcNbNode < agNbNode) { serialize(agGraph,lcArcKey,lcArcKeyS,agNodeKeyS); lcNbNode++; } else parallelize(agGraph,lcArcKey,lcArcKeyS); }
lcNbArc++; } } //-------------------------------------------------------------------------------------GenerateTree template <tdGraph> void generateTree(clGraph<tuGraph> & agGraph,tyCardinal agNbNode,clNodeKeyS & agNodeKeyS) { typedef clArc<tuGraph> cpArc; typedef clNode<tuGraph> cpNode;
tyCardinal lcCurrentNode = 0;
tyNodeKey lcFirstKey; tyNodeKey lcSecondKey;
agNodeKeyS.erase(agNodeKeyS.begin(),agNodeKeyS.end()); agNodeKeyS.reserve(agNbNode);
// Nodes & Arcs Generation // while (lcCurrentNode<agNbNode) { lcFirstKey=agGraph.getNewNodeKey(); agNodeKeyS.push_back(lcFirstKey); new_object(cpNode(agGraph,lcFirstKey,prNodeData()));
if (lcCurrentNode>0) { lcSecondKey=agNodeKeyS[randomCardinal(lcCurrentNode)];
if (randomCardinal(2)) new_object(cpArc(agGraph,agGraph.getNewArcKey(),prArcData(),lcFirstKey,lcSecondKey)); else new_object(cpArc(agGraph,agGraph.getNewArcKey(),prArcData(),lcSecondKey,lcFirstKey)); }
lcCurrentNode++; } } //--------------------------------------------------------------------------------------Parallelize template <tdGraph> void parallelize(clGraph<tuGraph> & agGraph,tyArcKey agKey,clArcKeyS & agKeyS) { typedef clArc<tuGraph> cpArc;
tyArcKey lcKey = agGraph.getNewArcKey(); cpArc & lcArc = agGraph.arc(agKey);
agKeyS.push_back(lcKey); new_object(cpArc(agGraph,lcKey,prArcData(),lcArc.sourceNode()->key(),lcArc.targetNode()->key())); } //----------------------------------------------------------------------------------------Serialize template <tdGraph> void serialize(clGraph<tuGraph> & agGraph,tyArcKey agKey, clArcKeyS & agArcKeyS,clNodeKeyS & agNodeKeyS) { typedef clArc<tuGraph> cpArc; typedef clNode<tuGraph> cpNode;
cpArc & lcArc = agGraph.arc(agKey); tyArcKey lcArcKey = agGraph.getNewArcKey(); tyNodeKey lcNodeKey1 = agGraph.getNewNodeKey(); tyNodeKey lcNodeKey2 = lcArc.targetNode()->key();
cpNode * lcNode;
agArcKeyS.push_back(lcArcKey); agNodeKeyS.push_back(lcNodeKey1); lcNode=new_object(cpNode(agGraph,lcNodeKey1,prNodeData())); lcArc.setTargetNode(lcNode); new_object(cpArc(agGraph,lcArcKey,prArcData(),lcNodeKey1,lcNodeKey2)); } }
// End //------------------------------------------------------------------------------------------- } #undef dll_export #undef tdGraph #undef tuGraph #undef public_area #undef private_area #endif |
//================================================================================================== // G r a p h Implementation // R a n d o m _ g e n e r a t i o n // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU Library General Public License for more details (http://www.gnu.org).
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph/random_generation.cpp"
// DLL Belonging //--------------------------------------------------------------------------------- #define GRAPH_DLL
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph/random_generation.hpp> /*INTERFACE*/
namespace bpp {
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphRandomGeneration #define private_area graphRandomGeneration_private #define dll_export DLL_EXPORT
namespace public_area {} namespace private_area {}
static_module_name("Graph/Random_generation");
// Initialization //-------------------------------------------------------------------------------- #undef iniGraphRandomGeneration static_constant(private_area::clInitializer,goInitializer);
// Errors //---------------------------------------------------------------------------------------- namespace public_area { static_error erEmptyKeyList; static_error erNotEnoughArcsForConnexity; }
// Constants & Variables //------------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// Static Members //-------------------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// Functions Implementation //---------------------------------------------------------------------- namespace public_area {} namespace private_area {}
// X X X Implementation //------------------------------------------------------------------------- namespace {}
// 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);
erEmptyKeyList.create("Graph - The key list is empty."); erNotEnoughArcsForConnexity.create("Graph - Not enough arcs to obtain a connex graph."); }
initializer_catch; } } //---------------------------------------------------------------------------------------------Stop property void clInitializer::stop(void) { environment::informTermination(goModuleName); } }
// End //------------------------------------------------------------------------------------------- } |
|