274 CHECK_GE(k, 0) <<
"k must be nonnegative. Input value: " << k;
275 CHECK_NE(k, 0) <<
"k cannot be zero: you are requesting zero paths!";
277 CHECK_GT(
graph.num_nodes(), 0) <<
"The graph is empty: it has no nodes";
278 CHECK_GT(
graph.num_arcs(), 0) <<
"The graph is empty: it has no arcs";
280 CHECK_GE(source, 0) <<
"The source node must be nonnegative. Input value: "
282 CHECK_LT(source,
graph.num_nodes())
283 <<
"The source node must be a valid node. Input value: " << source
284 <<
". Number of nodes in the input graph: " <<
graph.num_nodes();
285 CHECK_GE(destination, 0)
286 <<
"The source node must be nonnegative. Input value: " << destination;
287 CHECK_LT(destination,
graph.num_nodes())
288 <<
"The destination node must be a valid node. Input value: "
290 <<
". Number of nodes in the input graph: " <<
graph.num_nodes();
296 std::tuple<std::vector<NodeIndex>,
PathDistance> first_path =
298 if (std::get<0>(first_path).empty())
return paths;
299 paths.paths.push_back(std::move(std::get<0>(first_path)));
300 paths.distances.push_back(std::get<1>(first_path));
309 std::priority_queue<internal::PathWithPriority>>
315 VLOG(1) <<
"k: " << k;
318 const absl::Span<NodeIndex> last_shortest_path =
319 absl::MakeSpan(paths.paths.back());
324 for (
int spur_node_position = 0;
325 spur_node_position < last_shortest_path.size() - 1;
326 ++spur_node_position) {
327 VLOG(4) <<
" spur_node_position: " << spur_node_position;
328 VLOG(4) <<
" last_shortest_path: "
329 << absl::StrJoin(last_shortest_path,
" - ") <<
" ("
330 << last_shortest_path.size() <<
")";
331 if (spur_node_position > 0) {
332 DCHECK_NE(last_shortest_path[spur_node_position], source);
334 DCHECK_NE(last_shortest_path[spur_node_position], destination);
336 const NodeIndex spur_node = last_shortest_path[spur_node_position];
340 const absl::Span<NodeIndex> root_path =
341 last_shortest_path.subspan(0, spur_node_position + 1);
342 DCHECK_GE(root_path.length(), 1);
343 DCHECK_NE(root_path.back(), destination);
354 std::vector<PathDistance> arc_lengths_for_detour =
arc_lengths;
355 for (absl::Span<const NodeIndex> previous_path : paths.paths) {
361 if (previous_path.size() <= root_path.length())
continue;
362 const bool has_same_prefix_as_root_path = std::equal(
363 root_path.begin(), root_path.end(), previous_path.begin(),
364 previous_path.begin() + root_path.length());
365 if (!has_same_prefix_as_root_path)
continue;
367 const ArcIndex after_spur_node_arc =
369 previous_path[spur_node_position + 1]);
370 VLOG(4) <<
" after_spur_node_arc: " <<
graph.Tail(after_spur_node_arc)
371 <<
" - " <<
graph.Head(after_spur_node_arc) <<
" (" << source
372 <<
" - " << destination <<
")";
373 arc_lengths_for_detour[after_spur_node_arc] =
381 for (
int node_position = 0; node_position < spur_node_position;
383 for (
const int arc :
graph.OutgoingArcs(root_path[node_position])) {
387 VLOG(3) <<
" arc_lengths_for_detour: "
388 << absl::StrJoin(arc_lengths_for_detour,
" - ");
393 std::tuple<std::vector<NodeIndex>,
PathDistance> detour_path =
395 spur_node, destination);
397 if (std::get<0>(detour_path).empty()) {
401 VLOG(2) <<
" detour_path: "
402 << absl::StrJoin(std::get<0>(detour_path),
" - ") <<
" ("
403 << std::get<0>(detour_path).size()
404 <<
"): " << std::get<1>(detour_path);
405 std::vector<NodeIndex> spur_path = std::move(std::get<0>(detour_path));
406 if (ABSL_PREDICT_FALSE(spur_path.empty()))
continue;
409 CHECK_EQ(root_path.back(), spur_path.front());
410 CHECK_EQ(spur_node, spur_path.front());
412 if (spur_path.size() == 1) {
413 CHECK_EQ(spur_path.front(), destination);
418 const bool root_path_leads_to_spur_path = absl::c_any_of(
419 graph.OutgoingArcs(root_path.back()),
420 [&
graph, node_after_spur_in_spur_path =
421 *(spur_path.begin() + 1)](
const ArcIndex arc_index) {
422 return graph.Head(arc_index) == node_after_spur_in_spur_path;
424 CHECK(root_path_leads_to_spur_path);
429 for (absl::Span<const NodeIndex> previous_path : paths.paths) {
430 if (previous_path.size() <= spur_node_position + 1)
continue;
431 const bool has_same_prefix_as_root_path = std::equal(
432 root_path.begin(), root_path.end(), previous_path.begin(),
433 previous_path.begin() + root_path.length());
434 if (has_same_prefix_as_root_path) {
435 CHECK_NE(spur_path[1], previous_path[spur_node_position + 1])
436 <<
"Forbidden arc " << previous_path[spur_node_position]
437 <<
" - " << previous_path[spur_node_position + 1]
438 <<
" is present in the spur path "
439 << absl::StrJoin(spur_path,
" - ");
445 std::vector<NodeIndex> new_path;
446 absl::c_copy(root_path.subspan(0, spur_node_position),
447 std::back_inserter(new_path));
448 absl::c_copy(spur_path, std::back_inserter(new_path));
450 DCHECK_EQ(new_path.front(), source);
451 DCHECK_EQ(new_path.back(), destination);
456 absl::flat_hash_set<NodeIndex> visited_nodes(new_path.begin(),
458 CHECK_EQ(visited_nodes.size(), new_path.size());
474 const bool is_new_path_already_known =
475 std::any_of(variant_path_queue.container().cbegin(),
476 variant_path_queue.container().cend(),
478 return element.path() == new_path;
480 if (is_new_path_already_known)
continue;
484 VLOG(5) <<
" New potential path generated: "
485 << absl::StrJoin(new_path,
" - ") <<
" (" << new_path.size()
487 VLOG(5) <<
" Root: " << absl::StrJoin(root_path,
" - ") <<
" ("
488 << root_path.size() <<
")";
489 VLOG(5) <<
" Spur: " << absl::StrJoin(spur_path,
" - ") <<
" ("
490 << spur_path.size() <<
")";
491 variant_path_queue.emplace(
492 path_length, std::move(new_path));
499 if (variant_path_queue.empty())
break;
502 variant_path_queue.top();
503 VLOG(5) <<
"> New path generated: "
504 << absl::StrJoin(next_shortest_path.
path(),
" - ") <<
" ("
505 << next_shortest_path.
path().size() <<
")";
506 paths.paths.emplace_back(next_shortest_path.
path());
507 paths.distances.push_back(next_shortest_path.
priority());
508 variant_path_queue.pop();