14#ifndef ORTOOLS_GRAPH_DAG_CONSTRAINED_SHORTEST_PATH_H_
15#define ORTOOLS_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 for (
const Direction dir : {FORWARD, BACKWARD}) {
561 search_threads.Schedule([
this, dir, &sub_arc_lengths]() {
562 RunHalfConstrainedShortestPathOnDag(
563 sub_reverse_graph_[dir],
564 sub_arc_lengths[dir],
565 sub_arc_resources_[dir],
566 sub_min_arc_resources_[dir],
568 max_num_created_labels_[dir],
569 lengths_from_sources_[dir],
570 resources_from_sources_[dir],
572 incoming_arc_indices_from_sources_[dir],
574 incoming_label_indices_from_sources_[dir],
575 node_first_label_[dir],
576 node_num_labels_[dir]);
582 LabelPair best_label_pair = {
583 .length = std::numeric_limits<double>::infinity(),
584 .label_index = {-1, -1}};
585 for (
const Direction dir : {FORWARD, BACKWARD}) {
586 absl::Span<const NodeIndex> destinations =
587 dir == FORWARD ? destinations_ : sources_;
588 for (
const NodeIndex dst : destinations) {
589 const NodeIndex sub_dst = sub_node_indices_[dir][dst];
593 const int num_labels_dst = node_num_labels_[dir][sub_dst];
594 if (num_labels_dst == 0) {
597 const int first_label_dst = node_first_label_[dir][sub_dst];
598 for (
int label_index = first_label_dst;
599 label_index < first_label_dst + num_labels_dst; ++label_index) {
600 const double length_dst = lengths_from_sources_[dir][label_index];
601 if (length_dst < best_label_pair.length) {
602 best_label_pair.length = length_dst;
603 best_label_pair.label_index[dir] = label_index;
609 const ArcIndex merging_arc_index = MergeHalfRuns(
610 *graph_, *arc_lengths_,
614 lengths_from_sources_,
615 resources_from_sources_,
617 node_num_labels_, best_label_pair);
619 std::vector<ArcIndex> arc_path;
620 for (
const Direction dir : {FORWARD, BACKWARD}) {
621 for (
const ArcIndex sub_arc_index : ArcPathTo(
622 best_label_pair.label_index[dir],
624 incoming_arc_indices_from_sources_[dir],
626 incoming_label_indices_from_sources_[dir])) {
627 const ArcIndex arc_index = sub_full_arc_indices_[dir][sub_arc_index];
628 if (arc_index == -1) {
631 arc_path.push_back(arc_index);
633 if (dir == FORWARD && merging_arc_index != -1) {
634 absl::c_reverse(arc_path);
635 arc_path.push_back(merging_arc_index);
640 for (
const Direction dir : {FORWARD, BACKWARD}) {
641 lengths_from_sources_[dir].clear();
642 for (
int r = 0; r < num_resources_; ++r) {
643 resources_from_sources_[dir][r].clear();
645 incoming_arc_indices_from_sources_[dir].clear();
646 incoming_label_indices_from_sources_[dir].clear();
648 return {.length = best_label_pair.length,
649 .arc_path = arc_path,
653template <
class GraphType>
656 const GraphType& reverse_graph, absl::Span<const double> arc_lengths,
657 absl::Span<
const std::vector<double>> arc_resources,
658 absl::Span<
const std::vector<double>> min_arc_resources,
659 absl::Span<const double> max_resources,
660 const int max_num_created_labels,
661 std::vector<double>& lengths_from_sources,
662 std::vector<std::vector<double>>& resources_from_sources,
663 std::vector<ArcIndex>& incoming_arc_indices_from_sources,
664 std::vector<int>& incoming_label_indices_from_sources,
665 std::vector<int>& first_label, std::vector<int>& num_labels) {
667 const NodeIndex source_node = reverse_graph.num_nodes() - 1;
668 first_label[source_node] = 0;
669 num_labels[source_node] = 1;
670 lengths_from_sources.push_back(0);
671 for (
int r = 0; r < num_resources_; ++r) {
672 resources_from_sources[r].push_back(0);
674 incoming_arc_indices_from_sources.push_back(-1);
675 incoming_label_indices_from_sources.push_back(-1);
677 std::vector<double> lengths_to;
678 std::vector<std::vector<double>> resources_to(num_resources_);
679 std::vector<ArcIndex> incoming_arc_indices_to;
680 std::vector<int> incoming_label_indices_to;
681 std::vector<int> label_indices_to;
682 std::vector<double> resources(num_resources_);
685 for (
int r = 0; r < num_resources_; ++r) {
686 resources_to[r].clear();
688 incoming_arc_indices_to.clear();
689 incoming_label_indices_to.clear();
690 for (
const ArcIndex reverse_arc_index : reverse_graph.OutgoingArcs(
to)) {
691 const NodeIndex from = reverse_graph.Head(reverse_arc_index);
692 const double arc_length = arc_lengths[reverse_arc_index];
693 DCHECK(arc_length != -std::numeric_limits<double>::infinity());
694 if (arc_length == std::numeric_limits<double>::infinity()) {
697 for (
int label_index = first_label[from];
698 label_index < first_label[from] + num_labels[from]; ++label_index) {
699 bool path_is_feasible =
true;
700 for (
int r = 0; r < num_resources_; ++r) {
701 DCHECK_GE(arc_resources[r][reverse_arc_index], 0.0);
702 resources[r] = resources_from_sources[r][label_index] +
703 arc_resources[r][reverse_arc_index];
704 if (resources[r] + min_arc_resources[r][
to] > max_resources[r]) {
705 path_is_feasible =
false;
709 if (!path_is_feasible) {
712 lengths_to.push_back(lengths_from_sources[label_index] + arc_length);
713 for (
int r = 0; r < num_resources_; ++r) {
714 resources_to[r].push_back(resources[r]);
716 incoming_arc_indices_to.push_back(reverse_arc_index);
717 incoming_label_indices_to.push_back(label_index);
721 label_indices_to.clear();
722 label_indices_to.reserve(lengths_to.size());
723 for (
int i = 0;
i < lengths_to.size(); ++
i) {
724 label_indices_to.push_back(i);
726 absl::c_sort(label_indices_to, [&](
const int i,
const int j) {
727 if (lengths_to[i] < lengths_to[j])
return true;
728 if (lengths_to[i] > lengths_to[j])
return false;
729 for (
int r = 0; r < num_resources_; ++r) {
730 if (resources_to[r][i] < resources_to[r][j])
return true;
731 if (resources_to[r][i] > resources_to[r][j])
return false;
736 first_label[
to] = lengths_from_sources.size();
737 int& num_labels_to = num_labels[
to];
741 for (
int i = 0;
i < label_indices_to.size(); ++
i) {
743 const int label_i_index = label_indices_to[
i];
744 bool label_i_is_dominated =
false;
745 for (
int j = 0; j <
i - 1; ++j) {
746 const int label_j_index = label_indices_to[j];
747 if (lengths_to[label_i_index] <= lengths_to[label_j_index])
continue;
748 bool label_j_dominates_label_i =
true;
749 for (
int r = 0; r < num_resources_; ++r) {
750 if (resources_to[r][label_i_index] <=
751 resources_to[r][label_j_index]) {
752 label_j_dominates_label_i =
false;
756 if (label_j_dominates_label_i) {
757 label_i_is_dominated =
true;
761 if (label_i_is_dominated)
continue;
762 lengths_from_sources.push_back(lengths_to[label_i_index]);
763 for (
int r = 0; r < num_resources_; ++r) {
764 resources_from_sources[r].push_back(resources_to[r][label_i_index]);
766 incoming_arc_indices_from_sources.push_back(
767 incoming_arc_indices_to[label_i_index]);
768 incoming_label_indices_from_sources.push_back(
769 incoming_label_indices_to[label_i_index]);
771 if (lengths_from_sources.size() >= max_num_created_labels) {
778template <
class GraphType>
779typename GraphType::ArcIndex
780ConstrainedShortestPathsOnDagWrapper<GraphType>::MergeHalfRuns(
781 const GraphType& graph, absl::Span<const double> arc_lengths,
782 absl::Span<
const std::vector<double>> arc_resources,
783 absl::Span<const double> max_resources,
784 const std::vector<NodeIndex> sub_node_indices[2],
785 const std::vector<double> lengths_from_sources[2],
786 const std::vector<std::vector<double>> resources_from_sources[2],
787 const std::vector<int> first_label[2],
const std::vector<int> num_labels[2],
788 LabelPair& best_label_pair) {
789 const std::vector<NodeIndex>& forward_sub_node_indices =
790 sub_node_indices[FORWARD];
791 absl::Span<const double> forward_lengths = lengths_from_sources[FORWARD];
792 const std::vector<std::vector<double>>& forward_resources =
793 resources_from_sources[FORWARD];
794 absl::Span<const int> forward_first_label = first_label[FORWARD];
795 absl::Span<const int> forward_num_labels = num_labels[FORWARD];
796 const std::vector<NodeIndex>& backward_sub_node_indices =
797 sub_node_indices[BACKWARD];
798 absl::Span<const double> backward_lengths = lengths_from_sources[BACKWARD];
799 const std::vector<std::vector<double>>& backward_resources =
800 resources_from_sources[BACKWARD];
801 absl::Span<const int> backward_first_label = first_label[BACKWARD];
802 absl::Span<const int> backward_num_labels = num_labels[BACKWARD];
803 ArcIndex merging_arc_index = -1;
804 for (ArcIndex arc_index = 0; arc_index < graph.num_arcs(); ++arc_index) {
805 const NodeIndex sub_from = forward_sub_node_indices[graph.Tail(arc_index)];
806 if (sub_from == -1) {
809 const NodeIndex sub_to = backward_sub_node_indices[graph.Head(arc_index)];
813 const int num_labels_from = forward_num_labels[sub_from];
814 if (num_labels_from == 0) {
817 const int num_labels_to = backward_num_labels[sub_to];
818 if (num_labels_to == 0) {
821 const double arc_length = arc_lengths[arc_index];
822 DCHECK(arc_length != -std::numeric_limits<double>::infinity());
823 if (arc_length == std::numeric_limits<double>::infinity()) {
826 const int first_label_from = forward_first_label[sub_from];
827 const int first_label_to = backward_first_label[sub_to];
828 for (
int label_to_index = first_label_to;
829 label_to_index < first_label_to + num_labels_to; ++label_to_index) {
830 const double length_to = backward_lengths[label_to_index];
831 for (
int label_from_index = first_label_from;
832 label_from_index < first_label_from + num_labels_from;
833 ++label_from_index) {
834 const double length_from = forward_lengths[label_from_index];
835 if (length_from + arc_length + length_to >= best_label_pair.length) {
838 bool path_is_feasible =
true;
839 for (
int r = 0; r < num_resources_; ++r) {
840 DCHECK_GE(arc_resources[r][arc_index], 0.0);
841 if (forward_resources[r][label_from_index] +
842 arc_resources[r][arc_index] +
843 backward_resources[r][label_to_index] >
845 path_is_feasible =
false;
849 if (!path_is_feasible) {
852 best_label_pair.length = length_from + arc_length + length_to;
853 best_label_pair.label_index[FORWARD] = label_from_index;
854 best_label_pair.label_index[BACKWARD] = label_to_index;
855 merging_arc_index = arc_index;
859 return merging_arc_index;
862template <
class GraphType>
863std::vector<typename GraphType::ArcIndex>
864ConstrainedShortestPathsOnDagWrapper<GraphType>::ArcPathTo(
865 const int best_label_index,
866 absl::Span<const ArcIndex> incoming_arc_indices_from_sources,
867 absl::Span<const int> incoming_label_indices_from_sources)
const {
868 int current_label_index = best_label_index;
869 std::vector<ArcIndex> arc_path;
870 for (
int i = 0;
i < graph_->num_nodes(); ++
i) {
871 if (current_label_index == -1) {
874 arc_path.push_back(incoming_arc_indices_from_sources[current_label_index]);
875 current_label_index =
876 incoming_label_indices_from_sources[current_label_index];
881template <
typename GraphType>
882std::vector<typename GraphType::NodeIndex>
883ConstrainedShortestPathsOnDagWrapper<GraphType>::NodePathImpliedBy(
884 absl::Span<const ArcIndex> arc_path,
const GraphType& graph)
const {
885 if (arc_path.empty()) {
888 std::vector<NodeIndex> node_path;
889 node_path.reserve(arc_path.size() + 1);
890 for (
const ArcIndex arc_index : arc_path) {
891 node_path.push_back(graph.Tail(arc_index));
893 node_path.push_back(graph.Head(arc_path.back()));
901 std::vector<T> inverse_permutation(permutation.size());
902 if (!permutation.empty()) {
903 for (T i = 0;
i < permutation.size(); ++
i) {
904 inverse_permutation[permutation[
i]] =
i;
907 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
void RunShortestPathOnDag(absl::Span< const NodeIndex > sources)
std::vector< T > GetInversePermutation(const std::vector< T > &permutation)
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