2010-07-09 05:05:40 -04:00
|
|
|
/*
|
|
|
|
open source routing machine
|
|
|
|
Copyright (C) Dennis Luxen, others 2010
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU AFFERO General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
or see http://www.gnu.org/licenses/agpl.txt.
|
2010-09-13 10:16:07 -04:00
|
|
|
*/
|
2010-07-09 05:05:40 -04:00
|
|
|
|
|
|
|
#ifndef DYNAMICGRAPH_H_INCLUDED
|
|
|
|
#define DYNAMICGRAPH_H_INCLUDED
|
|
|
|
|
2013-06-24 17:02:28 -04:00
|
|
|
#include "../DataStructures/DeallocatingVector.h"
|
|
|
|
|
|
|
|
#include <boost/integer.hpp>
|
|
|
|
|
2010-07-09 05:05:40 -04:00
|
|
|
#include <algorithm>
|
2010-09-13 10:16:07 -04:00
|
|
|
#include <limits>
|
2013-06-24 17:02:28 -04:00
|
|
|
#include <vector>
|
2012-11-15 07:39:23 -05:00
|
|
|
|
2011-11-17 04:37:43 -05:00
|
|
|
template< typename EdgeDataT>
|
2010-07-09 05:05:40 -04:00
|
|
|
class DynamicGraph {
|
|
|
|
public:
|
2011-11-17 04:37:43 -05:00
|
|
|
typedef EdgeDataT EdgeData;
|
2013-06-24 17:02:28 -04:00
|
|
|
typedef uint32_t NodeIterator;
|
|
|
|
typedef uint32_t EdgeIterator;
|
2010-09-13 10:16:07 -04:00
|
|
|
|
|
|
|
class InputEdge {
|
|
|
|
public:
|
|
|
|
NodeIterator source;
|
|
|
|
NodeIterator target;
|
2011-11-17 04:37:43 -05:00
|
|
|
EdgeDataT data;
|
2010-09-13 10:16:07 -04:00
|
|
|
bool operator<( const InputEdge& right ) const {
|
|
|
|
if ( source != right.source )
|
|
|
|
return source < right.source;
|
|
|
|
return target < right.target;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-10-10 12:56:01 -04:00
|
|
|
//Constructs an empty graph with a given number of nodes.
|
2013-06-24 17:02:28 -04:00
|
|
|
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
2011-10-10 12:56:01 -04:00
|
|
|
m_nodes.reserve( m_numNodes );
|
|
|
|
m_nodes.resize( m_numNodes );
|
|
|
|
|
2012-04-14 08:36:11 -04:00
|
|
|
m_edges.reserve( m_numNodes * 1.1 );
|
2011-10-10 12:56:01 -04:00
|
|
|
m_edges.resize( m_numNodes );
|
|
|
|
}
|
2013-06-24 17:02:28 -04:00
|
|
|
|
2012-04-26 08:03:01 -04:00
|
|
|
template<class ContainerT>
|
2013-06-24 17:02:28 -04:00
|
|
|
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
|
2010-09-13 10:16:07 -04:00
|
|
|
m_numNodes = nodes;
|
|
|
|
m_numEdges = ( EdgeIterator ) graph.size();
|
2013-02-12 09:23:09 -05:00
|
|
|
m_nodes.reserve( m_numNodes +1);
|
|
|
|
m_nodes.resize( m_numNodes +1);
|
2010-09-13 10:16:07 -04:00
|
|
|
EdgeIterator edge = 0;
|
|
|
|
EdgeIterator position = 0;
|
|
|
|
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
|
|
|
EdgeIterator lastEdge = edge;
|
|
|
|
while ( edge < m_numEdges && graph[edge].source == node ) {
|
|
|
|
++edge;
|
|
|
|
}
|
|
|
|
m_nodes[node].firstEdge = position;
|
|
|
|
m_nodes[node].edges = edge - lastEdge;
|
|
|
|
position += m_nodes[node].edges;
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2013-01-27 08:19:48 -05:00
|
|
|
m_nodes.back().firstEdge = position;
|
2012-04-14 08:36:11 -04:00
|
|
|
m_edges.reserve( position * 1.1 );
|
2010-09-13 10:16:07 -04:00
|
|
|
m_edges.resize( position );
|
|
|
|
edge = 0;
|
|
|
|
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
|
|
|
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
|
|
|
|
m_edges[i].target = graph[edge].target;
|
|
|
|
m_edges[i].data = graph[edge].data;
|
2013-06-24 16:55:43 -04:00
|
|
|
BOOST_ASSERT_MSG(
|
|
|
|
graph[edge].data.distance > 0,
|
|
|
|
"edge distance invalid"
|
|
|
|
);
|
2012-11-19 05:45:10 -05:00
|
|
|
++edge;
|
2010-09-13 10:16:07 -04:00
|
|
|
}
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2011-11-14 13:36:31 -05:00
|
|
|
~DynamicGraph(){ }
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2013-06-24 17:02:28 -04:00
|
|
|
uint32_t GetNumberOfNodes() const {
|
2010-09-13 10:16:07 -04:00
|
|
|
return m_numNodes;
|
|
|
|
}
|
|
|
|
|
2013-06-24 17:02:28 -04:00
|
|
|
uint32_t GetNumberOfEdges() const {
|
2010-09-13 10:16:07 -04:00
|
|
|
return m_numEdges;
|
|
|
|
}
|
|
|
|
|
2013-06-24 17:02:28 -04:00
|
|
|
uint32_t GetOutDegree( const NodeIterator n ) const {
|
2010-09-13 10:16:07 -04:00
|
|
|
return m_nodes[n].edges;
|
|
|
|
}
|
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
NodeIterator GetTarget( const EdgeIterator e ) const {
|
2010-09-13 10:16:07 -04:00
|
|
|
return NodeIterator( m_edges[e].target );
|
|
|
|
}
|
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
2010-09-13 10:16:07 -04:00
|
|
|
return m_edges[e].data;
|
|
|
|
}
|
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
2010-09-13 10:16:07 -04:00
|
|
|
return m_edges[e].data;
|
|
|
|
}
|
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
2010-09-13 10:16:07 -04:00
|
|
|
//assert( EndEdges( n ) - EdgeIterator( _nodes[n].firstEdge ) <= 100 );
|
|
|
|
return EdgeIterator( m_nodes[n].firstEdge );
|
|
|
|
}
|
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
EdgeIterator EndEdges( const NodeIterator n ) const {
|
2010-09-13 10:16:07 -04:00
|
|
|
return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
|
|
|
|
}
|
|
|
|
|
|
|
|
//adds an edge. Invalidates edge iterators for the source node
|
2013-02-12 09:23:09 -05:00
|
|
|
EdgeIterator InsertEdge( const NodeIterator from, const NodeIterator to, const EdgeDataT &data ) {
|
2010-09-13 10:16:07 -04:00
|
|
|
Node &node = m_nodes[from];
|
|
|
|
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
|
|
|
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
|
|
|
|
if ( node.firstEdge != 0 && isDummy( node.firstEdge - 1 ) ) {
|
|
|
|
node.firstEdge--;
|
|
|
|
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
|
|
|
} else {
|
|
|
|
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
2013-06-24 17:02:28 -04:00
|
|
|
uint32_t newSize = node.edges * 1.1 + 2;
|
2010-09-13 10:16:07 -04:00
|
|
|
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
|
|
|
EdgeIterator oldCapacity = m_edges.capacity();
|
|
|
|
if ( requiredCapacity >= oldCapacity ) {
|
|
|
|
m_edges.reserve( requiredCapacity * 1.1 );
|
|
|
|
}
|
|
|
|
m_edges.resize( m_edges.size() + newSize );
|
|
|
|
for ( EdgeIterator i = 0; i < node.edges; ++i ) {
|
|
|
|
m_edges[newFirstEdge + i ] = m_edges[node.firstEdge + i];
|
|
|
|
makeDummy( node.firstEdge + i );
|
|
|
|
}
|
2012-01-07 09:00:40 -05:00
|
|
|
for ( EdgeIterator i = node.edges + 1; i < newSize; ++i )
|
2010-09-13 10:16:07 -04:00
|
|
|
makeDummy( newFirstEdge + i );
|
|
|
|
node.firstEdge = newFirstEdge;
|
|
|
|
}
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
Edge &edge = m_edges[node.firstEdge + node.edges];
|
|
|
|
edge.target = to;
|
|
|
|
edge.data = data;
|
2012-01-07 09:00:40 -05:00
|
|
|
++m_numEdges;
|
|
|
|
++node.edges;
|
2010-09-13 10:16:07 -04:00
|
|
|
return EdgeIterator( node.firstEdge + node.edges );
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
|
|
|
|
2010-09-13 10:16:07 -04:00
|
|
|
//removes an edge. Invalidates edge iterators for the source node
|
2013-02-12 09:23:09 -05:00
|
|
|
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
|
2010-09-13 10:16:07 -04:00
|
|
|
Node &node = m_nodes[source];
|
|
|
|
--m_numEdges;
|
|
|
|
--node.edges;
|
2013-06-24 17:02:28 -04:00
|
|
|
const uint32_t last = node.firstEdge + node.edges;
|
2010-09-13 10:16:07 -04:00
|
|
|
//swap with last edge
|
|
|
|
m_edges[e] = m_edges[last];
|
|
|
|
makeDummy( last );
|
|
|
|
}
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2010-09-13 10:16:07 -04:00
|
|
|
//removes all edges (source,target)
|
2013-06-24 17:02:28 -04:00
|
|
|
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
|
|
|
|
int32_t deleted = 0;
|
2010-09-13 10:16:07 -04:00
|
|
|
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
|
|
|
|
if ( m_edges[i].target == target ) {
|
|
|
|
do {
|
|
|
|
deleted++;
|
|
|
|
m_edges[i] = m_edges[iend - deleted];
|
|
|
|
makeDummy( iend - deleted );
|
|
|
|
} while ( i < iend - deleted && m_edges[i].target == target );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma omp atomic
|
|
|
|
m_numEdges -= deleted;
|
|
|
|
m_nodes[source].edges -= deleted;
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2010-09-13 10:16:07 -04:00
|
|
|
return deleted;
|
|
|
|
}
|
|
|
|
|
|
|
|
//searches for a specific edge
|
2013-02-12 09:23:09 -05:00
|
|
|
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
2010-09-13 10:16:07 -04:00
|
|
|
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
|
|
|
|
if ( m_edges[i].target == to ) {
|
|
|
|
return i;
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
return EndEdges( from );
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
|
|
|
|
2010-09-13 10:16:07 -04:00
|
|
|
protected:
|
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
bool isDummy( EdgeIterator edge ) const {
|
2011-09-28 11:22:03 -04:00
|
|
|
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
|
2010-09-13 10:16:07 -04:00
|
|
|
}
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
void makeDummy( EdgeIterator edge ) {
|
2011-09-28 11:22:03 -04:00
|
|
|
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
|
2010-09-13 10:16:07 -04:00
|
|
|
}
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2010-09-13 10:16:07 -04:00
|
|
|
struct Node {
|
|
|
|
//index of the first edge
|
|
|
|
EdgeIterator firstEdge;
|
|
|
|
//amount of edges
|
2013-06-24 17:02:28 -04:00
|
|
|
uint32_t edges;
|
2010-09-13 10:16:07 -04:00
|
|
|
};
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2010-09-13 10:16:07 -04:00
|
|
|
struct Edge {
|
|
|
|
NodeIterator target;
|
2011-11-17 04:37:43 -05:00
|
|
|
EdgeDataT data;
|
2010-09-13 10:16:07 -04:00
|
|
|
};
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2010-09-13 10:16:07 -04:00
|
|
|
NodeIterator m_numNodes;
|
|
|
|
EdgeIterator m_numEdges;
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2013-02-12 09:23:09 -05:00
|
|
|
std::vector< Node > m_nodes;
|
|
|
|
DeallocatingVector< Edge > m_edges;
|
2010-07-09 05:05:40 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // DYNAMICGRAPH_H_INCLUDED
|