Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
adjustable_priority_queue.h
Go to the documentation of this file.
1// Copyright 2010-2025 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#ifndef OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_
15#define OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_
16
17#include <stddef.h>
18
19#include <functional>
20#include <list>
21#include <vector>
22
23template <typename T, typename Comparator>
25 public:
26 explicit LowerPriorityThan(Comparator* compare) : compare_(compare) {}
27 bool operator()(T* a, T* b) const { return (*compare_)(*a, *b); }
28
29 private:
30 Comparator* compare_;
31};
32
33template <typename T, typename Comp = std::less<T> >
35 public:
36 // The objects references 'c' and 'm' are not required to be alive for the
37 // lifetime of this object.
39 explicit AdjustablePriorityQueue(const Comp& c) : c_(c) {}
44
45 void Add(T* val) {
46 // Extend the size of the vector by one. We could just use
47 // vector<T>::resize(), but maybe T is not default-constructible.
48 elems_.push_back(val);
49 AdjustUpwards(elems_.size() - 1);
50 }
51
52 void Remove(T* val) {
53 int end = elems_.size() - 1;
54 int i = val->GetHeapIndex();
55 if (i == end) {
56 elems_.pop_back();
57 return;
58 }
59 elems_[i] = elems_[end];
60 elems_[i]->SetHeapIndex(i);
61 elems_.pop_back();
62 NoteChangedPriority(elems_[i]);
63 }
64
65 bool Contains(const T* val) const {
66 int i = val->GetHeapIndex();
67 return (i >= 0 && i < elems_.size() && elems_[i] == val);
68 }
69
70 void NoteChangedPriority(T* val) {
71 LowerPriorityThan<T, Comp> lower_priority(&c_);
72 int i = val->GetHeapIndex();
73 int parent = (i - 1) / 2;
74 if (lower_priority(elems_[parent], val)) {
75 AdjustUpwards(i);
76 } else {
77 AdjustDownwards(i);
78 }
79 }
80 // If val ever changes its priority, you need to call this function
81 // to notify the pq so it can move it in the heap accordingly.
82
83 T* Top() { return elems_[0]; }
84
85 const T* Top() const { return elems_[0]; }
86
87 void AllTop(std::vector<T*>* topvec) {
88 topvec->clear();
89 if (Size() == 0) return;
90 std::list<int> need_to_check_children;
91 need_to_check_children.push_back(0);
92 // Implements breadth-first search down tree, stopping whenever
93 // there's an element < top
94 while (!need_to_check_children.empty()) {
95 int ind = need_to_check_children.front();
96 need_to_check_children.pop_front();
97 topvec->push_back(elems_[ind]);
98 int leftchild = 1 + 2 * ind;
99 if (leftchild < Size()) {
100 if (!LowerPriorityThan<T, Comp>(&c_)(elems_[leftchild], elems_[ind])) {
101 need_to_check_children.push_back(leftchild);
102 }
103 int rightchild = leftchild + 1;
104 if (rightchild < Size() &&
105 !LowerPriorityThan<T, Comp>(&c_)(elems_[rightchild], elems_[ind])) {
106 need_to_check_children.push_back(rightchild);
107 }
108 }
109 }
110 }
111 // If there are ties for the top, this returns all of them.
112
113 void Pop() { Remove(Top()); }
114
115 int Size() const { return elems_.size(); }
116
117 // Returns the number of elements for which storage has been allocated.
118 int Capacity() const { return elems_.capacity(); }
119
120 // Allocates storage for a given number of elements.
121 void SetCapacity(size_t c) { elems_.reserve(c); }
122
123 bool IsEmpty() const { return elems_.empty(); }
124
125 void Clear() { elems_.clear(); }
126
127 // CHECKs that the heap is actually a heap (each "parent" of >=
128 // priority than its child).
129 void CheckValid() {
130 for (int i = 0; i < elems_.size(); ++i) {
131 int left_child = 1 + 2 * i;
132 if (left_child < elems_.size()) {
133 CHECK(
134 !(LowerPriorityThan<T, Comp>(&c_))(elems_[i], elems_[left_child]));
135 }
136 int right_child = left_child + 1;
137 if (right_child < elems_.size()) {
138 CHECK(
139 !(LowerPriorityThan<T, Comp>(&c_))(elems_[i], elems_[right_child]));
140 }
141 }
142 }
143
144 // This is for debugging, e.g. the caller can use it to
145 // examine the heap for rationality w.r.t. other parts of the
146 // program.
147 const std::vector<T*>* Raw() const { return &elems_; }
148
149 private:
150 void AdjustUpwards(int i) {
151 T* const t = elems_[i];
152 while (i > 0) {
153 const int parent = (i - 1) / 2;
154 if (!c_(*elems_[parent], *t)) {
155 break;
156 }
157 elems_[i] = elems_[parent];
158 elems_[i]->SetHeapIndex(i);
159 i = parent;
160 }
161 elems_[i] = t;
162 t->SetHeapIndex(i);
163 }
164
165 void AdjustDownwards(int i) {
166 T* const t = elems_[i];
167 while (true) {
168 const int left_child = 1 + 2 * i;
169 if (left_child >= elems_.size()) {
170 break;
171 }
172 const int right_child = left_child + 1;
173 const int next_i = (right_child < elems_.size() &&
174 c_(*elems_[left_child], *elems_[right_child]))
175 ? right_child
176 : left_child;
177 if (!c_(*t, *elems_[next_i])) {
178 break;
179 }
180 elems_[i] = elems_[next_i];
181 elems_[i]->SetHeapIndex(i);
182 i = next_i;
183 }
184 elems_[i] = t;
185 t->SetHeapIndex(i);
186 }
187
188 Comp c_;
189 std::vector<T*> elems_;
190};
191
192#endif // OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_
AdjustablePriorityQueue(AdjustablePriorityQueue &&)=default
bool Contains(const T *val) const
int Capacity() const
Returns the number of elements for which storage has been allocated.
AdjustablePriorityQueue & operator=(AdjustablePriorityQueue &&)=default
AdjustablePriorityQueue & operator=(const AdjustablePriorityQueue &)=delete
void SetCapacity(size_t c)
Allocates storage for a given number of elements.
void AllTop(std::vector< T * > *topvec)
void Pop()
If there are ties for the top, this returns all of them.
AdjustablePriorityQueue(const AdjustablePriorityQueue &)=delete
AdjustablePriorityQueue()=default
const std::vector< T * > * Raw() const
bool operator()(T *a, T *b) const
LowerPriorityThan(Comparator *compare)
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp