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