Merge branch 'TheMarex-ebgf-refactor' into develop
This commit is contained in:
commit
5579388896
@ -41,7 +41,7 @@ file(GLOB ExtractorGlob Extractor/*.cpp)
|
|||||||
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
add_executable(osrm-extract ${ExtractorSources})
|
add_executable(osrm-extract ${ExtractorSources})
|
||||||
|
|
||||||
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp)
|
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
|
||||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||||
add_executable(osrm-prepare ${PrepareSources})
|
add_executable(osrm-prepare ${PrepareSources})
|
||||||
|
|
||||||
|
145
Contractor/BFSComponentExplorer.h
Normal file
145
Contractor/BFSComponentExplorer.h
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#ifndef __BFS_COMPONENT_EXPLORER_H__
|
||||||
|
#define __BFS_COMPONENT_EXPLORER_H__
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explores the components of the given graph while respecting turn restrictions
|
||||||
|
* and barriers.
|
||||||
|
*/
|
||||||
|
template <typename GraphT> class BFSComponentExplorer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename GraphT::NodeIterator NodeIterator;
|
||||||
|
typedef typename GraphT::EdgeIterator EdgeIterator;
|
||||||
|
|
||||||
|
BFSComponentExplorer(const GraphT &dynamicGraph,
|
||||||
|
const RestrictionMap &restrictions,
|
||||||
|
const boost::unordered_set<NodeID> &barrier_nodes)
|
||||||
|
: m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the size of the component that the node belongs to.
|
||||||
|
*/
|
||||||
|
inline unsigned int getComponentSize(NodeID node)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node < m_component_index_list.size());
|
||||||
|
|
||||||
|
return m_component_index_size[m_component_index_list[node]];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int getNumberOfComponents() { return m_component_index_size.size(); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Computes the component sizes.
|
||||||
|
*/
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
|
||||||
|
unsigned current_component = 0;
|
||||||
|
|
||||||
|
BOOST_ASSERT(m_component_index_list.empty());
|
||||||
|
BOOST_ASSERT(m_component_index_size.empty());
|
||||||
|
|
||||||
|
unsigned num_nodes = m_graph.GetNumberOfNodes();
|
||||||
|
|
||||||
|
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
BOOST_ASSERT(num_nodes > 0);
|
||||||
|
|
||||||
|
// put unexplorered node with parent pointer into queue
|
||||||
|
for (NodeID node = 0; node < num_nodes; ++node)
|
||||||
|
{
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
|
||||||
|
{
|
||||||
|
unsigned size = exploreComponent(bfs_queue, node, current_component);
|
||||||
|
|
||||||
|
// push size into vector
|
||||||
|
m_component_index_size.push_back(size);
|
||||||
|
++current_component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* Explores the current component that starts at node using BFS.
|
||||||
|
*/
|
||||||
|
inline unsigned exploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
||||||
|
NodeID node,
|
||||||
|
unsigned current_component)
|
||||||
|
{
|
||||||
|
bfs_queue.push(std::make_pair(node, node));
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[node] = current_component;
|
||||||
|
|
||||||
|
unsigned current_component_size = 1;
|
||||||
|
|
||||||
|
while (!bfs_queue.empty())
|
||||||
|
{
|
||||||
|
// fetch element from BFS queue
|
||||||
|
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||||
|
bfs_queue.pop();
|
||||||
|
|
||||||
|
const NodeID v = current_queue_item.first; // current node
|
||||||
|
const NodeID u = current_queue_item.second; // parent
|
||||||
|
// increment size counter of current component
|
||||||
|
++current_component_size;
|
||||||
|
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||||
|
if (!is_barrier_node)
|
||||||
|
{
|
||||||
|
const NodeID to_node_of_only_restriction =
|
||||||
|
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
|
||||||
|
for (EdgeIterator e2 = m_graph.BeginEdges(v); e2 < m_graph.EndEdges(v); ++e2)
|
||||||
|
{
|
||||||
|
NodeIterator w = m_graph.GetTarget(e2);
|
||||||
|
|
||||||
|
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||||
|
w != to_node_of_only_restriction)
|
||||||
|
{
|
||||||
|
// At an only_-restriction but not at the right turn
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u != w)
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not a U-turn except
|
||||||
|
// when it is at the end of a dead-end street.
|
||||||
|
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not prohibited
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
|
||||||
|
{
|
||||||
|
// insert next (node, parent) only if w has
|
||||||
|
// not yet been explored
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[w] = current_component;
|
||||||
|
bfs_queue.push(std::make_pair(w, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_component_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> m_component_index_list;
|
||||||
|
std::vector<NodeID> m_component_index_size;
|
||||||
|
|
||||||
|
const GraphT &m_graph;
|
||||||
|
const RestrictionMap &m_restriction_map;
|
||||||
|
const boost::unordered_set<NodeID> &m_barrier_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -41,21 +41,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/lambda/lambda.hpp>
|
#include <boost/lambda/lambda.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Contractor {
|
class Contractor
|
||||||
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ContractorEdgeData {
|
struct ContractorEdgeData
|
||||||
ContractorEdgeData() :
|
{
|
||||||
distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {}
|
ContractorEdgeData()
|
||||||
ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) :
|
: distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0),
|
||||||
distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
|
originalViaNodeID(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ContractorEdgeData(unsigned _distance,
|
||||||
|
unsigned _originalEdges,
|
||||||
|
unsigned _id,
|
||||||
|
bool _shortcut,
|
||||||
|
bool _forward,
|
||||||
|
bool _backward)
|
||||||
|
: distance(_distance), id(_id),
|
||||||
|
originalEdges(std::min((unsigned)1 << 28, _originalEdges)), shortcut(_shortcut),
|
||||||
|
forward(_forward), backward(_backward), originalViaNodeID(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
unsigned distance;
|
unsigned distance;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned originalEdges : 28;
|
unsigned originalEdges : 28;
|
||||||
@ -65,7 +77,8 @@ private:
|
|||||||
bool originalViaNodeID : 1;
|
bool originalViaNodeID : 1;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
struct _HeapData {
|
struct _HeapData
|
||||||
|
{
|
||||||
short hop;
|
short hop;
|
||||||
bool target;
|
bool target;
|
||||||
_HeapData() : hop(0), target(false) {}
|
_HeapData() : hop(0), target(false) {}
|
||||||
@ -77,42 +90,50 @@ private:
|
|||||||
typedef BinaryHeap<NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID>> _Heap;
|
typedef BinaryHeap<NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID>> _Heap;
|
||||||
typedef _DynamicGraph::InputEdge _ContractorEdge;
|
typedef _DynamicGraph::InputEdge _ContractorEdge;
|
||||||
|
|
||||||
struct _ThreadData {
|
struct _ThreadData
|
||||||
|
{
|
||||||
_Heap heap;
|
_Heap heap;
|
||||||
std::vector<_ContractorEdge> insertedEdges;
|
std::vector<_ContractorEdge> insertedEdges;
|
||||||
std::vector<NodeID> neighbours;
|
std::vector<NodeID> neighbours;
|
||||||
_ThreadData(NodeID nodes) : heap(nodes) {}
|
_ThreadData(NodeID nodes) : heap(nodes) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _PriorityData {
|
struct _PriorityData
|
||||||
|
{
|
||||||
int depth;
|
int depth;
|
||||||
_PriorityData() : depth(0) {}
|
_PriorityData() : depth(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ContractionInformation {
|
struct _ContractionInformation
|
||||||
|
{
|
||||||
int edgesDeleted;
|
int edgesDeleted;
|
||||||
int edgesAdded;
|
int edgesAdded;
|
||||||
int originalEdgesDeleted;
|
int originalEdgesDeleted;
|
||||||
int originalEdgesAdded;
|
int originalEdgesAdded;
|
||||||
_ContractionInformation() : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) {}
|
_ContractionInformation()
|
||||||
|
: edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _RemainingNodeData {
|
struct _RemainingNodeData
|
||||||
|
{
|
||||||
_RemainingNodeData() : id(0), isIndependent(false) {}
|
_RemainingNodeData() : id(0), isIndependent(false) {}
|
||||||
NodeID id : 31;
|
NodeID id : 31;
|
||||||
bool isIndependent : 1;
|
bool isIndependent : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _NodePartitionor {
|
struct _NodePartitionor
|
||||||
inline bool operator()(_RemainingNodeData & nodeData ) const {
|
{
|
||||||
|
inline bool operator()(_RemainingNodeData &nodeData) const
|
||||||
|
{
|
||||||
return !nodeData.isIndependent;
|
return !nodeData.isIndependent;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
template <class ContainerT> Contractor(int nodes, ContainerT &inputEdges)
|
||||||
template<class ContainerT >
|
{
|
||||||
Contractor( int nodes, ContainerT& inputEdges) {
|
|
||||||
std::vector<_ContractorEdge> edges;
|
std::vector<_ContractorEdge> edges;
|
||||||
edges.reserve(inputEdges.size() * 2);
|
edges.reserve(inputEdges.size() * 2);
|
||||||
temp_edge_counter = 0;
|
temp_edge_counter = 0;
|
||||||
@ -121,15 +142,22 @@ public:
|
|||||||
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
|
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
|
||||||
|
|
||||||
_ContractorEdge newEdge;
|
_ContractorEdge newEdge;
|
||||||
while(diter!=dend) {
|
while (diter != dend)
|
||||||
|
{
|
||||||
newEdge.source = diter->source();
|
newEdge.source = diter->source();
|
||||||
newEdge.target = diter->target();
|
newEdge.target = diter->target();
|
||||||
newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
newEdge.data = ContractorEdgeData((std::max)((int)diter->weight(), 1),
|
||||||
|
1,
|
||||||
|
diter->id(),
|
||||||
|
false,
|
||||||
|
diter->isForward(),
|
||||||
|
diter->isBackward());
|
||||||
BOOST_ASSERT_MSG(newEdge.data.distance > 0, "edge distance < 1");
|
BOOST_ASSERT_MSG(newEdge.data.distance > 0, "edge distance < 1");
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
if (newEdge.data.distance > 24 * 60 * 60 * 10)
|
||||||
SimpleLogger().Write(logWARNING) <<
|
{
|
||||||
"Edge weight large -> " << newEdge.data.distance;
|
SimpleLogger().Write(logWARNING) << "Edge weight large -> "
|
||||||
|
<< newEdge.data.distance;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
edges.push_back(newEdge);
|
edges.push_back(newEdge);
|
||||||
@ -143,12 +171,14 @@ public:
|
|||||||
inputEdges.clear();
|
inputEdges.clear();
|
||||||
sort(edges.begin(), edges.end());
|
sort(edges.begin(), edges.end());
|
||||||
NodeID edge = 0;
|
NodeID edge = 0;
|
||||||
for ( NodeID i = 0; i < edges.size(); ) {
|
for (NodeID i = 0; i < edges.size();)
|
||||||
|
{
|
||||||
const NodeID source = edges[i].source;
|
const NodeID source = edges[i].source;
|
||||||
const NodeID target = edges[i].target;
|
const NodeID target = edges[i].target;
|
||||||
const NodeID id = edges[i].data.id;
|
const NodeID id = edges[i].data.id;
|
||||||
// remove eigenloops
|
// remove eigenloops
|
||||||
if ( source == target ) {
|
if (source == target)
|
||||||
|
{
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -161,35 +191,48 @@ public:
|
|||||||
forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
|
forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
|
||||||
forwardEdge.data.id = backwardEdge.data.id = id;
|
forwardEdge.data.id = backwardEdge.data.id = id;
|
||||||
forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1;
|
forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1;
|
||||||
forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
|
forwardEdge.data.distance = backwardEdge.data.distance =
|
||||||
|
std::numeric_limits<int>::max();
|
||||||
// remove parallel edges
|
// remove parallel edges
|
||||||
while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) {
|
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||||
if ( edges[i].data.forward) {
|
{
|
||||||
forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
|
if (edges[i].data.forward)
|
||||||
|
{
|
||||||
|
forwardEdge.data.distance =
|
||||||
|
std::min(edges[i].data.distance, forwardEdge.data.distance);
|
||||||
}
|
}
|
||||||
if ( edges[i].data.backward) {
|
if (edges[i].data.backward)
|
||||||
backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
|
{
|
||||||
|
backwardEdge.data.distance =
|
||||||
|
std::min(edges[i].data.distance, backwardEdge.data.distance);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||||
if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
|
if (forwardEdge.data.distance == backwardEdge.data.distance)
|
||||||
if ( (int)forwardEdge.data.distance != std::numeric_limits< int >::max() ) {
|
{
|
||||||
|
if ((int)forwardEdge.data.distance != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
forwardEdge.data.backward = true;
|
forwardEdge.data.backward = true;
|
||||||
edges[edge++] = forwardEdge;
|
edges[edge++] = forwardEdge;
|
||||||
}
|
}
|
||||||
} else { //insert seperate edges
|
}
|
||||||
if ( ((int)forwardEdge.data.distance) != std::numeric_limits< int >::max() ) {
|
else
|
||||||
|
{ // insert seperate edges
|
||||||
|
if (((int)forwardEdge.data.distance) != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
edges[edge++] = forwardEdge;
|
edges[edge++] = forwardEdge;
|
||||||
}
|
}
|
||||||
if ( (int)backwardEdge.data.distance != std::numeric_limits< int >::max() ) {
|
if ((int)backwardEdge.data.distance != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
edges[edge++] = backwardEdge;
|
edges[edge++] = backwardEdge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
|
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size()
|
||||||
|
<< std::endl;
|
||||||
edges.resize(edge);
|
edges.resize(edge);
|
||||||
_graph = boost::make_shared<_DynamicGraph>( nodes, edges );
|
_graph = std::make_shared<_DynamicGraph>(nodes, edges);
|
||||||
edges.clear();
|
edges.clear();
|
||||||
std::vector<_ContractorEdge>().swap(edges);
|
std::vector<_ContractorEdge>().swap(edges);
|
||||||
BOOST_ASSERT(0 == edges.capacity());
|
BOOST_ASSERT(0 == edges.capacity());
|
||||||
@ -204,9 +247,12 @@ public:
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree " << maxdegree;
|
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree
|
||||||
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
|
// " << maxdegree;
|
||||||
// SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via;
|
// for(unsigned i = _graph->BeginEdges(highestNode); i <
|
||||||
|
// _graph->EndEdges(highestNode); ++i) {
|
||||||
|
// SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i)
|
||||||
|
// << "); via: " << _graph->GetEdgeData(i).via;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Create temporary file
|
// Create temporary file
|
||||||
@ -216,19 +262,22 @@ public:
|
|||||||
std::cout << "contractor finished initalization" << std::endl;
|
std::cout << "contractor finished initalization" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Contractor() {
|
~Contractor()
|
||||||
|
{
|
||||||
// Delete temporary file
|
// Delete temporary file
|
||||||
// remove(temporaryEdgeStorageFilename.c_str());
|
// remove(temporaryEdgeStorageFilename.c_str());
|
||||||
TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot);
|
TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run() {
|
void Run()
|
||||||
|
{
|
||||||
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||||
Percent p(numberOfNodes);
|
Percent p(numberOfNodes);
|
||||||
|
|
||||||
const unsigned maxThreads = omp_get_max_threads();
|
const unsigned maxThreads = omp_get_max_threads();
|
||||||
std::vector<_ThreadData *> threadData;
|
std::vector<_ThreadData *> threadData;
|
||||||
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
for (unsigned threadNum = 0; threadNum < maxThreads; ++threadNum)
|
||||||
|
{
|
||||||
threadData.push_back(new _ThreadData(numberOfNodes));
|
threadData.push_back(new _ThreadData(numberOfNodes));
|
||||||
}
|
}
|
||||||
std::cout << "Contractor is using " << maxThreads << " threads" << std::endl;
|
std::cout << "Contractor is using " << maxThreads << " threads" << std::endl;
|
||||||
@ -240,7 +289,8 @@ public:
|
|||||||
|
|
||||||
// initialize the variables
|
// initialize the variables
|
||||||
#pragma omp parallel for schedule(guided)
|
#pragma omp parallel for schedule(guided)
|
||||||
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
|
for (int x = 0; x < (int)numberOfNodes; ++x)
|
||||||
|
{
|
||||||
remainingNodes[x].id = x;
|
remainingNodes[x].id = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,16 +299,22 @@ public:
|
|||||||
{
|
{
|
||||||
_ThreadData *data = threadData[omp_get_thread_num()];
|
_ThreadData *data = threadData[omp_get_thread_num()];
|
||||||
#pragma omp parallel for schedule(guided)
|
#pragma omp parallel for schedule(guided)
|
||||||
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
|
for (int x = 0; x < (int)numberOfNodes; ++x)
|
||||||
|
{
|
||||||
nodePriority[x] = _Evaluate(data, &nodeData[x], x);
|
nodePriority[x] = _Evaluate(data, &nodeData[x], x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
|
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..."
|
||||||
|
<< std::flush;
|
||||||
|
|
||||||
bool flushedContractor = false;
|
bool flushedContractor = false;
|
||||||
while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) {
|
while (numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes)
|
||||||
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
|
{
|
||||||
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
|
if (!flushedContractor && (numberOfContractedNodes > (numberOfNodes * 0.65)))
|
||||||
|
{
|
||||||
|
DeallocatingVector<_ContractorEdge> newSetOfEdges; // this one is not explicitely
|
||||||
|
// cleared since it goes out of
|
||||||
|
// scope anywa
|
||||||
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
||||||
|
|
||||||
//Delete old heap data to free memory that we need for the coming operations
|
//Delete old heap data to free memory that we need for the coming operations
|
||||||
@ -269,13 +325,17 @@ public:
|
|||||||
|
|
||||||
// Create new priority array
|
// Create new priority array
|
||||||
std::vector<float> newNodePriority(remainingNodes.size());
|
std::vector<float> newNodePriority(remainingNodes.size());
|
||||||
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
|
// this map gives the old IDs from the new ones, necessary to get a consistent graph
|
||||||
|
// at the end of contraction
|
||||||
oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size());
|
oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size());
|
||||||
//this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
|
// this map gives the new IDs from the old ones, necessary to remap targets from the
|
||||||
|
// remaining graph
|
||||||
std::vector<NodeID> newNodeIDFromOldNodeIDMap(numberOfNodes, UINT_MAX);
|
std::vector<NodeID> newNodeIDFromOldNodeIDMap(numberOfNodes, UINT_MAX);
|
||||||
|
|
||||||
//build forward and backward renumbering map and remap ids in remainingNodes and Priorities.
|
// build forward and backward renumbering map and remap ids in remainingNodes and
|
||||||
for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) {
|
// Priorities.
|
||||||
|
for (unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID)
|
||||||
|
{
|
||||||
// create renumbering maps in both directions
|
// create renumbering maps in both directions
|
||||||
oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].id;
|
oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].id;
|
||||||
newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].id] = newNodeID;
|
newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].id] = newNodeID;
|
||||||
@ -284,18 +344,28 @@ public:
|
|||||||
}
|
}
|
||||||
TemporaryStorage &tempStorage = TemporaryStorage::GetInstance();
|
TemporaryStorage &tempStorage = TemporaryStorage::GetInstance();
|
||||||
// walk over all nodes
|
// walk over all nodes
|
||||||
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
|
for (unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i)
|
||||||
|
{
|
||||||
const NodeID start = i;
|
const NodeID start = i;
|
||||||
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
|
for (_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start);
|
||||||
|
currentEdge < _graph->EndEdges(start);
|
||||||
|
++currentEdge)
|
||||||
|
{
|
||||||
_DynamicGraph::EdgeData &data = _graph->GetEdgeData(currentEdge);
|
_DynamicGraph::EdgeData &data = _graph->GetEdgeData(currentEdge);
|
||||||
const NodeID target = _graph->GetTarget(currentEdge);
|
const NodeID target = _graph->GetTarget(currentEdge);
|
||||||
if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){
|
if (UINT_MAX == newNodeIDFromOldNodeIDMap[i])
|
||||||
|
{
|
||||||
// Save edges of this node w/o renumbering.
|
// Save edges of this node w/o renumbering.
|
||||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
|
tempStorage.WriteToSlot(
|
||||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
|
edge_storage_slot, (char *)&start, sizeof(NodeID));
|
||||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
tempStorage.WriteToSlot(
|
||||||
|
edge_storage_slot, (char *)&target, sizeof(NodeID));
|
||||||
|
tempStorage.WriteToSlot(
|
||||||
|
edge_storage_slot, (char *)&data, sizeof(_DynamicGraph::EdgeData));
|
||||||
++temp_edge_counter;
|
++temp_edge_counter;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// node is not yet contracted.
|
// node is not yet contracted.
|
||||||
// add (renumbered) outgoing edges to new DynamicGraph.
|
// add (renumbered) outgoing edges to new DynamicGraph.
|
||||||
_ContractorEdge newEdge;
|
_ContractorEdge newEdge;
|
||||||
@ -303,14 +373,10 @@ public:
|
|||||||
newEdge.target = newNodeIDFromOldNodeIDMap[target];
|
newEdge.target = newNodeIDFromOldNodeIDMap[target];
|
||||||
newEdge.data = data;
|
newEdge.data = data;
|
||||||
newEdge.data.originalViaNodeID = true;
|
newEdge.data.originalViaNodeID = true;
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(UINT_MAX != newNodeIDFromOldNodeIDMap[start],
|
||||||
UINT_MAX != newNodeIDFromOldNodeIDMap[start],
|
"new start id not resolveable");
|
||||||
"new start id not resolveable"
|
BOOST_ASSERT_MSG(UINT_MAX != newNodeIDFromOldNodeIDMap[target],
|
||||||
);
|
"new target id not resolveable");
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
UINT_MAX != newNodeIDFromOldNodeIDMap[target],
|
|
||||||
"new target id not resolveable"
|
|
||||||
);
|
|
||||||
newSetOfEdges.push_back(newEdge);
|
newSetOfEdges.push_back(newEdge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -328,14 +394,15 @@ public:
|
|||||||
|
|
||||||
// create new graph
|
// create new graph
|
||||||
std::sort(newSetOfEdges.begin(), newSetOfEdges.end());
|
std::sort(newSetOfEdges.begin(), newSetOfEdges.end());
|
||||||
_graph = boost::make_shared<_DynamicGraph>(remainingNodes.size(), newSetOfEdges);
|
_graph = std::make_shared<_DynamicGraph>(remainingNodes.size(), newSetOfEdges);
|
||||||
|
|
||||||
newSetOfEdges.clear();
|
newSetOfEdges.clear();
|
||||||
flushedContractor = true;
|
flushedContractor = true;
|
||||||
|
|
||||||
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
|
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
|
||||||
// reinitialize heaps and ThreadData objects with appropriate size
|
// reinitialize heaps and ThreadData objects with appropriate size
|
||||||
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
for (unsigned threadNum = 0; threadNum < maxThreads; ++threadNum)
|
||||||
|
{
|
||||||
threadData.push_back(new _ThreadData(_graph->GetNumberOfNodes()));
|
threadData.push_back(new _ThreadData(_graph->GetNumberOfNodes()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,20 +413,24 @@ public:
|
|||||||
// determine independent node set
|
// determine independent node set
|
||||||
_ThreadData *const data = threadData[omp_get_thread_num()];
|
_ThreadData *const data = threadData[omp_get_thread_num()];
|
||||||
#pragma omp for schedule(guided)
|
#pragma omp for schedule(guided)
|
||||||
for ( int i = 0; i < last; ++i ) {
|
for (int i = 0; i < last; ++i)
|
||||||
|
{
|
||||||
const NodeID node = remainingNodes[i].id;
|
const NodeID node = remainingNodes[i].id;
|
||||||
remainingNodes[i].isIndependent = _IsIndependent( nodePriority/*, nodeData*/, data, node );
|
remainingNodes[i].isIndependent =
|
||||||
|
_IsIndependent(nodePriority /*, nodeData*/, data, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_NodePartitionor functor;
|
_NodePartitionor functor;
|
||||||
const std::vector < _RemainingNodeData >::const_iterator first = stable_partition( remainingNodes.begin(), remainingNodes.end(), functor );
|
const std::vector<_RemainingNodeData>::const_iterator first =
|
||||||
|
stable_partition(remainingNodes.begin(), remainingNodes.end(), functor);
|
||||||
const int firstIndependent = first - remainingNodes.begin();
|
const int firstIndependent = first - remainingNodes.begin();
|
||||||
// contract independent nodes
|
// contract independent nodes
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
{
|
{
|
||||||
_ThreadData *data = threadData[omp_get_thread_num()];
|
_ThreadData *data = threadData[omp_get_thread_num()];
|
||||||
#pragma omp for schedule(guided) nowait
|
#pragma omp for schedule(guided) nowait
|
||||||
for ( int position = firstIndependent ; position < last; ++position ) {
|
for (int position = firstIndependent; position < last; ++position)
|
||||||
|
{
|
||||||
NodeID x = remainingNodes[position].id;
|
NodeID x = remainingNodes[position].id;
|
||||||
_Contract<false>(data, x);
|
_Contract<false>(data, x);
|
||||||
// nodePriority[x] = -1;
|
// nodePriority[x] = -1;
|
||||||
@ -371,7 +442,8 @@ public:
|
|||||||
{
|
{
|
||||||
_ThreadData *data = threadData[omp_get_thread_num()];
|
_ThreadData *data = threadData[omp_get_thread_num()];
|
||||||
#pragma omp for schedule(guided) nowait
|
#pragma omp for schedule(guided) nowait
|
||||||
for ( int position = firstIndependent ; position < last; ++position ) {
|
for (int position = firstIndependent; position < last; ++position)
|
||||||
|
{
|
||||||
NodeID x = remainingNodes[position].id;
|
NodeID x = remainingNodes[position].id;
|
||||||
_DeleteIncomingEdges(data, x);
|
_DeleteIncomingEdges(data, x);
|
||||||
}
|
}
|
||||||
@ -386,11 +458,12 @@ public:
|
|||||||
if(currentEdgeData.shortcut &&
|
if(currentEdgeData.shortcut &&
|
||||||
edge.data.forward == currentEdgeData.forward &&
|
edge.data.forward == currentEdgeData.forward &&
|
||||||
edge.data.backward == currentEdgeData.backward &&
|
edge.data.backward == currentEdgeData.backward &&
|
||||||
edge.data.distance < currentEdgeData.distance
|
edge.data.distance < currentEdgeData.distance)
|
||||||
) {
|
{
|
||||||
// found a duplicate edge with smaller weight, update it.
|
// found a duplicate edge with smaller weight, update it.
|
||||||
currentEdgeData = edge.data;
|
currentEdgeData = edge.data;
|
||||||
// currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
|
// currentEdgeData.distance = std::min(currentEdgeData.distance,
|
||||||
|
// edge.data.distance);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,7 +476,8 @@ public:
|
|||||||
{
|
{
|
||||||
_ThreadData *data = threadData[omp_get_thread_num()];
|
_ThreadData *data = threadData[omp_get_thread_num()];
|
||||||
#pragma omp for schedule(guided) nowait
|
#pragma omp for schedule(guided) nowait
|
||||||
for ( int position = firstIndependent ; position < last; ++position ) {
|
for (int position = firstIndependent; position < last; ++position)
|
||||||
|
{
|
||||||
NodeID x = remainingNodes[position].id;
|
NodeID x = remainingNodes[position].id;
|
||||||
_UpdateNeighbours(nodePriority, nodeData, data, x);
|
_UpdateNeighbours(nodePriority, nodeData, data, x);
|
||||||
}
|
}
|
||||||
@ -418,7 +492,8 @@ public:
|
|||||||
// unsigned quaddegree = 0;
|
// unsigned quaddegree = 0;
|
||||||
//
|
//
|
||||||
// for(unsigned i = 0; i < remainingNodes.size(); ++i) {
|
// for(unsigned i = 0; i < remainingNodes.size(); ++i) {
|
||||||
// unsigned degree = _graph->EndEdges(remainingNodes[i].first) - _graph->BeginEdges(remainingNodes[i].first);
|
// unsigned degree = _graph->EndEdges(remainingNodes[i].first) -
|
||||||
|
// _graph->BeginEdges(remainingNodes[i].first);
|
||||||
// if(degree > maxdegree)
|
// if(degree > maxdegree)
|
||||||
// maxdegree = degree;
|
// maxdegree = degree;
|
||||||
// if(degree < mindegree)
|
// if(degree < mindegree)
|
||||||
@ -431,7 +506,9 @@ public:
|
|||||||
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||||
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||||
//
|
//
|
||||||
// SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree;
|
// SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: "
|
||||||
|
// << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ",
|
||||||
|
// quad: " << quaddegree;
|
||||||
|
|
||||||
p.printStatus(numberOfContractedNodes);
|
p.printStatus(numberOfContractedNodes);
|
||||||
}
|
}
|
||||||
@ -441,47 +518,48 @@ public:
|
|||||||
threadData.clear();
|
threadData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template< class Edge >
|
template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
|
||||||
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
|
{
|
||||||
Percent p(_graph->GetNumberOfNodes());
|
Percent p(_graph->GetNumberOfNodes());
|
||||||
SimpleLogger().Write() << "Getting edges of minimized graph";
|
SimpleLogger().Write() << "Getting edges of minimized graph";
|
||||||
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||||
if(_graph->GetNumberOfNodes()) {
|
if (_graph->GetNumberOfNodes())
|
||||||
|
{
|
||||||
Edge newEdge;
|
Edge newEdge;
|
||||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
for (NodeID node = 0; node < numberOfNodes; ++node)
|
||||||
|
{
|
||||||
p.printStatus(node);
|
p.printStatus(node);
|
||||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
for (_DynamicGraph::EdgeIterator edge = _graph->BeginEdges(node),
|
||||||
|
endEdges = _graph->EndEdges(node);
|
||||||
|
edge < endEdges;
|
||||||
|
++edge)
|
||||||
|
{
|
||||||
const NodeID target = _graph->GetTarget(edge);
|
const NodeID target = _graph->GetTarget(edge);
|
||||||
const _DynamicGraph::EdgeData &data = _graph->GetEdgeData(edge);
|
const _DynamicGraph::EdgeData &data = _graph->GetEdgeData(edge);
|
||||||
if( !oldNodeIDFromNewNodeIDMap.empty() ) {
|
if (!oldNodeIDFromNewNodeIDMap.empty())
|
||||||
|
{
|
||||||
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
||||||
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
newEdge.source = node;
|
newEdge.source = node;
|
||||||
newEdge.target = target;
|
newEdge.target = target;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(UINT_MAX != newEdge.source, "Source id invalid");
|
||||||
UINT_MAX != newEdge.source,
|
BOOST_ASSERT_MSG(UINT_MAX != newEdge.target, "Target id invalid");
|
||||||
"Source id invalid"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
UINT_MAX != newEdge.target,
|
|
||||||
"Target id invalid"
|
|
||||||
);
|
|
||||||
newEdge.data.distance = data.distance;
|
newEdge.data.distance = data.distance;
|
||||||
newEdge.data.shortcut = data.shortcut;
|
newEdge.data.shortcut = data.shortcut;
|
||||||
if(
|
if (!data.originalViaNodeID && !oldNodeIDFromNewNodeIDMap.empty())
|
||||||
!data.originalViaNodeID &&
|
{
|
||||||
!oldNodeIDFromNewNodeIDMap.empty()
|
|
||||||
) {
|
|
||||||
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
newEdge.data.id = data.id;
|
newEdge.data.id = data.id;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(newEdge.data.id != INT_MAX, // 2^31
|
||||||
newEdge.data.id != INT_MAX, //2^31
|
"edge id invalid");
|
||||||
"edge id invalid"
|
|
||||||
);
|
|
||||||
newEdge.data.forward = data.forward;
|
newEdge.data.forward = data.forward;
|
||||||
newEdge.data.backward = data.backward;
|
newEdge.data.backward = data.backward;
|
||||||
edges.push_back(newEdge);
|
edges.push_back(newEdge);
|
||||||
@ -499,10 +577,12 @@ public:
|
|||||||
_DynamicGraph::EdgeData data;
|
_DynamicGraph::EdgeData data;
|
||||||
|
|
||||||
Edge restored_edge;
|
Edge restored_edge;
|
||||||
for(unsigned i = 0; i < temp_edge_counter; ++i) {
|
for (unsigned i = 0; i < temp_edge_counter; ++i)
|
||||||
|
{
|
||||||
tempStorage.ReadFromSlot(edge_storage_slot, (char *)&start, sizeof(NodeID));
|
tempStorage.ReadFromSlot(edge_storage_slot, (char *)&start, sizeof(NodeID));
|
||||||
tempStorage.ReadFromSlot(edge_storage_slot, (char *)&target, sizeof(NodeID));
|
tempStorage.ReadFromSlot(edge_storage_slot, (char *)&target, sizeof(NodeID));
|
||||||
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
tempStorage.ReadFromSlot(
|
||||||
|
edge_storage_slot, (char *)&data, sizeof(_DynamicGraph::EdgeData));
|
||||||
restored_edge.source = start;
|
restored_edge.source = start;
|
||||||
restored_edge.target = target;
|
restored_edge.target = target;
|
||||||
restored_edge.data.distance = data.distance;
|
restored_edge.data.distance = data.distance;
|
||||||
@ -516,13 +596,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data, const NodeID middleNode ){
|
inline void _Dijkstra(const int maxDistance,
|
||||||
|
const unsigned numTargets,
|
||||||
|
const int maxNodes,
|
||||||
|
_ThreadData *const data,
|
||||||
|
const NodeID middleNode)
|
||||||
|
{
|
||||||
|
|
||||||
_Heap &heap = data->heap;
|
_Heap &heap = data->heap;
|
||||||
|
|
||||||
int nodes = 0;
|
int nodes = 0;
|
||||||
unsigned targetsFound = 0;
|
unsigned targetsFound = 0;
|
||||||
while ( heap.Size() > 0 ) {
|
while (heap.Size() > 0)
|
||||||
|
{
|
||||||
const NodeID node = heap.DeleteMin();
|
const NodeID node = heap.DeleteMin();
|
||||||
const int distance = heap.GetKey(node);
|
const int distance = heap.GetKey(node);
|
||||||
const short currentHop = heap.GetData(node).hop + 1;
|
const short currentHop = heap.GetData(node).hop + 1;
|
||||||
@ -533,31 +619,41 @@ private:
|
|||||||
if (distance > maxDistance)
|
if (distance > maxDistance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( heap.GetData( node ).target ) {
|
if (heap.GetData(node).target)
|
||||||
|
{
|
||||||
++targetsFound;
|
++targetsFound;
|
||||||
if ( targetsFound >= numTargets ) {
|
if (targetsFound >= numTargets)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate over all edges of node
|
// iterate over all edges of node
|
||||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
|
for (_DynamicGraph::EdgeIterator edge = _graph->BeginEdges(node),
|
||||||
|
endEdges = _graph->EndEdges(node);
|
||||||
|
edge != endEdges;
|
||||||
|
++edge)
|
||||||
|
{
|
||||||
const ContractorEdgeData &data = _graph->GetEdgeData(edge);
|
const ContractorEdgeData &data = _graph->GetEdgeData(edge);
|
||||||
if ( !data.forward ){
|
if (!data.forward)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const NodeID to = _graph->GetTarget(edge);
|
const NodeID to = _graph->GetTarget(edge);
|
||||||
if(middleNode == to) {
|
if (middleNode == to)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int toDistance = distance + data.distance;
|
const int toDistance = distance + data.distance;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if ( !heap.WasInserted( to ) ) {
|
if (!heap.WasInserted(to))
|
||||||
|
{
|
||||||
heap.Insert(to, toDistance, _HeapData(currentHop, false));
|
heap.Insert(to, toDistance, _HeapData(currentHop, false));
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update distance
|
// Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < heap.GetKey( to ) ) {
|
else if (toDistance < heap.GetKey(to))
|
||||||
|
{
|
||||||
heap.DecreaseKey(to, toDistance);
|
heap.DecreaseKey(to, toDistance);
|
||||||
heap.GetData(to).hop = currentHop;
|
heap.GetData(to).hop = currentHop;
|
||||||
}
|
}
|
||||||
@ -565,7 +661,9 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){
|
inline float
|
||||||
|
_Evaluate(_ThreadData *const data, _PriorityData *const nodeData, const NodeID node)
|
||||||
|
{
|
||||||
_ContractionInformation stats;
|
_ContractionInformation stats;
|
||||||
|
|
||||||
// perform simulated contraction
|
// perform simulated contraction
|
||||||
@ -576,21 +674,29 @@ private:
|
|||||||
if (0 == (stats.edgesDeleted * stats.originalEdgesDeleted))
|
if (0 == (stats.edgesDeleted * stats.originalEdgesDeleted))
|
||||||
result = 1 * nodeData->depth;
|
result = 1 * nodeData->depth;
|
||||||
else
|
else
|
||||||
result = 2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
|
result = 2 * (((float)stats.edgesAdded) / stats.edgesDeleted) +
|
||||||
|
4 * (((float)stats.originalEdgesAdded) / stats.originalEdgesDeleted) +
|
||||||
|
1 * nodeData->depth;
|
||||||
assert(result >= 0);
|
assert(result >= 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Simulate>
|
template <bool Simulate>
|
||||||
inline bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
|
inline bool _Contract(_ThreadData *data, NodeID node, _ContractionInformation *stats = NULL)
|
||||||
|
{
|
||||||
_Heap &heap = data->heap;
|
_Heap &heap = data->heap;
|
||||||
int insertedEdgesSize = data->insertedEdges.size();
|
int insertedEdgesSize = data->insertedEdges.size();
|
||||||
std::vector<_ContractorEdge> &insertedEdges = data->insertedEdges;
|
std::vector<_ContractorEdge> &insertedEdges = data->insertedEdges;
|
||||||
|
|
||||||
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
|
for (_DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges(node),
|
||||||
|
endInEdges = _graph->EndEdges(node);
|
||||||
|
inEdge != endInEdges;
|
||||||
|
++inEdge)
|
||||||
|
{
|
||||||
const ContractorEdgeData &inData = _graph->GetEdgeData(inEdge);
|
const ContractorEdgeData &inData = _graph->GetEdgeData(inEdge);
|
||||||
const NodeID source = _graph->GetTarget(inEdge);
|
const NodeID source = _graph->GetTarget(inEdge);
|
||||||
if ( Simulate ) {
|
if (Simulate)
|
||||||
|
{
|
||||||
assert(stats != NULL);
|
assert(stats != NULL);
|
||||||
++stats->edgesDeleted;
|
++stats->edgesDeleted;
|
||||||
stats->originalEdgesDeleted += inData.originalEdges;
|
stats->originalEdgesDeleted += inData.originalEdges;
|
||||||
@ -603,43 +709,69 @@ private:
|
|||||||
int maxDistance = 0;
|
int maxDistance = 0;
|
||||||
unsigned numTargets = 0;
|
unsigned numTargets = 0;
|
||||||
|
|
||||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
for (_DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges(node),
|
||||||
|
endOutEdges = _graph->EndEdges(node);
|
||||||
|
outEdge != endOutEdges;
|
||||||
|
++outEdge)
|
||||||
|
{
|
||||||
const ContractorEdgeData &outData = _graph->GetEdgeData(outEdge);
|
const ContractorEdgeData &outData = _graph->GetEdgeData(outEdge);
|
||||||
if ( !outData.forward ) {
|
if (!outData.forward)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const NodeID target = _graph->GetTarget(outEdge);
|
const NodeID target = _graph->GetTarget(outEdge);
|
||||||
const int pathDistance = inData.distance + outData.distance;
|
const int pathDistance = inData.distance + outData.distance;
|
||||||
maxDistance = std::max(maxDistance, pathDistance);
|
maxDistance = std::max(maxDistance, pathDistance);
|
||||||
if ( !heap.WasInserted( target ) ) {
|
if (!heap.WasInserted(target))
|
||||||
|
{
|
||||||
heap.Insert(target, INT_MAX, _HeapData(0, true));
|
heap.Insert(target, INT_MAX, _HeapData(0, true));
|
||||||
++numTargets;
|
++numTargets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( Simulate ) {
|
if (Simulate)
|
||||||
|
{
|
||||||
_Dijkstra(maxDistance, numTargets, 1000, data, node);
|
_Dijkstra(maxDistance, numTargets, 1000, data, node);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_Dijkstra(maxDistance, numTargets, 2000, data, node);
|
_Dijkstra(maxDistance, numTargets, 2000, data, node);
|
||||||
}
|
}
|
||||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
for (_DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges(node),
|
||||||
|
endOutEdges = _graph->EndEdges(node);
|
||||||
|
outEdge != endOutEdges;
|
||||||
|
++outEdge)
|
||||||
|
{
|
||||||
const ContractorEdgeData &outData = _graph->GetEdgeData(outEdge);
|
const ContractorEdgeData &outData = _graph->GetEdgeData(outEdge);
|
||||||
if ( !outData.forward ) {
|
if (!outData.forward)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const NodeID target = _graph->GetTarget(outEdge);
|
const NodeID target = _graph->GetTarget(outEdge);
|
||||||
const int pathDistance = inData.distance + outData.distance;
|
const int pathDistance = inData.distance + outData.distance;
|
||||||
const int distance = heap.GetKey(target);
|
const int distance = heap.GetKey(target);
|
||||||
if ( pathDistance < distance ) {
|
if (pathDistance < distance)
|
||||||
if ( Simulate ) {
|
{
|
||||||
|
if (Simulate)
|
||||||
|
{
|
||||||
assert(stats != NULL);
|
assert(stats != NULL);
|
||||||
stats->edgesAdded += 2;
|
stats->edgesAdded += 2;
|
||||||
stats->originalEdgesAdded += 2* ( outData.originalEdges + inData.originalEdges );
|
stats->originalEdgesAdded +=
|
||||||
} else {
|
2 * (outData.originalEdges + inData.originalEdges);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_ContractorEdge newEdge;
|
_ContractorEdge newEdge;
|
||||||
newEdge.source = source;
|
newEdge.source = source;
|
||||||
newEdge.target = target;
|
newEdge.target = target;
|
||||||
newEdge.data = ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);;
|
newEdge.data =
|
||||||
|
ContractorEdgeData(pathDistance,
|
||||||
|
outData.originalEdges + inData.originalEdges,
|
||||||
|
node /*, 0, inData.turnInstruction*/,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false);
|
||||||
|
;
|
||||||
insertedEdges.push_back(newEdge);
|
insertedEdges.push_back(newEdge);
|
||||||
std::swap(newEdge.source, newEdge.target);
|
std::swap(newEdge.source, newEdge.target);
|
||||||
newEdge.data.forward = false;
|
newEdge.data.forward = false;
|
||||||
@ -649,10 +781,13 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !Simulate ) {
|
if (!Simulate)
|
||||||
for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i ) {
|
{
|
||||||
|
for (int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i)
|
||||||
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for ( int other = i + 1 ; other < iend ; ++other ) {
|
for (int other = i + 1; other < iend; ++other)
|
||||||
|
{
|
||||||
if (insertedEdges[other].source != insertedEdges[i].source)
|
if (insertedEdges[other].source != insertedEdges[i].source)
|
||||||
continue;
|
continue;
|
||||||
if (insertedEdges[other].target != insertedEdges[i].target)
|
if (insertedEdges[other].target != insertedEdges[i].target)
|
||||||
@ -675,12 +810,15 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void _DeleteIncomingEdges( _ThreadData* data, const NodeID node ) {
|
inline void _DeleteIncomingEdges(_ThreadData *data, const NodeID node)
|
||||||
|
{
|
||||||
std::vector<NodeID> &neighbours = data->neighbours;
|
std::vector<NodeID> &neighbours = data->neighbours;
|
||||||
neighbours.clear();
|
neighbours.clear();
|
||||||
|
|
||||||
// find all neighbours
|
// find all neighbours
|
||||||
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
|
for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(node); e < _graph->EndEdges(node);
|
||||||
|
++e)
|
||||||
|
{
|
||||||
const NodeID u = _graph->GetTarget(e);
|
const NodeID u = _graph->GetTarget(e);
|
||||||
if (u != node)
|
if (u != node)
|
||||||
neighbours.push_back(u);
|
neighbours.push_back(u);
|
||||||
@ -689,17 +827,26 @@ private:
|
|||||||
std::sort(neighbours.begin(), neighbours.end());
|
std::sort(neighbours.begin(), neighbours.end());
|
||||||
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
||||||
|
|
||||||
for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
|
for (int i = 0, e = (int)neighbours.size(); i < e; ++i)
|
||||||
|
{
|
||||||
_graph->DeleteEdgesTo(neighbours[i], node);
|
_graph->DeleteEdgesTo(neighbours[i], node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, const NodeID node) {
|
inline bool _UpdateNeighbours(std::vector<float> &priorities,
|
||||||
|
std::vector<_PriorityData> &nodeData,
|
||||||
|
_ThreadData *const data,
|
||||||
|
const NodeID node)
|
||||||
|
{
|
||||||
std::vector<NodeID> &neighbours = data->neighbours;
|
std::vector<NodeID> &neighbours = data->neighbours;
|
||||||
neighbours.clear();
|
neighbours.clear();
|
||||||
|
|
||||||
// find all neighbours
|
// find all neighbours
|
||||||
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ) ; e < endEdges ; ++e ) {
|
for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(node),
|
||||||
|
endEdges = _graph->EndEdges(node);
|
||||||
|
e < endEdges;
|
||||||
|
++e)
|
||||||
|
{
|
||||||
const NodeID u = _graph->GetTarget(e);
|
const NodeID u = _graph->GetTarget(e);
|
||||||
if (u == node)
|
if (u == node)
|
||||||
continue;
|
continue;
|
||||||
@ -716,13 +863,19 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool _IsIndependent( const std::vector< float >& priorities/*, const std::vector< _PriorityData >& nodeData*/, _ThreadData* const data, NodeID node ) const {
|
inline bool _IsIndependent(
|
||||||
|
const std::vector<float> &priorities /*, const std::vector< _PriorityData >& nodeData*/,
|
||||||
|
_ThreadData *const data,
|
||||||
|
NodeID node) const
|
||||||
|
{
|
||||||
const double priority = priorities[node];
|
const double priority = priorities[node];
|
||||||
|
|
||||||
std::vector<NodeID> &neighbours = data->neighbours;
|
std::vector<NodeID> &neighbours = data->neighbours;
|
||||||
neighbours.clear();
|
neighbours.clear();
|
||||||
|
|
||||||
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
|
for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(node); e < _graph->EndEdges(node);
|
||||||
|
++e)
|
||||||
|
{
|
||||||
const NodeID target = _graph->GetTarget(e);
|
const NodeID target = _graph->GetTarget(e);
|
||||||
if (node == target)
|
if (node == target)
|
||||||
continue;
|
continue;
|
||||||
@ -732,7 +885,9 @@ private:
|
|||||||
if (priority > targetPriority)
|
if (priority > targetPriority)
|
||||||
return false;
|
return false;
|
||||||
// tie breaking
|
// tie breaking
|
||||||
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
if (std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() &&
|
||||||
|
bias(node, target))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO: C++11 copy_if with lambda
|
// TODO: C++11 copy_if with lambda
|
||||||
@ -743,13 +898,14 @@ private:
|
|||||||
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
||||||
|
|
||||||
// examine all neighbours that are at most 2 hops away
|
// examine all neighbours that are at most 2 hops away
|
||||||
for(const NodeID u : neighbours) {
|
for(const NodeID u : neighbours)
|
||||||
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) {
|
{
|
||||||
|
for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(u); e < _graph->EndEdges(u);
|
||||||
|
++e)
|
||||||
|
{
|
||||||
const NodeID target = _graph->GetTarget(e);
|
const NodeID target = _graph->GetTarget(e);
|
||||||
if (node == target)
|
if (node == target)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
const double targetPriority = priorities[target];
|
const double targetPriority = priorities[target];
|
||||||
assert( targetPriority >= 0 );
|
assert( targetPriority >= 0 );
|
||||||
@ -769,17 +925,19 @@ private:
|
|||||||
/**
|
/**
|
||||||
* This bias function takes up 22 assembly instructions in total on X86
|
* This bias function takes up 22 assembly instructions in total on X86
|
||||||
*/
|
*/
|
||||||
inline bool bias(const NodeID a, const NodeID b) const {
|
inline bool bias(const NodeID a, const NodeID b) const
|
||||||
|
{
|
||||||
unsigned short hasha = fastHash(a);
|
unsigned short hasha = fastHash(a);
|
||||||
unsigned short hashb = fastHash(b);
|
unsigned short hashb = fastHash(b);
|
||||||
|
|
||||||
//The compiler optimizes that to conditional register flags but without branching statements!
|
// The compiler optimizes that to conditional register flags but without branching
|
||||||
|
// statements!
|
||||||
if (hasha != hashb)
|
if (hasha != hashb)
|
||||||
return hasha < hashb;
|
return hasha < hashb;
|
||||||
return a < b;
|
return a < b;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<_DynamicGraph> _graph;
|
std::shared_ptr<_DynamicGraph> _graph;
|
||||||
std::vector<_DynamicGraph::InputEdge> contractedEdges;
|
std::vector<_DynamicGraph::InputEdge> contractedEdges;
|
||||||
unsigned edge_storage_slot;
|
unsigned edge_storage_slot;
|
||||||
uint64_t temp_edge_counter;
|
uint64_t temp_edge_counter;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -35,20 +35,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/EdgeBasedNode.h"
|
#include "../DataStructures/EdgeBasedNode.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
|
||||||
#include "../DataStructures/OriginalEdgeData.h"
|
#include "../DataStructures/OriginalEdgeData.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/QueryNode.h"
|
#include "../DataStructures/QueryNode.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
|
#include "../DataStructures/NodeBasedGraph.h"
|
||||||
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../Util/LuaUtil.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include "GeometryCompressor.h"
|
#include "GeometryCompressor.h"
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
#include <boost/unordered_set.hpp>
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
@ -57,51 +57,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
class EdgeBasedGraphFactory : boost::noncopyable
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
struct SpeedProfileProperties;
|
struct SpeedProfileProperties;
|
||||||
|
|
||||||
explicit EdgeBasedGraphFactory(
|
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
|
||||||
int number_of_nodes,
|
std::unique_ptr<RestrictionMap> restricion_map,
|
||||||
std::vector<ImportEdge> & input_edge_list,
|
|
||||||
std::vector<NodeID> &barrier_node_list,
|
std::vector<NodeID> &barrier_node_list,
|
||||||
std::vector<NodeID> &traffic_light_node_list,
|
std::vector<NodeID> &traffic_light_node_list,
|
||||||
std::vector<TurnRestriction> & input_restrictions_list,
|
|
||||||
std::vector<NodeInfo> &m_node_info_list,
|
std::vector<NodeInfo> &m_node_info_list,
|
||||||
SpeedProfileProperties & speed_profile
|
SpeedProfileProperties &speed_profile);
|
||||||
);
|
|
||||||
|
|
||||||
void Run(
|
void Run(const std::string &original_edge_data_filename,
|
||||||
const std::string & original_edge_data_filename,
|
|
||||||
const std::string &geometry_filename,
|
const std::string &geometry_filename,
|
||||||
lua_State *myLuaState
|
lua_State *myLuaState);
|
||||||
);
|
|
||||||
|
|
||||||
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
||||||
|
|
||||||
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||||
|
|
||||||
TurnInstruction AnalyzeTurn(
|
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
) const;
|
|
||||||
|
|
||||||
int GetTurnPenalty(
|
int GetTurnPenalty(const NodeID u, const NodeID v, const NodeID w, lua_State *myLuaState) const;
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w,
|
|
||||||
lua_State *myLuaState
|
|
||||||
) const;
|
|
||||||
|
|
||||||
unsigned GetNumberOfEdgeBasedNodes() const;
|
unsigned GetNumberOfEdgeBasedNodes() const;
|
||||||
|
|
||||||
struct SpeedProfileProperties{
|
struct SpeedProfileProperties
|
||||||
SpeedProfileProperties() :
|
{
|
||||||
trafficSignalPenalty(0),
|
SpeedProfileProperties()
|
||||||
uTurnPenalty(0),
|
: trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
|
||||||
has_turn_penalty_function(false)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
int trafficSignalPenalty;
|
int trafficSignalPenalty;
|
||||||
int uTurnPenalty;
|
int uTurnPenalty;
|
||||||
@ -109,103 +96,37 @@ public:
|
|||||||
} speed_profile;
|
} speed_profile;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NodeBasedEdgeData {
|
|
||||||
NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), nameID(std::numeric_limits<unsigned>::max()),
|
|
||||||
type(std::numeric_limits<short>::max()), isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
|
||||||
roundabout(false), ignore_in_grid(false), contraFlow(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int distance;
|
|
||||||
unsigned edgeBasedNodeID;
|
|
||||||
unsigned nameID;
|
|
||||||
short type;
|
|
||||||
bool isAccessRestricted:1;
|
|
||||||
bool shortcut:1;
|
|
||||||
bool forward:1;
|
|
||||||
bool backward:1;
|
|
||||||
bool roundabout:1;
|
|
||||||
bool ignore_in_grid:1;
|
|
||||||
bool contraFlow:1;
|
|
||||||
|
|
||||||
void SwapDirectionFlags() {
|
|
||||||
bool temp_flag = forward;
|
|
||||||
forward = backward;
|
|
||||||
backward = temp_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsEqualTo( const NodeBasedEdgeData & other ) const {
|
|
||||||
return (forward == other.forward) &&
|
|
||||||
(backward == other.backward) &&
|
|
||||||
(nameID == other.nameID) &&
|
|
||||||
(ignore_in_grid == other.ignore_in_grid) &&
|
|
||||||
(contraFlow == other.contraFlow);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned m_turn_restrictions_count;
|
|
||||||
unsigned m_number_of_edge_based_nodes;
|
|
||||||
|
|
||||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
|
||||||
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
|
||||||
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
|
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
|
||||||
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
|
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
|
||||||
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
unsigned m_number_of_edge_based_nodes;
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
|
||||||
|
|
||||||
std::vector<NodeInfo> m_node_info_list;
|
std::vector<NodeInfo> m_node_info_list;
|
||||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
|
||||||
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||||
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||||
|
|
||||||
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||||
boost::unordered_set<NodeID> m_barrier_nodes;
|
boost::unordered_set<NodeID> m_barrier_nodes;
|
||||||
boost::unordered_set<NodeID> m_traffic_lights;
|
boost::unordered_set<NodeID> m_traffic_lights;
|
||||||
|
|
||||||
RestrictionMap m_restriction_map;
|
std::unique_ptr<RestrictionMap> m_restriction_map;
|
||||||
|
|
||||||
GeometryCompressor m_geometry_compressor;
|
GeometryCompressor m_geometry_compressor;
|
||||||
|
|
||||||
NodeID CheckForEmanatingIsOnlyTurn(
|
void CompressGeometry();
|
||||||
const NodeID u,
|
void RenumberEdges();
|
||||||
const NodeID v
|
void GenerateEdgeExpandedNodes();
|
||||||
) const;
|
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||||
|
lua_State *lua_state);
|
||||||
|
|
||||||
bool CheckIfTurnIsRestricted(
|
void InsertEdgeBasedNode(NodeBasedDynamicGraph::NodeIterator u,
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void InsertEdgeBasedNode(
|
|
||||||
NodeBasedDynamicGraph::NodeIterator u,
|
|
||||||
NodeBasedDynamicGraph::NodeIterator v,
|
NodeBasedDynamicGraph::NodeIterator v,
|
||||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||||
bool belongsToTinyComponent
|
bool belongsToTinyComponent);
|
||||||
);
|
|
||||||
|
|
||||||
void BFSCompentExplorer(
|
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||||
std::vector<unsigned> & component_index_list,
|
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||||
std::vector<unsigned> & component_index_size
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void FlushVectorToStream(
|
|
||||||
std::ofstream & edge_data_file,
|
|
||||||
std::vector<OriginalEdgeData> & original_edge_data_vector
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void FixupArrivingTurnRestriction(
|
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
);
|
|
||||||
|
|
||||||
void FixupStartingTurnRestriction(
|
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
);
|
|
||||||
|
|
||||||
unsigned max_id;
|
unsigned max_id;
|
||||||
};
|
};
|
||||||
|
@ -77,11 +77,11 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
|||||||
|
|
||||||
// write indices array
|
// write indices array
|
||||||
unsigned prefix_sum_of_list_indices = 0;
|
unsigned prefix_sum_of_list_indices = 0;
|
||||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
for (auto &elem : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||||
|
|
||||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries.at(i);
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
const unsigned unpacked_size = current_vector.size();
|
const unsigned unpacked_size = current_vector.size();
|
||||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
||||||
prefix_sum_of_list_indices += unpacked_size;
|
prefix_sum_of_list_indices += unpacked_size;
|
||||||
@ -94,9 +94,9 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
|||||||
|
|
||||||
unsigned control_sum = 0;
|
unsigned control_sum = 0;
|
||||||
// write compressed geometries
|
// write compressed geometries
|
||||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
for (auto &elem : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries[i];
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
const unsigned unpacked_size = current_vector.size();
|
const unsigned unpacked_size = current_vector.size();
|
||||||
control_sum += unpacked_size;
|
control_sum += unpacked_size;
|
||||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
||||||
@ -122,8 +122,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
||||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight1);
|
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1);
|
||||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight2);
|
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2);
|
||||||
|
|
||||||
// append list of removed edge_id plus via node to surviving edge id:
|
// append list of removed edge_id plus via node to surviving edge id:
|
||||||
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
||||||
@ -146,7 +146,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|||||||
m_free_list.pop_back();
|
m_free_list.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const boost::unordered_map<EdgeID, unsigned>::const_iterator iter = m_edge_id_to_list_index_map.find(edge_id_1);
|
const boost::unordered_map<EdgeID, unsigned>::const_iterator iter =
|
||||||
|
m_edge_id_to_list_index_map.find(edge_id_1);
|
||||||
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
||||||
const unsigned edge_bucket_id1 = iter->second;
|
const unsigned edge_bucket_id1 = iter->second;
|
||||||
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
||||||
|
@ -27,90 +27,95 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "TemporaryStorage.h"
|
#include "TemporaryStorage.h"
|
||||||
|
|
||||||
TemporaryStorage::TemporaryStorage() {
|
TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
|
||||||
temp_directory = boost::filesystem::temp_directory_path();
|
|
||||||
}
|
|
||||||
|
|
||||||
TemporaryStorage & TemporaryStorage::GetInstance(){
|
TemporaryStorage &TemporaryStorage::GetInstance()
|
||||||
|
{
|
||||||
static TemporaryStorage static_instance;
|
static TemporaryStorage static_instance;
|
||||||
return static_instance;
|
return static_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryStorage::~TemporaryStorage() {
|
TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
|
||||||
RemoveAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemporaryStorage::RemoveAll() {
|
void TemporaryStorage::RemoveAll()
|
||||||
|
{
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) {
|
for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
|
||||||
|
{
|
||||||
DeallocateSlot(slot_id);
|
DeallocateSlot(slot_id);
|
||||||
}
|
}
|
||||||
stream_data_list.clear();
|
stream_data_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int TemporaryStorage::AllocateSlot() {
|
int TemporaryStorage::AllocateSlot()
|
||||||
|
{
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
stream_data_list.push_back(StreamData());
|
stream_data_list.push_back(StreamData());
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e)
|
||||||
|
{
|
||||||
Abort(e);
|
Abort(e);
|
||||||
}
|
}
|
||||||
CheckIfTemporaryDeviceFull();
|
CheckIfTemporaryDeviceFull();
|
||||||
return stream_data_list.size() - 1;
|
return stream_data_list.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::DeallocateSlot(const int slot_id) {
|
void TemporaryStorage::DeallocateSlot(const int slot_id)
|
||||||
try {
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if(!boost::filesystem::exists(data.temp_path)) {
|
if (!boost::filesystem::exists(data.temp_path))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(data.temp_file->is_open()) {
|
if (data.temp_file->is_open())
|
||||||
|
{
|
||||||
data.temp_file->close();
|
data.temp_file->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::remove(data.temp_path);
|
boost::filesystem::remove(data.temp_path);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e)
|
||||||
|
{
|
||||||
Abort(e);
|
Abort(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::WriteToSlot(
|
void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size)
|
||||||
const int slot_id,
|
{
|
||||||
char * pointer,
|
try
|
||||||
const std::size_t size
|
{
|
||||||
) {
|
|
||||||
try {
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
BOOST_ASSERT(data.write_mode);
|
BOOST_ASSERT(data.write_mode);
|
||||||
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
|
||||||
data.write_mode,
|
if (1073741824 < data.buffer.size())
|
||||||
"Writing after first read is not allowed"
|
{
|
||||||
);
|
|
||||||
if( 1073741824 < data.buffer.size() ) {
|
|
||||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||||
// data.temp_file->write(pointer, size);
|
// data.temp_file->write(pointer, size);
|
||||||
data.buffer.clear();
|
data.buffer.clear();
|
||||||
CheckIfTemporaryDeviceFull();
|
CheckIfTemporaryDeviceFull();
|
||||||
}
|
}
|
||||||
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
|
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
|
||||||
|
}
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
catch (boost::filesystem::filesystem_error &e)
|
||||||
|
{
|
||||||
Abort(e);
|
Abort(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TemporaryStorage::ReadFromSlot(
|
void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
|
||||||
const int slot_id,
|
{
|
||||||
char * pointer,
|
try
|
||||||
const std::size_t size
|
{
|
||||||
) {
|
|
||||||
try {
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if( data.write_mode ) {
|
if (data.write_mode)
|
||||||
|
{
|
||||||
data.write_mode = false;
|
data.write_mode = false;
|
||||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||||
data.buffer.clear();
|
data.buffer.clear();
|
||||||
@ -119,44 +124,57 @@ void TemporaryStorage::ReadFromSlot(
|
|||||||
}
|
}
|
||||||
BOOST_ASSERT(!data.write_mode);
|
BOOST_ASSERT(!data.write_mode);
|
||||||
data.temp_file->read(pointer, size);
|
data.temp_file->read(pointer, size);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e)
|
||||||
|
{
|
||||||
Abort(e);
|
Abort(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() {
|
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
|
||||||
|
{
|
||||||
uint64_t value = -1;
|
uint64_t value = -1;
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
||||||
boost::filesystem::space_info s = boost::filesystem::space(p);
|
boost::filesystem::space_info s = boost::filesystem::space(p);
|
||||||
value = s.free;
|
value = s.free;
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e)
|
||||||
|
{
|
||||||
Abort(e);
|
Abort(e);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::CheckIfTemporaryDeviceFull() {
|
void TemporaryStorage::CheckIfTemporaryDeviceFull()
|
||||||
|
{
|
||||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
||||||
boost::filesystem::space_info s = boost::filesystem::space(p);
|
boost::filesystem::space_info s = boost::filesystem::space(p);
|
||||||
if( (1024*1024) > s.free ) {
|
if ((1024 * 1024) > s.free)
|
||||||
|
{
|
||||||
throw OSRMException("temporary device is full");
|
throw OSRMException("temporary device is full");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) {
|
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
|
||||||
|
{
|
||||||
boost::filesystem::fstream::pos_type position;
|
boost::filesystem::fstream::pos_type position;
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
position = data.temp_file->tellp();
|
position = data.temp_file->tellp();
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e)
|
||||||
|
{
|
||||||
Abort(e);
|
Abort(e);
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) {
|
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &e)
|
||||||
|
{
|
||||||
RemoveAll();
|
RemoveAll();
|
||||||
throw OSRMException(e.what());
|
throw OSRMException(e.what());
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -56,7 +54,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
static boost::filesystem::path temp_directory;
|
static boost::filesystem::path temp_directory;
|
||||||
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
||||||
class TemporaryStorage {
|
class TemporaryStorage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static TemporaryStorage &GetInstance();
|
static TemporaryStorage &GetInstance();
|
||||||
virtual ~TemporaryStorage();
|
virtual ~TemporaryStorage();
|
||||||
@ -69,43 +68,33 @@ public:
|
|||||||
uint64_t GetFreeBytesOnTemporaryDevice();
|
uint64_t GetFreeBytesOnTemporaryDevice();
|
||||||
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
||||||
void RemoveAll();
|
void RemoveAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TemporaryStorage();
|
TemporaryStorage();
|
||||||
TemporaryStorage(TemporaryStorage const &) {};
|
TemporaryStorage(TemporaryStorage const &) {};
|
||||||
|
|
||||||
TemporaryStorage & operator=(TemporaryStorage const &) {
|
TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Abort(const boost::filesystem::filesystem_error &e);
|
void Abort(const boost::filesystem::filesystem_error &e);
|
||||||
void CheckIfTemporaryDeviceFull();
|
void CheckIfTemporaryDeviceFull();
|
||||||
|
|
||||||
struct StreamData {
|
struct StreamData
|
||||||
|
{
|
||||||
bool write_mode;
|
bool write_mode;
|
||||||
boost::filesystem::path temp_path;
|
boost::filesystem::path temp_path;
|
||||||
boost::shared_ptr<boost::filesystem::fstream> temp_file;
|
std::shared_ptr<boost::filesystem::fstream> temp_file;
|
||||||
boost::shared_ptr<boost::mutex> readWriteMutex;
|
std::shared_ptr<boost::mutex> readWriteMutex;
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
|
|
||||||
StreamData() :
|
StreamData()
|
||||||
write_mode(true),
|
: write_mode(true), temp_path(boost::filesystem::unique_path(temp_directory.append(
|
||||||
temp_path(
|
TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
|
||||||
boost::filesystem::unique_path(
|
temp_file(new boost::filesystem::fstream(
|
||||||
temp_directory.append(
|
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
||||||
TemporaryFilePattern.begin(),
|
readWriteMutex(std::make_shared<boost::mutex>())
|
||||||
TemporaryFilePattern.end()
|
{
|
||||||
)
|
if (temp_file->fail())
|
||||||
)
|
|
||||||
),
|
|
||||||
temp_file(
|
|
||||||
new boost::filesystem::fstream(
|
|
||||||
temp_path,
|
|
||||||
std::ios::in|std::ios::out|std::ios::trunc|std::ios::binary
|
|
||||||
)
|
|
||||||
),
|
|
||||||
readWriteMutex(boost::make_shared<boost::mutex>())
|
|
||||||
{
|
{
|
||||||
if( temp_file->fail() ) {
|
|
||||||
throw OSRMException("temporary file could not be created");
|
throw OSRMException("temporary file could not be created");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
110
DataStructures/NodeBasedGraph.h
Normal file
110
DataStructures/NodeBasedGraph.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#ifndef __NODE_BASED_GRAPH_H__
|
||||||
|
#define __NODE_BASED_GRAPH_H__
|
||||||
|
|
||||||
|
#include "DynamicGraph.h"
|
||||||
|
#include "ImportEdge.h"
|
||||||
|
|
||||||
|
struct NodeBasedEdgeData
|
||||||
|
{
|
||||||
|
NodeBasedEdgeData()
|
||||||
|
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
||||||
|
nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
|
||||||
|
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
||||||
|
roundabout(false), ignore_in_grid(false), contraFlow(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int distance;
|
||||||
|
unsigned edgeBasedNodeID;
|
||||||
|
unsigned nameID;
|
||||||
|
short type;
|
||||||
|
bool isAccessRestricted : 1;
|
||||||
|
bool shortcut : 1;
|
||||||
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
bool roundabout : 1;
|
||||||
|
bool ignore_in_grid : 1;
|
||||||
|
bool contraFlow : 1;
|
||||||
|
|
||||||
|
void SwapDirectionFlags()
|
||||||
|
{
|
||||||
|
bool temp_flag = forward;
|
||||||
|
forward = backward;
|
||||||
|
backward = temp_flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEqualTo(const NodeBasedEdgeData &other) const
|
||||||
|
{
|
||||||
|
return (forward == other.forward) && (backward == other.backward) &&
|
||||||
|
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
|
||||||
|
(contraFlow == other.contraFlow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||||
|
|
||||||
|
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
||||||
|
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||||
|
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
|
||||||
|
{
|
||||||
|
typedef NodeBasedDynamicGraph::InputEdge DynInputEdge;
|
||||||
|
|
||||||
|
std::sort(input_edge_list.begin(), input_edge_list.end());
|
||||||
|
|
||||||
|
// TODO: remove duplicate edges
|
||||||
|
DeallocatingVector<DynInputEdge> edges_list;
|
||||||
|
DynInputEdge edge;
|
||||||
|
for (const ImportEdge &import_edge : input_edge_list)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!import_edge.isForward())
|
||||||
|
{
|
||||||
|
edge.source = import_edge.target();
|
||||||
|
edge.target = import_edge.source();
|
||||||
|
edge.data.backward = import_edge.isForward();
|
||||||
|
edge.data.forward = import_edge.isBackward();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
edge.source = import_edge.source();
|
||||||
|
edge.target = import_edge.target();
|
||||||
|
edge.data.forward = import_edge.isForward();
|
||||||
|
edge.data.backward = import_edge.isBackward();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge.source == edge.target)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
edge.data.distance = (std::max)((int)import_edge.weight(), 1);
|
||||||
|
BOOST_ASSERT(edge.data.distance > 0);
|
||||||
|
edge.data.shortcut = false;
|
||||||
|
edge.data.roundabout = import_edge.isRoundabout();
|
||||||
|
edge.data.ignore_in_grid = import_edge.ignoreInGrid();
|
||||||
|
edge.data.nameID = import_edge.name();
|
||||||
|
edge.data.type = import_edge.type();
|
||||||
|
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
|
||||||
|
edge.data.contraFlow = import_edge.isContraFlow();
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
|
||||||
|
if (!import_edge.IsSplit())
|
||||||
|
{
|
||||||
|
using std::swap; // enable ADL
|
||||||
|
swap(edge.source, edge.target);
|
||||||
|
edge.data.SwapDirectionFlags();
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(edges_list.begin(), edges_list.end());
|
||||||
|
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
|
||||||
|
|
||||||
|
// FIXME probably unneeded since this is the end of scope
|
||||||
|
DeallocatingVector<DynInputEdge>().swap(edges_list);
|
||||||
|
BOOST_ASSERT(0 == edges_list.size());
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
168
DataStructures/RestrictionMap.cpp
Normal file
168
DataStructures/RestrictionMap.cpp
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#include "RestrictionMap.h"
|
||||||
|
#include "NodeBasedGraph.h"
|
||||||
|
|
||||||
|
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||||
|
const std::vector<TurnRestriction> &input_restrictions_list)
|
||||||
|
: m_count(0), m_graph(graph)
|
||||||
|
{
|
||||||
|
// decompose restirction consisting of a start, via and end note into a start-edge
|
||||||
|
// and all end-nodes
|
||||||
|
for (auto &restriction : input_restrictions_list)
|
||||||
|
{
|
||||||
|
std::pair<NodeID, NodeID> restriction_source =
|
||||||
|
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||||
|
unsigned index;
|
||||||
|
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
|
if (restriction_iter == m_restriction_map.end())
|
||||||
|
{
|
||||||
|
index = m_restriction_bucket_list.size();
|
||||||
|
m_restriction_bucket_list.resize(index + 1);
|
||||||
|
m_restriction_map.emplace(restriction_source, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = restriction_iter->second;
|
||||||
|
// Map already contains an is_only_*-restriction
|
||||||
|
if (m_restriction_bucket_list.at(index).begin()->second)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (restriction.flags.isOnly)
|
||||||
|
{
|
||||||
|
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
|
m_count -= m_restriction_bucket_list.at(index).size();
|
||||||
|
m_restriction_bucket_list.at(index).clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++m_count;
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
.push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace end v with w in each turn restriction containing u as via node
|
||||||
|
*
|
||||||
|
* Note: We need access to node based graph.
|
||||||
|
*/
|
||||||
|
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
|
||||||
|
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
|
||||||
|
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
// find all possible start edges
|
||||||
|
// it is more efficent to get a (small) list of potential start edges
|
||||||
|
// than iterating over all buckets
|
||||||
|
std::vector<NodeID> predecessors;
|
||||||
|
for (EdgeID current_edge_id = m_graph->BeginEdges(u); current_edge_id < m_graph->EndEdges(u);
|
||||||
|
++current_edge_id)
|
||||||
|
{
|
||||||
|
const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id);
|
||||||
|
const NodeID target = m_graph->GetTarget(current_edge_id);
|
||||||
|
if (edge_data.backward && (v != target))
|
||||||
|
{
|
||||||
|
predecessors.push_back(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const NodeID x : predecessors)
|
||||||
|
{
|
||||||
|
const std::pair<NodeID, NodeID> restr_start = std::make_pair(x, u);
|
||||||
|
auto restriction_iterator = m_restriction_map.find(restr_start);
|
||||||
|
if (restriction_iterator == m_restriction_map.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const unsigned index = restriction_iterator->second;
|
||||||
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if (v == restriction_target.first)
|
||||||
|
{
|
||||||
|
restriction_target.first = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the start edge (v, w) with (u, w), only start node changes.
|
||||||
|
*/
|
||||||
|
void RestrictionMap::FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
|
||||||
|
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
|
||||||
|
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
const std::pair<NodeID, NodeID> old_start = std::make_pair(v, w);
|
||||||
|
|
||||||
|
auto restriction_iterator = m_restriction_map.find(old_start);
|
||||||
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iterator->second;
|
||||||
|
// remove old restriction start (v,w)
|
||||||
|
m_restriction_map.erase(restriction_iterator);
|
||||||
|
|
||||||
|
// insert new restriction start (u,w) (point to index)
|
||||||
|
const std::pair<NodeID, NodeID> new_start = std::make_pair(u, w);
|
||||||
|
m_restriction_map.insert(std::make_pair(new_start, index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the edge (u, v) is contained in any turn restriction.
|
||||||
|
* If so returns id of first target node.
|
||||||
|
*/
|
||||||
|
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
|
||||||
|
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
|
||||||
|
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
|
|
||||||
|
if (restriction_iter != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iter->second;
|
||||||
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (const RestrictionSource &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if (restriction_target.second)
|
||||||
|
{
|
||||||
|
return restriction_target.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::numeric_limits<unsigned>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the turn described by start u, via v and targed w is covert by any turn restriction.
|
||||||
|
*/
|
||||||
|
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
|
||||||
|
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
|
||||||
|
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
|
||||||
|
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
|
|
||||||
|
if (restriction_iter != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iter->second;
|
||||||
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (const RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if ((w == restriction_target.first) && // target found
|
||||||
|
(!restriction_target.second) // and not an only_-restr.
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
71
DataStructures/RestrictionMap.h
Normal file
71
DataStructures/RestrictionMap.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RESTRICTION_MAP_H__
|
||||||
|
#define __RESTRICTION_MAP_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "DynamicGraph.h"
|
||||||
|
#include "Restriction.h"
|
||||||
|
#include "NodeBasedGraph.h"
|
||||||
|
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Makee it efficent to look up if an edge is the start + via node of a TurnRestriction.
|
||||||
|
* Is needed by EdgeBasedGraphFactory.
|
||||||
|
*/
|
||||||
|
class RestrictionMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||||
|
const std::vector<TurnRestriction> &input_restrictions_list);
|
||||||
|
|
||||||
|
void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||||
|
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||||
|
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
||||||
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
||||||
|
|
||||||
|
unsigned size() { return m_count; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
|
typedef std::pair<NodeID, bool> RestrictionTarget;
|
||||||
|
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
||||||
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
|
|
||||||
|
unsigned m_count;
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
|
||||||
|
//! index -> list of (target, isOnly)
|
||||||
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
|
//! maps (start, via) -> bucket index
|
||||||
|
boost::unordered_map<RestrictionSource, unsigned> m_restriction_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
58
Util/TimingUtil.h
Normal file
58
Util/TimingUtil.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TIMINGUTIL_H_
|
||||||
|
#define TIMINGUTIL_H_
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <sys/timeb.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <winsock.h>
|
||||||
|
void gettimeofday(struct timeval* t,void* timezone) {
|
||||||
|
struct _timeb timebuffer;
|
||||||
|
_ftime( &timebuffer );
|
||||||
|
t->tv_sec=timebuffer.time;
|
||||||
|
t->tv_usec=1000*timebuffer.millitm;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Returns a timestamp (now) in seconds (incl. a fractional part). */
|
||||||
|
static inline double get_timestamp() {
|
||||||
|
struct timeval tp;
|
||||||
|
gettimeofday(&tp, NULL);
|
||||||
|
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TIMER_START(_X) timeval _X##_start, _X##_stop; gettimeofday(&_X##_start, NULL)
|
||||||
|
#define TIMER_STOP(_X) gettimeofday(&_X##_stop, NULL);
|
||||||
|
#define TIMER_MSEC(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) * 1000.0 + (_X##_stop.tv_usec - _X##_start.tv_usec) / 1000.0)
|
||||||
|
#define TIMER_SEC(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) + (_X##_stop.tv_usec - _X##_start.tv_usec) / 1000.0 / 1000.0)
|
||||||
|
#define TIMER_MIN(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) / 60.0)
|
||||||
|
|
||||||
|
#endif /* TIMINGUTIL_H_ */
|
12
prepare.cpp
12
prepare.cpp
@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "DataStructures/QueryEdge.h"
|
#include "DataStructures/QueryEdge.h"
|
||||||
#include "DataStructures/StaticGraph.h"
|
#include "DataStructures/StaticGraph.h"
|
||||||
#include "DataStructures/StaticRTree.h"
|
#include "DataStructures/StaticRTree.h"
|
||||||
|
#include "DataStructures/RestrictionMap.h"
|
||||||
#include "Util/GitDescription.h"
|
#include "Util/GitDescription.h"
|
||||||
#include "Util/GraphLoader.h"
|
#include "Util/GraphLoader.h"
|
||||||
#include "Util/LuaUtil.h"
|
#include "Util/LuaUtil.h"
|
||||||
@ -48,7 +49,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <luabind/luabind.hpp>
|
#include <luabind/luabind.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -274,12 +274,13 @@ int main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
SimpleLogger().Write() << "Generating edge-expanded graph representation";
|
SimpleLogger().Write() << "Generating edge-expanded graph representation";
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> node_based_graph = NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
|
||||||
|
std::unique_ptr<RestrictionMap> restriction_map = std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
|
||||||
EdgeBasedGraphFactory * edge_based_graph_factor =
|
EdgeBasedGraphFactory * edge_based_graph_factor =
|
||||||
new EdgeBasedGraphFactory(number_of_node_based_nodes,
|
new EdgeBasedGraphFactory(node_based_graph,
|
||||||
edge_list,
|
std::move(restriction_map),
|
||||||
barrier_node_list,
|
barrier_node_list,
|
||||||
traffic_light_list,
|
traffic_light_list,
|
||||||
restriction_list,
|
|
||||||
internal_to_external_node_map,
|
internal_to_external_node_map,
|
||||||
speed_profile);
|
speed_profile);
|
||||||
edge_list.clear();
|
edge_list.clear();
|
||||||
@ -302,6 +303,9 @@ int main(int argc, char *argv[])
|
|||||||
edge_based_graph_factor->GetEdgeBasedNodes(node_based_edge_list);
|
edge_based_graph_factor->GetEdgeBasedNodes(node_based_edge_list);
|
||||||
delete edge_based_graph_factor;
|
delete edge_based_graph_factor;
|
||||||
|
|
||||||
|
// TODO actually use scoping: Split this up in subfunctions
|
||||||
|
node_based_graph.reset();
|
||||||
|
|
||||||
std::chrono::duration<double> end_of_expansion_time =
|
std::chrono::duration<double> end_of_expansion_time =
|
||||||
std::chrono::steady_clock::now() - startup_time;
|
std::chrono::steady_clock::now() - startup_time;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user