//================================================================================================== // G r a p h _ p r o b l e m Interface // M i n _ s p a n n i n g_ t r e e // 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 solve the minimum spanning tree problem in graphs. */
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph_problem/min_spanning_tree.hpp"
// Guardian //-------------------------------------------------------------------------------------- #ifndef guGraphProblemMinSpanningTree #define guGraphProblemMinSpanningTree
// Headers //--------------------------------------------------------------------------------------- #include <algorithm> /*INCLUDE*/ #include <bpp/graph.hpp> /*INCLUDE*/
namespace bpp {
// Importation/Exportation //----------------------------------------------------------------------- #ifdef GRAPH_PROBLEM_DLL #define dll_export DLL_EXPORT #else #define dll_export DLL_IMPORT #endif
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphProblemMinSpanningTree #define private_area graphProblemMinSpanningTree_private
namespace public_area { /*NAMESPACE*/ using namespace graph; } namespace private_area { using namespace public_area; }
extern_module_name;
// Initialization //-------------------------------------------------------------------------------- #define iniGraphProblemMinSpanningTree has_initializer;
// Macrocommands //--------------------------------------------------------------------------------- /*ALIAS*/ #define tdGraph class prArcData,class prNodeData //
/*ALIAS*/ #define tuGraph prArcData,prNodeData //
// Types & Classes //------------------------------------------------------------------------------- namespace public_area { //------------------------------------------------------------------------------------------Classes template <tdGraph> class clKruskalAlgo; template <tdGraph> class clPrimAlgo; template <tdGraph> class clSolveAlgo; //-----------------------------------------------------------------------------------Variable Types /*TYPE*/ /* Arc of a graph with a minimum spanning tree problem. */ typedef clArc<clCostData,clNoData> clSpanningArc;
/*TYPE*/ /* Graph with a minimum spanning tree problem. */ typedef clGraph<clCostData,clNoData> clSpanningGraph;
/*TYPE*/ /* Node of a graph with a minimum spanning tree problem. */ typedef clNode<clCostData,clNoData> clSpanningNode; //-----------------------------------------------------------------------------------Constant Types typedef const clSpanningArc ctSpanningArc; typedef const clSpanningGraph ctSpanningGraph; typedef const clSpanningNode ctSpanningNode; }
namespace private_area { template <class prArc> class clLessArc; }
// Functions Interface //--------------------------------------------------------------------------- namespace public_area { template <tdGraph> tyReal totalCost(const clGraph<tuGraph> &); }
namespace private_area { testing_mode ( function void test(void); ) }
// Errors //---------------------------------------------------------------------------------------- namespace public_area {}
// Constants & Variables //------------------------------------------------------------------------- extern_dynamic_constant(private,clString,goDataLocation,?);
// K r u s k a l A l g o Interface //-------------------------------------------------------------- namespace public_area { /*CLASS clKruskalAlgo */ /* Represents Kruskal's algorithm to solve the minimum spanning tree problem in a graph. */ template <tdGraph> class clKruskalAlgo : public clSolveAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clKruskalAlgo(const clKruskalAlgo &); private_property clKruskalAlgo & operator = (const clKruskalAlgo &); //------------------------------------------------------------------------------------------Public public_property constructor clKruskalAlgo(void); public_property virtual destructor clKruskalAlgo(void);
public_property void run(clGraph<tuGraph> &,clGraph<tuGraph> &) const; }; }
// P r i m A l g o Interface //-------------------------------------------------------------------- namespace public_area { /*CLASS clPrimAlgo */ /* Represents Prim's algorithm to solve the minimum spanning tree problem in a graph. */ template <tdGraph> class clPrimAlgo : public clSolveAlgo<tuGraph> { //-----------------------------------------------------------------------------------------Private private_property constructor clPrimAlgo(const clPrimAlgo &); private_property clPrimAlgo & operator = (const clPrimAlgo &); //------------------------------------------------------------------------------------------Public public_property constructor clPrimAlgo(void); public_property virtual destructor clPrimAlgo(void);
public_property void run(clGraph<tuGraph> &,clGraph<tuGraph> &) const; }; }
// S o l v e A l g o Interface //------------------------------------------------------------------ namespace public_area { /*CLASS clSolveAlgo */ /* Represents an algorithm to solve the minimum spanning tree problem in a graph. It is an abstract class. */ template <tdGraph> class clSolveAlgo { //-----------------------------------------------------------------------------------------Private private_property constructor clSolveAlgo(const clSolveAlgo &); private_property clSolveAlgo & operator = (const clSolveAlgo &); //------------------------------------------------------------------------------------------Public public_property constructor clSolveAlgo(void); public_property virtual destructor clSolveAlgo(void);
/*AMETHOD clSolveAlgo */ /* Executes the algorithm. Abstract method. */ public_property virtual void run(clGraph<tuGraph> & agGraph,clGraph<tuGraph> & agTree) const = 0;
public_property static void defaultRun(clGraph<tuGraph> &,clGraph<tuGraph> &); }; }
// L e s s A r c Interfacce //--------------------------------------------------------------------- namespace private_area { template <class prArc> class clLessArc : public std::binary_function<prArc,prArc,tyBoolean> { //------------------------------------------------------------------------------------------Public public_property constructor clLessArc(void); public_property destructor clLessArc(void);
public_property tyBoolean operator () (const prArc &,const prArc &) const; }; }
// Functions Inline //------------------------------------------------------------------------------ namespace public_area {} namespace private_area {}
// K r u s k a l A l g o Inline //----------------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clKruskalAlgo */ /* Builds Kruskal's algorithm that solves the minimum spanning tree problem in a graph. */ template <tdGraph> inline clKruskalAlgo<tuGraph>::clKruskalAlgo(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clKruskalAlgo */ /* Destructs the algorithm. */ template <tdGraph> inline clKruskalAlgo<tuGraph>::~clKruskalAlgo(void) {} }
// P r i m A l g o Inline //----------------------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clPrimAlgo */ /* Builds Prim's algorithm that solves the minimum spanning tree problem in a graph. */ template <tdGraph> inline clPrimAlgo<tuGraph>::clPrimAlgo(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clPrimAlgo */ /* Destructs the algorithm. */ template <tdGraph> inline clPrimAlgo<tuGraph>::~clPrimAlgo(void) {} }
// S o l v e A l g o Inline //--------------------------------------------------------------------- namespace public_area { //--------------------------------------------------------------------------------------Constructor /*METHOD clSolveAlgo */ /* Builds an algorithm to solve the minimum spanning tree problem in a graph. */ template <tdGraph> inline clSolveAlgo<tuGraph>::clSolveAlgo(void) {} //---------------------------------------------------------------------------------------Destructor /*METHOD clSolveAlgo */ /* Destructs the algorithm. */ template <tdGraph> inline clSolveAlgo<tuGraph>::~clSolveAlgo(void) {} }
// L e s s A r c Inline //------------------------------------------------------------------------- namespace private_area { //--------------------------------------------------------------------------------------Constructor template <class prArc> clLessArc<prArc>::clLessArc(void) : std::binary_function<prArc,prArc,tyBoolean>() {} //---------------------------------------------------------------------------------------Destructor template <class prArc> clLessArc<prArc>::~clLessArc(void) {} //--------------------------------------------------------------------------------------Operator () template <class prArc> tyBoolean clLessArc<prArc>::operator () (const prArc & agArc1,const prArc & agArc2) const { return (agArc1->data().cost()<agArc2->data().cost()); } }
// Functions Implementation //---------------------------------------------------------------------- namespace public_area { //----------------------------------------------------------------------------------------TotalCost /*FUNCTION*/ /* Computes the total cost of a graph. */ template <tdGraph> tyReal totalCost(const clGraph<tuGraph> & agGraph) { typedef typename clGraph<tuGraph>::cpArcX::const_iterator clArcIterator;
tyReal lcCost = 0.0; clArcIterator lcCurrentArc = agGraph.arcs().begin(); clArcIterator lcLastArc = agGraph.arcs().end();
while (lcCurrentArc!=lcLastArc) { lcCost+=(*lcCurrentArc).second->data().cost(); lcCurrentArc++; }
return (lcCost); } }
namespace private_area {}
// K r u s k a l A l g o Implementation //--------------------------------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clKruskalAlgo */ /* Solves the minimum spanning tree problem in a graph. */ template <tdGraph> void clKruskalAlgo<tuGraph>::run(clGraph<tuGraph> & agGraph,clGraph<tuGraph> & agTree) const { typedef clArc<tuGraph> cpArc; typedef std_vector(clArc<tuGraph> *) cpArcS; typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator1; typedef typename cpArcS::const_iterator cpArcIterator2; typedef clNode<tuGraph> cpNode; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
cpArc * lcArc; cpArcS lcArcS; cpArcIterator1 lcCurrentArc1; cpArcIterator2 lcCurrentArc2; cpNodeIterator lcCurrentNode; clCycle lcCycle; cpArcIterator1 lcLastArc1; cpArcIterator2 lcLastArc2; cpNodeIterator lcLastNode; cpArc * lcNewArc;
// Arcs Sorting // lcArcS.reserve(agGraph.arcs().size()); lcCurrentArc1=agGraph.arcs().begin(); lcLastArc1=agGraph.arcs().end();
while (lcCurrentArc1!=lcLastArc1) { lcArcS.push_back((*lcCurrentArc1).second); lcCurrentArc1++; }
std_sort(lcArcS.begin(),lcArcS.end(),private_area::clLessArc<clArc<tuGraph> *>());
// Nodes Copy // agTree.clear(); lcCurrentNode=agGraph.nodes().begin(); lcLastNode=agGraph.nodes().end();
while (lcCurrentNode!=lcLastNode) { new_object(cpNode(agTree,*((*lcCurrentNode).second))); lcCurrentNode++; }
// Tree Construction // lcCurrentArc2=lcArcS.begin(); lcLastArc2=lcArcS.end();
while (lcCurrentArc2!=lcLastArc2 and (agTree.arcs().size()+1 < agTree.nodes().size())) { lcArc=*lcCurrentArc2; lcNewArc=new_object(cpArc(agTree,*lcArc)); if (findCycle(agTree,lcNewArc->key(),lcCycle)) delete_object(lcNewArc); lcCurrentArc2++; } } }
// P r i m A l g o Implementation //--------------------------------------------------------------- namespace public_area { //----------------------------------------------------------------------------------------------Run /*METHOD clPrimAlgo */ /* Solves the minimum spanning tree problem in a graph. */ template <tdGraph> void clPrimAlgo<tuGraph>::run(clGraph<tuGraph> & agGraph,clGraph<tuGraph> & agTree) const { method_name("primAlgo::run");
typedef clArc<tuGraph> cpArc; typedef clNode<tuGraph> cpNode; typedef typename cpNode::cpArcX::const_iterator cpArcIterator; typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;
cpArc * lcArc; cpArcIterator lcCurrentArc; cpNodeIterator lcCurrentNode; cpArcIterator lcLastArc; cpNodeIterator lcLastNode; cpNode * lcNode; cpArc * lcSelectedArc;
clGraph<tuGraph> lcGraph(agGraph); tyReal lcMin = 0;
// Nodes Copy // agTree.clear(); lcCurrentNode=agGraph.nodes().begin(); lcLastNode=agGraph.nodes().end();
while (lcCurrentNode!=lcLastNode) { new_object(cpNode(agTree,*((*lcCurrentNode).second))); lcCurrentNode++; }
// Tree Construction // while (lcGraph.nodes().size()>1) { lcNode=(*(lcGraph.nodes().begin())).second; lcCurrentArc=lcNode->outgoingArcs().begin(); lcLastArc=lcNode->outgoingArcs().end(); lcSelectedArc=nil;
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcSelectedArc==nil or lcArc->data().cost()<lcMin) { lcSelectedArc=lcArc; lcMin=lcArc->data().cost(); }
lcCurrentArc++; }
lcCurrentArc=lcNode->incomingArcs().begin(); lcLastArc=lcNode->incomingArcs().end();
while (lcCurrentArc!=lcLastArc) { lcArc=(*lcCurrentArc).second;
if (lcSelectedArc==nil or lcArc->data().cost()<lcMin) { lcSelectedArc=lcArc; lcMin=lcArc->data().cost(); }
lcCurrentArc++; }
if (lcSelectedArc==nil) send_error(erGraphNotConnex); new_object(cpArc(agTree,agGraph.arc(lcSelectedArc->key()))); lcGraph.mergeNodes(*(lcSelectedArc->targetNode()),*(lcSelectedArc->sourceNode())); } } }
// S o l v e A l g o Implementation //------------------------------------------------------------- namespace public_area { //---------------------------------------------------------------------------------------DefaultRun /*METHOD clSolveAlgo */ /* Solves the minimum spanning tree problem in a graph using the default version of the algorithm (Kruskal's method). Static method. */ template <tdGraph> inline void clSolveAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph,clGraph<tuGraph> & agTree) { clKruskalAlgo<tuGraph>().run(agGraph,agTree); } }
// End //------------------------------------------------------------------------------------------- } #undef dll_export #undef public_area #undef private_area #undef tdGraph #undef tuGraph #endif |
//================================================================================================== // G r a p h _ p r o b l e m Implementation // M i n _ s p a n n i n g _ t r e e // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU Library General Public License for more details (http://www.gnu.org).
// File Name //------------------------------------------------------------------------------------- #line __LINE__ "graph_problem/min_spanning_tree.cpp"
// DLL Belonging //--------------------------------------------------------------------------------- #define GRAPH_PROBLEM_DLL
// Headers //--------------------------------------------------------------------------------------- #include <bpp/graph_problem/min_spanning_tree.hpp> /*INTERFACE*/
namespace bpp {
// Namespaces //------------------------------------------------------------------------------------ #define public_area graphProblemMinSpanningTree #define private_area graphProblemMinSpanningTree_private #define dll_export DLL_EXPORT
namespace public_area {} namespace private_area {}
static_module_name("Graph_problem/Min_spanning_tree");
// Initialization //-------------------------------------------------------------------------------- #undef iniGraphProblemMinSpanningTree 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()+"min_spanning_tree")); }
initializer_catch; } } //---------------------------------------------------------------------------------------------Stop property void clInitializer::stop(void) { try { environment::informTermination(goModuleName);
delete_object(goDataLocation); }
initializer_catch; } }
// End //------------------------------------------------------------------------------------------- } |
|