14#ifndef OR_TOOLS_GRAPH_DAG_CONSTRAINED_SHORTEST_PATH_H_
15#define OR_TOOLS_GRAPH_DAG_CONSTRAINED_SHORTEST_PATH_H_
22#include "absl/algorithm/container.h"
23#include "absl/base/log_severity.h"
24#include "absl/log/check.h"
25#include "absl/strings/str_format.h"
26#include "absl/types/span.h"
77 absl::Span<const ArcWithLengthAndResources> arcs_with_length_and_resources,
78 int source,
int destination,
const std::vector<double>& max_resources);
83template <
class GraphType>
88 std::vector<typename GraphType::ArcIndex>
arc_path;
89 std::vector<typename GraphType::NodeIndex>
96template <
class GraphType>
99 using NodeIndex =
typename GraphType::NodeIndex;
100 using ArcIndex =
typename GraphType::ArcIndex;
128 const GraphType* graph,
const std::vector<double>* arc_lengths,
129 const std::vector<std::vector<double>>* arc_resources,
130 absl::Span<const NodeIndex> topological_order,
131 absl::Span<const NodeIndex> sources,
132 absl::Span<const NodeIndex> destinations,
133 const std::vector<double>* max_resources,
134 int max_num_created_labels = 1e9);
144 return lengths_from_sources_[FORWARD].size() +
145 lengths_from_sources_[BACKWARD].size();
154 inline static Direction Reverse(Direction d) {
155 return d == FORWARD ? BACKWARD : FORWARD;
166 void RunHalfConstrainedShortestPathOnDag(
167 const GraphType& reverse_graph, absl::Span<const double> arc_lengths,
168 absl::Span<
const std::vector<double>> arc_resources,
169 absl::Span<
const std::vector<double>> min_arc_resources,
170 absl::Span<const double> max_resources,
int max_num_created_labels,
171 std::vector<double>& lengths_from_sources,
172 std::vector<std::vector<double>>& resources_from_sources,
173 std::vector<ArcIndex>& incoming_arc_indices_from_sources,
174 std::vector<int>& incoming_label_indices_from_sources,
175 std::vector<int>& first_label, std::vector<int>& num_labels);
181 const GraphType& graph, absl::Span<const double> arc_lengths,
182 absl::Span<
const std::vector<double>> arc_resources,
183 absl::Span<const double> max_resources,
184 const std::vector<NodeIndex> sub_node_indices[2],
185 const std::vector<double> lengths_from_sources[2],
186 const std::vector<std::vector<double>> resources_from_sources[2],
187 const std::vector<int> first_label[2],
188 const std::vector<int> num_labels[2], LabelPair& best_label_pair);
193 std::vector<ArcIndex> ArcPathTo(
194 int best_label_index,
195 absl::Span<const ArcIndex> incoming_arc_indices_from_sources,
196 absl::Span<const int> incoming_label_indices_from_sources)
const;
199 std::vector<NodeIndex> NodePathImpliedBy(absl::Span<const ArcIndex> arc_path,
200 const GraphType& graph)
const;
202 static constexpr double kTolerance = 1e-6;
204 const GraphType*
const graph_;
205 const std::vector<double>*
const arc_lengths_;
206 const std::vector<std::vector<double>>*
const arc_resources_;
207 const std::vector<double>*
const max_resources_;
208 absl::Span<const NodeIndex> sources_;
209 absl::Span<const NodeIndex> destinations_;
210 const int num_resources_;
214 std::optional<NodeIndex> source_is_destination_ = std::nullopt;
226 GraphType sub_reverse_graph_[2];
227 std::vector<std::vector<double>> sub_arc_resources_[2];
233 std::vector<NodeIndex> sub_full_arc_indices_[2];
239 std::vector<NodeIndex> sub_node_indices_[2];
246 std::vector<bool> sub_is_source_[2][2];
252 std::vector<std::vector<double>> sub_min_arc_resources_[2];
254 int max_num_created_labels_[2];
264 std::vector<double> lengths_from_sources_[2];
265 std::vector<std::vector<double>> resources_from_sources_[2];
266 std::vector<ArcIndex> incoming_arc_indices_from_sources_[2];
267 std::vector<int> incoming_label_indices_from_sources_[2];
268 std::vector<int> node_first_label_[2];
269 std::vector<int> node_num_labels_[2];
281template <
class GraphType>
284 const GraphType* graph,
const std::vector<double>* arc_lengths,
285 const std::vector<std::vector<double>>* arc_resources,
286 absl::Span<const NodeIndex> topological_order,
287 absl::Span<const NodeIndex> sources,
288 absl::Span<const NodeIndex> destinations,
289 const std::vector<double>* max_resources,
int max_num_created_labels)
291 arc_lengths_(arc_lengths),
292 arc_resources_(arc_resources),
293 max_resources_(max_resources),
295 destinations_(destinations),
296 num_resources_(max_resources->size()) {
297 CHECK(graph_ !=
nullptr);
298 CHECK(arc_lengths_ !=
nullptr);
299 CHECK(arc_resources_ !=
nullptr);
300 CHECK(!sources_.empty());
301 CHECK(!destinations_.empty());
302 CHECK(max_resources_ !=
nullptr);
303 CHECK(!max_resources_->empty())
304 <<
"max_resources cannot be empty. Use "
305 "ortools/graph/dag_shortest_path.h instead";
307 CHECK_EQ(arc_lengths->size(), graph->num_arcs());
308 CHECK_EQ(arc_resources->size(), max_resources->size());
309 for (absl::Span<const double> arcs_resource : *arc_resources) {
310 CHECK_EQ(arcs_resource.size(), graph->num_arcs());
311 for (
const double arc_resource : arcs_resource) {
312 CHECK(arc_resource >= 0 &&
313 arc_resource != std::numeric_limits<double>::infinity() &&
314 !std::isnan(arc_resource))
315 << absl::StrFormat(
"resource cannot be negative nor +inf nor NaN");
318 for (
const double arc_length : *arc_lengths) {
319 CHECK(arc_length != -std::numeric_limits<double>::infinity() &&
320 !std::isnan(arc_length))
321 << absl::StrFormat(
"length cannot be -inf nor NaN");
324 <<
"Invalid topological order";
325 for (
const double max_resource : *max_resources) {
326 CHECK(max_resource >= 0 &&
327 max_resource != std::numeric_limits<double>::infinity() &&
328 !std::isnan(max_resource))
330 "max_resource cannot be negative not +inf nor NaN");
333 std::vector<bool> is_source(graph->num_nodes(),
false);
335 is_source[source] =
true;
337 for (
const NodeIndex destination : destinations) {
338 if (is_source[destination]) {
339 source_is_destination_ = destination;
345 const GraphType* full_graph[2];
346 const std::vector<std::vector<double>>* full_arc_resources[2];
347 absl::Span<const NodeIndex> full_topological_order[2];
348 absl::Span<const NodeIndex> full_sources[2];
350 const int num_nodes = graph->num_nodes();
351 const int num_arcs = graph->num_arcs();
352 full_graph[FORWARD] = graph;
353 full_arc_resources[FORWARD] = arc_resources;
354 full_topological_order[FORWARD] = topological_order;
355 full_sources[FORWARD] = sources;
357 GraphType full_backward_graph(num_nodes, num_arcs);
358 for (
ArcIndex arc_index = 0; arc_index < num_arcs; ++arc_index) {
359 full_backward_graph.AddArc(graph->Head(arc_index), graph->Tail(arc_index));
361 std::vector<ArcIndex> full_permutation;
362 full_backward_graph.Build(&full_permutation);
363 const std::vector<ArcIndex> full_inverse_arc_indices =
365 std::vector<std::vector<double>> backward_arc_resources(num_resources_);
366 for (
int r = 0; r < num_resources_; ++r) {
367 backward_arc_resources[r] = (*arc_resources)[r];
370 std::vector<NodeIndex> full_backward_topological_order;
371 full_backward_topological_order.reserve(num_nodes);
372 for (
int i = num_nodes - 1; i >= 0; --i) {
373 full_backward_topological_order.push_back(topological_order[i]);
375 full_graph[BACKWARD] = &full_backward_graph;
376 full_arc_resources[BACKWARD] = &backward_arc_resources;
377 full_topological_order[BACKWARD] = full_backward_topological_order;
378 full_sources[BACKWARD] = destinations;
382 std::vector<std::vector<double>> full_min_arc_resources[2];
383 for (
const Direction dir : {FORWARD, BACKWARD}) {
384 full_min_arc_resources[dir].reserve(num_resources_);
385 std::vector<double> full_arc_resource = full_arc_resources[dir]->front();
387 full_graph[dir], &full_arc_resource, full_topological_order[dir]);
388 for (
int r = 0; r < num_resources_; ++r) {
389 full_arc_resource = (*(full_arc_resources[dir]))[r];
391 full_min_arc_resources[dir].push_back(shortest_paths_on_dag.
LengthTo());
396 std::vector<bool> is_reachable(num_nodes,
true);
397 std::vector<NodeIndex> sub_topological_order;
398 sub_topological_order.reserve(num_nodes);
399 for (
const NodeIndex node_index : topological_order) {
400 for (
int r = 0; r < num_resources_; ++r) {
401 if (full_min_arc_resources[FORWARD][r][node_index] +
402 full_min_arc_resources[BACKWARD][r][node_index] >
403 (*max_resources)[r]) {
404 is_reachable[node_index] =
false;
408 if (is_reachable[node_index]) {
409 sub_topological_order.push_back(node_index);
412 const int reachable_node_count = sub_topological_order.size();
416 max_num_created_labels_[BACKWARD] = max_num_created_labels / 2 + 1;
417 max_num_created_labels_[FORWARD] =
418 max_num_created_labels - max_num_created_labels / 2 + 1;
427 std::vector<double> path_count[2];
428 for (
const Direction dir : {FORWARD, BACKWARD}) {
429 const GraphType& reverse_full_graph = *(full_graph[Reverse(dir)]);
430 path_count[dir].resize(num_nodes);
431 for (
const NodeIndex source : full_sources[dir]) {
432 ++path_count[dir][source];
434 for (
const NodeIndex to : full_topological_order[dir]) {
435 if (!is_reachable[
to])
continue;
436 for (
const ArcIndex arc : reverse_full_graph.OutgoingArcs(
to)) {
437 const NodeIndex from = reverse_full_graph.Head(arc);
438 if (!is_reachable[from])
continue;
439 path_count[dir][
to] += path_count[dir][from];
443 for (
const NodeIndex node_index : sub_topological_order) {
444 if (path_count[FORWARD][node_index] > path_count[BACKWARD][node_index]) {
449 if (mid_index == reachable_node_count) {
450 mid_index = reachable_node_count / 2;
454 for (
const Direction dir : {FORWARD, BACKWARD}) {
455 absl::Span<const NodeIndex>
const sub_nodes =
457 ? absl::MakeSpan(sub_topological_order).subspan(0, mid_index)
458 : absl::MakeSpan(sub_topological_order)
459 .subspan(mid_index, reachable_node_count - mid_index);
460 sub_node_indices_[dir].assign(num_nodes, -1);
461 sub_min_arc_resources_[dir].resize(num_resources_);
462 for (
int r = 0; r < num_resources_; ++r) {
463 sub_min_arc_resources_[dir][r].resize(sub_nodes.size());
465 for (
NodeIndex i = 0; i < sub_nodes.size(); ++i) {
467 dir == FORWARD ? i : sub_nodes.size() - 1 - i;
468 sub_node_indices_[dir][sub_nodes[i]] = sub_node_index;
469 for (
int r = 0; r < num_resources_; ++r) {
470 sub_min_arc_resources_[dir][r][sub_node_index] =
471 full_min_arc_resources[Reverse(dir)][r][sub_nodes[i]];
478 const int sub_arcs_count = num_arcs + full_sources[dir].size();
479 sub_reverse_graph_[dir] = GraphType(sub_nodes.size() + 1, sub_arcs_count);
480 sub_arc_resources_[dir].resize(num_resources_);
481 for (
int r = 0; r < num_resources_; ++r) {
482 sub_arc_resources_[dir][r].reserve(sub_arcs_count);
484 sub_full_arc_indices_[dir].reserve(sub_arcs_count);
485 const GraphType& reverse_full_graph = *(full_graph[Reverse(dir)]);
486 for (
ArcIndex arc_index = 0; arc_index < num_arcs; ++arc_index) {
488 sub_node_indices_[dir][reverse_full_graph.Tail(arc_index)];
490 sub_node_indices_[dir][reverse_full_graph.Head(arc_index)];
491 if (from == -1 ||
to == -1) {
494 sub_reverse_graph_[dir].AddArc(from,
to);
496 if (dir == FORWARD && !full_inverse_arc_indices.empty()) {
497 sub_full_arc_index = full_inverse_arc_indices[arc_index];
499 sub_full_arc_index = arc_index;
501 for (
int r = 0; r < num_resources_; ++r) {
502 sub_arc_resources_[dir][r].push_back(
503 (*arc_resources_)[r][sub_full_arc_index]);
505 sub_full_arc_indices_[dir].push_back(sub_full_arc_index);
507 for (
const NodeIndex source : full_sources[dir]) {
508 const NodeIndex sub_source = sub_node_indices_[dir][source];
509 if (sub_source == -1) {
512 sub_reverse_graph_[dir].AddArc(sub_source, sub_nodes.size());
513 for (
int r = 0; r < num_resources_; ++r) {
514 sub_arc_resources_[dir][r].push_back(0.0);
516 sub_full_arc_indices_[dir].push_back(-1);
518 std::vector<ArcIndex> sub_permutation;
519 sub_reverse_graph_[dir].Build(&sub_permutation);
520 for (
int r = 0; r < num_resources_; ++r) {
529 for (
const Direction dir : {FORWARD, BACKWARD}) {
530 resources_from_sources_[dir].resize(num_resources_);
531 node_first_label_[dir].resize(sub_reverse_graph_[dir].size());
532 node_num_labels_[dir].resize(sub_reverse_graph_[dir].size());
536template <
class GraphType>
538 GraphType>::RunConstrainedShortestPathOnDag() {
539 if (source_is_destination_.has_value()) {
541 .length = 0, .arc_path = {}, .node_path = {*source_is_destination_}};
544 std::vector<double> sub_arc_lengths[2];
545 for (
const Direction dir : {FORWARD, BACKWARD}) {
546 sub_arc_lengths[dir].reserve(sub_reverse_graph_[dir].num_arcs());
547 for (ArcIndex sub_arc_index = 0;
548 sub_arc_index < sub_reverse_graph_[dir].num_arcs(); ++sub_arc_index) {
549 const ArcIndex arc_index = sub_full_arc_indices_[dir][sub_arc_index];
550 if (arc_index == -1) {
551 sub_arc_lengths[dir].push_back(0.0);
554 sub_arc_lengths[dir].push_back((*arc_lengths_)[arc_index]);
560 search_threads.StartWorkers();
561 for (
const Direction dir : {FORWARD, BACKWARD}) {
562 search_threads.Schedule([
this, dir, &sub_arc_lengths]() {
563 RunHalfConstrainedShortestPathOnDag(
564 sub_reverse_graph_[dir],
565 sub_arc_lengths[dir],
566 sub_arc_resources_[dir],
567 sub_min_arc_resources_[dir],
569 max_num_created_labels_[dir],
570 lengths_from_sources_[dir],
571 resources_from_sources_[dir],
573 incoming_arc_indices_from_sources_[dir],
575 incoming_label_indices_from_sources_[dir],
576 node_first_label_[dir],
577 node_num_labels_[dir]);
583 LabelPair best_label_pair = {
584 .length = std::numeric_limits<double>::infinity(),
585 .label_index = {-1, -1}};
586 for (
const Direction dir : {FORWARD, BACKWARD}) {
587 absl::Span<const NodeIndex> destinations =
588 dir == FORWARD ? destinations_ : sources_;
589 for (
const NodeIndex dst : destinations) {
590 const NodeIndex sub_dst = sub_node_indices_[dir][dst];
594 const int num_labels_dst = node_num_labels_[dir][sub_dst];
595 if (num_labels_dst == 0) {
598 const int first_label_dst = node_first_label_[dir][sub_dst];
599 for (
int label_index = first_label_dst;
600 label_index < first_label_dst + num_labels_dst; ++label_index) {
601 const double length_dst = lengths_from_sources_[dir][label_index];
602 if (length_dst < best_label_pair.length) {
603 best_label_pair.length = length_dst;
604 best_label_pair.label_index[dir] = label_index;
610 const ArcIndex merging_arc_index = MergeHalfRuns(
611 *graph_, *arc_lengths_,
615 lengths_from_sources_,
616 resources_from_sources_,
618 node_num_labels_, best_label_pair);
620 std::vector<ArcIndex> arc_path;
621 for (
const Direction dir : {FORWARD, BACKWARD}) {
622 for (
const ArcIndex sub_arc_index : ArcPathTo(
623 best_label_pair.label_index[dir],
625 incoming_arc_indices_from_sources_[dir],
627 incoming_label_indices_from_sources_[dir])) {
628 const ArcIndex arc_index = sub_full_arc_indices_[dir][sub_arc_index];
629 if (arc_index == -1) {
632 arc_path.push_back(arc_index);
634 if (dir == FORWARD && merging_arc_index != -1) {
635 absl::c_reverse(arc_path);
636 arc_path.push_back(merging_arc_index);
641 for (
const Direction dir : {FORWARD, BACKWARD}) {
642 lengths_from_sources_[dir].clear();
643 for (
int r = 0; r < num_resources_; ++r) {
644 resources_from_sources_[dir][r].clear();
646 incoming_arc_indices_from_sources_[dir].clear();
647 incoming_label_indices_from_sources_[dir].clear();
649 return {.length = best_label_pair.length,
650 .arc_path = arc_path,
654template <
class GraphType>
657 const GraphType& reverse_graph, absl::Span<const double> arc_lengths,
658 absl::Span<
const std::vector<double>> arc_resources,
659 absl::Span<
const std::vector<double>> min_arc_resources,
660 absl::Span<const double> max_resources,
661 const int max_num_created_labels,
662 std::vector<double>& lengths_from_sources,
663 std::vector<std::vector<double>>& resources_from_sources,
664 std::vector<ArcIndex>& incoming_arc_indices_from_sources,
665 std::vector<int>& incoming_label_indices_from_sources,
666 std::vector<int>& first_label, std::vector<int>& num_labels) {
668 const NodeIndex source_node = reverse_graph.num_nodes() - 1;
669 first_label[source_node] = 0;
670 num_labels[source_node] = 1;
671 lengths_from_sources.push_back(0);
672 for (
int r = 0; r < num_resources_; ++r) {
673 resources_from_sources[r].push_back(0);
675 incoming_arc_indices_from_sources.push_back(-1);
676 incoming_label_indices_from_sources.push_back(-1);
678 std::vector<double> lengths_to;
679 std::vector<std::vector<double>> resources_to(num_resources_);
680 std::vector<ArcIndex> incoming_arc_indices_to;
681 std::vector<int> incoming_label_indices_to;
682 std::vector<int> label_indices_to;
683 std::vector<double> resources(num_resources_);
686 for (
int r = 0; r < num_resources_; ++r) {
687 resources_to[r].clear();
689 incoming_arc_indices_to.clear();
690 incoming_label_indices_to.clear();
691 for (
const ArcIndex reverse_arc_index : reverse_graph.OutgoingArcs(
to)) {
692 const NodeIndex from = reverse_graph.Head(reverse_arc_index);
693 const double arc_length = arc_lengths[reverse_arc_index];
694 DCHECK(arc_length != -std::numeric_limits<double>::infinity());
695 if (arc_length == std::numeric_limits<double>::infinity()) {
698 for (
int label_index = first_label[from];
699 label_index < first_label[from] + num_labels[from]; ++label_index) {
700 bool path_is_feasible =
true;
701 for (
int r = 0; r < num_resources_; ++r) {
702 DCHECK_GE(arc_resources[r][reverse_arc_index], 0.0);
703 resources[r] = resources_from_sources[r][label_index] +
704 arc_resources[r][reverse_arc_index];
705 if (resources[r] + min_arc_resources[r][
to] > max_resources[r]) {
706 path_is_feasible =
false;
710 if (!path_is_feasible) {
713 lengths_to.push_back(lengths_from_sources[label_index] + arc_length);
714 for (
int r = 0; r < num_resources_; ++r) {
715 resources_to[r].push_back(resources[r]);
717 incoming_arc_indices_to.push_back(reverse_arc_index);
718 incoming_label_indices_to.push_back(label_index);
722 label_indices_to.clear();
723 label_indices_to.reserve(lengths_to.size());
724 for (
int i = 0;
i < lengths_to.size(); ++
i) {
725 label_indices_to.push_back(i);
727 absl::c_sort(label_indices_to, [&](
const int i,
const int j) {
728 if (lengths_to[i] < lengths_to[j])
return true;
729 if (lengths_to[i] > lengths_to[j])
return false;
730 for (
int r = 0; r < num_resources_; ++r) {
731 if (resources_to[r][i] < resources_to[r][j])
return true;
732 if (resources_to[r][i] > resources_to[r][j])
return false;
737 first_label[
to] = lengths_from_sources.size();
738 int& num_labels_to = num_labels[
to];
742 for (
int i = 0;
i < label_indices_to.size(); ++
i) {
744 const int label_i_index = label_indices_to[
i];
745 bool label_i_is_dominated =
false;
746 for (
int j = 0; j <
i - 1; ++j) {
747 const int label_j_index = label_indices_to[j];
748 if (lengths_to[label_i_index] <= lengths_to[label_j_index])
continue;
749 bool label_j_dominates_label_i =
true;
750 for (
int r = 0; r < num_resources_; ++r) {
751 if (resources_to[r][label_i_index] <=
752 resources_to[r][label_j_index]) {
753 label_j_dominates_label_i =
false;
757 if (label_j_dominates_label_i) {
758 label_i_is_dominated =
true;
762 if (label_i_is_dominated)
continue;
763 lengths_from_sources.push_back(lengths_to[label_i_index]);
764 for (
int r = 0; r < num_resources_; ++r) {
765 resources_from_sources[r].push_back(resources_to[r][label_i_index]);
767 incoming_arc_indices_from_sources.push_back(
768 incoming_arc_indices_to[label_i_index]);
769 incoming_label_indices_from_sources.push_back(
770 incoming_label_indices_to[label_i_index]);
772 if (lengths_from_sources.size() >= max_num_created_labels) {
779template <
class GraphType>
780typename GraphType::ArcIndex
781ConstrainedShortestPathsOnDagWrapper<GraphType>::MergeHalfRuns(
782 const GraphType& graph, absl::Span<const double> arc_lengths,
783 absl::Span<
const std::vector<double>> arc_resources,
784 absl::Span<const double> max_resources,
785 const std::vector<NodeIndex> sub_node_indices[2],
786 const std::vector<double> lengths_from_sources[2],
787 const std::vector<std::vector<double>> resources_from_sources[2],
788 const std::vector<int> first_label[2],
const std::vector<int> num_labels[2],
789 LabelPair& best_label_pair) {
790 const std::vector<NodeIndex>& forward_sub_node_indices =
791 sub_node_indices[FORWARD];
792 absl::Span<const double> forward_lengths = lengths_from_sources[FORWARD];
793 const std::vector<std::vector<double>>& forward_resources =
794 resources_from_sources[FORWARD];
795 absl::Span<const int> forward_first_label = first_label[FORWARD];
796 absl::Span<const int> forward_num_labels = num_labels[FORWARD];
797 const std::vector<NodeIndex>& backward_sub_node_indices =
798 sub_node_indices[BACKWARD];
799 absl::Span<const double> backward_lengths = lengths_from_sources[BACKWARD];
800 const std::vector<std::vector<double>>& backward_resources =
801 resources_from_sources[BACKWARD];
802 absl::Span<const int> backward_first_label = first_label[BACKWARD];
803 absl::Span<const int> backward_num_labels = num_labels[BACKWARD];
804 ArcIndex merging_arc_index = -1;
805 for (ArcIndex arc_index = 0; arc_index < graph.num_arcs(); ++arc_index) {
806 const NodeIndex sub_from = forward_sub_node_indices[graph.Tail(arc_index)];
807 if (sub_from == -1) {
810 const NodeIndex sub_to = backward_sub_node_indices[graph.Head(arc_index)];
814 const int num_labels_from = forward_num_labels[sub_from];
815 if (num_labels_from == 0) {
818 const int num_labels_to = backward_num_labels[sub_to];
819 if (num_labels_to == 0) {
822 const double arc_length = arc_lengths[arc_index];
823 DCHECK(arc_length != -std::numeric_limits<double>::infinity());
824 if (arc_length == std::numeric_limits<double>::infinity()) {
827 const int first_label_from = forward_first_label[sub_from];
828 const int first_label_to = backward_first_label[sub_to];
829 for (
int label_to_index = first_label_to;
830 label_to_index < first_label_to + num_labels_to; ++label_to_index) {
831 const double length_to = backward_lengths[label_to_index];
832 for (
int label_from_index = first_label_from;
833 label_from_index < first_label_from + num_labels_from;
834 ++label_from_index) {
835 const double length_from = forward_lengths[label_from_index];
836 if (length_from + arc_length + length_to >= best_label_pair.length) {
839 bool path_is_feasible =
true;
840 for (
int r = 0; r < num_resources_; ++r) {
841 DCHECK_GE(arc_resources[r][arc_index], 0.0);
842 if (forward_resources[r][label_from_index] +
843 arc_resources[r][arc_index] +
844 backward_resources[r][label_to_index] >
846 path_is_feasible =
false;
850 if (!path_is_feasible) {
853 best_label_pair.length = length_from + arc_length + length_to;
854 best_label_pair.label_index[FORWARD] = label_from_index;
855 best_label_pair.label_index[BACKWARD] = label_to_index;
856 merging_arc_index = arc_index;
860 return merging_arc_index;
863template <
class GraphType>
864std::vector<typename GraphType::ArcIndex>
865ConstrainedShortestPathsOnDagWrapper<GraphType>::ArcPathTo(
866 const int best_label_index,
867 absl::Span<const ArcIndex> incoming_arc_indices_from_sources,
868 absl::Span<const int> incoming_label_indices_from_sources)
const {
869 int current_label_index = best_label_index;
870 std::vector<ArcIndex> arc_path;
871 for (
int i = 0;
i < graph_->num_nodes(); ++
i) {
872 if (current_label_index == -1) {
875 arc_path.push_back(incoming_arc_indices_from_sources[current_label_index]);
876 current_label_index =
877 incoming_label_indices_from_sources[current_label_index];
882template <
typename GraphType>
883std::vector<typename GraphType::NodeIndex>
884ConstrainedShortestPathsOnDagWrapper<GraphType>::NodePathImpliedBy(
885 absl::Span<const ArcIndex> arc_path,
const GraphType& graph)
const {
886 if (arc_path.empty()) {
889 std::vector<NodeIndex> node_path;
890 node_path.reserve(arc_path.size() + 1);
891 for (
const ArcIndex arc_index : arc_path) {
892 node_path.push_back(graph.Tail(arc_index));
894 node_path.push_back(graph.Head(arc_path.back()));
902 std::vector<T> inverse_permutation(permutation.size());
903 if (!permutation.empty()) {
904 for (T i = 0;
i < permutation.size(); ++
i) {
905 inverse_permutation[permutation[
i]] =
i;
908 return inverse_permutation;
typename GraphType::NodeIndex NodeIndex
ConstrainedShortestPathsOnDagWrapper(const GraphType *graph, const std::vector< double > *arc_lengths, const std::vector< std::vector< double > > *arc_resources, absl::Span< const NodeIndex > topological_order, absl::Span< const NodeIndex > sources, absl::Span< const NodeIndex > destinations, const std::vector< double > *max_resources, int max_num_created_labels=1e9)
GraphPathWithLength< GraphType > RunConstrainedShortestPathOnDag()
typename GraphType::ArcIndex ArcIndex
double LengthTo(NodeIndex node) const
Returns the length of the shortest path from node's source to node.
void RunShortestPathOnDag(absl::Span< const NodeIndex > sources)
End of the interface. Below is the implementation.
std::vector< T > GetInversePermutation(const std::vector< T > &permutation)
In SWIG mode, we don't want anything besides these top-level includes.
absl::Status TopologicalOrderIsValid(const GraphType &graph, absl::Span< const typename GraphType::NodeIndex > topological_order)
BlossomGraph::NodeIndex NodeIndex
std::vector< typename GraphType::NodeIndex > NodePathImpliedBy(absl::Span< const typename GraphType::ArcIndex > arc_path, const GraphType &graph)
PathWithLength ConstrainedShortestPathsOnDag(const int num_nodes, absl::Span< const ArcWithLengthAndResources > arcs_with_length_and_resources, int source, int destination, const std::vector< double > &max_resources)
void Permute(const IntVector &permutation, Array *array_to_permute)
trees with all degrees equal to
std::vector< double > resources
std::vector< typename GraphType::ArcIndex > arc_path
std::vector< typename GraphType::NodeIndex > node_path