OR-Tools  9.3
astar.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 <memory>
15#include <vector>
16
17#include "absl/container/flat_hash_map.h"
18#include "absl/container/flat_hash_set.h"
21
22namespace operations_research {
23namespace {
24
25// Priority queue element
26class Element {
27 public:
28 Element()
29 : heap_index_(-1), distance_(0), distance_with_heuristic_(0), node_(-1) {}
30
31 // The distance_with_heuristic is used for the comparison
32 // in the priority queue
33 bool operator<(const Element& other) const {
34 return distance_with_heuristic_ > other.distance_with_heuristic_;
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 void set_distance_with_heuristic(int64_t distance_with_heuristic) {
40 distance_with_heuristic_ = distance_with_heuristic;
41 }
42 int64_t distance_with_heuristic() { return distance_with_heuristic_; }
43
44 int64_t distance() const { return distance_; }
45 void set_node(int node) { node_ = node; }
46 int node() const { return node_; }
47
48 private:
49 int heap_index_;
50 int64_t distance_;
51 int64_t distance_with_heuristic_;
52 int node_;
53};
54} // namespace
55
56class AStarSP {
57 public:
58 static const int64_t kInfinity = kint64max / 2;
59
60 AStarSP(int node_count, int start_node,
61 std::function<int64_t(int, int)> graph,
62 std::function<int64_t(int)> heuristic, int64_t disconnected_distance)
63 : node_count_(node_count),
64 start_node_(start_node),
65 graph_(std::move(graph)),
66 heuristic_(std::move(heuristic)),
67 disconnected_distance_(disconnected_distance),
68 predecessor_(new int[node_count]),
69 elements_(node_count) {}
70 bool ShortestPath(int end_node, std::vector<int>* nodes);
71
72 private:
73 void Initialize();
74 int SelectClosestNode(int64_t* distance);
75 void Update(int label);
76 void FindPath(int dest, std::vector<int>* nodes);
77
78 const int node_count_;
79 const int start_node_;
80 std::function<int64_t(int, int)> graph_;
81 std::function<int64_t(int)> heuristic_;
82 const int64_t disconnected_distance_;
83 std::unique_ptr<int[]> predecessor_;
85 std::vector<Element> elements_;
86 absl::flat_hash_set<int> not_visited_;
87 absl::flat_hash_set<int> added_to_the_frontier_;
88};
89
90void AStarSP::Initialize() {
91 for (int i = 0; i < node_count_; i++) {
92 elements_[i].set_node(i);
93 if (i == start_node_) {
94 predecessor_[i] = -1;
95 elements_[i].set_distance(0);
96 elements_[i].set_distance_with_heuristic(heuristic_(i));
97 frontier_.Add(&elements_[i]);
98 } else {
99 elements_[i].set_distance(kInfinity);
100 elements_[i].set_distance_with_heuristic(kInfinity);
101 predecessor_[i] = start_node_;
102 not_visited_.insert(i);
103 }
104 }
105}
106
107int AStarSP::SelectClosestNode(int64_t* distance) {
108 const int node = frontier_.Top()->node();
109 *distance = frontier_.Top()->distance();
110 frontier_.Pop();
111 not_visited_.erase(node);
112 added_to_the_frontier_.erase(node);
113 return node;
114}
115
116void AStarSP::Update(int node) {
117 for (absl::flat_hash_set<int>::const_iterator it = not_visited_.begin();
118 it != not_visited_.end(); ++it) {
119 const int other_node = *it;
120 const int64_t graph_node_i = graph_(node, other_node);
121 if (graph_node_i != disconnected_distance_) {
122 if (added_to_the_frontier_.find(other_node) ==
123 added_to_the_frontier_.end()) {
124 frontier_.Add(&elements_[other_node]);
125 added_to_the_frontier_.insert(other_node);
126 }
127
128 const int64_t other_distance = elements_[node].distance() + graph_node_i;
129 if (elements_[other_node].distance() > other_distance) {
130 elements_[other_node].set_distance(other_distance);
131 elements_[other_node].set_distance_with_heuristic(
132 other_distance + heuristic_(other_node));
133 frontier_.NoteChangedPriority(&elements_[other_node]);
134 predecessor_[other_node] = node;
135 }
136 }
137 }
138}
139
140void AStarSP::FindPath(int dest, std::vector<int>* nodes) {
141 int j = dest;
142 nodes->push_back(j);
143 while (predecessor_[j] != -1) {
144 nodes->push_back(predecessor_[j]);
145 j = predecessor_[j];
146 }
147}
148
149bool AStarSP::ShortestPath(int end_node, std::vector<int>* nodes) {
150 Initialize();
151 bool found = false;
152 while (!frontier_.IsEmpty()) {
153 int64_t distance;
154 int node = SelectClosestNode(&distance);
155 if (distance == kInfinity) {
156 found = false;
157 break;
158 } else if (node == end_node) {
159 found = true;
160 break;
161 }
162 Update(node);
163 }
164 if (found) {
165 FindPath(end_node, nodes);
166 }
167 return found;
168}
169
170bool AStarShortestPath(int node_count, int start_node, int end_node,
171 std::function<int64_t(int, int)> graph,
172 std::function<int64_t(int)> heuristic,
173 int64_t disconnected_distance, std::vector<int>* nodes) {
174 AStarSP bf(node_count, start_node, std::move(graph), std::move(heuristic),
175 disconnected_distance);
176 return bf.ShortestPath(end_node, nodes);
177}
178} // namespace operations_research
bool ShortestPath(int end_node, std::vector< int > *nodes)
Definition: astar.cc:149
static const int64_t kInfinity
Definition: astar.cc:58
AStarSP(int node_count, int start_node, std::function< int64_t(int, int)> graph, std::function< int64_t(int)> heuristic, int64_t disconnected_distance)
Definition: astar.cc:60
static const int64_t kint64max
Collection of objects used to extend the Constraint Solver library.
bool AStarShortestPath(int node_count, int start_node, int end_node, std::function< int64_t(int, int)> graph, std::function< int64_t(int)> heuristic, int64_t disconnected_distance, std::vector< int > *nodes)
Definition: astar.cc:170
STL namespace.
int nodes
double distance