2010-07-14 08:55:53 -04:00
|
|
|
/*
|
2013-10-14 07:42:28 -04:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
#ifndef STATIC_GRAPH_H
|
|
|
|
#define STATIC_GRAPH_H
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2013-08-16 08:06:04 -04:00
|
|
|
#include "../DataStructures/Percent.h"
|
2013-09-18 11:49:49 -04:00
|
|
|
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
2013-08-08 08:17:01 -04:00
|
|
|
#include "../Util/SimpleLogger.h"
|
2010-07-14 08:55:53 -04:00
|
|
|
#include "../typedefs.h"
|
2013-06-26 19:48:22 -04:00
|
|
|
|
2014-05-23 08:32:28 -04:00
|
|
|
#include <boost/assert.hpp>
|
2014-05-13 10:56:30 -04:00
|
|
|
#include <boost/range/irange.hpp>
|
|
|
|
|
2014-05-23 08:32:28 -04:00
|
|
|
#include <tbb/parallel_sort.h>
|
|
|
|
|
2013-06-26 19:48:22 -04:00
|
|
|
#include <algorithm>
|
2014-05-05 11:19:47 -04:00
|
|
|
#include <limits>
|
2013-06-26 19:48:22 -04:00
|
|
|
#include <vector>
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|
|
|
{
|
|
|
|
public:
|
2014-05-13 10:56:30 -04:00
|
|
|
typedef decltype(boost::irange(0u,0u)) EdgeRange;
|
2010-07-14 08:55:53 -04:00
|
|
|
typedef NodeID NodeIterator;
|
|
|
|
typedef NodeID EdgeIterator;
|
2011-11-17 12:55:31 -05:00
|
|
|
typedef EdgeDataT EdgeData;
|
2014-05-05 11:19:47 -04:00
|
|
|
class InputEdge
|
|
|
|
{
|
|
|
|
public:
|
2011-11-17 12:55:31 -05:00
|
|
|
EdgeDataT data;
|
2010-07-14 08:55:53 -04:00
|
|
|
NodeIterator source;
|
|
|
|
NodeIterator target;
|
2014-07-14 08:49:53 -04:00
|
|
|
InputEdge(NodeIterator source, NodeIterator target, EdgeDataT data) : source(source), target(target), data(data) { }
|
2014-05-05 11:19:47 -04:00
|
|
|
bool operator<(const InputEdge &right) const
|
|
|
|
{
|
|
|
|
if (source != right.source)
|
|
|
|
{
|
2010-07-14 08:55:53 -04:00
|
|
|
return source < right.source;
|
2013-09-18 11:49:49 -04:00
|
|
|
}
|
2010-07-14 08:55:53 -04:00
|
|
|
return target < right.target;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
struct NodeArrayEntry
|
|
|
|
{
|
|
|
|
// index of the first edge
|
2014-05-13 10:56:30 -04:00
|
|
|
EdgeIterator first_edge;
|
2011-12-15 11:48:00 -05:00
|
|
|
};
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
struct EdgeArrayEntry
|
|
|
|
{
|
2011-12-15 11:48:00 -05:00
|
|
|
NodeID target;
|
|
|
|
EdgeDataT data;
|
|
|
|
};
|
|
|
|
|
2014-05-13 10:56:30 -04:00
|
|
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
|
|
|
{
|
|
|
|
return boost::irange(BeginEdges(node), EndEdges(node));
|
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
|
|
|
{
|
2014-05-23 08:32:28 -04:00
|
|
|
tbb::parallel_sort(graph.begin(), graph.end());
|
2014-05-05 11:19:47 -04:00
|
|
|
number_of_nodes = nodes;
|
|
|
|
number_of_edges = (EdgeIterator)graph.size();
|
|
|
|
node_array.resize(number_of_nodes + 1);
|
2010-07-14 08:55:53 -04:00
|
|
|
EdgeIterator edge = 0;
|
|
|
|
EdgeIterator position = 0;
|
2014-07-04 11:23:45 -04:00
|
|
|
for (const auto node : boost::irange(0u, number_of_nodes+1))
|
2014-05-05 11:19:47 -04:00
|
|
|
{
|
2014-05-13 10:56:30 -04:00
|
|
|
EdgeIterator last_edge = edge;
|
2014-05-05 11:19:47 -04:00
|
|
|
while (edge < number_of_edges && graph[edge].source == node)
|
2014-05-13 10:56:30 -04:00
|
|
|
{
|
2010-07-14 08:55:53 -04:00
|
|
|
++edge;
|
2014-05-13 10:56:30 -04:00
|
|
|
}
|
|
|
|
node_array[node].first_edge = position; //=edge
|
|
|
|
position += edge - last_edge; // remove
|
2010-07-14 08:55:53 -04:00
|
|
|
}
|
2014-05-05 11:19:47 -04:00
|
|
|
edge_array.resize(position); //(edge)
|
2010-07-14 08:55:53 -04:00
|
|
|
edge = 0;
|
2014-07-04 11:23:45 -04:00
|
|
|
for (const auto node : boost::irange(0u, number_of_nodes))
|
2014-05-05 11:19:47 -04:00
|
|
|
{
|
2014-05-13 10:56:30 -04:00
|
|
|
EdgeIterator e = node_array[node + 1].first_edge;
|
|
|
|
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
|
2014-05-05 11:19:47 -04:00
|
|
|
{
|
|
|
|
edge_array[i].target = graph[edge].target;
|
|
|
|
edge_array[i].data = graph[edge].data;
|
2014-05-23 08:32:28 -04:00
|
|
|
BOOST_ASSERT(edge_array[i].data.distance > 0);
|
2010-07-14 08:55:53 -04:00
|
|
|
edge++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
|
|
|
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
|
|
|
|
{
|
|
|
|
number_of_nodes = nodes.size() - 1;
|
|
|
|
number_of_edges = edges.size();
|
2011-12-15 11:48:00 -05:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
node_array.swap(nodes);
|
|
|
|
edge_array.swap(edges);
|
2012-03-05 13:08:10 -05:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
Percent p(GetNumberOfNodes());
|
2014-07-04 11:41:56 -04:00
|
|
|
for (const auto u : boost::irange(0u, GetNumberOfNodes()))
|
2014-05-05 11:19:47 -04:00
|
|
|
{
|
2014-05-13 10:56:30 -04:00
|
|
|
for (auto eid : GetAdjacentEdgeRange(u))
|
2014-05-05 11:19:47 -04:00
|
|
|
{
|
2014-05-13 10:56:30 -04:00
|
|
|
const EdgeData &data = GetEdgeData(eid);
|
2014-05-23 08:32:28 -04:00
|
|
|
if (!data.shortcut)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const unsigned v = GetTarget(eid);
|
|
|
|
const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
|
|
|
|
if (SPECIAL_EDGEID == first_edge_id)
|
|
|
|
{
|
|
|
|
SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
|
|
|
|
<< u << "," << data.id << "," << v
|
|
|
|
<< "), eid: " << eid;
|
|
|
|
BOOST_ASSERT(false);
|
|
|
|
}
|
|
|
|
const EdgeID second_edge_id = FindEdgeInEitherDirection(data.id, v);
|
|
|
|
if (SPECIAL_EDGEID == second_edge_id)
|
2014-05-05 11:19:47 -04:00
|
|
|
{
|
2014-05-23 08:32:28 -04:00
|
|
|
SimpleLogger().Write(logWARNING) << "cannot find second segment of edge ("
|
|
|
|
<< u << "," << data.id << "," << v
|
|
|
|
<< "), eid: " << eid;
|
|
|
|
BOOST_ASSERT(false);
|
2012-03-05 13:08:10 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
p.printIncrement();
|
|
|
|
}
|
|
|
|
#endif
|
2011-12-15 11:48:00 -05:00
|
|
|
}
|
|
|
|
|
2014-05-13 10:56:30 -04:00
|
|
|
unsigned GetNumberOfNodes() const { return number_of_nodes -1; }
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
unsigned GetOutDegree(const NodeIterator n) const { return BeginEdges(n) - EndEdges(n) - 1; }
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
inline NodeIterator GetTarget(const EdgeIterator e) const
|
|
|
|
{
|
|
|
|
return NodeIterator(edge_array[e].target);
|
2010-07-14 08:55:53 -04:00
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
2011-04-15 12:39:44 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
EdgeIterator BeginEdges(const NodeIterator n) const
|
|
|
|
{
|
2014-05-13 10:56:30 -04:00
|
|
|
return EdgeIterator(node_array.at(n).first_edge);
|
2010-07-14 08:55:53 -04:00
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
EdgeIterator EndEdges(const NodeIterator n) const
|
|
|
|
{
|
2014-05-13 10:56:30 -04:00
|
|
|
return EdgeIterator(node_array.at(n + 1).first_edge);
|
2010-07-14 08:55:53 -04:00
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
// searches for a specific edge
|
|
|
|
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
|
|
|
{
|
|
|
|
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
|
|
|
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
2014-05-13 10:56:30 -04:00
|
|
|
for (auto edge : GetAdjacentEdgeRange(from))
|
2014-05-05 11:19:47 -04:00
|
|
|
{
|
2010-07-14 08:55:53 -04:00
|
|
|
const NodeID target = GetTarget(edge);
|
|
|
|
const EdgeWeight weight = GetEdgeData(edge).distance;
|
2014-05-05 11:19:47 -04:00
|
|
|
if (target == to && weight < smallest_weight)
|
|
|
|
{
|
|
|
|
smallest_edge = edge;
|
|
|
|
smallest_weight = weight;
|
2010-07-14 08:55:53 -04:00
|
|
|
}
|
|
|
|
}
|
2014-05-05 11:19:47 -04:00
|
|
|
return smallest_edge;
|
2010-07-14 08:55:53 -04:00
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
|
|
|
|
{
|
|
|
|
EdgeIterator tmp = FindEdge(from, to);
|
|
|
|
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
|
2011-07-21 10:30:36 -04:00
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
EdgeIterator
|
|
|
|
FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
|
|
|
|
{
|
|
|
|
EdgeIterator current_iterator = FindEdge(from, to);
|
|
|
|
if (SPECIAL_NODEID == current_iterator)
|
|
|
|
{
|
|
|
|
current_iterator = FindEdge(to, from);
|
|
|
|
if (SPECIAL_NODEID != current_iterator)
|
|
|
|
{
|
2011-07-18 11:50:08 -04:00
|
|
|
result = true;
|
2013-09-18 11:49:49 -04:00
|
|
|
}
|
2011-07-18 11:50:08 -04:00
|
|
|
}
|
2014-05-05 11:19:47 -04:00
|
|
|
return current_iterator;
|
2011-07-18 11:50:08 -04:00
|
|
|
}
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
private:
|
|
|
|
NodeIterator number_of_nodes;
|
|
|
|
EdgeIterator number_of_edges;
|
2010-07-14 08:55:53 -04:00
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
|
|
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
2010-07-14 08:55:53 -04:00
|
|
|
};
|
|
|
|
|
2014-05-05 11:19:47 -04:00
|
|
|
#endif // STATIC_GRAPH_H
|