1use vstd::prelude::*;
2
3use vstd::seq::*;
4use vstd::seq_lib::*;
5
6use super::ownership::*;
7use super::seq_extra::*;
8
9verus! {
10
11#[verifier::ext_equal]
15pub tracked struct TreePath<const N: usize>(pub Seq<usize>);
16
17impl<const N: usize> TreePath<N> {
18 pub open spec fn len(self) -> nat {
19 self.0.len()
20 }
21
22 pub open spec fn index(self, i: int) -> usize
23 recommends
24 0 <= i < self.len(),
25 {
26 self.0[i]
27 }
28
29 pub open spec fn elem_inv(e: usize) -> bool {
30 0 <= e < N
31 }
32
33 pub open spec fn inv(self) -> bool {
34 &&& N > 0
35 &&& forall|i: int| 0 <= i < self.len() ==> Self::elem_inv(#[trigger] self.index(i))
36 }
37
38 pub broadcast proof fn inv_property(self)
39 requires
40 #[trigger] self.inv(),
41 ensures
42 forall|i: int| 0 <= i < self.len() ==> #[trigger] Self::elem_inv(self.index(i)),
43 {
44 }
45
46 pub broadcast proof fn index_satisfies_elem_inv(self, i: int)
47 requires
48 self.inv(),
49 0 <= i < self.len(),
50 ensures
51 #[trigger] Self::elem_inv(self.index(i)),
52 {
53 }
54
55 pub open spec fn is_empty(self) -> bool {
56 self.len() == 0
57 }
58
59 pub broadcast proof fn empty_satisfies_inv(self)
60 requires
61 N > 0,
62 #[trigger] self.is_empty(),
63 ensures
64 #[trigger] self.inv(),
65 {
66 }
67
68 pub open spec fn append(self, path: Self) -> Self {
69 Self(self.0.add(path.0))
70 }
71
72 pub broadcast proof fn drop_head_property(self)
73 requires
74 !#[trigger] self.is_empty(),
75 ensures
76 self.0.drop_first().len() == self.len() - 1,
77 forall|i: int|
78 0 <= i < self.0.drop_first().len() ==> #[trigger] self.0.drop_first().index(i)
79 == self.index(i + 1),
80 {
81 }
82
83 pub broadcast proof fn drop_last_property(self)
84 requires
85 !#[trigger] self.is_empty(),
86 ensures
87 self.0.drop_last().len() == self.len() - 1,
88 forall|i: int|
89 0 <= i < self.0.drop_last().len() ==> #[trigger] self.0.drop_last().index(i)
90 == self.index(i),
91 {
92 }
93
94 pub open spec fn pop_head(self) -> (usize, TreePath<N>)
95 recommends
96 !self.is_empty(),
97 {
98 (self.index(0), TreePath(self.0.drop_first()))
99 }
100
101 pub broadcast proof fn pop_head_preserves_inv(self)
102 requires
103 #[trigger] self.inv(),
104 !self.is_empty(),
105 ensures
106 Self::elem_inv(self.pop_head().0),
107 self.pop_head().1.inv(),
108 {
109 let (hd, s1) = self.pop_head();
110 assert(forall|i: int| 0 <= i < s1.len() ==> s1.index(i) == self.index(i + 1));
111 }
112
113 pub broadcast proof fn pop_head_decreases_len(self)
114 requires
115 self.inv(),
116 !self.is_empty(),
117 ensures
118 #[trigger] self.pop_head().1.len() == self.len() - 1,
119 {
120 }
121
122 pub broadcast proof fn pop_head_head_satisfies_inv(self)
123 requires
124 self.inv(),
125 !self.is_empty(),
126 ensures
127 #[trigger] Self::elem_inv(self.pop_head().0),
128 {
129 }
130
131 pub broadcast proof fn pop_head_property(self)
132 requires
133 self.inv(),
134 !self.is_empty(),
135 ensures
136 #[trigger] self.pop_head().0 == self.index(0),
137 self.pop_head().1.len() == self.len() - 1,
138 Self::elem_inv(self.pop_head().0),
139 self.pop_head().1.inv(),
140 {
141 self.pop_head_preserves_inv();
142 }
143
144 pub open spec fn pop_tail(self) -> (usize, TreePath<N>)
145 recommends
146 !self.is_empty(),
147 {
148 (self.index(self.len() as int - 1), TreePath(self.0.drop_last()))
149 }
150
151 pub broadcast proof fn pop_tail_preserves_inv(self)
152 requires
153 #[trigger] self.inv(),
154 !self.is_empty(),
155 ensures
156 Self::elem_inv(self.pop_tail().0),
157 self.pop_tail().1.inv(),
158 {
159 let (tl, s1) = self.pop_tail();
160 if s1.is_empty() {
161 } else {
162 assert(forall|i: int| 0 <= i < s1.len() ==> s1.index(i) == self.index(i));
163 }
164 }
165
166 pub broadcast proof fn pop_tail_decreases_len(self)
167 requires
168 self.inv(),
169 !self.is_empty(),
170 ensures
171 #[trigger] self.pop_tail().1.len() == self.len() - 1,
172 {
173 }
174
175 pub broadcast proof fn pop_tail_tail_satisfies_inv(self)
176 requires
177 self.inv(),
178 !self.is_empty(),
179 ensures
180 #[trigger] Self::elem_inv(self.pop_tail().0),
181 {
182 }
183
184 pub broadcast proof fn pop_tail_property(self)
185 requires
186 self.inv(),
187 !self.is_empty(),
188 ensures
189 #[trigger] self.pop_tail().0 == self.index(self.len() as int - 1),
190 self.pop_tail().1.len() == self.len() - 1,
191 Self::elem_inv(self.pop_tail().0),
192 self.pop_tail().1.inv(),
193 {
194 self.pop_tail_preserves_inv();
195 }
196
197 pub open spec fn push_head(self, hd: usize) -> TreePath<N>
198 recommends
199 0 <= hd < N,
200 {
201 TreePath(seq![hd].add(self.0))
202 }
203
204 pub proof fn push_head_property_len(self, hd: usize)
205 requires
206 self.inv(),
207 0 <= hd < N,
208 ensures
209 self.push_head(hd).len() == self.len() + 1,
210 {
211 }
212
213 pub proof fn push_head_property_index(self, hd: usize)
214 requires
215 self.inv(),
216 0 <= hd < N,
217 ensures
218 self.push_head(hd).index(0) == hd,
219 forall|i: int| 0 <= i < self.len() ==> self.push_head(hd).index(i + 1) == self.index(i),
220 {
221 }
222
223 pub proof fn push_head_preserves_inv(self, hd: usize)
224 requires
225 self.inv(),
226 0 <= hd < N,
227 ensures
228 self.push_head(hd).inv(),
229 {
230 let s1 = self.push_head(hd);
231 assert forall|i: int| 0 <= i < s1.len() implies Self::elem_inv(#[trigger] s1.index(i)) by {
232 if i == 0 {
233 } else {
234 assert(Self::elem_inv(self.index(i - 1)));
235 }
236 }
237 }
238
239 pub broadcast proof fn push_head_property(self, hd: usize)
240 requires
241 self.inv(),
242 0 <= hd < N,
243 ensures
244 #[trigger] self.push_head(hd).inv(),
245 self.push_head(hd).len() == self.len() + 1,
246 self.push_head(hd).index(0) == hd,
247 forall|i: int| 0 <= i < self.len() ==> self.push_head(hd).index(i + 1) == self.index(i),
248 {
249 self.push_head_property_len(hd);
250 self.push_head_property_index(hd);
251 self.push_head_preserves_inv(hd);
252 }
253
254 pub open spec fn push_tail(self, val: usize) -> TreePath<N>
255 recommends
256 0 <= val < N,
257 {
258 TreePath(self.0.push(val))
259 }
260
261 pub proof fn push_tail_property_len(self, val: usize)
262 requires
263 self.inv(),
264 0 <= val < N,
265 ensures
266 self.push_tail(val).len() == self.len() + 1,
267 {
268 }
269
270 pub proof fn push_tail_property_index(self, val: usize)
271 requires
272 self.inv(),
273 0 <= val < N,
274 ensures
275 self.push_tail(val).index(self.len() as int) == val,
276 forall|i: int|
277 0 <= i < self.len() ==> #[trigger] self.push_tail(val).index(i) == self.index(i),
278 {
279 }
280
281 pub proof fn push_tail_preserves_inv(self, val: usize)
282 requires
283 self.inv(),
284 0 <= val < N,
285 ensures
286 self.push_tail(val).inv(),
287 {
288 let s1 = self.push_tail(val);
289 assert forall|i: int| 0 <= i < s1.len() implies Self::elem_inv(#[trigger] s1.index(i)) by {
290 if i == self.len() {
291 } else {
292 assert(Self::elem_inv(self.index(i)));
293 }
294 }
295 }
296
297 pub broadcast proof fn push_tail_property(self, val: usize)
298 requires
299 self.inv(),
300 0 <= val < N,
301 ensures
302 #[trigger] self.push_tail(val).inv(),
303 self.push_tail(val).len() == self.len() + 1,
304 self.push_tail(val).index(self.len() as int) == val,
305 forall|i: int|
306 0 <= i < self.len() ==> #[trigger] self.push_tail(val).index(i) == self.index(i),
307 {
308 self.push_tail_property_len(val);
309 self.push_tail_property_index(val);
310 self.push_tail_preserves_inv(val);
311 }
312
313 pub open spec fn new(path: Seq<usize>) -> TreePath<N>
314 recommends
315 forall|i: int| 0 <= i < path.len() ==> Self::elem_inv(#[trigger] path[i]),
316 {
317 TreePath(path)
318 }
319
320 pub broadcast proof fn new_preserves_inv(path: Seq<usize>)
321 requires
322 N > 0,
323 forall|i: int| 0 <= i < path.len() ==> Self::elem_inv(#[trigger] path[i]),
324 ensures
325 #[trigger] Self::new(path).inv(),
326 {
327 }
328
329 pub broadcast proof fn new_empty_preserves_inv()
330 requires
331 N > 0,
332 ensures
333 #[trigger] Self::new(Seq::empty()).inv(),
334 {
335 }
336}
337
338} verus! {
340
341pub trait TreeNodeValue<const L: usize>: Sized + Inv {
342 spec fn default(lv: nat) -> Self;
343
344 proof fn default_preserves_inv()
345 ensures
346 forall|lv: nat| #[trigger] Self::default(lv).inv(),
347 ;
348
349 spec fn la_inv(self, lv: nat) -> bool;
350
351 proof fn default_preserves_la_inv()
352 ensures
353 forall|lv: nat| #[trigger] Self::default(lv).la_inv(lv),
354 ;
355
356 spec fn rel_children(self, index: int, child: Option<Self>) -> bool;
357
358 proof fn default_preserves_rel_children(self, lv: nat)
359 requires
360 self.inv(),
361 self.la_inv(lv),
362 ensures
363 forall|i: int| #[trigger] self.rel_children(i, Some(Self::default(lv + 1))),
364 ;
365}
366
367pub tracked struct Node<T: TreeNodeValue<L>, const N: usize, const L: usize> {
371 pub tracked value: T,
372 pub ghost level: nat,
373 pub tracked children: Seq<Option<Node<T, N, L>>>,
374}
375
376impl<T: TreeNodeValue<L>, const N: usize, const L: usize> Node<T, N, L> {
377 #[verifier::inline]
378 pub open spec fn size() -> nat {
379 N as nat
380 }
381
382 #[verifier::inline]
383 pub open spec fn max_depth() -> nat {
384 L as nat
385 }
386
387 pub proof fn borrow_value(tracked &self) -> (tracked res: &T)
388 ensures
389 *res == self.value,
390 {
391 &self.value
392 }
393
394 pub open spec fn tree_predicate_map(
395 self,
396 path: TreePath<N>,
397 f: spec_fn(T, TreePath<N>) -> bool,
398 ) -> bool
399 decreases L - self.level,
400 when self.inv()
401 {
402 if self.level < L - 1 {
403 &&& f(self.value, path)
404 &&& forall|i: int|
405 0 <= i < self.children.len() ==> (#[trigger] self.children[i]) is Some
406 ==> self.children[i]->Some_0.tree_predicate_map(path.push_tail(i as usize), f)
407 } else {
408 &&& f(self.value, path)
409 }
410 }
411
412 pub proof fn map_unroll_once(
413 self,
414 path: TreePath<N>,
415 f: spec_fn(T, TreePath<N>) -> bool,
416 i: int,
417 )
418 requires
419 self.inv(),
420 self.level < L - 1,
421 0 <= i < self.children.len(),
422 self.children[i] is Some,
423 self.tree_predicate_map(path, f),
424 ensures
425 self.children[i]->Some_0.tree_predicate_map(path.push_tail(i as usize), f),
426 {
427 }
428
429 pub open spec fn implies(
430 f: spec_fn(T, TreePath<N>) -> bool,
431 g: spec_fn(T, TreePath<N>) -> bool,
432 ) -> bool {
433 forall|value: T, path: TreePath<N>|
434 value.inv() ==> f(value, path) ==> #[trigger] g(value, path)
435 }
436
437 pub proof fn map_implies(
438 self,
439 path: TreePath<N>,
440 f: spec_fn(T, TreePath<N>) -> bool,
441 g: spec_fn(T, TreePath<N>) -> bool,
442 )
443 requires
444 self.inv(),
445 Self::implies(f, g),
446 Self::tree_predicate_map(self, path, f),
447 ensures
448 Self::tree_predicate_map(self, path, g),
449 decreases L - self.level,
450 {
451 if self.level < L - 1 {
452 assert forall|i: int|
453 #![trigger self.children[i]->Some_0]
454 0 <= i < self.children.len()
455 && self.children[i] is Some implies self.children[i]->Some_0.tree_predicate_map(
456 path.push_tail(i as usize),
457 g,
458 ) by {
459 self.children[i]->Some_0.map_implies(path.push_tail(i as usize), f, g);
460 }
461 }
462 }
463
464 pub proof fn new_tree_predicate_map(
466 lv: nat,
467 path: TreePath<N>,
468 f: spec_fn(T, TreePath<N>) -> bool,
469 )
470 requires
471 lv < L,
472 Self::new(lv).inv(),
473 f(T::default(lv), path),
474 ensures
475 Self::new(lv).tree_predicate_map(path, f),
476 {
477 }
479
480 pub proof fn new_val_tree_predicate_map(
483 self,
484 path: TreePath<N>,
485 f: spec_fn(T, TreePath<N>) -> bool,
486 )
487 requires
488 self.inv(),
489 self == Self::new_val(self.value, self.level),
490 f(self.value, path),
491 forall|lv: nat, p: TreePath<N>| lv < L ==> #[trigger] f(T::default(lv), p),
492 ensures
493 self.tree_predicate_map(path, f),
494 {
495 if self.level < L - 1 {
496 assert forall|j: int|
497 #![auto]
498 0 <= j < self.children.len()
499 && self.children[j] is Some implies self.children[j].unwrap().tree_predicate_map(
500 path.push_tail(j as usize), f) by {
501 assert(self.children[j] == Some(Self::new(self.level + 1)));
503 assert(self.children[j].unwrap().inv());
505 assert(Self::new(self.level + 1).inv());
506 Self::new_tree_predicate_map(self.level + 1, path.push_tail(j as usize), f);
507 };
508 }
509 }
510
511 pub proof fn map_implies_and(
514 self,
515 path: TreePath<N>,
516 f1: spec_fn(T, TreePath<N>) -> bool,
517 f2: spec_fn(T, TreePath<N>) -> bool,
518 g: spec_fn(T, TreePath<N>) -> bool,
519 )
520 requires
521 self.inv(),
522 Self::implies(|v: T, p: TreePath<N>| f1(v, p) && f2(v, p), g),
523 Self::tree_predicate_map(self, path, f1),
524 Self::tree_predicate_map(self, path, f2),
525 ensures
526 Self::tree_predicate_map(self, path, g),
527 decreases L - self.level,
528 {
529 if self.level < L - 1 {
530 assert forall|i: int|
531 #![trigger self.children[i]->Some_0]
532 0 <= i < self.children.len()
533 && self.children[i] is Some implies self.children[i]->Some_0.tree_predicate_map(
534 path.push_tail(i as usize),
535 g,
536 ) by {
537 self.children[i]->Some_0.map_implies_and(path.push_tail(i as usize), f1, f2, g);
538 }
539 }
540 }
541
542 pub open spec fn inv_node(self) -> bool {
543 &&& self.value.inv()
544 &&& self.value.la_inv(self.level)
545 &&& self.level < L
546 &&& self.children.len() == Self::size()
547 }
548
549 pub open spec fn inv_children(self) -> bool {
550 if self.level == L - 1 {
551 forall|i: int| 0 <= i < Self::size() ==> #[trigger] self.children[i] is None
552 } else {
553 forall|i: int|
554 0 <= i < Self::size() ==> match #[trigger] self.children[i] {
555 Some(child) => {
556 &&& child.level == self.level + 1
557 &&& self.value.rel_children(i, Some(child.value))
558 },
559 None => self.value.rel_children(i, None),
560 }
561 }
562 }
563
564 pub open spec fn inv(self) -> bool
565 decreases (L - self.level),
566 {
567 &&& L > 0
568 &&& N > 0
569 &&& self.inv_node()
570 &&& self.inv_children()
571 &&& if L - self.level == 1 {
572 true
574 } else {
575 forall|i: int|
577 0 <= i < Self::size() ==> match #[trigger] self.children[i] {
578 Some(child) => child.inv(),
579 None => true,
580 }
581 }
582 }
583
584 pub open spec fn new(lv: nat) -> Self {
585 Node { value: T::default(lv), level: lv, children: Seq::new(N as nat, |i| None) }
586 }
587
588 pub open spec fn new_val(val: T, lv: nat) -> Self
589 recommends
590 lv < L,
591 {
592 Node { value: val, level: lv, children: Seq::new(N as nat, |i| Some(Self::new(lv + 1))) }
593 }
594
595 pub axiom fn new_val_tracked(tracked val: T, lv: nat) -> (tracked res: Self)
596 requires
597 0 <= lv < L,
598 N > 0,
599 ensures
600 res.inv(),
601 returns
602 Self::new_val(val, lv),
603 ;
604
605 pub broadcast proof fn new_preserves_inv(lv: nat)
606 requires
607 0 <= lv < L,
608 N > 0,
609 forall|i: int| 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
610 ensures
611 #[trigger] Self::new(lv).inv(),
612 forall|i: int| 0 <= i < N ==> #[trigger] Self::new(lv).value.rel_children(i, None),
613 {
614 let n = Self::new(lv);
615 T::default_preserves_inv();
616 T::default_preserves_la_inv();
617 }
618
619 pub open spec fn insert(self, key: usize, node: Self) -> Self
620 recommends
621 0 <= key < Self::size(),
622 self.inv(),
623 node.inv(),
624 self.level < L - 1,
625 node.level == self.level + 1,
626 {
627 Node { children: self.children.update(key as int, Some(node)), ..self }
628 }
629
630 pub broadcast proof fn insert_preserves_inv(self, key: usize, node: Self)
631 requires
632 0 <= key < Self::size(),
633 self.inv(),
634 node.inv(),
635 self.level < L - 1,
636 node.level == self.level + 1,
637 self.value.rel_children(key as int, Some(node.value)),
638 ensures
639 #[trigger] self.insert(key, node).inv(),
640 {
641 }
642
643 pub broadcast proof fn insert_property(self, key: usize, node: Self)
644 requires
645 0 <= key < Self::size(),
646 self.inv(),
647 node.inv(),
648 self.level < L - 1,
649 node.level == self.level + 1,
650 ensures
651 #[trigger] self.insert(key, node).value == self.value,
652 self.insert(key, node).children[key as int] == Some(node),
653 forall|i: int|
654 0 <= i < Self::size() && i != key ==> #[trigger] self.insert(key, node).children[i]
655 == self.children[i],
656 {
657 }
658
659 pub broadcast proof fn insert_same_child_identical(self, key: usize, node: Self)
660 requires
661 0 <= key < Self::size(),
662 self.inv(),
663 self.child(key) == Some(node),
664 ensures
665 #[trigger] self.insert(key, node) == self,
666 {
667 self.child_some_properties(key);
668 self.insert_property(key, node);
669 assert(self.insert(key, node).children =~= self.children);
670 }
671
672 pub open spec fn remove(self, key: usize) -> Self
673 recommends
674 0 <= key < Self::size(),
675 self.inv(),
676 {
677 Node { children: self.children.update(key as int, None), ..self }
678 }
679
680 pub broadcast proof fn remove_preserves_inv(self, key: usize)
681 requires
682 0 <= key < Self::size(),
683 self.inv(),
684 self.children[key as int] is None || self.value.rel_children(key as int, None),
685 ensures
686 #[trigger] self.remove(key).inv(),
687 {
688 }
689
690 pub broadcast proof fn remove_property(self, key: usize)
691 requires
692 0 <= key < Self::size(),
693 self.inv(),
694 ensures
695 #[trigger] self.remove(key).value == self.value,
696 self.remove(key).children[key as int] is None,
697 forall|i: int|
698 0 <= i < Self::size() && i != key ==> #[trigger] self.remove(key).children[i]
699 == self.children[i],
700 {
701 }
702
703 pub open spec fn child(self, key: usize) -> Option<Self>
704 recommends
705 0 <= key < Self::size(),
706 self.inv(),
707 {
708 self.children[key as int]
709 }
710
711 pub broadcast proof fn child_property(self, key: usize)
712 requires
713 0 <= key < Self::size(),
714 self.inv(),
715 ensures
716 #[trigger] self.child(key) == self.children[key as int],
717 {
718 }
719
720 pub broadcast proof fn child_property_cases(self, key: usize)
721 requires
722 0 <= key < Self::size(),
723 self.inv(),
724 ensures
725 self.level == L - 1 ==> #[trigger] self.child(key) is None,
726 self.level < L - 1 && self.children[key as int] is None ==> #[trigger] self.child(
727 key,
728 ) is None,
729 self.level < L - 1 && self.children[key as int] is Some ==> #[trigger] self.child(
730 key,
731 ) is Some && self.child(key)->Some_0.level == self.level + 1 && self.child(
732 key,
733 )->Some_0.inv(),
734 {
735 }
736
737 pub proof fn child_some_properties(self, key: usize)
738 requires
739 0 <= key < Self::size(),
740 self.inv(),
741 self.child(key) is Some,
742 ensures
743 self.level < L - 1,
744 self.child(key)->Some_0.level == self.level + 1,
745 self.child(key)->Some_0.inv(),
746 {
747 self.child_property(key);
748 self.child_property_cases(key);
749 }
750
751 pub broadcast proof fn lemma_insert_child_is_child(self, key: usize, node: Self)
752 requires
753 0 <= key < Self::size(),
754 self.inv(),
755 node.inv(),
756 self.level < L - 1,
757 node.level == self.level + 1,
758 ensures
759 #[trigger] self.insert(key, node).child(key) == Some(node),
760 {
761 self.insert_property(key, node);
762 self.child_property(key);
763 }
764
765 pub broadcast proof fn lemma_remove_child_is_none(self, key: usize)
766 requires
767 0 <= key < Self::size(),
768 self.inv(),
769 ensures
770 #[trigger] self.remove(key).child(key) is None,
771 {
772 self.remove_property(key);
773 self.child_property(key);
774 }
775
776 pub open spec fn get_value(self) -> T {
777 self.value
778 }
779
780 pub broadcast proof fn get_value_property(self)
781 requires
782 self.inv(),
783 ensures
784 #[trigger] self.get_value() == self.value,
785 self.get_value().inv(),
786 {
787 }
788
789 pub open spec fn set_value(self, value: T) -> Self
790 recommends
791 self.inv(),
792 value.inv(),
793 {
794 Node { value: value, ..self }
795 }
796
797 pub broadcast proof fn set_value_property(self, value: T)
798 requires
799 self.inv(),
800 value.inv(),
801 value.la_inv(self.level),
802 forall|i: int|
803 0 <= i < N ==> #[trigger] self.children[i] is Some ==> value.rel_children(
804 i,
805 Some(self.children[i]->Some_0.value),
806 ),
807 forall|i: int|
808 0 <= i < N ==> #[trigger] self.children[i] is None ==> value.rel_children(i, None),
809 ensures
810 #[trigger] self.set_value(value).value == value,
811 self.set_value(value).children == self.children,
812 self.set_value(value).inv(),
813 {
814 let n = self.set_value(value);
815
816 if n.level == L - 1 {
817 } else {
818 assert forall|i: int| 0 <= i < Self::size() implies match #[trigger] n.children[i] {
819 Some(child) => {
820 &&& child.level == n.level + 1
821 &&& n.value.rel_children(i, Some(child.value))
822 },
823 None => n.value.rel_children(i, None),
824 } by {
825 if n.children[i] is Some {
826 let child = n.children[i]->Some_0;
827 }
828 }
829 }
830 }
831
832 pub open spec fn is_leaf(self) -> bool {
833 forall|i: int| 0 <= i < Self::size() ==> self.children[i] is None
834 }
835
836 pub broadcast proof fn is_leaf_bounded(self)
837 requires
838 self.inv(),
839 self.level == L - 1,
840 ensures
841 #[trigger] self.is_leaf(),
842 {
843 }
844
845 pub open spec fn recursive_insert(self, path: TreePath<N>, node: Self) -> Self
846 recommends
847 self.inv(),
848 path.inv(),
849 node.inv(),
850 path.len() < L - self.level,
851 node.level == self.level + path.len() as nat,
852 decreases path.len(),
853 {
854 if path.is_empty() {
855 self
856 } else if path.len() == 1 {
857 self.insert(path.index(0), node)
858 } else {
859 let (hd, tl) = path.pop_head();
860 let child = match self.child(hd) {
861 Some(child) => child,
862 None => Node::new(self.level + 1),
863 };
864 let updated_child = child.recursive_insert(tl, node);
865 self.insert(hd, updated_child)
866 }
867 }
868
869 pub broadcast proof fn lemma_recursive_insert_path_empty_identical(
870 self,
871 path: TreePath<N>,
872 node: Self,
873 )
874 requires
875 self.inv(),
876 node.inv(),
877 path.inv(),
878 path.is_empty(),
879 ensures
880 #[trigger] self.recursive_insert(path, node) == self,
881 {
882 }
883
884 pub broadcast proof fn lemma_recursive_insert_path_len_1(self, path: TreePath<N>, node: Self)
885 requires
886 self.inv(),
887 node.inv(),
888 path.inv(),
889 path.len() == 1,
890 1 < L - self.level,
891 node.level == self.level + 1,
892 ensures
893 #[trigger] self.recursive_insert(path, node) == self.insert(path.index(0), node),
894 {
895 }
896
897 pub broadcast proof fn lemma_recursive_insert_path_len_step(self, path: TreePath<N>, node: Self)
898 requires
899 self.inv(),
900 path.inv(),
901 node.inv(),
902 path.len() < L - self.level,
903 node.level == self.level + path.len() as nat,
904 path.len() > 1,
905 ensures
906 self.child(path.index(0)) is Some ==> #[trigger] self.recursive_insert(path, node)
907 == self.insert(
908 path.index(0),
909 self.child(path.index(0))->Some_0.recursive_insert(path.pop_head().1, node),
910 ),
911 self.child(path.index(0)) is None ==> #[trigger] self.recursive_insert(path, node)
912 == self.insert(
913 path.index(0),
914 Node::new(self.level + 1).recursive_insert(path.pop_head().1, node),
915 ),
916 {
917 }
918
919 pub broadcast proof fn lemma_recursive_insert_preserves_level(
920 self,
921 path: TreePath<N>,
922 node: Self,
923 )
924 requires
925 self.inv(),
926 path.inv(),
927 node.inv(),
928 path.len() < L - self.level,
929 node.level == self.level + path.len() as nat,
930 forall|lv: nat|
931 lv < L ==> #[trigger] T::default(lv).rel_children(path.pop_tail().0 as int, None),
932 ensures
933 #[trigger] self.recursive_insert(path, node).level == self.level,
934 decreases path.len(),
935 {
936 if path.is_empty() {
937 self.lemma_recursive_insert_path_empty_identical(path, node);
938 } else if path.len() == 1 {
939 path.index_satisfies_elem_inv(0);
940 self.lemma_recursive_insert_path_len_1(path, node);
941 assert(self.insert(path.index(0), node).level == self.level);
942 } else {
943 self.lemma_recursive_insert_path_len_step(path, node);
944 let (hd, tl) = path.pop_head();
945 path.pop_head_preserves_inv();
946 if self.child(hd) is Some {
947 let c = self.child(hd)->Some_0;
948 self.child_some_properties(hd);
949 assert(self.insert(hd, c.recursive_insert(tl, node)).level == self.level);
950 } else {
951 let c = Node::new(self.level + 1);
952 assert(self.insert(hd, c.recursive_insert(tl, node)).level == self.level);
953 }
954 }
955 }
956
957 pub broadcast proof fn lemma_recursive_insert_preserves_value(
958 self,
959 path: TreePath<N>,
960 node: Self,
961 )
962 requires
963 self.inv(),
964 path.inv(),
965 node.inv(),
966 path.len() < L - self.level,
967 node.level == self.level + path.len() as nat,
968 forall|lv: nat, i: int|
969 lv < L && 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
970 ensures
971 #[trigger] self.recursive_insert(path, node).value == self.value,
972 decreases path.len(),
973 {
974 if path.is_empty() {
975 self.lemma_recursive_insert_path_empty_identical(path, node);
976 } else if path.len() == 1 {
977 path.index_satisfies_elem_inv(0);
978 self.lemma_recursive_insert_path_len_1(path, node);
979 } else {
980 self.lemma_recursive_insert_path_len_step(path, node);
981 let (hd, tl) = path.pop_head();
982 path.pop_head_preserves_inv();
983 if self.child(hd) is Some {
984 let c = self.child(hd)->Some_0;
985 self.child_some_properties(hd);
986 c.lemma_recursive_insert_preserves_value(tl, node);
987 let updated_child = c.recursive_insert(tl, node);
988 } else {
989 let c = Node::new(self.level + 1);
990 Self::new_preserves_inv(self.level + 1);
991 c.lemma_recursive_insert_preserves_value(tl, node);
992 let updated_child = c.recursive_insert(tl, node);
993 }
994 }
995 }
996
997 pub broadcast proof fn lemma_recursive_insert_preserves_inv(self, path: TreePath<N>, node: Self)
998 requires
999 self.inv(),
1000 path.inv(),
1001 node.inv(),
1002 path.len() < L - self.level,
1003 node.level == self.level + path.len() as nat,
1004 self.recursive_seek(path.pop_tail().1) is Some ==> self.recursive_seek(
1005 path.pop_tail().1,
1006 )->Some_0.value.rel_children(path.pop_tail().0 as int, Some(node.value)),
1007 self.recursive_seek(path.pop_tail().1) is None ==> T::default(
1008 (node.level - 1) as nat,
1009 ).rel_children(path.pop_tail().0 as int, Some(node.value)),
1010 forall|lv: nat, i: int|
1011 lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
1012 ensures
1013 #[trigger] self.recursive_insert(path, node).inv(),
1014 decreases path.len(),
1015 {
1016 if path.is_empty() {
1017 self.lemma_recursive_insert_path_empty_identical(path, node);
1018 } else if path.len() == 1 {
1019 path.index_satisfies_elem_inv(0);
1020 self.lemma_recursive_insert_path_len_1(path, node);
1021 self.insert_preserves_inv(path.index(0), node);
1022 } else {
1023 self.lemma_recursive_insert_path_len_step(path, node);
1024 let (hd, tl) = path.pop_head();
1025 path.pop_head_preserves_inv();
1026 if self.child(hd) is Some {
1027 let c = self.child(hd)->Some_0;
1028 self.child_some_properties(hd);
1029 assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
1030 c.lemma_recursive_insert_preserves_inv(tl, node);
1031 c.lemma_recursive_insert_preserves_level(tl, node);
1032 c.lemma_recursive_insert_preserves_value(tl, node);
1033 let updated_child = c.recursive_insert(tl, node);
1034 self.insert_preserves_inv(hd, updated_child);
1035 } else {
1036 let c = Node::new(self.level + 1);
1037 Self::new_preserves_inv(self.level + 1);
1038 self.value.default_preserves_rel_children(self.level);
1039 c.lemma_recursive_insert_preserves_inv(tl, node);
1040 c.lemma_recursive_insert_preserves_level(tl, node);
1041 c.lemma_recursive_insert_preserves_value(tl, node);
1042 let updated_child = c.recursive_insert(tl, node);
1043 self.insert_preserves_inv(hd, updated_child);
1044 }
1045 }
1046 }
1047
1048 pub open spec fn recursive_trace(self, path: TreePath<N>) -> Seq<T>
1053 recommends
1054 self.inv(),
1055 path.inv(),
1056 path.len() < L - self.level,
1057 decreases path.len(),
1058 {
1059 if path.is_empty() {
1060 seq![self.value]
1061 } else {
1062 let (hd, tl) = path.pop_head();
1063 match self.child(hd) {
1064 Some(child) => seq![self.value].add(child.recursive_trace(tl)),
1065 None => seq![self.value],
1066 }
1067 }
1068 }
1069
1070 pub proof fn lemma_recursive_trace_length(self, path: TreePath<N>)
1071 requires
1072 self.inv(),
1073 path.inv(),
1074 ensures
1075 #[trigger] self.recursive_trace(path).len() <= path.len() + 1,
1076 decreases path.len(),
1077 {
1078 if path.len() == 0 {
1079 } else {
1080 let (hd, tl) = path.pop_head();
1081 path.pop_head_preserves_inv();
1082 match self.child(hd) {
1083 None => {},
1084 Some(child) => {
1085 child.lemma_recursive_trace_length(tl);
1086 },
1087 }
1088 }
1089 }
1090
1091 pub proof fn lemma_recursive_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1092 requires
1093 self.inv(),
1094 path1.inv(),
1095 path2.inv(),
1096 n <= path1.len(),
1097 n <= path2.len(),
1098 forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1099 self.recursive_trace(path1).len() > n,
1100 ensures
1101 self.recursive_trace(path2).len() > n,
1102 forall|i: int|
1103 0 <= i <= n ==> self.recursive_trace(path1)[i] == self.recursive_trace(path2)[i],
1104 decreases n,
1105 {
1106 if n <= 0 {
1107 } else {
1108 let (hd1, tl1) = path1.pop_head();
1109 let (hd2, tl2) = path2.pop_head();
1110 match self.child(hd1) {
1111 None => {},
1112 Some(child) => {
1113 path1.pop_head_preserves_inv();
1114 path2.pop_head_preserves_inv();
1115 child.lemma_recursive_trace_up_to(tl1, tl2, n - 1);
1116 },
1117 }
1118 }
1119 }
1120
1121 pub open spec fn recursive_seek(self, path: TreePath<N>) -> Option<Self>
1125 recommends
1126 self.inv(),
1127 path.inv(),
1128 path.len() < L - self.level,
1129 decreases path.len(),
1130 {
1131 if path.is_empty() {
1132 Some(self)
1133 } else {
1134 let (hd, tl) = path.pop_head();
1135 match self.child(hd) {
1136 Some(child) => child.recursive_seek(tl),
1137 None => None,
1138 }
1139 }
1140 }
1141
1142 pub proof fn lemma_recursive_seek_trace_length(self, path: TreePath<N>)
1143 requires
1144 self.inv(),
1145 path.inv(),
1146 path.len() < L - self.level,
1147 self.recursive_seek(path) is Some,
1148 ensures
1149 self.recursive_trace(path).len() == path.len() + 1,
1150 decreases path.len(),
1151 {
1152 if path.len() == 0 {
1153 } else {
1154 let (hd, tl) = path.pop_head();
1155 match self.child(hd) {
1156 None => {},
1157 Some(child) => {
1158 path.pop_head_preserves_inv();
1159 child.lemma_recursive_seek_trace_length(tl)
1160 },
1161 }
1162 }
1163 }
1164
1165 pub proof fn lemma_recursive_seek_trace_next(self, path: TreePath<N>, idx: usize)
1166 requires
1167 self.recursive_seek(path) is Some,
1168 self.recursive_seek(path)->Some_0.children[idx as int] is Some,
1169 self.inv(),
1170 path.inv(),
1171 path.len() < L - self.level,
1172 0 <= idx < N,
1173 ensures
1174 self.recursive_trace(path.push_tail(idx)).len() == path.len() + 2,
1175 self.recursive_seek(path)->Some_0.children[idx as int]->Some_0.value
1176 == self.recursive_trace(path.push_tail(idx))[path.len() as int + 1],
1177 decreases path.len(),
1178 {
1179 let path2 = path.push_tail(idx);
1180
1181 if path.len() == 0 {
1182 assert(self.recursive_trace(path2) =~= seq![
1183 self.value,
1184 self.children[idx as int]->Some_0.value,
1185 ]) by { reveal_with_fuel(Node::recursive_trace, 2) }
1186 } else {
1187 let (hd1, tl1) = path.pop_head();
1188 let (hd2, tl2) = path2.pop_head();
1189 assert(tl2 == tl1.push_tail(idx)) by {}
1190 assert(tl1.inv()) by { path.pop_head_preserves_inv() }
1191 match self.child(hd2) {
1192 None => {},
1193 Some(child) => {
1194 child.lemma_recursive_seek_trace_next(tl1, idx);
1195
1196 },
1197 }
1198 }
1199 }
1200
1201 pub open spec fn recursive_visit(self, path: TreePath<N>) -> Seq<Self>
1207 recommends
1208 self.inv(),
1209 path.inv(),
1210 path.len() < L - self.level,
1211 decreases path.len(),
1212 {
1213 if path.is_empty() {
1214 Seq::empty()
1215 } else if path.len() == 1 {
1216 match self.child(path.index(0)) {
1217 Some(child) => seq![child],
1218 None => Seq::empty(),
1219 }
1220 } else {
1221 let (hd, tl) = path.pop_head();
1222 match self.child(hd) {
1223 Some(child) => seq![child].add(child.recursive_visit(tl)),
1224 None => Seq::empty(),
1225 }
1226 }
1227 }
1228
1229 pub broadcast proof fn lemma_recursive_visited_node_inv(self, path: TreePath<N>)
1230 requires
1231 #[trigger] self.inv(),
1232 #[trigger] path.inv(),
1233 path.len() < L - self.level,
1234 ensures
1235 forall|i: int|
1236 0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1237 path,
1238 ).index(i).inv(),
1239 decreases path.len(),
1240 {
1241 if path.is_empty() {
1242 } else if path.len() == 1 {
1243 if self.child(path.index(0)) is Some {
1244 }
1245 } else {
1246 let (hd, tl) = path.pop_head();
1247 path.pop_head_preserves_inv();
1248 if self.child(hd) is Some {
1249 let c = self.child(hd)->Some_0;
1250 assert(self.recursive_visit(path) =~= seq![c].add(c.recursive_visit(tl)));
1251 c.lemma_recursive_visited_node_inv(tl);
1252 }
1253 }
1254 }
1255
1256 pub broadcast proof fn lemma_recursive_visited_node_levels(self, path: TreePath<N>)
1257 requires
1258 #[trigger] self.inv(),
1259 #[trigger] path.inv(),
1260 path.len() < L - self.level,
1261 ensures
1262 forall|i: int|
1263 0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1264 path,
1265 ).index(i).level == self.level + i + 1,
1266 decreases path.len(),
1267 {
1268 if path.is_empty() {
1269 } else if path.len() == 1 {
1270 if self.child(path.index(0)) is Some {
1271 }
1272 } else {
1273 let (hd, tl) = path.pop_head();
1274 path.pop_head_preserves_inv();
1275 if self.child(hd) is Some {
1276 let c = self.child(hd)->Some_0;
1277 assert(self.recursive_visit(path) =~= seq![c].add(c.recursive_visit(tl)));
1278 c.lemma_recursive_visited_node_levels(tl);
1279 }
1280 }
1281 }
1282
1283 pub broadcast proof fn lemma_recursive_visit_head(self, path: TreePath<N>)
1284 requires
1285 #[trigger] self.inv(),
1286 #[trigger] path.inv(),
1287 path.len() < L - self.level,
1288 !path.is_empty(),
1289 self.recursive_visit(path).len() > 0,
1290 ensures
1291 self.recursive_visit(path).index(0) == self.child(path.index(0))->Some_0,
1292 {
1293 if path.len() == 0 {
1294 } else if path.len() == 1 {
1295 if self.child(path.index(0)) is None {
1296 }
1297 } else {
1298 if self.child(path.index(0)) is None {
1299 }
1300 }
1301 }
1302
1303 pub broadcast proof fn lemma_recursive_visit_induction(self, path: TreePath<N>)
1304 requires
1305 self.inv(),
1306 path.inv(),
1307 path.len() < L - self.level,
1308 !path.is_empty(),
1309 self.recursive_visit(path).len() > 0,
1310 ensures
1311 #[trigger] self.recursive_visit(path) == seq![
1312 self.child(path.pop_head().0)->Some_0,
1313 ].add(self.child(path.pop_head().0)->Some_0.recursive_visit(path.pop_head().1)),
1314 {
1315 if path.len() == 1 {
1316 let (hd, tl) = path.pop_head();
1317 path.pop_head_preserves_inv();
1318 path.pop_head_property();
1319 let c = self.child(hd);
1320 if c is None {
1321 } else {
1322 let c = c->Some_0;
1323 }
1324 } else {
1325 let (hd, tl) = path.pop_head();
1326 path.pop_head_preserves_inv();
1327 path.pop_head_property();
1328
1329 let c = self.child(hd);
1330 if c is None {
1331 } else {
1332 let c = c->Some_0;
1333 self.lemma_recursive_visit_head(path);
1334 }
1335 }
1336 }
1337
1338 pub broadcast proof fn lemma_recursive_visit_one_is_child(self, path: TreePath<N>)
1339 requires
1340 self.inv(),
1341 path.inv(),
1342 path.len() < L - self.level,
1343 path.len() == 1,
1344 ensures
1345 self.child(path.index(0)) is Some ==> #[trigger] self.recursive_visit(path) =~= seq![
1346 self.child(path.index(0))->Some_0,
1347 ],
1348 self.child(path.index(0)) is None ==> #[trigger] self.recursive_visit(path) =~= seq![],
1349 {
1350 }
1351
1352 pub open spec fn on_subtree(self, node: Self) -> bool
1353 recommends
1354 self.inv(),
1355 node.inv(),
1356 node.level >= self.level,
1357 node.level < L,
1358 {
1359 node == self || exists|path: TreePath<N>| #[trigger]
1360 path.inv() && path.len() > 0 && path.len() == node.level - self.level
1361 && self.recursive_visit(path).last() == node
1362 }
1363
1364 pub broadcast proof fn on_subtree_property(self, node: Self)
1365 requires
1366 self.inv(),
1367 node.inv(),
1368 node.level >= self.level,
1369 node.level < L,
1370 #[trigger] self.on_subtree(node),
1371 ensures
1372 node.level == self.level ==> self == node,
1373 node.level > self.level ==> exists|path: TreePath<N>| #[trigger]
1374 path.inv() && path.len() == node.level - self.level && self.recursive_visit(
1375 path,
1376 ).last() == node,
1377 {
1378 }
1379
1380 pub broadcast proof fn not_on_subtree_property(self, node: Self)
1381 requires
1382 self.inv(),
1383 node.inv(),
1384 node.level < L,
1385 !#[trigger] self.on_subtree(node),
1386 ensures
1387 self != node,
1388 node.level > self.level ==> forall|path: TreePath<N>| #[trigger]
1389 path.inv() && path.len() == node.level - self.level ==> self.recursive_visit(
1390 path,
1391 ).last() != node,
1392 {
1393 }
1394
1395 pub broadcast proof fn lemma_on_subtree_reflexive(self)
1396 requires
1397 self.inv(),
1398 ensures
1399 #[trigger] self.on_subtree(self),
1400 {
1401 }
1402
1403 pub broadcast proof fn lemma_child_on_subtree(self, key: usize)
1404 requires
1405 0 <= key < Self::size(),
1406 self.inv(),
1407 self.child(key) is Some,
1408 ensures
1409 #[trigger] self.on_subtree(self.child(key)->Some_0),
1410 {
1411 let path = TreePath::<N>::new(seq![key]);
1412 let c = self.child(key)->Some_0;
1413 assert(path.inv());
1414 }
1415
1416 pub broadcast proof fn lemma_insert_on_subtree(self, key: usize, node: Self)
1417 requires
1418 0 <= key < Self::size(),
1419 self.inv(),
1420 node.inv(),
1421 self.level < L - 1,
1422 node.level == self.level + 1,
1423 self.value.rel_children(key as int, Some(node.value)),
1424 ensures
1425 #[trigger] self.insert(key, node).on_subtree(node),
1426 {
1427 self.lemma_insert_child_is_child(key, node);
1428 self.insert(key, node).lemma_child_on_subtree(key);
1429 }
1430
1431 pub open spec fn recursive_remove(self, path: TreePath<N>) -> Self
1437 recommends
1438 self.inv(),
1439 path.inv(),
1440 path.len() < L - self.level,
1441 decreases path.len(),
1442 {
1443 if path.is_empty() {
1444 self
1445 } else if path.len() == 1 {
1446 self.remove(path.index(0))
1447 } else {
1448 let (hd, tl) = path.pop_head();
1449 if self.child(hd) is None {
1450 self
1451 } else {
1452 let child = self.child(hd)->Some_0;
1453 let updated_child = child.recursive_remove(tl);
1454 self.insert(hd, updated_child)
1455 }
1456 }
1457 }
1458
1459 pub broadcast proof fn lemma_recursive_remove_preserves_level(self, path: TreePath<N>)
1460 requires
1461 self.inv(),
1462 path.inv(),
1463 path.len() < L - self.level,
1464 ensures
1465 #[trigger] self.recursive_remove(path).level == self.level,
1466 decreases path.len(),
1467 {
1468 if path.is_empty() {
1469 } else if path.len() == 1 {
1470 path.index_satisfies_elem_inv(0);
1471 } else {
1472 let (hd, tl) = path.pop_head();
1473 path.pop_head_preserves_inv();
1474 if self.child(hd) is Some {
1475 let c = self.child(hd)->Some_0;
1476 self.child_some_properties(hd);
1477 c.lemma_recursive_remove_preserves_level(tl);
1478 }
1479 }
1480 }
1481
1482 pub broadcast proof fn lemma_recursive_remove_preserves_value(self, path: TreePath<N>)
1483 requires
1484 self.inv(),
1485 path.inv(),
1486 path.len() < L - self.level,
1487 ensures
1488 #[trigger] self.recursive_remove(path).value == self.value,
1489 decreases path.len(),
1490 {
1491 if path.is_empty() {
1492 } else if path.len() == 1 {
1493 path.index_satisfies_elem_inv(0);
1494 } else {
1495 let (hd, tl) = path.pop_head();
1496 path.pop_head_preserves_inv();
1497 if self.child(hd) is Some {
1498 let c = self.child(hd)->Some_0;
1499 self.child_some_properties(hd);
1500 c.lemma_recursive_remove_preserves_value(tl);
1501 }
1502 }
1503 }
1504
1505 pub broadcast proof fn lemma_recursive_remove_preserves_inv(self, path: TreePath<N>)
1506 requires
1507 self.inv(),
1508 path.inv(),
1509 path.len() < L - self.level,
1510 path.len() > 0 ==> self.recursive_seek(path.pop_tail().1) is Some
1511 ==> self.recursive_seek(
1512 path.pop_tail().1,
1513 )->Some_0.children[path.pop_tail().0 as int] is None || self.recursive_seek(
1514 path.pop_tail().1,
1515 )->Some_0.value.rel_children(path.pop_tail().0 as int, None),
1516 ensures
1517 #[trigger] self.recursive_remove(path).inv(),
1518 decreases path.len(),
1519 {
1520 if path.is_empty() {
1521 } else if path.len() == 1 {
1522 path.index_satisfies_elem_inv(0);
1523
1524 self.remove_preserves_inv(path.index(0));
1525 } else {
1526 let (hd, tl) = path.pop_head();
1527 path.pop_head_preserves_inv();
1528 if self.child(hd) is Some {
1529 let c = self.child(hd)->Some_0;
1530 self.child_some_properties(hd);
1531 assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
1532 c.lemma_recursive_remove_preserves_inv(tl);
1533 c.lemma_recursive_remove_preserves_level(tl);
1534 c.lemma_recursive_remove_preserves_value(tl);
1535 let updated_child = c.recursive_remove(tl);
1536 self.insert_preserves_inv(hd, updated_child);
1537 }
1538 }
1539 }
1540}
1541
1542} verus! {
1544
1545pub closed spec fn path_between<T: TreeNodeValue<L>, const N: usize, const L: usize>(
1546 src: Node<T, N, L>,
1547 dst: Node<T, N, L>,
1548) -> TreePath<N>
1549 recommends
1550 src.inv(),
1551 dst.inv(),
1552 src.level <= dst.level,
1553 src.on_subtree(dst),
1554{
1555 if src.inv() && dst.inv() && dst.level >= src.level && dst.level < L && src.on_subtree(dst) {
1556 if src == dst {
1557 TreePath::new(seq![])
1558 } else {
1559 choose|path: TreePath<N>| #[trigger]
1560 path.inv() && path.len() > 0 && path.len() == dst.level - src.level
1561 && src.recursive_visit(path).last() == dst
1562 }
1563 } else {
1564 vstd::pervasive::arbitrary()
1565 }
1566}
1567
1568pub broadcast proof fn path_between_properties<T: TreeNodeValue<L>, const N: usize, const L: usize>(
1569 src: Node<T, N, L>,
1570 dst: Node<T, N, L>,
1571)
1572 requires
1573 src.inv(),
1574 dst.inv(),
1575 src.level <= dst.level,
1576 #[trigger] src.on_subtree(dst),
1577 ensures
1578 path_between(src, dst).inv(),
1579 path_between(src, dst).len() == dst.level - src.level,
1580 dst.level == src.level ==> path_between(src, dst).is_empty() && src == dst,
1581 dst.level > src.level ==> src.recursive_visit(path_between(src, dst)).last() == dst,
1582{
1583}
1584
1585} verus! {
1587
1588pub tracked struct Tree<T: TreeNodeValue<L>, const N: usize, const L: usize> {
1589 pub tracked root: Node<T, N, L>,
1590}
1591
1592impl<T: TreeNodeValue<L>, const N: usize, const L: usize> Tree<T, N, L> {
1593 pub open spec fn inv(self) -> bool {
1594 &&& L > 0
1595 &&& N > 0
1596 &&& self.root.inv()
1597 &&& self.root.level == 0
1598 }
1599
1600 pub open spec fn new() -> Self {
1601 Tree { root: Node::new(0) }
1602 }
1603
1604 pub broadcast proof fn new_preserves_inv()
1605 requires
1606 N > 0,
1607 L > 0,
1608 forall|i: int| 0 <= i < N ==> #[trigger] T::default(0).rel_children(i, None),
1609 ensures
1610 #[trigger] Self::new().inv(),
1611 {
1612 let t = Self::new();
1613 Node::<T, N, L>::new_preserves_inv(0);
1614 }
1615
1616 pub open spec fn insert(self, path: TreePath<N>, node: Node<T, N, L>) -> Self
1617 recommends
1618 self.inv(),
1619 path.inv(),
1620 node.inv(),
1621 path.len() < L,
1622 node.level == path.len() as nat,
1623 decreases path.len(),
1624 {
1625 Tree { root: self.root.recursive_insert(path, node), ..self }
1626 }
1627
1628 pub open spec fn remove(self, path: TreePath<N>) -> Self
1629 recommends
1630 self.inv(),
1631 path.inv(),
1632 path.len() < L,
1633 decreases path.len(),
1634 {
1635 Tree { root: self.root.recursive_remove(path), ..self }
1636 }
1637
1638 pub open spec fn visit(self, path: TreePath<N>) -> Seq<Node<T, N, L>>
1639 recommends
1640 self.inv(),
1641 path.inv(),
1642 path.len() < L,
1643 decreases path.len(),
1644 {
1645 self.root.recursive_visit(path)
1646 }
1647
1648 pub broadcast proof fn visit_is_recursive_visit(self, path: TreePath<N>)
1649 requires
1650 self.inv(),
1651 path.inv(),
1652 path.len() < L,
1653 ensures
1654 #[trigger] self.visit(path) == self.root.recursive_visit(path),
1655 {
1656 }
1657
1658 pub open spec fn trace(self, path: TreePath<N>) -> Seq<T>
1659 recommends
1660 self.inv(),
1661 path.inv(),
1662 path.len() < L,
1663 decreases path.len(),
1664 {
1665 self.root.recursive_trace(path)
1666 }
1667
1668 pub broadcast proof fn trace_empty_is_head(self, path: TreePath<N>)
1669 requires
1670 path.len() == 0,
1671 ensures
1672 #[trigger] self.trace(path) == seq![self.root.value],
1673 {
1674 }
1675
1676 pub proof fn lemma_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1677 requires
1678 self.inv(),
1679 path1.inv(),
1680 path2.inv(),
1681 n <= path1.len(),
1682 n <= path2.len(),
1683 forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1684 self.trace(path1).len() > n,
1685 ensures
1686 self.trace(path2).len() > n,
1687 forall|i: int| 0 <= i <= n ==> self.trace(path1)[i] == self.trace(path2)[i],
1688 {
1689 self.root.lemma_recursive_trace_up_to(path1, path2, n)
1690 }
1691
1692 pub broadcast proof fn lemma_trace_length(self, path: TreePath<N>)
1693 requires
1694 self.inv(),
1695 path.inv(),
1696 ensures
1697 #[trigger] self.trace(path).len() <= path.len() + 1,
1698 {
1699 self.root.lemma_recursive_trace_length(path);
1700 }
1701
1702 pub open spec fn seek(self, path: TreePath<N>) -> Option<Node<T, N, L>> {
1703 self.root.recursive_seek(path)
1704 }
1705
1706 pub proof fn lemma_seek_trace_length(self, path: TreePath<N>)
1707 requires
1708 self.inv(),
1709 path.inv(),
1710 path.len() < L,
1711 self.seek(path) is Some,
1712 ensures
1713 self.trace(path).len() == path.len() + 1,
1714 {
1715 self.root.lemma_recursive_seek_trace_length(path)
1716 }
1717
1718 pub proof fn lemma_seek_trace_next(self, path: TreePath<N>, idx: usize)
1719 requires
1720 self.seek(path) is Some,
1721 self.seek(path)->Some_0.children[idx as int] is Some,
1722 self.inv(),
1723 path.inv(),
1724 path.len() < L,
1725 0 <= idx < N,
1726 ensures
1727 self.trace(path.push_tail(idx)).len() == path.len() + 2,
1728 self.seek(path)->Some_0.children[idx as int]->Some_0.value == self.trace(
1729 path.push_tail(idx),
1730 )[path.len() as int + 1],
1731 {
1732 self.root.lemma_recursive_seek_trace_next(path, idx)
1733 }
1734
1735 pub broadcast proof fn insert_preserves_inv(self, path: TreePath<N>, node: Node<T, N, L>)
1736 requires
1737 self.inv(),
1738 path.inv(),
1739 node.inv(),
1740 path.len() < L,
1741 node.level == path.len() as nat,
1742 self.seek(path.pop_tail().1) is Some ==> self.seek(
1743 path.pop_tail().1,
1744 )->Some_0.value.rel_children(path.index(path.len() - 1) as int, Some(node.value)),
1745 self.seek(path.pop_tail().1) is None ==> T::default(
1746 (path.len() - 1) as nat,
1747 ).rel_children(path.index(path.len() - 1) as int, Some(node.value)),
1748 forall|lv: nat, i: int|
1749 lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
1750 ensures
1751 #[trigger] self.insert(path, node).inv(),
1752 {
1753 self.root.lemma_recursive_insert_preserves_inv(path, node);
1754 }
1755
1756 pub broadcast proof fn remove_preserves_inv(self, path: TreePath<N>)
1757 requires
1758 self.inv(),
1759 path.inv(),
1760 path.len() < L,
1761 path.len() > 0 ==> self.seek(path.pop_tail().1) is Some ==> self.seek(
1762 path.pop_tail().1,
1763 )->Some_0.children[path.pop_tail().0 as int] is None || self.seek(
1764 path.pop_tail().1,
1765 )->Some_0.value.rel_children(path.index(path.len() - 1) as int, None),
1766 ensures
1767 #[trigger] self.remove(path).inv(),
1768 {
1769 self.root.lemma_recursive_remove_preserves_inv(path);
1770 }
1771
1772 pub broadcast proof fn visited_nodes_inv(self, path: TreePath<N>)
1773 requires
1774 #[trigger] self.inv(),
1775 #[trigger] path.inv(),
1776 path.len() < L,
1777 ensures
1778 forall|i: int|
1779 0 <= i < self.visit(path).len() ==> #[trigger] self.visit(path).index(i).inv(),
1780 {
1781 self.root.lemma_recursive_visited_node_inv(path);
1782 }
1783
1784 #[verifier::inline]
1785 pub open spec fn on_tree(self, node: Node<T, N, L>) -> bool
1786 recommends
1787 self.inv(),
1788 node.inv(),
1789 {
1790 self.root.on_subtree(node)
1791 }
1792
1793 pub broadcast proof fn on_tree_property(self, node: Node<T, N, L>)
1794 requires
1795 self.inv(),
1796 node.inv(),
1797 #[trigger] self.on_tree(node),
1798 ensures
1799 node.level == 0 ==> self.root == node,
1800 node.level > 0 ==> exists|path: TreePath<N>| #[trigger]
1801 path.inv() && path.len() == node.level && self.visit(path).last() == node,
1802 {
1803 }
1804
1805 pub broadcast proof fn not_on_tree_property(self, node: Node<T, N, L>)
1806 requires
1807 self.inv(),
1808 node.inv(),
1809 !#[trigger] self.on_tree(node),
1810 ensures
1811 node != self.root,
1812 node.level > 0 ==> forall|path: TreePath<N>| #[trigger]
1813 path.inv() && path.len() == node.level ==> self.visit(path).last() != node,
1814 {
1815 }
1816
1817 #[verifier::inline]
1818 pub open spec fn get_path(self, node: Node<T, N, L>) -> TreePath<N>
1819 recommends
1820 self.inv(),
1821 node.inv(),
1822 self.on_tree(node),
1823 {
1824 path_between::<T, N, L>(self.root, node)
1825 }
1826
1827 pub broadcast proof fn get_path_properties(self, node: Node<T, N, L>)
1828 requires
1829 self.inv(),
1830 node.inv(),
1831 self.on_tree(node),
1832 ensures
1833 #[trigger] self.get_path(node).inv(),
1834 #[trigger] self.get_path(node).len() == node.level,
1835 node.level == 0 ==> #[trigger] self.get_path(node).is_empty(),
1836 node.level > 0 ==> #[trigger] self.visit(self.get_path(node)).last() == node,
1837 {
1838 path_between_properties(self.root, node);
1839 }
1840}
1841
1842} verus! {
1844
1845pub broadcast group group_ghost_tree {
1846 TreePath::inv_property,
1847 TreePath::index_satisfies_elem_inv,
1848 TreePath::empty_satisfies_inv,
1849 TreePath::drop_head_property,
1850 TreePath::drop_last_property,
1851 TreePath::pop_head_preserves_inv,
1852 TreePath::pop_head_decreases_len,
1853 TreePath::pop_head_head_satisfies_inv,
1854 TreePath::pop_head_property,
1855 TreePath::pop_tail_preserves_inv,
1856 TreePath::pop_tail_decreases_len,
1857 TreePath::pop_tail_tail_satisfies_inv,
1858 TreePath::pop_tail_property,
1859 TreePath::push_head_property,
1860 TreePath::new_empty_preserves_inv,
1861 TreePath::new_preserves_inv,
1862 Node::insert_preserves_inv,
1863 Node::insert_property,
1864 Node::insert_same_child_identical,
1865 Node::remove_preserves_inv,
1866 Node::remove_property,
1867 Node::child_property,
1868 Node::child_property_cases,
1869 Node::lemma_insert_child_is_child,
1870 Node::lemma_remove_child_is_none,
1871 Node::get_value_property,
1872 Node::set_value_property,
1873 Node::is_leaf_bounded,
1874 Node::lemma_recursive_visited_node_inv,
1875 Node::lemma_recursive_visited_node_levels,
1876 Node::lemma_recursive_visit_head,
1877 Node::lemma_recursive_visit_induction,
1878 Node::lemma_recursive_visit_one_is_child,
1879 Node::on_subtree_property,
1880 Node::not_on_subtree_property,
1881 Node::lemma_on_subtree_reflexive,
1882 Node::lemma_child_on_subtree,
1883 Node::lemma_insert_on_subtree,
1884 Node::lemma_recursive_remove_preserves_inv,
1890 path_between_properties,
1891 Tree::new_preserves_inv,
1892 Tree::visit_is_recursive_visit,
1893 Tree::insert_preserves_inv,
1894 Tree::remove_preserves_inv,
1895 Tree::visited_nodes_inv,
1896 Tree::on_tree_property,
1897 Tree::not_on_tree_property,
1898}
1899
1900}