Fast map matching  0.1.0
network_graph.cpp
1 #include "network/network_graph.hpp"
2 #include "network/heap.hpp"
3 #include "network/network.hpp"
4 #include "util/debug.hpp"
5 
6 #include <cmath>
7 #include <iostream>
8 #include <algorithm>
9 #include <unordered_map>
10 #include <queue>
11 
12 using namespace FMM;
13 using namespace FMM::CORE;
14 using namespace FMM::NETWORK;
15 NetworkGraph::NetworkGraph(const Network &network_arg) : network(network_arg) {
16  const std::vector<Edge> &edges = network.get_edges();
17  SPDLOG_INFO("Construct graph from network edges start");
19  bool inserted;
20  g = Graph_T();
21  int N = edges.size();
22  for (int i = 0; i < N; ++i) {
23  const Edge &edge = edges[i];
24  boost::tie(e, inserted) = boost::add_edge(edge.source, edge.target, g);
25  // id is the FID read, id_attr is the external property in SHP
26  g[e].index = edge.index;
27  g[e].length = edge.length;
28  }
29  num_vertices = boost::num_vertices(g);
30  SPDLOG_INFO("Graph nodes {} edges {}", num_vertices, boost::num_edges(g));
31  SPDLOG_INFO("Construct graph from network edges end");
32 }
33 
35  boost::graph_traits<Graph_T>::edge_iterator it, end;
36  for (boost::tie(it, end) = boost::edges(g); it != end; ++it)
37  std::cout << " index " << g[*it].index << " edge " <<
38  network.get_edge_id(g[*it].index) << " "
39  << network.get_node_id(boost::source(*it, g)) << " -> "
40  << network.get_node_id(boost::target(*it, g)) << '\n';
41 }
42 
44  return g;
45 }
46 
48  return network;
49 }
50 unsigned int NetworkGraph::get_num_vertices() const {
51  return num_vertices;
52 }
53 
54 std::vector<EdgeIndex> NetworkGraph::shortest_path_dijkstra(
55  NodeIndex source, NodeIndex target) const {
56  SPDLOG_TRACE("Shortest path starts");
57  if (source == target) return {};
58  Heap Q;
59  PredecessorMap pmap;
60  DistanceMap dmap;
61  // Initialization
62  Q.push(source, 0);
63  pmap.insert({source, source});
64  dmap.insert({source, 0});
65  OutEdgeIterator out_i, out_end;
66  double temp_dist = 0;
67  // Dijkstra search
68  while (!Q.empty()) {
69  HeapNode node = Q.top();
70  Q.pop();
71  NodeIndex u = node.index;
72  if (u == target) break;
73  for (boost::tie(out_i, out_end) = boost::out_edges(u, g);
74  out_i != out_end; ++out_i) {
75  EdgeDescriptor e = *out_i;
76  NodeIndex v = boost::target(e, g);
77  temp_dist = node.value + g[e].length;
78  auto iter = dmap.find(v);
79  if (iter != dmap.end()) {
80  // dmap contains node v
81  if (iter->second > temp_dist) {
82  // a smaller distance is found for v
83  pmap[v] = u;
84  dmap[v] = temp_dist;
85  Q.decrease_key(v, temp_dist);
86  }
87  } else {
88  // dmap does not contain v
89  Q.push(v, temp_dist);
90  pmap.insert({v, u});
91  dmap.insert({v, temp_dist});
92  }
93  }
94  }
95  // Backtrack from target to source
96  return back_track(source, target, pmap, dmap);
97 }
98 
100  const Point &p1, const Point &p2) const {
101  return sqrt((p2.get<0>() - p1.get<0>()) * (p2.get<0>() - p1.get<0>()) +
102  (p2.get<1>() - p1.get<1>()) * (p2.get<1>() - p1.get<1>()));
103 }
104 
105 std::vector<EdgeIndex> NetworkGraph::shortest_path_astar(
106  NodeIndex source, NodeIndex target) const {
107  SPDLOG_TRACE("Shortest path astar starts");
108  if (source == target) return {};
109  const std::vector<Point> &vertex_points =
111  Heap Q;
112  PredecessorMap pmap;
113  DistanceMap dmap;
114  // Initialization
115  double h = calc_heuristic_dist(vertex_points[source],
116  vertex_points[target]);
117  Q.push(source, h);
118  pmap.insert({source, source});
119  dmap.insert({source, 0});
120  OutEdgeIterator out_i, out_end;
121  double temp_dist = 0;
122  // Dijkstra search
123  while (!Q.empty()) {
124  HeapNode node = Q.top();
125  Q.pop();
126  NodeIndex u = node.index;
127  if (u == target) break;
128  for (boost::tie(out_i, out_end) = boost::out_edges(u, g);
129  out_i != out_end; ++out_i) {
130  EdgeDescriptor e = *out_i;
131  NodeIndex v = boost::target(e, g);
132  temp_dist = dmap.at(u) + g[e].length;
133  h = calc_heuristic_dist(vertex_points[v], vertex_points[target]);
134  auto iter = dmap.find(v);
135  if (iter != dmap.end()) {
136  // dmap contains node v
137  if (iter->second > temp_dist) {
138  // a smaller distance is found for v
139  pmap[v] = u;
140  dmap[v] = temp_dist;
141  // Unsure if v is still in Q or not
142  if (Q.contain_node(v)) {
143  Q.decrease_key(v, temp_dist + h);
144  } else {
145  Q.push(v, temp_dist + h);
146  }
147  }
148  } else {
149  // dmap does not contain v
150  Q.push(v, temp_dist + h);
151  pmap.insert({v, u});
152  dmap.insert({v, temp_dist});
153  }
154  }
155  }
156  // Backtrack from target to source
157  return back_track(source, target, pmap, dmap);
158 }
159 
160 std::vector<EdgeIndex> NetworkGraph::back_track(
161  NodeIndex source, NodeIndex target, const PredecessorMap &pmap,
162  const DistanceMap &dmap) const {
163  SPDLOG_TRACE("Backtrack starts");
164  if (dmap.find(target) == dmap.end()) {
165  return {};
166  } else {
167  std::vector<EdgeIndex> path;
168  NodeIndex v = target;
169  NodeIndex u = pmap.at(v);
170  while (v != source) {
171  double cost = dmap.at(v) - dmap.at(u);
172  SPDLOG_TRACE("u {} d {} v {} d {} cost {}",
173  get_node_id(u), dmap.at(u),
174  get_node_id(v), dmap.at(v), cost);
175  path.push_back(get_edge_index(u, v, cost));
176  v = u;
177  u = pmap.at(v);
178  }
179  std::reverse(path.begin(), path.end());
180  return path;
181  }
182 }
183 
189  double cost) const {
190  SPDLOG_TRACE("Find edge from {} to {} cost {}", source, target, cost);
191  if (source >= num_vertices || target >= num_vertices) return -1;
192  EdgeDescriptor e;
193  OutEdgeIterator out_i, out_end;
194  for (boost::tie(out_i, out_end) = boost::out_edges(source, g);
195  out_i != out_end; ++out_i) {
196  e = *out_i;
197  SPDLOG_TRACE(" Check Edge from {} to {} cost {}",
198  source, boost::target(e, g), g[e].length);
199  if (target == boost::target(e, g) &&
200  (std::abs(g[e].length - cost) <= DOUBLE_MIN)) {
201  SPDLOG_TRACE(" Found edge idx {} id {}",
202  g[e].index, get_edge_id(g[e].index));
203  return g[e].index;
204  }
205  }
206  SPDLOG_ERROR("Edge not found");
207  return -1;
208 }
210  double delta,
211  PredecessorMap *pmap,
212  DistanceMap *dmap) const {
213  Heap Q;
214  // Initialization
215  Q.push(s, 0);
216  pmap->insert({s, s});
217  dmap->insert({s, 0});
218  OutEdgeIterator out_i, out_end;
219  double temp_dist = 0;
220  // Dijkstra search
221  while (!Q.empty()) {
222  HeapNode node = Q.top();
223  Q.pop();
224  NodeIndex u = node.index;
225  if (node.value > delta) break;
226  for (boost::tie(out_i, out_end) = boost::out_edges(u, g);
227  out_i != out_end; ++out_i) {
228  EdgeDescriptor e = *out_i;
229  NodeIndex v = boost::target(e, g);
230  temp_dist = node.value + g[e].length;
231  auto iter = dmap->find(v);
232  if (iter != dmap->end()) {
233  // dmap contains node v
234  if (iter->second > temp_dist) {
235  // a smaller distance is found for v
236  (*pmap)[v] = u;
237  (*dmap)[v] = temp_dist;
238  Q.decrease_key(v, temp_dist);
239  };
240  } else {
241  // dmap does not contain v
242  if (temp_dist <= delta) {
243  Q.push(v, temp_dist);
244  pmap->insert({v, u});
245  dmap->insert({v, temp_dist});
246  }
247  }
248  }
249  }
250 }
FMM::NETWORK::NetworkGraph::g
Graph_T g
The member storing a boost graph.
Definition: network_graph.hpp:156
FMM::NETWORK::Heap
Heap data structure used in the routing query
Definition: heap.hpp:40
FMM::NETWORK::Graph_T
boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, boost::no_property, EdgeProperty > Graph_T
Boost graph type.
Definition: graph.hpp:36
FMM::NETWORK::EdgeDescriptor
Graph_T::edge_descriptor EdgeDescriptor
Boost graph edge type.
Definition: graph.hpp:41
FMM::NETWORK::NetworkGraph::print_graph
void print_graph() const
Print graph information.
Definition: network_graph.cpp:34
FMM::NETWORK::Heap::decrease_key
void decrease_key(NodeIndex index, double value)
Decrease a node in the heap.
Definition: heap.hpp:93
FMM::NETWORK::Network::get_edges
const std::vector< Edge > & get_edges() const
Get edges in the network.
Definition: network.cpp:146
FMM::NETWORK::Heap::top
HeapNode top()
Get a copy of the top node in the heap.
Definition: heap.hpp:63
FMM::NETWORK::Heap::push
void push(NodeIndex index, double value)
Push a node into the heap.
Definition: heap.hpp:47
FMM::NETWORK::HeapNode
Node in the heap structure.
Definition: heap.hpp:22
FMM::NETWORK::NetworkGraph::network
const Network & network
Road network.
Definition: network_graph.hpp:161
FMM::NETWORK::HeapNode::index
NodeIndex index
Index of a node in the heap.
Definition: heap.hpp:24
FMM::NETWORK::Network::get_vertex_points
const std::vector< FMM::CORE::Point > & get_vertex_points() const
Get all node geometry.
Definition: network.cpp:303
FMM::NETWORK::NetworkGraph::shortest_path_astar
std::vector< EdgeIndex > shortest_path_astar(NodeIndex source, NodeIndex target) const
AStar Shortest path query from source to target.
Definition: network_graph.cpp:105
FMM::NETWORK::Edge::index
EdgeIndex index
Index of an edge, which is continuous [0,N-1].
Definition: type.hpp:47
FMM::NETWORK::DistanceMap
std::unordered_map< NodeIndex, double > DistanceMap
Distance map.
Definition: graph.hpp:61
FMM::NETWORK::NetworkGraph::single_source_upperbound_dijkstra
void single_source_upperbound_dijkstra(NodeIndex source, double delta, PredecessorMap *pmap, DistanceMap *dmap) const
Single source shortest path query with an uppper bound.
Definition: network_graph.cpp:209
FMM::NETWORK::NetworkGraph::get_edge_id
int get_edge_id(EdgeIndex idx) const
Get the edge ID from edge index.
Definition: network_graph.hpp:98
FMM::NETWORK::Network::get_node_id
NodeID get_node_id(NodeIndex index) const
Get node ID from index.
Definition: network.cpp:161
FMM::NETWORK::NetworkGraph::get_network
const Network & get_network()
Get inner network reference.
Definition: network_graph.cpp:47
FMM
Fast map matching.
Definition: geom_algorithm.hpp:17
FMM::NETWORK::Network
Road network class.
Definition: network.hpp:36
FMM::NETWORK::NetworkGraph::get_boost_graph
const Graph_T & get_boost_graph() const
Get inner boost graph.
Definition: network_graph.cpp:43
FMM::NETWORK::Network::get_edge_id
EdgeID get_edge_id(EdgeIndex index) const
Get edge ID from index.
Definition: network.cpp:152
FMM::NETWORK::NetworkGraph::DOUBLE_MIN
static constexpr double DOUBLE_MIN
A value used in checking edge from source,target and cost.
Definition: network_graph.hpp:160
FMM::NETWORK::NetworkGraph::get_num_vertices
unsigned int get_num_vertices() const
Get number of vertices in the graph.
Definition: network_graph.cpp:50
FMM::NETWORK::Heap::pop
void pop()
Pop a node from the heap.
Definition: heap.hpp:54
FMM::NETWORK::Heap::empty
bool empty()
Check if the heap is empty.
Definition: heap.hpp:70
FMM::NETWORK::NetworkGraph::num_vertices
unsigned int num_vertices
number of vertices
Definition: network_graph.hpp:162
FMM::NETWORK::OutEdgeIterator
boost::graph_traits< Graph_T >::out_edge_iterator OutEdgeIterator
Boost graph out edge iterator.
Definition: graph.hpp:49
FMM::CORE
Core data types.
Definition: geometry.hpp:22
FMM::NETWORK
Classes related with network and graph.
Definition: graph.hpp:21
FMM::NETWORK::NetworkGraph::get_edge_index
int get_edge_index(NodeIndex source, NodeIndex target, double cost) const
Find the edge ID given a pair of nodes and its cost, if not found, return -1.
Definition: network_graph.cpp:188
FMM::NETWORK::Heap::contain_node
bool contain_node(NodeIndex index)
Check if the heap contains a node.
Definition: heap.hpp:85
FMM::NETWORK::NetworkGraph::get_node_id
int get_node_id(NodeIndex idx) const
Get node ID from a node index.
Definition: network_graph.hpp:117
FMM::NETWORK::NetworkGraph::shortest_path_dijkstra
std::vector< EdgeIndex > shortest_path_dijkstra(NodeIndex source, NodeIndex target) const
Dijkstra Shortest path query from source to target.
Definition: network_graph.cpp:54
FMM::NETWORK::Edge::source
NodeIndex source
source node index
Definition: type.hpp:49
FMM::NETWORK::NodeIndex
unsigned int NodeIndex
Node Index in the network, range from [0,num_vertices-1 ].
Definition: type.hpp:24
FMM::NETWORK::NetworkGraph::calc_heuristic_dist
double calc_heuristic_dist(const CORE::Point &p1, const CORE::Point &p2) const
Calculate heuristic distance from p1 to p2,which is used in Astar routing.
Definition: network_graph.cpp:99
FMM::NETWORK::Edge::length
double length
length of the edge polyline
Definition: type.hpp:51
FMM::CORE::Point
boost::geometry::model::point< double, 2, boost::geometry::cs::cartesian > Point
Point class.
Definition: geometry.hpp:28
FMM::NETWORK::PredecessorMap
std::unordered_map< NodeIndex, NodeIndex > PredecessorMap
Predecessor Map.
Definition: graph.hpp:55
FMM::NETWORK::HeapNode::value
double value
Value of a node in the heap.
Definition: heap.hpp:25
FMM::NETWORK::Edge::target
NodeIndex target
target node index
Definition: type.hpp:50
FMM::NETWORK::NetworkGraph::back_track
std::vector< EdgeIndex > back_track(NodeIndex source, NodeIndex target, const PredecessorMap &pmap, const DistanceMap &dmap) const
Backtrack the routing result to find a path from source to target.
Definition: network_graph.cpp:160
FMM::NETWORK::Edge
Road edge class.
Definition: type.hpp:45