KShortestPaths.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. FindAndAugmentPath(1, true);
  23. // Find the k shortest paths
  24. for (size_t i = 1; i < max_path_count; ++i)
  25. {
  26. util::Logger::LogDebug("find shortest path #" + std::to_string(i + 1));
  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. // Create a copy of the original graph which is used
  36. // for the graph and edge transformations
  37. CopyOriginalGraph();
  38. //util::FileIO::WriteCSVMatlab(copied_graph_, "/home/wrede/Dokumente/graph_copy.csv");
  39. // Extend the graph (has negative and positive edge weights)
  40. ExtendGraph(i);
  41. //util::FileIO::WriteCSVMatlab(copied_graph_, "/home/wrede/Dokumente/graph_copy_extended.csv");
  42. //TODO (optional) Transform the edge weights (positive edge weights) and use dijkstra
  43. // Finds the next path and adds it to the found paths
  44. FindAndAugmentPath(i + 1, false);
  45. // Removes the duplicate edges to make the paths node-disjoint
  46. Interlace(i + 1);
  47. }
  48. // All k shortest paths have been found
  49. return i_shortest_paths_[max_path_count];
  50. }
  51. void KShortestPaths::ExtendGraph(size_t i)
  52. {
  53. boost::graph_traits<DirectedGraph>::out_edge_iterator oei, oei_end;
  54. boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
  55. VertexValueMap graph_values = boost::get(boost::vertex_name, copied_graph_);
  56. // Split all vertices within the paths
  57. for (boost::tie(vi, vi_end) = boost::vertices(original_graph_); vi != vi_end; ++vi)
  58. {
  59. Vertex v_original = (*vi);
  60. // Ignore vertices off the paths, the source and the sink
  61. if (i_shortest_paths_[i].count(v_original) == 0 || v_original == source_ || v_original == sink_)
  62. {
  63. continue;
  64. }
  65. Vertex v_in = original_to_copy_[v_original];
  66. Vertex v_out = boost::add_vertex(graph_values[v_in], copied_graph_);
  67. copy_to_original_[v_out] = v_original;
  68. // Copy outgoing edges to v_out
  69. for (boost::tie(oei, oei_end) = boost::out_edges(v_in, copied_graph_); oei != oei_end; ++oei)
  70. {
  71. QueueAddEdge(v_out, boost::target(*oei, copied_graph_),
  72. boost::get(boost::edge_weight, copied_graph_, *oei));
  73. }
  74. // Remove outgoing edges from vertex
  75. for (boost::tie(oei, oei_end) = boost::out_edges(v_in, copied_graph_); oei != oei_end; ++oei)
  76. {
  77. QueueRemoveEdge(v_in, boost::target(*oei, copied_graph_));
  78. }
  79. // Create auxiliary edge
  80. QueueAddEdge(v_in, v_out, 0.0);
  81. }
  82. UpdateEdges();
  83. // Iterate all vertices within the copied graph
  84. for (boost::tie(vi, vi_end) = boost::vertices(copied_graph_); vi != vi_end; ++vi)
  85. {
  86. Vertex v_copy = (*vi);
  87. Vertex v_original = copy_to_original_[v_copy];
  88. // Ignore vertices off the paths
  89. if (i_shortest_paths_[i].count(v_original) == 0)
  90. {
  91. continue;
  92. }
  93. // Iterate all outgoing edges at the current vertex
  94. for (boost::tie(oei, oei_end) = boost::out_edges(v_copy, copied_graph_); oei != oei_end; ++oei)
  95. {
  96. Vertex t_copy = boost::target(*oei, copied_graph_);
  97. Vertex t_original = copy_to_original_[t_copy];
  98. // Ignore edges off the paths
  99. if (i_shortest_paths_[i].count(t_original) == 0)
  100. {
  101. continue;
  102. }
  103. // Invert the edge direction and weight
  104. double weight = boost::get(boost::edge_weight, copied_graph_,
  105. *oei);
  106. QueueAddEdge(t_copy, v_copy, -weight);
  107. QueueRemoveEdge(v_copy, t_copy);
  108. }
  109. }
  110. UpdateEdges();
  111. }
  112. double KShortestPaths::OverallCosts(size_t i)
  113. {
  114. EdgeWeightMap weights = boost::get(boost::edge_weight, original_graph_);
  115. boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
  116. double value = 0.0;
  117. for (boost::tie(ei, ei_end) = boost::edges(original_graph_);
  118. ei != ei_end; ++ei)
  119. {
  120. Vertex source = boost::source(*ei, original_graph_);
  121. Vertex target = boost::target(*ei, original_graph_);
  122. // Is edge within paths?
  123. if (i_shortest_paths_[i].count(target) > 0 && i_shortest_paths_[i][target].count(source) > 0)
  124. {
  125. value += weights[*ei];
  126. }
  127. }
  128. return value;
  129. }
  130. void KShortestPaths::CopyOriginalGraph()
  131. {
  132. // Clear all previous data
  133. copied_graph_.clear();
  134. original_to_copy_.clear();
  135. copy_to_original_.clear();
  136. // Copy the graph and store the vertex map temporarily
  137. std::vector<Vertex> original_to_copy_vector(boost::num_vertices(original_graph_));
  138. VertexVertexMap temp_map(original_to_copy_vector.begin());
  139. boost::copy_graph(original_graph_,
  140. copied_graph_,
  141. boost::orig_to_copy(temp_map));
  142. // Copy the vertex map into the two persistent maps, one for each
  143. // mapping direction
  144. boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
  145. for (boost::tie(vi, vi_end) = boost::vertices(original_graph_);
  146. vi != vi_end; ++vi)
  147. {
  148. Vertex v_original = (*vi);
  149. Vertex v_copy = temp_map[v_original];
  150. original_to_copy_[v_original] = v_copy;
  151. copy_to_original_[v_copy] = v_original;
  152. }
  153. }
  154. void KShortestPaths::Interlace(size_t i)
  155. {
  156. boost::graph_traits<DirectedGraph>::edge_iterator ei, ei_end;
  157. for (boost::tie(ei, ei_end) = boost::edges(original_graph_);
  158. ei != ei_end; ++ei)
  159. {
  160. Vertex source = boost::source(*ei, original_graph_);
  161. Vertex target = boost::target(*ei, original_graph_);
  162. // Ignore source and sink
  163. if (source == source_ || target == sink_)
  164. {
  165. continue;
  166. }
  167. // Is edge within paths?
  168. if (i_shortest_paths_[i].count(target) > 0 && i_shortest_paths_[i][target].count(source) > 0)
  169. {
  170. // Is edge duplicate?
  171. if (i_shortest_paths_[i].count(source) > 0 && i_shortest_paths_[i][source].count(target) > 0)
  172. {
  173. i_shortest_paths_[i][target].erase(source);
  174. i_shortest_paths_[i][source].erase(target);
  175. }
  176. }
  177. }
  178. }
  179. void KShortestPaths::FindAndAugmentPath(size_t i, bool original)
  180. {
  181. // Add new path maps until the needed iteration is reached
  182. while (i_shortest_paths_.size() < (i + 1))
  183. {
  184. i_shortest_paths_.push_back(MultiPredecessorMap());
  185. }
  186. // Only copy old paths if old paths exist
  187. if (i > 0)
  188. {
  189. // Copy the old paths
  190. for (auto it = i_shortest_paths_[i - 1].begin();
  191. it != i_shortest_paths_[i - 1].end(); ++it)
  192. {
  193. i_shortest_paths_[i][(*it).first] = (*it).second;
  194. }
  195. }
  196. if (original)
  197. {
  198. // Prepare variables for path finding
  199. size_t graph_size = boost::num_vertices(original_graph_);
  200. std::vector<Vertex> pred_list(graph_size);
  201. std::vector<double> dist_list(graph_size);
  202. VertexIndexMap graph_indices = boost::get(boost::vertex_index,
  203. original_graph_);
  204. PredecessorMap pred_map(&pred_list[0], graph_indices);
  205. DistanceMap dist_map(&dist_list[0], graph_indices);
  206. // Find the shortest path
  207. boost::dijkstra_shortest_paths(original_graph_,
  208. source_,
  209. boost::predecessor_map(pred_map)
  210. .distance_map(dist_map));
  211. // Add the new path
  212. for (Vertex u = sink_, v = pred_map[u];
  213. u != v; u = v, v = pred_map[v])
  214. {
  215. i_shortest_paths_[i][u].insert(v);
  216. }
  217. }
  218. else
  219. {
  220. // Prepare variables for path finding
  221. size_t graph_size = boost::num_vertices(copied_graph_);
  222. Vertex root_vertex = original_to_copy_[source_];
  223. std::vector<Vertex> pred_list(graph_size);
  224. std::vector<double> dist_list(graph_size);
  225. VertexIndexMap graph_indices = boost::get(boost::vertex_index,
  226. copied_graph_);
  227. EdgeWeightMap weight_map = boost::get(boost::edge_weight,
  228. copied_graph_);
  229. PredecessorMap pred_map(&pred_list[0], graph_indices);
  230. DistanceMap dist_map(&dist_list[0], graph_indices);
  231. // Find the shortest path
  232. boost::bellman_ford_shortest_paths(copied_graph_,
  233. graph_size,
  234. boost::root_vertex(root_vertex)
  235. .weight_map(weight_map)
  236. .predecessor_map(pred_map)
  237. .distance_map(dist_map));
  238. // Add the new path (the given path is in the copied graph, so the
  239. // vertices need to be mapped to the original graph)
  240. Vertex sink_copy = original_to_copy_[sink_];
  241. for (Vertex u_copy = sink_copy, v_copy = pred_map[u_copy];
  242. u_copy != v_copy; u_copy = v_copy, v_copy = pred_map[v_copy])
  243. {
  244. Vertex u_original = copy_to_original_[u_copy];
  245. Vertex v_original = copy_to_original_[v_copy];
  246. // Ignore loops
  247. if (u_original == v_original)
  248. {
  249. continue;
  250. }
  251. i_shortest_paths_[i][u_original].insert(v_original);
  252. }
  253. }
  254. }
  255. void KShortestPaths::UpdateEdges()
  256. {
  257. // Remove the old edges, needs to be done without any iterator since
  258. // the removal invalidates any iterators
  259. for (auto edge : edges_to_remove_)
  260. {
  261. boost::remove_edge(edge.first, edge.second, copied_graph_);
  262. }
  263. edges_to_remove_.clear();
  264. // Add the new edges, needs to be done without any iterator since
  265. // the addition invalidates any iterators
  266. for (auto edge : edges_to_add_)
  267. {
  268. boost::add_edge(edge.first.first, edge.first.second,
  269. edge.second, copied_graph_);
  270. }
  271. edges_to_add_.clear();
  272. }
  273. void KShortestPaths::QueueAddEdge(Vertex source, Vertex target, double weight)
  274. {
  275. edges_to_add_.push_back(
  276. std::pair<std::pair<Vertex, Vertex>, double>(
  277. std::pair<Vertex, Vertex>(source, target), weight));
  278. }
  279. void KShortestPaths::QueueRemoveEdge(Vertex source, Vertex target)
  280. {
  281. edges_to_remove_.push_back(std::pair<Vertex, Vertex>(source, target));
  282. }
  283. }