/* * vim: ts=4 sw=4 et tw=0 wm=0 * * libcola - A library providing force-directed network layout using the * stress-majorization method subject to separation constraints. * * Copyright (C) 2006-2014 Monash University * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * See the file LICENSE.LGPL distributed with the library. * * 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. * * Author(s): Tim Dwyer */ #ifndef SHORTEST_PATHS_H #define SHORTEST_PATHS_H #include #include #include #include #include #include #include #include "libcola/commondefs.h" #include #include template struct PairNode; namespace shortest_paths { template struct Node { unsigned id; T d; Node* p; // predecessor std::vector*> neighbours; std::vector nweights; PairNode*>* qnode; }; template struct CompareNodes { bool operator() (Node *const &u, Node *const &v) const { if(u==v) return false; // with g++ 4.1.2 unless I have this explicit check // it returns true for this case when using -O3 optimization // CRAZY! if(u->d < v->d) { return true; } return false; } }; typedef std::pair Edge; template /** * returns the adjacency matrix, 0 entries for non-adjacent nodes * @param n total number of nodes * @param D n*n matrix of shortest paths * @param es edge pairs * @param eweights edge weights, if empty then all weights will be taken as 1 */ void neighbours(unsigned const n, T** D, std::vector const & es, std::valarray const & eweights = std::valarray()); /** * find all pairs shortest paths, n^3 dynamic programming approach * @param n total number of nodes * @param D n*n matrix of shortest paths * @param es edge pairs * @param eweights edge weights, if empty then all weights will be taken as 1 */ template void floyd_warshall(unsigned const n, T** D, std::vector const & es, std::valarray const & eweights = std::valarray()); /** * find all pairs shortest paths, faster, uses dijkstra * @param n total number of nodes * @param D n*n matrix of shortest paths * @param es edge pairs * @param eweights edge weights, if empty then all weights will be taken as 1 */ template void johnsons(unsigned const n, T** D, std::vector const & es, std::valarray const & eweights = std::valarray()); /** * find shortest path lengths from node s to all other nodes * @param s starting node * @param n total number of nodes * @param d n vector of path lengths * @param es edge pairs * @param eweights edge weights, if empty then all weights will be taken as 1 */ template void dijkstra(unsigned const s, unsigned const n, T* d, std::vector const & es, std::valarray const & eweights = std::valarray()); //----------------------------------------------------------------------------- // Implementation: // O(n^3) time dynamic programming approach. Slow, but fool proof. // Use for testing. template void floyd_warshall( unsigned const n, T** D, std::vector const & es, std::valarray const & eweights) { COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); for(unsigned i=0;i::max(); } } for(unsigned i=0;i 0) ? eweights[i] : 1; } for(unsigned k=0; k void neighbours( unsigned const n, T** D, std::vector const & es, std::valarray const & eweights) { COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); for(unsigned i=0;i 0) ? eweights[i] : 1; } } template void dijkstra_init( std::vector > & vs, std::vector const& es, std::valarray const & eweights) { COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); #ifndef NDEBUG const unsigned n=vs.size(); #endif for(unsigned i=0;i 0) ? eweights[i] : 1; vs[u].neighbours.push_back(&vs[v]); vs[u].nweights.push_back(w); vs[v].neighbours.push_back(&vs[u]); vs[v].nweights.push_back(w); } } template void dijkstra( unsigned const s, std::vector > & vs, T* d) { const unsigned n=vs.size(); COLA_ASSERT(s::max(); vs[i].p=nullptr; } vs[s].d=0; PairingHeap*,CompareNodes > Q; for(unsigned i=0;i *u=Q.extractMin(); d[u->id]=u->d; for(unsigned i=0;ineighbours.size();i++) { Node *v=u->neighbours[i]; T w=u->nweights[i]; if(u->d!=std::numeric_limits::max() && v->d > u->d+w) { v->p=u; v->d=u->d+w; Q.decreaseKey(v->qnode,v); } } } } template void dijkstra( unsigned const s, unsigned const n, T* d, std::vector const & es, std::valarray const & eweights) { COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size())); COLA_ASSERT(s > vs(n); dijkstra_init(vs,es,eweights); dijkstra(s,vs,d); } template void johnsons( unsigned const n, T** D, std::vector const & es, std::valarray const & eweights) { std::vector > vs(n); dijkstra_init(vs,es,eweights); for(unsigned k=0;k