1use crate::float::Float;
2
3#[derive(Debug, Default)]
13pub struct LinkageHeap<T> {
14 heap: Vec<usize>,
16 observations: Vec<usize>,
18 priorities: Vec<T>,
20 removed: Vec<bool>,
22}
23
24impl<T: Float> LinkageHeap<T> {
25 pub fn new() -> LinkageHeap<T> {
26 LinkageHeap::with_len(0)
27 }
28
29 pub fn with_len(len: usize) -> LinkageHeap<T> {
30 LinkageHeap {
31 heap: (0..len).collect(),
32 observations: (0..len).collect(),
33 priorities: vec![T::max_value(); len],
34 removed: vec![false; len],
35 }
36 }
37
38 pub fn reset(&mut self, len: usize) {
39 self.heap.resize(len, 0);
40 self.observations.resize(len, 0);
41 self.priorities.resize(len, T::max_value());
42 self.removed.resize(len, false);
43
44 for i in 0..len {
45 self.heap[i] = i;
46 self.observations[i] = i;
47 self.priorities[i] = T::max_value();
48 self.removed[i] = false;
49 }
50 }
51
52 pub fn is_empty(&self) -> bool {
53 self.len() == 0
54 }
55
56 pub fn len(&self) -> usize {
57 self.heap.len()
58 }
59
60 pub fn pop(&mut self) -> Option<usize> {
61 if self.is_empty() {
62 return None;
63 }
64 if self.heap.len() >= 2 {
65 let (first, last) = (self.heap[0], *self.heap.last().unwrap());
66 self.swap(first, last);
67 }
68 let last = self.heap.pop().unwrap();
69 self.removed[last] = true;
70 if self.heap.len() >= 2 {
71 let first = self.heap[0];
72 self.sift_down(first);
73 }
74 Some(last)
75 }
76
77 pub fn peek(&self) -> Option<usize> {
78 if self.is_empty() {
79 None
80 } else {
81 Some(self.heap[0])
82 }
83 }
84
85 pub fn heapify<F: FnMut(&mut [T])>(&mut self, mut f: F) {
86 let len = self.priorities.len();
87 self.reset(len);
88 f(&mut self.priorities);
89
90 for i in (0..len / 2).rev() {
91 let o = self.heap[i];
92 self.sift_down(o);
93 }
94 }
95
96 pub fn priority(&self, observation: usize) -> &T {
97 assert!(!self.removed[observation]);
98 &self.priorities[observation]
99 }
100
101 pub fn set_priority(&mut self, observation: usize, priority: T) {
102 assert!(!self.removed[observation]);
103
104 let old = self.priorities[observation];
105 self.priorities[observation] = priority;
106 if priority < old {
107 self.sift_up(observation);
108 } else if priority > old {
109 self.sift_down(observation);
110 }
111 }
112
113 fn sift_up(&mut self, o: usize) {
114 loop {
115 let po = match self.parent(o) {
116 None => break,
117 Some(po) => po,
118 };
119 if self.priorities[po] < self.priorities[o] {
120 break;
121 }
122 self.swap(o, po);
123 }
124 }
125
126 fn sift_down(&mut self, o: usize) {
127 loop {
128 let mut child = o;
129 let (left, right) = self.children(o);
130 if let Some(left) = left {
131 if self.priorities[left] < self.priorities[child] {
132 child = left;
133 }
134 }
135 if let Some(right) = right {
136 if self.priorities[right] < self.priorities[child] {
137 child = right;
138 }
139 }
140 if o == child {
141 break;
142 }
143 self.swap(o, child);
144 }
145 }
146
147 fn parent(&self, o: usize) -> Option<usize> {
148 if self.observations[o] == 0 {
149 None
150 } else {
151 Some(self.heap[(self.observations[o] - 1) / 2])
152 }
153 }
154
155 fn children(&self, o: usize) -> (Option<usize>, Option<usize>) {
156 let i = self.observations[o];
157 let (left, right) = (2 * i + 1, 2 * i + 2);
158 (self.heap.get(left).cloned(), self.heap.get(right).cloned())
159 }
160
161 fn swap(&mut self, o1: usize, o2: usize) {
162 self.heap.swap(self.observations[o1], self.observations[o2]);
163 self.observations.swap(o1, o2);
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use crate::float::Float;
170
171 use super::LinkageHeap;
172
173 fn is_sorted_asc<T: Float>(xs: &[T]) -> bool {
174 for win in xs.windows(2) {
175 if win[0] > win[1] {
176 return false;
177 }
178 }
179 true
180 }
181
182 fn pop_all<T: Float>(heap: &mut LinkageHeap<T>) -> Vec<T> {
183 let mut xs = vec![];
184 while let Some(o) = heap.peek() {
185 xs.push(*heap.priority(o));
186 heap.pop().unwrap();
187 }
188 xs
189 }
190
191 fn new_heap<T: Float>(priorities: &[T]) -> LinkageHeap<T> {
192 let mut heap = LinkageHeap::with_len(priorities.len());
193 for (i, p) in priorities.iter().enumerate() {
194 heap.set_priority(i, *p);
195 }
196 heap
197 }
198
199 fn heapify<T: Float>(priorities: &[T]) -> LinkageHeap<T> {
200 let mut heap = LinkageHeap::with_len(priorities.len());
201 heap.heapify(|ps| ps.copy_from_slice(priorities));
202 heap
203 }
204
205 #[test]
206 fn simple() {
207 let mut heap = new_heap(&[2.0, 1.0, 10.0, 5.0, 4.0, 4.5]);
208 let ps = pop_all(&mut heap);
209 assert_eq!(ps, &[1.0, 2.0, 4.0, 4.5, 5.0, 10.0]);
210
211 let mut heap = heapify(&[2.0, 1.0, 10.0, 5.0, 4.0, 4.5]);
212 let ps = pop_all(&mut heap);
213 assert_eq!(ps, &[1.0, 2.0, 4.0, 4.5, 5.0, 10.0]);
214 }
215
216 #[test]
217 fn empty() {
218 let mut heap = new_heap::<f64>(&[]);
219 let ps = pop_all(&mut heap);
220 assert_eq!(ps, &[]);
221
222 let mut heap = heapify::<f64>(&[]);
223 let ps = pop_all(&mut heap);
224 assert_eq!(ps, &[]);
225 }
226
227 #[test]
228 fn one() {
229 let mut heap = new_heap(&[1.0]);
230 let ps = pop_all(&mut heap);
231 assert_eq!(ps, &[1.0]);
232
233 let mut heap = heapify(&[1.0]);
234 let ps = pop_all(&mut heap);
235 assert_eq!(ps, &[1.0]);
236 }
237
238 #[test]
239 fn two() {
240 let mut heap = new_heap(&[2.0, 1.0]);
241 let ps = pop_all(&mut heap);
242 assert_eq!(ps, &[1.0, 2.0]);
243
244 let mut heap = heapify(&[2.0, 1.0]);
245 let ps = pop_all(&mut heap);
246 assert_eq!(ps, &[1.0, 2.0]);
247 }
248
249 quickcheck::quickcheck! {
250 fn prop_heap_invariant(xs: Vec<f64>) -> bool {
251 let mut xs = xs;
252 for x in &mut xs {
253 if x.is_nan() {
254 *x = 0.0;
255 }
256 }
257 let mut heap = new_heap(&xs);
258 is_sorted_asc(&pop_all(&mut heap))
259 }
260 }
261
262 quickcheck::quickcheck! {
263 fn prop_heapify_heap_invariant(xs: Vec<f64>) -> bool {
264 let mut xs = xs;
265 for x in &mut xs {
266 if x.is_nan() {
267 *x = 0.0;
268 }
269 }
270 let mut heap = heapify(&xs);
271 is_sorted_asc(&pop_all(&mut heap))
272 }
273 }
274}