OR-Tools  9.6
dijkstra.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <utility>
20 #include <vector>
21 
22 #include "absl/container/flat_hash_set.h"
26 
27 namespace operations_research {
28 namespace {
29 
30 // Priority queue element
31 class Element {
32  public:
33  bool operator<(const Element& other) const {
34  return distance_ != other.distance_ ? distance_ > other.distance_
35  : node_ > other.node_;
36  }
37  void SetHeapIndex(int h) { heap_index_ = h; }
38  int GetHeapIndex() const { return heap_index_; }
39  void set_distance(int64_t distance) { distance_ = distance; }
40  int64_t distance() const { return distance_; }
41  void set_node(int node) { node_ = node; }
42  int node() const { return node_; }
43 
44  private:
45  int64_t distance_ = 0;
46  int heap_index_ = -1;
47  int node_ = -1;
48 };
49 } // namespace
50 
51 template <class S>
52 class DijkstraSP {
53  public:
54  static constexpr int64_t kInfinity = std::numeric_limits<int64_t>::max() / 2;
55 
56  DijkstraSP(int node_count, int start_node,
57  std::function<int64_t(int, int)> graph,
58  int64_t disconnected_distance)
59  : node_count_(node_count),
60  start_node_(start_node),
61  graph_(std::move(graph)),
62  disconnected_distance_(disconnected_distance),
63  predecessor_(new int[node_count]),
64  elements_(node_count) {}
65 
66  bool ShortestPath(int end_node, std::vector<int>* nodes) {
67  Initialize();
68  bool found = false;
69  while (!frontier_.IsEmpty()) {
70  int64_t distance;
71  int node = SelectClosestNode(&distance);
72  if (distance == kInfinity) {
73  found = false;
74  break;
75  } else if (node == end_node) {
76  found = true;
77  break;
78  }
79  Update(node);
80  }
81  if (found) {
82  FindPath(end_node, nodes);
83  }
84  return found;
85  }
86 
87  private:
88  void Initialize() {
89  for (int i = 0; i < node_count_; i++) {
90  elements_[i].set_node(i);
91  if (i == start_node_) {
92  predecessor_[i] = -1;
93  elements_[i].set_distance(0);
94  frontier_.Add(&elements_[i]);
95  } else {
96  elements_[i].set_distance(kInfinity);
97  predecessor_[i] = start_node_;
98  not_visited_.insert(i);
99  }
100  }
101  }
102 
103  int SelectClosestNode(int64_t* distance) {
104  const int node = frontier_.Top()->node();
105  *distance = frontier_.Top()->distance();
106  frontier_.Pop();
107  not_visited_.erase(node);
108  added_to_the_frontier_.erase(node);
109  return node;
110  }
111 
112  void Update(int node) {
113  for (const auto& other_node : not_visited_) {
114  const int64_t graph_node_i = graph_(node, other_node);
115  if (graph_node_i != disconnected_distance_) {
116  if (added_to_the_frontier_.find(other_node) ==
117  added_to_the_frontier_.end()) {
118  frontier_.Add(&elements_[other_node]);
119  added_to_the_frontier_.insert(other_node);
120  }
121  const int64_t other_distance =
122  elements_[node].distance() + graph_node_i;
123  if (elements_[other_node].distance() > other_distance) {
124  elements_[other_node].set_distance(other_distance);
125  frontier_.NoteChangedPriority(&elements_[other_node]);
126  predecessor_[other_node] = node;
127  }
128  }
129  }
130  }
131 
132  void FindPath(int dest, std::vector<int>* nodes) {
133  int j = dest;
134  nodes->push_back(j);
135  while (predecessor_[j] != -1) {
136  nodes->push_back(predecessor_[j]);
137  j = predecessor_[j];
138  }
139  }
140 
141  const int node_count_;
142  const int start_node_;
143  std::function<int64_t(int, int)> graph_;
144  const int64_t disconnected_distance_;
145  std::unique_ptr<int[]> predecessor_;
147  std::vector<Element> elements_;
148  S not_visited_;
149  S added_to_the_frontier_;
150 };
151 
152 bool DijkstraShortestPath(int node_count, int start_node, int end_node,
153  std::function<int64_t(int, int)> graph,
154  int64_t disconnected_distance,
155  std::vector<int>* nodes) {
157  node_count, start_node, std::move(graph), disconnected_distance);
158  return bf.ShortestPath(end_node, nodes);
159 }
160 
161 bool StableDijkstraShortestPath(int node_count, int start_node, int end_node,
162  std::function<int64_t(int, int)> graph,
163  int64_t disconnected_distance,
164  std::vector<int>* nodes) {
165  DijkstraSP<std::set<int>> bf(node_count, start_node, std::move(graph),
166  disconnected_distance);
167  return bf.ShortestPath(end_node, nodes);
168 }
169 } // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
bool ShortestPath(int end_node, std::vector< int > *nodes)
Definition: dijkstra.cc:66
DijkstraSP(int node_count, int start_node, std::function< int64_t(int, int)> graph, int64_t disconnected_distance)
Definition: dijkstra.cc:56
static constexpr int64_t kInfinity
Definition: dijkstra.cc:54
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:152
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:161
int nodes
double distance