add functions to load graph into simplified data structures
This commit is contained in:
parent
a09f97c9d5
commit
1d1be10f16
@ -104,7 +104,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
{
|
||||
m_edges[i].target = graph[edge].target;
|
||||
m_edges[i].data = graph[edge].data;
|
||||
BOOST_ASSERT_MSG(graph[edge].data.distance > 0, "edge distance invalid");
|
||||
// BOOST_ASSERT_MSG(graph[edge].data.distance > 0, "edge distance invalid");
|
||||
++edge;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,14 @@ struct NodeBasedEdgeData
|
||||
}
|
||||
};
|
||||
|
||||
struct SimpleEdgeData
|
||||
{
|
||||
SimpleEdgeData() : capacity(0) {}
|
||||
EdgeWeight capacity;
|
||||
};
|
||||
|
||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||
typedef DynamicGraph<SimpleEdgeData> SimpleNodeBasedDynamicGraph;
|
||||
|
||||
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
||||
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||
@ -163,4 +170,77 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
||||
return graph;
|
||||
}
|
||||
|
||||
template<class SimpleEdgeT>
|
||||
inline std::shared_ptr<SimpleNodeBasedDynamicGraph>
|
||||
SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdgeT> &input_edge_list)
|
||||
{
|
||||
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
|
||||
tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
|
||||
|
||||
DeallocatingVector<SimpleNodeBasedDynamicGraph::InputEdge> edges_list;
|
||||
SimpleNodeBasedDynamicGraph::InputEdge edge;
|
||||
edge.data.capacity = 1;
|
||||
for (const SimpleEdgeT &import_edge : input_edge_list)
|
||||
{
|
||||
if (import_edge.source == import_edge.target)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
edge.source = import_edge.source;
|
||||
edge.target = import_edge.target;
|
||||
edges_list.push_back(edge);
|
||||
std::swap(edge.source, edge.target);
|
||||
edges_list.push_back(edge);
|
||||
}
|
||||
|
||||
// remove duplicate edges
|
||||
std::sort(edges_list.begin(), edges_list.end());
|
||||
NodeID edge_count = 0;
|
||||
for (NodeID i = 0; i < edges_list.size(); )
|
||||
{
|
||||
const NodeID source = edges_list[i].source;
|
||||
const NodeID target = edges_list[i].target;
|
||||
// remove eigenloops
|
||||
if (source == target)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
SimpleNodeBasedDynamicGraph::InputEdge forward_edge;
|
||||
SimpleNodeBasedDynamicGraph::InputEdge reverse_edge;
|
||||
forward_edge = reverse_edge = edges_list[i];
|
||||
forward_edge.data.capacity = reverse_edge.data.capacity = INVALID_EDGE_WEIGHT;
|
||||
// remove parallel edges
|
||||
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
|
||||
{
|
||||
forward_edge.data.capacity = std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
|
||||
reverse_edge.data.capacity = std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
|
||||
++i;
|
||||
}
|
||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||
if (forward_edge.data.capacity == reverse_edge.data.capacity)
|
||||
{
|
||||
if ((int)forward_edge.data.capacity != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // insert seperate edges
|
||||
if (((int)forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
if ((int)reverse_edge.data.capacity != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = reverse_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
|
||||
|
||||
auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
|
||||
return graph;
|
||||
}
|
||||
|
||||
#endif // __NODE_BASED_GRAPH_H__
|
||||
|
@ -268,6 +268,118 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename EdgeT>
|
||||
NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, std::vector<EdgeT> &edge_list)
|
||||
{
|
||||
const FingerPrint fingerprint_orig;
|
||||
FingerPrint fingerprint_loaded;
|
||||
input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||
|
||||
if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n"
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
NodeID n, source, target;
|
||||
EdgeID m;
|
||||
short dir; // direction (0 = open, 1 = forward, 2+ = open)
|
||||
std::unordered_map<NodeID, NodeID> ext_to_int_id_map;
|
||||
std::vector<NodeInfo> int_to_ext_node_id_map;
|
||||
|
||||
input_stream.read((char *)&n, sizeof(NodeID));
|
||||
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
|
||||
ExternalMemoryNode current_node;
|
||||
for (NodeID i = 0; i < n; ++i)
|
||||
{
|
||||
input_stream.read((char *)¤t_node, sizeof(ExternalMemoryNode));
|
||||
int_to_ext_node_id_map.emplace_back(current_node.lat, current_node.lon, current_node.node_id);
|
||||
ext_to_int_id_map.emplace(current_node.node_id, i);
|
||||
}
|
||||
|
||||
input_stream.read((char *)&m, sizeof(unsigned));
|
||||
SimpleLogger().Write() << " and " << m << " edges ";
|
||||
|
||||
edge_list.reserve(m);
|
||||
EdgeWeight weight;
|
||||
short type;
|
||||
NodeID nameID;
|
||||
int length;
|
||||
bool is_roundabout, ignore_in_grid, is_access_restricted, is_contra_flow, is_split;
|
||||
|
||||
for (EdgeID i = 0; i < m; ++i)
|
||||
{
|
||||
input_stream.read((char *)&source, sizeof(unsigned));
|
||||
input_stream.read((char *)&target, sizeof(unsigned));
|
||||
input_stream.read((char *)&length, sizeof(int));
|
||||
input_stream.read((char *)&dir, sizeof(short));
|
||||
input_stream.read((char *)&weight, sizeof(int));
|
||||
input_stream.read((char *)&type, sizeof(short));
|
||||
input_stream.read((char *)&nameID, sizeof(unsigned));
|
||||
input_stream.read((char *)&is_roundabout, sizeof(bool));
|
||||
input_stream.read((char *)&ignore_in_grid, sizeof(bool));
|
||||
input_stream.read((char *)&is_access_restricted, sizeof(bool));
|
||||
input_stream.read((char *)&is_contra_flow, sizeof(bool));
|
||||
input_stream.read((char *)&is_split, sizeof(bool));
|
||||
|
||||
BOOST_ASSERT_MSG(length > 0, "loaded null length edge");
|
||||
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
||||
BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction");
|
||||
|
||||
BOOST_ASSERT(type >= 0);
|
||||
|
||||
// translate the external NodeIDs to internal IDs
|
||||
auto internal_id_iter = ext_to_int_id_map.find(source);
|
||||
if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
source = internal_id_iter->second;
|
||||
internal_id_iter = ext_to_int_id_map.find(target);
|
||||
if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
target = internal_id_iter->second;
|
||||
BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX, "nonexisting source or target");
|
||||
|
||||
if (source > target)
|
||||
{
|
||||
std::swap(source, target);
|
||||
}
|
||||
|
||||
edge_list.emplace_back(source,
|
||||
target);
|
||||
}
|
||||
|
||||
tbb::parallel_sort(edge_list.begin(), edge_list.end());
|
||||
for (unsigned i = 1; i < edge_list.size(); ++i)
|
||||
{
|
||||
if ((edge_list[i - 1].target == edge_list[i].target) &&
|
||||
(edge_list[i - 1].source == edge_list[i].source))
|
||||
{
|
||||
edge_list[i].capacity = std::min(edge_list[i - 1].capacity, edge_list[i].capacity);
|
||||
edge_list[i - 1].source = UINT_MAX;
|
||||
}
|
||||
}
|
||||
const auto new_end_iter = std::remove_if(edge_list.begin(),
|
||||
edge_list.end(),
|
||||
[](const EdgeT &edge)
|
||||
{ return edge.source == SPECIAL_NODEID; });
|
||||
ext_to_int_id_map.clear();
|
||||
edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
|
||||
edge_list.shrink_to_fit();
|
||||
SimpleLogger().Write() << "Graph loaded ok and has " << n << " nodes and " << edge_list.size() << " edges";
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
template <typename NodeT, typename EdgeT>
|
||||
unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file,
|
||||
std::vector<NodeT> &node_list,
|
||||
|
Loading…
Reference in New Issue
Block a user