KShortestPaths.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. //
  2. // Created by wrede on 25.05.16.
  3. //
  4. #include "KShortestPaths.h"
  5. #include "../util/Logger.h"
  6. #include "../util/FileIO.h"
  7. #include <boost/graph/dijkstra_shortest_paths.hpp>
  8. #include <boost/graph/bellman_ford_shortest_paths.hpp>
  9. #include <boost/graph/copy.hpp>
  10. namespace algo
  11. {
  12. KShortestPaths::KShortestPaths(DirectedGraph graph, Vertex source, Vertex sink)
  13. : original_graph_(graph), source_(source), sink_(sink)
  14. {
  15. }
  16. MultiPredecessorMap KShortestPaths::Run(size_t max_path_count)
  17. {
  18. util::Logger::LogInfo("Running k-shortest-paths");
  19. // Clear all data from previous runs
  20. i_shortest_paths_.clear();
  21. util::Logger::LogDebug("find shortest path #1");
  22. util::Logger::LogDebug("find");
  23. FindAndAugmentPath(1, true);
  24. // Find the k shortest paths
  25. for (size_t i = 1; i < max_path_count; ++i)
  26. {
  27. if (i != 1)
  28. {
  29. //If the costs are increasing, no further shortest paths will be found
  30. if (OverallCosts(i) > OverallCosts(i - 1))
  31. {
  32. return i_shortest_paths_[i];
  33. }
  34. }
  35. util::Logger::LogDebug("find shortest path #" + std::to_string(i + 1));
  36. util::Logger::LogDebug("copy");
  37. // Create a copy of the original graph which is used
  38. // for the graph and edge transformations
  39. CopyOriginalGraph();
  40. util::Logger::LogDebug("extend");
  41. // Extend the graph (has negative and positive edge weights)
  42. ExtendGraph(i);
  43. util::Logger::LogDebug("transform");
  44. // Transforms the edge costs (has only positive edge weights)
  45. TransformEdgeCosts(i);
  46. util::Logger::LogDebug("find");
  47. // Finds the next path and adds it to the found paths
  48. FindAndAugmentPath(i + 1, false);
  49. util::Logger::LogDebug("interlace");
  50. // Removes the duplicate edges to make the paths node-disjoint
  51. Interlace(i + 1);
  52. }
  53. // All k shortest paths have been found
  54. return i_shortest_paths_[max_path_count];
  55. }
  56. void KShortestPaths::ExtendGraph(size_t i)
  57. {
  58. boost::graph_traits<DirectedGraph>::out_edge_iterator oei, oei_end;
  59. boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
  60. boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
  61. VertexValueMap graph_values = boost::get(boost::vertex_name, copied_graph_);
  62. // Split all vertices within the paths
  63. for (boost::tie(vi, vi_end) = boost::vertices(original_graph_);
  64. vi != vi_end; ++vi)
  65. {
  66. Vertex v_original = (*vi);
  67. // Ignore vertices off the paths, the source and the sink
  68. if (i_shortest_paths_[i].count(v_original) == 0 ||
  69. v_original == source_ || v_original == sink_)
  70. {
  71. continue;
  72. }
  73. Vertex v_in = original_to_copy_[v_original];
  74. Vertex v_out = boost::add_vertex(graph_values[v_in], copied_graph_);
  75. copy_to_original_[v_out] = v_original;
  76. // Copy outgoing edges to v_out
  77. for (boost::tie(oei, oei_end) = boost::out_edges(v_in, copied_graph_);
  78. oei != oei_end; ++oei)
  79. {
  80. QueueAddEdge(v_out, boost::target(*oei, copied_graph_),
  81. boost::get(boost::edge_weight, copied_graph_, *oei));
  82. }
  83. // Remove outgoing edges from vertex
  84. for (boost::tie(oei, oei_end) = boost::out_edges(v_in, copied_graph_);
  85. oei != oei_end; ++oei)
  86. {
  87. QueueRemoveEdge(v_in, boost::target(*oei, copied_graph_));
  88. }
  89. // Create auxiliary edge
  90. QueueAddEdge(v_in, v_out, 0.0);
  91. }
  92. UpdateEdges();
  93. // Iterate all edges within the copied graph
  94. EdgeWeightMap weights = boost::get(boost::edge_weight, copied_graph_);
  95. for (boost::tie(ei, ei_end) = boost::edges(copied_graph_);
  96. ei != ei_end; ++ei)
  97. {
  98. Vertex s_copy = boost::source(*ei, copied_graph_);
  99. Vertex t_copy = boost::target(*ei, copied_graph_);
  100. Vertex s_orig = copy_to_original_[s_copy];
  101. Vertex t_orig = copy_to_original_[t_copy];
  102. double weight = weights[*ei];
  103. // If the edge is part of the paths
  104. if (i_shortest_paths_[i].count(t_orig) > 0 &&
  105. i_shortest_paths_[i][t_orig].count(s_orig) > 0)
  106. {
  107. // Add the edge with direction and weight inverted
  108. QueueAddEdge(t_copy, s_copy, -weight);
  109. // Remove the old edge
  110. QueueRemoveEdge(s_copy, t_copy);
  111. }
  112. }
  113. UpdateEdges();
  114. }
  115. double KShortestPaths::OverallCosts(size_t i)
  116. {
  117. double value = 0.0;
  118. EdgeWeightMap weights = boost::get(boost::edge_weight, original_graph_);
  119. // Iterate all edges
  120. boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
  121. for (boost::tie(ei, ei_end) = boost::edges(original_graph_);
  122. ei != ei_end; ++ei)
  123. {
  124. Vertex source = boost::source(*ei, original_graph_);
  125. Vertex target = boost::target(*ei, original_graph_);
  126. if (i_shortest_paths_[i].count(target) > 0 &&
  127. i_shortest_paths_[i][target].count(source) > 0)
  128. {
  129. value += weights[*ei];
  130. }
  131. }
  132. util::Logger::LogDebug("cost in " + std::to_string(i) + " : " + std::to_string(value));
  133. return value;
  134. }
  135. void KShortestPaths::CopyOriginalGraph()
  136. {
  137. // Clear all previous data
  138. copied_graph_.clear();
  139. original_to_copy_.clear();
  140. copy_to_original_.clear();
  141. // Copy the graph and store the vertex map temporarily
  142. std::vector<Vertex> original_to_copy_vector(boost::num_vertices(original_graph_));
  143. VertexVertexMap temp_map(original_to_copy_vector.begin());
  144. boost::copy_graph(original_graph_,
  145. copied_graph_,
  146. boost::orig_to_copy(temp_map));
  147. // Copy the vertex map into the two persistent maps, one for each
  148. // mapping direction
  149. boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
  150. for (boost::tie(vi, vi_end) = boost::vertices(original_graph_);
  151. vi != vi_end; ++vi)
  152. {
  153. Vertex v_original = (*vi);
  154. Vertex v_copy = temp_map[v_original];
  155. original_to_copy_[v_original] = v_copy;
  156. copy_to_original_[v_copy] = v_original;
  157. }
  158. }
  159. void KShortestPaths::Interlace(size_t i)
  160. {
  161. boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
  162. for (boost::tie(ei, ei_end) = boost::edges(original_graph_);
  163. ei != ei_end; ++ei)
  164. {
  165. Vertex source = boost::source(*ei, original_graph_);
  166. Vertex target = boost::target(*ei, original_graph_);
  167. // Ignore source and sink
  168. if (source == source_ || target == sink_)
  169. {
  170. continue;
  171. }
  172. // Is edge within paths?
  173. if (i_shortest_paths_[i].count(target) > 0 &&
  174. i_shortest_paths_[i][target].count(source) > 0)
  175. {
  176. // Is edge duplicate?
  177. if (i_shortest_paths_[i].count(source) > 0 &&
  178. i_shortest_paths_[i][source].count(target) > 0)
  179. {
  180. i_shortest_paths_[i][target].erase(source);
  181. i_shortest_paths_[i][source].erase(target);
  182. }
  183. }
  184. }
  185. }
  186. void KShortestPaths::FindAndAugmentPath(size_t i, bool original)
  187. {
  188. // Add new path maps until the needed iteration is reached
  189. while (i_shortest_paths_.size() < (i + 1))
  190. {
  191. i_shortest_paths_.push_back(MultiPredecessorMap());
  192. }
  193. // Add new distance maps until the needed iteration is reached
  194. while (i_distances_.size() < (i + 1))
  195. {
  196. i_distances_.push_back(std::unordered_map<Vertex, double>());
  197. }
  198. // Only copy old paths if old paths exist
  199. if (i > 1)
  200. {
  201. // Copy the old paths
  202. for (auto it = i_shortest_paths_[i - 1].begin();
  203. it != i_shortest_paths_[i - 1].end(); ++it)
  204. {
  205. i_shortest_paths_[i][it->first] = it->second;
  206. }
  207. }
  208. if (original)
  209. {
  210. // Prepare variables for path finding
  211. size_t graph_size = boost::num_vertices(original_graph_);
  212. Vertex root_vertex = source_;
  213. std::vector<Vertex> pred_list(graph_size);
  214. std::vector<double> dist_list(graph_size);
  215. VertexIndexMap graph_indices = boost::get(boost::vertex_index,
  216. original_graph_);
  217. EdgeWeightMap weight_map = boost::get(boost::edge_weight,
  218. original_graph_);
  219. PredecessorMap pred_map(&pred_list[0], graph_indices);
  220. DistanceMap dist_map(&dist_list[0], graph_indices);
  221. // Find the shortest path
  222. boost::bellman_ford_shortest_paths(original_graph_,
  223. graph_size,
  224. boost::root_vertex(root_vertex)
  225. .weight_map(weight_map)
  226. .predecessor_map(pred_map)
  227. .distance_map(dist_map));
  228. // Add the new distances
  229. boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
  230. for (boost::tie(vi, vi_end) = boost::vertices(original_graph_);
  231. vi != vi_end; ++vi)
  232. {
  233. i_distances_[i][*vi] = dist_map[*vi];
  234. }
  235. // Add the new path
  236. size_t path_length = 0;
  237. for (Vertex u = sink_, v = pred_map[u];
  238. u != v; u = v, v = pred_map[v])
  239. {
  240. i_shortest_paths_[i][u].insert(v);
  241. ++path_length;
  242. }
  243. util::Logger::LogDebug("path length " + std::to_string(path_length));
  244. }
  245. else
  246. {
  247. // Prepare variables for path finding
  248. size_t graph_size = boost::num_vertices(copied_graph_);
  249. Vertex root_vertex = original_to_copy_[source_];
  250. std::vector<Vertex> pred_list(graph_size);
  251. std::vector<double> dist_list(graph_size);
  252. VertexIndexMap graph_indices = boost::get(boost::vertex_index,
  253. copied_graph_);
  254. EdgeWeightMap weight_map = boost::get(boost::edge_weight,
  255. copied_graph_);
  256. PredecessorMap pred_map(&pred_list[0], graph_indices);
  257. DistanceMap dist_map(&dist_list[0], graph_indices);
  258. // Find the shortest path
  259. boost::dijkstra_shortest_paths(copied_graph_, root_vertex,
  260. boost::predecessor_map(pred_map)
  261. .distance_map(dist_map));
  262. // boost::bellman_ford_shortest_paths(copied_graph_,
  263. // graph_size,
  264. // boost::root_vertex(root_vertex)
  265. // .weight_map(weight_map)
  266. // .predecessor_map(pred_map)
  267. // .distance_map(dist_map));
  268. util::Logger::LogDebug("add the path");
  269. // Add the new distances
  270. boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
  271. for (boost::tie(vi, vi_end) = boost::vertices(copied_graph_);
  272. vi != vi_end; ++vi)
  273. {
  274. Vertex v_copy = *vi;
  275. Vertex v_orig = copy_to_original_[v_copy];
  276. i_distances_[i][v_orig] = dist_map[v_copy];
  277. }
  278. // Prevent cycles
  279. // unsigned long vertex_count = boost::num_vertices(original_graph_);
  280. // bool* visited = new bool[vertex_count];
  281. // for (unsigned long j = 0; j < vertex_count; j++)
  282. // {
  283. // visited[j] = false;
  284. // }
  285. // Add the new path (the given path is in the copied graph, so the
  286. // vertices need to be mapped to the original graph)
  287. size_t path_length = 0;
  288. Vertex sink_copy = original_to_copy_[sink_];
  289. for (Vertex u_copy = sink_copy, v_copy = pred_map[u_copy];
  290. u_copy != v_copy; u_copy = v_copy, v_copy = pred_map[v_copy])
  291. {
  292. Vertex u_original = copy_to_original_[u_copy];
  293. Vertex v_original = copy_to_original_[v_copy];
  294. // Ignore loops
  295. if (u_original == v_original)
  296. {
  297. continue;
  298. }
  299. // Cycle found
  300. // if (visited[u_original])
  301. // {
  302. // break;
  303. // }
  304. //
  305. // visited[u_original] = true;
  306. i_shortest_paths_[i][u_original].insert(v_original);
  307. i_distances_[i][u_original] = dist_map[u_copy];
  308. ++path_length;
  309. }
  310. util::Logger::LogDebug("path length " + std::to_string(path_length));
  311. // delete[] visited;
  312. }
  313. // Add source
  314. i_shortest_paths_[i][source_].insert(source_);
  315. }
  316. void KShortestPaths::TransformEdgeCosts(size_t i)
  317. {
  318. EdgeWeightMap weights = boost::get(boost::edge_weight, copied_graph_);
  319. boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
  320. double min_weight = 0.0;
  321. for (boost::tie(ei, ei_end) = boost::edges(copied_graph_);
  322. ei != ei_end; ++ei)
  323. {
  324. Vertex s_copy = boost::source(*ei, copied_graph_);
  325. Vertex t_copy = boost::target(*ei, copied_graph_);
  326. Vertex s_orig = copy_to_original_[s_copy];
  327. Vertex t_orig = copy_to_original_[t_copy];
  328. weights[*ei] += i_distances_[i][s_orig] - i_distances_[i][t_orig];
  329. if (weights[*ei] < min_weight)
  330. {
  331. min_weight = weights[*ei];
  332. }
  333. }
  334. for (boost::tie(ei, ei_end) = boost::edges(copied_graph_);
  335. ei != ei_end; ++ei)
  336. {
  337. weights[*ei] -= min_weight;
  338. }
  339. }
  340. void KShortestPaths::UpdateEdges()
  341. {
  342. // Remove the old edges, needs to be done without any iterator since
  343. // the removal invalidates any iterators
  344. for (auto edge : edges_to_remove_)
  345. {
  346. boost::remove_edge(edge.first, edge.second, copied_graph_);
  347. }
  348. edges_to_remove_.clear();
  349. // Add the new edges, needs to be done without any iterator since
  350. // the addition invalidates any iterators
  351. for (auto edge : edges_to_add_)
  352. {
  353. boost::add_edge(edge.first.first, edge.first.second,
  354. edge.second, copied_graph_);
  355. }
  356. edges_to_add_.clear();
  357. }
  358. void KShortestPaths::QueueAddEdge(Vertex source, Vertex target, double weight)
  359. {
  360. edges_to_add_.push_back(
  361. std::pair<std::pair<Vertex, Vertex>, double>(
  362. std::pair<Vertex, Vertex>(source, target), weight));
  363. }
  364. void KShortestPaths::QueueRemoveEdge(Vertex source, Vertex target)
  365. {
  366. edges_to_remove_.push_back(std::pair<Vertex, Vertex>(source, target));
  367. }
  368. }