OR-Tools  9.1
dijkstra.cc
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#include <cstdint>
15#include <functional>
16#include <limits>
17#include <memory>
18#include <set>
19#include <vector>
20
21#include "absl/container/flat_hash_set.h"
25
26namespace operations_research {
27namespace {
28
29// Priority queue element
30class Element {
31 public:
32 bool operator<(const Element& other) const {
33 return distance_ != other.distance_ ? distance_ > other.distance_
34 : node_ > other.node_;
35 }
36 void SetHeapIndex(int h) { heap_index_ = h; }
37 int GetHeapIndex() const { return heap_index_; }
38 void set_distance(int64_t distance) { distance_ = distance; }
39 int64_t distance() const { return distance_; }
40 void set_node(int node) { node_ = node; }
41 int node() const { return node_; }
42
43 private:
44 int64_t distance_ = 0;
45 int heap_index_ = -1;
46 int node_ = -1;
47};
48} // namespace
49
50template <class S>
52 public:
53 static constexpr int64_t kInfinity = std::numeric_limits<int64_t>::max() / 2;
54
55 DijkstraSP(int node_count, int start_node,
56 std::function<int64_t(int, int)> graph,
57 int64_t disconnected_distance)
58 : node_count_(node_count),
59 start_node_(start_node),
60 graph_(std::move(graph)),
61 disconnected_distance_(disconnected_distance),
62 predecessor_(new int[node_count]),
63 elements_(node_count) {}
64
65 bool ShortestPath(int end_node, std::vector<int>* nodes) {
66 Initialize();
67 bool found = false;
68 while (!frontier_.IsEmpty()) {
69 int64_t distance;
70 int node = SelectClosestNode(&distance);
71 if (distance == kInfinity) {
72 found = false;
73 break;
74 } else if (node == end_node) {
75 found = true;
76 break;
77 }
78 Update(node);
79 }
80 if (found) {
81 FindPath(end_node, nodes);
82 }
83 return found;
84 }
85
86 private:
87 void Initialize() {
88 for (int i = 0; i < node_count_; i++) {
89 elements_[i].set_node(i);
90 if (i == start_node_) {
91 predecessor_[i] = -1;
92 elements_[i].set_distance(0);
93 frontier_.Add(&elements_[i]);
94 } else {
95 elements_[i].set_distance(kInfinity);
96 predecessor_[i] = start_node_;
97 not_visited_.insert(i);
98 }
99 }
100 }
101
102 int SelectClosestNode(int64_t* distance) {
103 const int node = frontier_.Top()->node();
104 *distance = frontier_.Top()->distance();
105 frontier_.Pop();
106 not_visited_.erase(node);
107 added_to_the_frontier_.erase(node);
108 return node;
109 }
110
111 void Update(int node) {
112 for (const auto& other_node : not_visited_) {
113 const int64_t graph_node_i = graph_(node, other_node);
114 if (graph_node_i != disconnected_distance_) {
115 if (added_to_the_frontier_.find(other_node) ==
116 added_to_the_frontier_.end()) {
117 frontier_.Add(&elements_[other_node]);
118 added_to_the_frontier_.insert(other_node);
119 }
120 const int64_t other_distance =
121 elements_[node].distance() + graph_node_i;
122 if (elements_[other_node].distance() > other_distance) {
123 elements_[other_node].set_distance(other_distance);
124 frontier_.NoteChangedPriority(&elements_[other_node]);
125 predecessor_[other_node] = node;
126 }
127 }
128 }
129 }
130
131 void FindPath(int dest, std::vector<int>* nodes) {
132 int j = dest;
133 nodes->push_back(j);
134 while (predecessor_[j] != -1) {
135 nodes->push_back(predecessor_[j]);
136 j = predecessor_[j];
137 }
138 }
139
140 const int node_count_;
141 const int start_node_;
142 std::function<int64_t(int, int)> graph_;
143 const int64_t disconnected_distance_;
144 std::unique_ptr<int[]> predecessor_;
146 std::vector<Element> elements_;
147 S not_visited_;
148 S added_to_the_frontier_;
149};
150
151bool DijkstraShortestPath(int node_count, int start_node, int end_node,
152 std::function<int64_t(int, int)> graph,
153 int64_t disconnected_distance,
154 std::vector<int>* nodes) {
156 node_count, start_node, std::move(graph), disconnected_distance);
157 return bf.ShortestPath(end_node, nodes);
158}
159
160bool StableDijkstraShortestPath(int node_count, int start_node, int end_node,
161 std::function<int64_t(int, int)> graph,
162 int64_t disconnected_distance,
163 std::vector<int>* nodes) {
164 DijkstraSP<std::set<int>> bf(node_count, start_node, std::move(graph),
165 disconnected_distance);
166 return bf.ShortestPath(end_node, nodes);
167}
168} // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
bool ShortestPath(int end_node, std::vector< int > *nodes)
Definition: dijkstra.cc:65
DijkstraSP(int node_count, int start_node, std::function< int64_t(int, int)> graph, int64_t disconnected_distance)
Definition: dijkstra.cc:55
static constexpr int64_t kInfinity
Definition: dijkstra.cc:53
Collection of objects used to extend the Constraint Solver library.
bool DijkstraShortestPath(int node_count, int start_node, int end_node, std::function< int64_t(int, int)> graph, int64_t disconnected_distance, std::vector< int > *nodes)
Definition: dijkstra.cc:151
bool StableDijkstraShortestPath(int node_count, int start_node, int end_node, std::function< int64_t(int, int)> graph, int64_t disconnected_distance, std::vector< int > *nodes)
Definition: dijkstra.cc:160
STL namespace.
int nodes
double distance