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