KShortestPaths.cpp 17 KB

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