KShortestPaths4.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. //
  2. // Created by wrede on 24.06.16.
  3. //
  4. #include <boost/graph/named_function_params.hpp>
  5. #include <boost/graph/bellman_ford_shortest_paths.hpp>
  6. #include "KShortestPaths4.h"
  7. namespace algo
  8. {
  9. KShortestPaths4::KShortestPaths4(DirectedGraph graph, Vertex source, Vertex sink,
  10. size_t max_paths_count)
  11. {
  12. graph_ = graph;
  13. source_ = source;
  14. sink_ = sink;
  15. vertex_labels_ = VertexDistanceMap();
  16. vertex_distances_ = VertexDistanceMap();
  17. vertex_predecessors_ = VertexVertexMap();
  18. vertex_candidates_ = std::vector<Vertex>();
  19. i_shortest_paths_ = std::vector<VertexVertexMap>();
  20. max_paths_count_ = max_paths_count;
  21. total_paths_count_ = 0;
  22. total_paths_distance_ = 0.0;
  23. }
  24. void KShortestPaths4::Run()
  25. {
  26. Initialization();
  27. }
  28. void KShortestPaths4::Initialization()
  29. {
  30. // Find the first path with predecessors and distances
  31. size_t graph_size = boost::num_vertices(graph_);
  32. std::vector<Vertex> pred_list(graph_size);
  33. std::vector<double> dist_list(graph_size);
  34. VertexIndexMap graph_indices = boost::get(boost::vertex_index, graph_);
  35. EdgeWeightMap weight_map = boost::get(boost::edge_weight, graph_);
  36. PredecessorMap path_pred_map(&pred_list[0], graph_indices);
  37. DistanceMap path_dist_map(&dist_list[0], graph_indices);
  38. boost::bellman_ford_shortest_paths(graph_, graph_size,
  39. boost::root_vertex(source_)
  40. .weight_map(weight_map)
  41. .predecessor_map(path_pred_map)
  42. .distance_map(path_dist_map));
  43. double path_total_distance = path_dist_map[sink_];
  44. //TODO add the path to the i_shortest_paths_;
  45. // If only one path is needed the algorithm can terminate successful
  46. if (max_paths_count_ == 1) return; //TODO return with the found path
  47. // Store the vertices of the path that are the predecessor of the source vertex
  48. // and the successor of the sink vertex
  49. Vertex source_predecessor = source_;
  50. Vertex sink_successor = sink_;
  51. for (Vertex u = path_pred_map[sink_], v = path_pred_map[u]; u != v; u = v, v = path_pred_map[v])
  52. {
  53. if (v == sink_)
  54. {
  55. source_predecessor = u;
  56. break;
  57. }
  58. }
  59. sink_successor = path_pred_map[sink_];
  60. // Set the distance label for all vertices
  61. boost::graph_traits<DirectedGraph>::vertex_iterator vi, vi_end;
  62. for (boost::tie(vi, vi_end) = boost::vertices(graph_); vi != vi_end; ++vi)
  63. {
  64. double distance = path_dist_map[*vi];
  65. // If the vertex is not part of the spanning tree, set the distance to the total
  66. // distance of the path from source to sink
  67. if (path_pred_map[*vi] == *vi && vi != source_)
  68. {
  69. distance = path_total_distance;
  70. }
  71. vertex_labels_[*vi] = distance;
  72. }
  73. // Define the candidate list
  74. for (boost::tie(vi, vi_end) = boost::vertices(graph_); vi != vi_end; ++vi)
  75. {
  76. if (*vi == source_ || *vi == source_predecessor) continue;
  77. vertex_candidates_.push_back(*vi);
  78. }
  79. // For each candidate define the distance and predecessors
  80. EdgeWeightMap edge_weights = boost::get(boost::edge_weight, graph_);
  81. boost::graph_traits<DirectedGraph>::edge_descriptor ed;
  82. bool e_found;
  83. for (Vertex v : vertex_candidates_)
  84. {
  85. if (path_pred_map[v] == source_)
  86. {
  87. boost::tie(ed, e_found) = boost::edge(source_, v, graph_);
  88. vertex_distances_[v] = boost::get(edge_weights, ed) - vertex_labels_[v];
  89. vertex_predecessors_[v] = source_;
  90. }
  91. else
  92. {
  93. vertex_distances_[v] = std::numeric_limits<double>::max();
  94. vertex_predecessors_[v] = std::numeric_limits<size_t>::max();
  95. }
  96. }
  97. total_paths_count_ = 1;
  98. total_paths_distance_ = path_total_distance;
  99. InterlacingConstruction();
  100. }
  101. void KShortestPaths4::InterlacingConstruction()
  102. {
  103. // Find the vertex in the candidate list with the minimum distance
  104. Vertex min_distance_vertex = 0;
  105. size_t min_distance_index = 0;
  106. double min_distance = std::numeric_limits<double>::max();
  107. for (size_t i = 0; i < vertex_candidates_.size(); ++i)
  108. {
  109. Vertex v = vertex_candidates_[i];
  110. double distance = vertex_distances_[v];
  111. if (distance < min_distance)
  112. {
  113. min_distance_vertex = v;
  114. min_distance_index = i;
  115. min_distance = distance;
  116. }
  117. }
  118. if (min_distance == std::numeric_limits<double>::max())
  119. {
  120. NonFeasibleTermination();
  121. return;
  122. }
  123. // Add the distance to the vertex label and remove the vertex from the candidates
  124. vertex_labels_[min_distance_vertex] += min_distance;
  125. vertex_candidates_.erase(vertex_candidates_.begin() + min_distance_index);
  126. if (min_distance_vertex == sink_)
  127. {
  128. //TODO goto P_M+1 Definition
  129. }
  130. else
  131. {
  132. for (Vertex v : i_shortest_paths_[total_paths_count_ - 1])
  133. {
  134. if (min_distance_vertex == v)
  135. {
  136. NegativeInterlacing(min_distance_vertex);
  137. return;
  138. }
  139. }
  140. NeighborDistanceTest(min_distance_vertex);
  141. InterlacingConstruction();
  142. }
  143. }
  144. void KShortestPaths4::NeighborDistanceTest(Vertex r)
  145. {
  146. // Compute the distance to all neighbors and find the best fitting neighbor,
  147. // than save that neighbor and the new calculated distance
  148. EdgeWeightMap edge_weights = boost::get(boost::edge_weight, graph_);
  149. boost::graph_traits<DirectedGraph>::edge_iterator oei, oei_end;
  150. for (boost::tie(oei, oei_end) = boost::out_edges(r, graph_); oei != oei_end; ++oei)
  151. {
  152. Vertex j = boost::target(*oei, graph_);
  153. // Check if the vertex is a candidate
  154. if (Contains(vertex_candidates_, j))
  155. {
  156. // Calculate possible new edge weight for the candidate
  157. double delta = vertex_labels_[r] + edge_weights[*oei] - vertex_labels_[j];
  158. if (vertex_distances_[j] > delta)
  159. {
  160. vertex_distances_[j] = delta;
  161. vertex_predecessors_[j] = r;
  162. }
  163. }
  164. }
  165. }
  166. void KShortestPaths4::NegativeInterlacing(Vertex input)
  167. {
  168. // Find the path containing the specified vertex
  169. std::list<Vertex> path;
  170. for (auto p : i_shortest_paths_)
  171. {
  172. if (Contains(p, input) > 0)
  173. {
  174. path = p;
  175. break;
  176. }
  177. }
  178. // Iterate the path in reverse vertex order //TODO check for correct order
  179. Vertex j;
  180. bool found_input = false;
  181. bool is_last = false;
  182. for (auto vertex = path.rbegin(); vertex != path.rend(); ++vertex)
  183. {
  184. // Find the first vertex which is not a candidate
  185. if (!found_input)
  186. {
  187. if (*vertex == input)
  188. {
  189. found_input = true;
  190. }
  191. }
  192. else
  193. {
  194. j = *vertex;
  195. break;
  196. }
  197. }
  198. //TODO implement
  199. }
  200. void KShortestPaths4::FeasibleTermination()
  201. {
  202. //TODO implement
  203. }
  204. void KShortestPaths4::NonFeasibleTermination()
  205. {
  206. //TODO implement
  207. }
  208. bool KShortestPaths4::Contains(std::vector<Vertex>& vector, Vertex& element)
  209. {
  210. for (Vertex v : vector)
  211. {
  212. if (v == element)
  213. {
  214. return true;
  215. }
  216. }
  217. return false;
  218. }
  219. bool KShortestPaths4::Contains(std::list<Vertex>& list, Vertex& element)
  220. {
  221. for (Vertex v : list)
  222. {
  223. if (v == element)
  224. {
  225. return true;
  226. }
  227. }
  228. return false;
  229. }
  230. }