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 proof fn tracked_new_val(tracked val: T, lv: nat) -> (tracked res: Self)
598 requires
599 0 <= lv < L,
600 N > 0,
601 val.inv(),
602 val.la_inv(lv),
603 forall|i: int| 0 <= i < N ==> #[trigger] val.rel_children(i, None),
604 ensures
605 res.inv(),
606 returns
607 Self::new_val(val, lv),
608 {
609 proof fn tracked_none_seq<A>(n: nat) -> (tracked res: Seq<Option<A>>)
610 ensures
611 res == Seq::new(n, |i| None),
612 decreases n,
613 {
614 if n == 0 {
615 Seq::tracked_empty()
616 } else {
617 let tracked mut res = tracked_none_seq((n - 1) as nat);
618 res.tracked_push(None);
619 res
620 }
621 }
622 let tracked children = tracked_none_seq(N as nat);
623 Self::tracked_new(val, lv, children)
624 }
625
626 pub proof fn lemma_new_default_preserves_inv(lv: nat)
627 requires
628 0 <= lv < L,
629 N > 0,
630 forall|i: int| 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
631 ensures
632 Self::new_default(lv).inv(),
633 {
634 T::lemma_default_preserves_inv();
635 T::lemma_default_preserves_la_inv();
636 }
637
638 pub open spec fn insert(self, key: int, node: Self) -> Self
640 recommends
641 0 <= key < Self::size(),
642 node.level() == self.level() + 1,
643 {
644 Self::new(self.value(), self.level(), self.children().update(key, Some(node)))
645 }
646
647 pub broadcast proof fn lemma_insert_preserves_inv(self, key: int, node: Self)
648 requires
649 self.inv(),
650 node.inv(),
651 node.level() == self.level() + 1,
652 self.value().rel_children(key, Some(node.value())),
653 ensures
654 #![trigger self.insert(key, node)]
655 self.insert(key, node).inv(),
656 {
657 }
658
659 pub broadcast proof fn lemma_insert_property(self, key: int, node: Self)
660 requires
661 0 <= key < Self::size(),
662 self.inv(),
663 ensures
664 #![trigger self.insert(key, node)]
665 self.insert(key, node).value() == self.value(),
666 self.insert(key, node).children()[key] == Some(node),
667 self.insert(key, node).children() == self.children().update(key, Some(node)),
668 {
669 }
670
671 pub proof fn lemma_insert_same_child_identical(self, key: int, node: Self)
672 requires
673 0 <= key < Self::size(),
674 self.inv(),
675 self.has_child(key),
676 self.child(key) == node,
677 ensures
678 self.insert(key, node) == self,
679 {
680 self.lemma_insert_property(key, node);
681 assert(self.insert(key, node).children() == self.children());
682 }
683
684 pub open spec fn remove(self, key: int) -> Self
685 recommends
686 0 <= key < Self::size(),
687 {
688 Self::new(self.value(), self.level(), self.children().update(key, None))
689 }
690
691 pub broadcast proof fn lemma_remove_preserves_inv(self, key: int)
692 requires
693 0 <= key < Self::size(),
694 self.inv(),
695 self.children()[key] is None || self.value().rel_children(key, None),
696 ensures
697 (#[trigger] self.remove(key)).inv(),
698 {
699 }
700
701 pub broadcast proof fn lemma_remove_property(self, key: int)
702 requires
703 0 <= key < Self::size(),
704 self.inv(),
705 ensures
706 #![trigger self.remove(key)]
707 self.remove(key).value() == self.value(),
708 self.remove(key).children()[key] is None,
709 self.remove(key).children() == self.children().update(key, None),
710 {
711 }
712
713 pub proof fn lemma_insert_child_is_child(self, key: int, node: Self)
714 requires
715 0 <= key < Self::size(),
716 self.inv(),
717 node.inv(),
718 self.level() < L - 1,
719 node.level() == self.level() + 1,
720 ensures
721 self.insert(key, node).has_child(key),
722 self.insert(key, node).child(key) == node,
723 {
724 self.lemma_insert_property(key, node);
725 }
726
727 pub proof fn lemma_remove_child_is_none(self, key: int)
728 requires
729 0 <= key < Self::size(),
730 self.inv(),
731 ensures
732 !self.remove(key).has_child(key),
733 {
734 self.lemma_remove_property(key);
735 }
736
737 pub open spec fn set_value(self, value: T) -> Self
738 recommends
739 self.inv(),
740 value.inv(),
741 {
742 Self::new(value, self.level(), self.children())
743 }
744
745 pub broadcast proof fn lemma_set_value_observable_fields(self, value: T)
747 ensures
748 #![trigger self.set_value(value)]
749 (#[trigger] self.set_value(value)).value() == value,
750 self.set_value(value).level() == self.level(),
751 self.set_value(value).children() == self.children(),
752 {
753 Self::lemma_new_properties(value, self.level(), self.children());
754 }
755
756 pub proof fn lemma_set_value_preserves_new_val_shape(self, value: T)
758 requires
759 self == Self::new_val(self.value(), self.level()),
760 ensures
761 self.set_value(value) == Self::new_val(value, self.level()),
762 {
763 self.lemma_set_value_observable_fields(value);
764 Self::lemma_new_properties(value, self.level(), Seq::new(N as nat, |i| None));
765 Self::lemma_ext_equal(self.set_value(value), Self::new_val(value, self.level()));
766 }
767
768 pub open spec fn is_leaf(self) -> bool {
769 forall|i: int| 0 <= i < Self::size() ==> !#[trigger] self.has_child(i)
770 }
771
772 pub broadcast proof fn lemma_is_leaf_bounded(self)
773 requires
774 self.inv(),
775 self.level() == L - 1,
776 ensures
777 #[trigger] self.is_leaf(),
778 {
779 }
780
781 pub open spec fn recursive_insert(self, path: TreePath<N>, node: Self) -> Self
782 recommends
783 self.inv(),
784 path.inv(),
785 path.len() < L - self.level(),
786 node.level() == self.level() + path.len() as nat,
787 decreases path.len(),
788 {
789 if path.is_empty() {
790 self
791 } else if path.len() == 1 {
792 self.insert(path[0], node)
793 } else {
794 let (hd, tl) = path.pop_head();
795 let child = if self.has_child(hd) {
796 self.child(hd)
797 } else {
798 TreeNode::new_default(self.level() + 1)
799 };
800 let updated_child = child.recursive_insert(tl, node);
801 self.insert(hd, updated_child)
802 }
803 }
804
805 pub proof fn lemma_recursive_insert_path_empty_identical(self, path: TreePath<N>, node: Self)
806 requires
807 self.inv(),
808 node.inv(),
809 path.inv(),
810 path.is_empty(),
811 ensures
812 self.recursive_insert(path, node) == self,
813 {
814 }
815
816 pub proof fn lemma_recursive_insert_path_len_1(self, path: TreePath<N>, node: Self)
817 requires
818 self.inv(),
819 node.inv(),
820 path.inv(),
821 path.len() == 1,
822 1 < L - self.level(),
823 node.level() == self.level() + 1,
824 ensures
825 self.recursive_insert(path, node) == self.insert(path[0], node),
826 {
827 }
828
829 pub proof fn lemma_recursive_insert_path_len_step(self, path: TreePath<N>, node: Self)
830 requires
831 self.inv(),
832 path.inv(),
833 node.inv(),
834 path.len() < L - self.level(),
835 node.level() == self.level() + path.len() as nat,
836 path.len() > 1,
837 ensures
838 self.has_child(path[0]) ==> self.recursive_insert(path, node) == self.insert(
839 path[0],
840 self.child(path[0]).recursive_insert(path.pop_head().1, node),
841 ),
842 !self.has_child(path[0]) ==> self.recursive_insert(path, node) == self.insert(
843 path[0],
844 TreeNode::new_default(self.level() + 1).recursive_insert(path.pop_head().1, node),
845 ),
846 {
847 }
848
849 pub proof fn lemma_recursive_insert_preserves_level(self, path: TreePath<N>, node: Self)
850 requires
851 self.inv(),
852 path.inv(),
853 node.inv(),
854 path.len() < L - self.level(),
855 node.level() == self.level() + path.len() as nat,
856 forall|lv: nat|
857 lv < L ==> #[trigger] T::default(lv).rel_children(path.pop_tail().0 as int, None),
858 ensures
859 self.recursive_insert(path, node).level() == self.level(),
860 decreases path.len(),
861 {
862 if path.is_empty() {
863 self.lemma_recursive_insert_path_empty_identical(path, node);
864 } else if path.len() == 1 {
865 path.lemma_index_satisfies_elem_inv(0);
866 self.lemma_recursive_insert_path_len_1(path, node);
867 assert(self.insert(path[0], node).level() == self.level());
868 } else {
869 self.lemma_recursive_insert_path_len_step(path, node);
870 let (hd, tl) = path.pop_head();
871 path.lemma_pop_head_preserves_inv();
872 if self.has_child(hd) {
873 let c = self.child(hd);
874 assert(self.insert(hd, c.recursive_insert(tl, node)).level() == self.level());
875 } else {
876 let c = TreeNode::new_default(self.level() + 1);
877 assert(self.insert(hd, c.recursive_insert(tl, node)).level() == self.level());
878 }
879 }
880 }
881
882 pub proof fn lemma_recursive_insert_preserves_value(self, path: TreePath<N>, node: Self)
883 requires
884 self.inv(),
885 path.inv(),
886 node.inv(),
887 path.len() < L - self.level(),
888 node.level() == self.level() + path.len() as nat,
889 forall|lv: nat, i: int|
890 lv < L && 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
891 ensures
892 self.recursive_insert(path, node).value() == self.value(),
893 decreases path.len(),
894 {
895 if path.is_empty() {
896 self.lemma_recursive_insert_path_empty_identical(path, node);
897 } else if path.len() == 1 {
898 path.lemma_index_satisfies_elem_inv(0);
899 self.lemma_recursive_insert_path_len_1(path, node);
900 } else {
901 self.lemma_recursive_insert_path_len_step(path, node);
902 let (hd, tl) = path.pop_head();
903 path.lemma_pop_head_preserves_inv();
904 if self.has_child(hd) {
905 let c = self.child(hd);
906 c.lemma_recursive_insert_preserves_value(tl, node);
907 } else {
908 let c = TreeNode::new_default(self.level() + 1);
909 Self::lemma_new_default_preserves_inv(self.level() + 1);
910 c.lemma_recursive_insert_preserves_value(tl, node);
911 }
912 }
913 }
914
915 pub proof fn lemma_recursive_insert_preserves_inv(self, path: TreePath<N>, node: Self)
916 requires
917 self.inv(),
918 path.inv(),
919 node.inv(),
920 path.len() < L - self.level(),
921 node.level() == self.level() + path.len() as nat,
922 self.recursive_seek(path.pop_tail().1) is Some ==> self.recursive_seek(
923 path.pop_tail().1,
924 )->0.value().rel_children(path.pop_tail().0 as int, Some(node.value())),
925 self.recursive_seek(path.pop_tail().1) is None ==> T::default(
926 (node.level() - 1) as nat,
927 ).rel_children(path.pop_tail().0 as int, Some(node.value())),
928 forall|lv: nat, i: int|
929 lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
930 ensures
931 self.recursive_insert(path, node).inv(),
932 decreases path.len(),
933 {
934 if path.is_empty() {
935 self.lemma_recursive_insert_path_empty_identical(path, node);
936 } else if path.len() == 1 {
937 path.lemma_index_satisfies_elem_inv(0);
938 self.lemma_recursive_insert_path_len_1(path, node);
939 self.lemma_insert_preserves_inv(path[0], node);
940 } else {
941 self.lemma_recursive_insert_path_len_step(path, node);
942 let (hd, tl) = path.pop_head();
943 path.lemma_pop_head_preserves_inv();
944 if self.has_child(hd) {
945 let c = self.child(hd);
946 assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
947 c.lemma_recursive_insert_preserves_inv(tl, node);
948 c.lemma_recursive_insert_preserves_level(tl, node);
949 c.lemma_recursive_insert_preserves_value(tl, node);
950 let updated_child = c.recursive_insert(tl, node);
951 self.lemma_insert_preserves_inv(hd, updated_child);
952 } else {
953 let c = TreeNode::new_default(self.level() + 1);
954 Self::lemma_new_default_preserves_inv(self.level() + 1);
955 self.value().lemma_default_preserves_rel_children(self.level());
956 c.lemma_recursive_insert_preserves_inv(tl, node);
957 c.lemma_recursive_insert_preserves_level(tl, node);
958 c.lemma_recursive_insert_preserves_value(tl, node);
959 let updated_child = c.recursive_insert(tl, node);
960 self.lemma_insert_preserves_inv(hd, updated_child);
961 }
962 }
963 }
964
965 pub open spec fn recursive_trace(self, path: TreePath<N>) -> Seq<T>
970 recommends
971 self.inv(),
972 path.inv(),
973 path.len() < L - self.level(),
974 decreases path.len(),
975 {
976 if path.is_empty() {
977 seq![self.value()]
978 } else {
979 let (hd, tl) = path.pop_head();
980 if self.has_child(hd) {
981 seq![self.value()].add(self.child(hd).recursive_trace(tl))
982 } else {
983 seq![self.value()]
984 }
985 }
986 }
987
988 pub proof fn lemma_recursive_trace_length(self, path: TreePath<N>)
989 requires
990 self.inv(),
991 path.inv(),
992 ensures
993 #[trigger] self.recursive_trace(path).len() <= path.len() + 1,
994 decreases path.len(),
995 {
996 if path.len() == 0 {
997 } else {
998 let (hd, tl) = path.pop_head();
999 path.lemma_pop_head_preserves_inv();
1000 if self.has_child(hd) {
1001 self.child(hd).lemma_recursive_trace_length(tl);
1002 }
1003 }
1004 }
1005
1006 pub proof fn lemma_recursive_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1007 requires
1008 self.inv(),
1009 path1.inv(),
1010 path2.inv(),
1011 n <= path1.len(),
1012 n <= path2.len(),
1013 forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1014 self.recursive_trace(path1).len() > n,
1015 ensures
1016 self.recursive_trace(path2).len() > n,
1017 forall|i: int|
1018 0 <= i <= n ==> self.recursive_trace(path1)[i] == self.recursive_trace(path2)[i],
1019 decreases n,
1020 {
1021 if n <= 0 {
1022 } else {
1023 let (hd1, tl1) = path1.pop_head();
1024 let (hd2, tl2) = path2.pop_head();
1025 if self.has_child(hd1) {
1026 path1.lemma_pop_head_preserves_inv();
1027 path2.lemma_pop_head_preserves_inv();
1028 self.child(hd1).lemma_recursive_trace_up_to(tl1, tl2, n - 1);
1029 }
1030 }
1031 }
1032
1033 pub open spec fn recursive_seek(self, path: TreePath<N>) -> Option<Self>
1037 recommends
1038 self.inv(),
1039 path.inv(),
1040 path.len() < L - self.level(),
1041 decreases path.len(),
1042 {
1043 if path.is_empty() {
1044 Some(self)
1045 } else {
1046 let (hd, tl) = path.pop_head();
1047 if self.has_child(hd) {
1048 self.child(hd).recursive_seek(tl)
1049 } else {
1050 None
1051 }
1052 }
1053 }
1054
1055 pub proof fn lemma_recursive_seek_trace_length(self, path: TreePath<N>)
1056 requires
1057 self.inv(),
1058 path.inv(),
1059 path.len() < L - self.level(),
1060 self.recursive_seek(path) is Some,
1061 ensures
1062 self.recursive_trace(path).len() == path.len() + 1,
1063 decreases path.len(),
1064 {
1065 if path.len() == 0 {
1066 } else {
1067 let (hd, tl) = path.pop_head();
1068 if self.has_child(hd) {
1069 path.lemma_pop_head_preserves_inv();
1070 self.child(hd).lemma_recursive_seek_trace_length(tl)
1071 }
1072 }
1073 }
1074
1075 pub proof fn lemma_recursive_seek_trace_next(self, path: TreePath<N>, idx: usize)
1076 requires
1077 self.recursive_seek(path) is Some,
1078 self.recursive_seek(path)->0.has_child(idx as int),
1079 self.inv(),
1080 path.inv(),
1081 path.len() < L - self.level(),
1082 0 <= idx < N,
1083 ensures
1084 self.recursive_trace(path.push_tail(idx as int)).len() == path.len() + 2,
1085 self.recursive_seek(path)->0.child(idx as int).value() == self.recursive_trace(
1086 path.push_tail(idx as int),
1087 )[path.len() as int + 1],
1088 decreases path.len(),
1089 {
1090 let path2 = path.push_tail(idx as int);
1091
1092 if path.len() == 0 {
1093 assert(self.recursive_trace(path2) == seq![
1094 self.value(),
1095 self.child(idx as int).value(),
1096 ]) by { reveal_with_fuel(TreeNode::recursive_trace, 2) }
1097 } else {
1098 let (_, tl1) = path.pop_head();
1099 let (hd2, tl2) = path2.pop_head();
1100 assert(tl2 == tl1.push_tail(idx as int)) by {}
1101 assert(tl1.inv()) by { path.lemma_pop_head_preserves_inv() }
1102 if self.has_child(hd2) {
1103 self.child(hd2).lemma_recursive_seek_trace_next(tl1, idx);
1104 }
1105 }
1106 }
1107
1108 pub open spec fn recursive_visit(self, path: TreePath<N>) -> Seq<Self>
1114 recommends
1115 self.inv(),
1116 path.inv(),
1117 path.len() < L - self.level(),
1118 decreases path.len(),
1119 {
1120 if path.is_empty() {
1121 Seq::empty()
1122 } else if path.len() == 1 {
1123 if self.has_child(path[0]) {
1124 seq![self.child(path[0])]
1125 } else {
1126 Seq::empty()
1127 }
1128 } else {
1129 let (hd, tl) = path.pop_head();
1130 if self.has_child(hd) {
1131 let child = self.child(hd);
1132 seq![child].add(child.recursive_visit(tl))
1133 } else {
1134 Seq::empty()
1135 }
1136 }
1137 }
1138
1139 pub proof fn lemma_recursive_visited_node_inv(self, path: TreePath<N>)
1140 requires
1141 self.inv(),
1142 path.inv(),
1143 path.len() < L - self.level(),
1144 ensures
1145 forall|i: int|
1146 0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1147 path,
1148 )[i].inv(),
1149 decreases path.len(),
1150 {
1151 if path.is_empty() {
1152 } else if path.len() == 1 {
1153 if self.has_child(path[0]) {
1154 }
1155 } else {
1156 let (hd, tl) = path.pop_head();
1157 path.lemma_pop_head_preserves_inv();
1158 if self.has_child(hd) {
1159 let c = self.child(hd);
1160 assert(self.recursive_visit(path) == seq![c].add(c.recursive_visit(tl)));
1161 c.lemma_recursive_visited_node_inv(tl);
1162 }
1163 }
1164 }
1165
1166 pub proof fn lemma_recursive_visited_node_levels(self, path: TreePath<N>)
1167 requires
1168 self.inv(),
1169 path.inv(),
1170 path.len() < L - self.level(),
1171 ensures
1172 forall|i: int|
1173 0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1174 path,
1175 )[i].level() == self.level() + i + 1,
1176 decreases path.len(),
1177 {
1178 if path.is_empty() {
1179 } else if path.len() == 1 {
1180 if self.has_child(path[0]) {
1181 }
1182 } else {
1183 let (hd, tl) = path.pop_head();
1184 path.lemma_pop_head_preserves_inv();
1185 if self.has_child(hd) {
1186 let c = self.child(hd);
1187 assert(self.recursive_visit(path) == seq![c].add(c.recursive_visit(tl)));
1188 c.lemma_recursive_visited_node_levels(tl);
1189 }
1190 }
1191 }
1192
1193 pub proof fn lemma_recursive_visit_head(self, path: TreePath<N>)
1194 requires
1195 self.inv(),
1196 path.inv(),
1197 path.len() < L - self.level(),
1198 !path.is_empty(),
1199 self.recursive_visit(path).len() > 0,
1200 ensures
1201 self.recursive_visit(path)[0] == self.child(path[0]),
1202 {
1203 }
1204
1205 pub proof fn lemma_recursive_visit_induction(self, path: TreePath<N>)
1206 requires
1207 self.inv(),
1208 path.inv(),
1209 path.len() < L - self.level(),
1210 !path.is_empty(),
1211 self.recursive_visit(path).len() > 0,
1212 ensures
1213 self.recursive_visit(path) == seq![self.child(path.pop_head().0)].add(
1214 self.child(path.pop_head().0).recursive_visit(path.pop_head().1),
1215 ),
1216 {
1217 if path.len() == 1 {
1218 path.lemma_pop_head_preserves_inv();
1219 } else {
1220 let (hd, _) = path.pop_head();
1221 path.lemma_pop_head_preserves_inv();
1222 if self.has_child(hd) {
1223 self.lemma_recursive_visit_head(path);
1224 }
1225 }
1226 }
1227
1228 pub proof fn lemma_recursive_visit_one_is_child(self, path: TreePath<N>)
1229 requires
1230 self.inv(),
1231 path.inv(),
1232 path.len() < L - self.level(),
1233 path.len() == 1,
1234 ensures
1235 self.has_child(path[0]) ==> self.recursive_visit(path) == seq![self.child(path[0])],
1236 !self.has_child(path[0]) ==> self.recursive_visit(path) == seq![],
1237 {
1238 }
1239
1240 pub open spec fn on_subtree(self, node: Self) -> bool
1241 recommends
1242 self.inv(),
1243 node.inv(),
1244 node.level() >= self.level(),
1245 node.level() < L,
1246 {
1247 node == self || exists|path: TreePath<N>| #[trigger]
1248 path.inv() && path.len() > 0 && path.len() == node.level() - self.level()
1249 && self.recursive_visit(path).last() == node
1250 }
1251
1252 pub broadcast proof fn lemma_on_subtree_property(self, node: Self)
1253 requires
1254 self.inv(),
1255 node.inv(),
1256 node.level() >= self.level(),
1257 node.level() < L,
1258 #[trigger] self.on_subtree(node),
1259 ensures
1260 node.level() == self.level() ==> self == node,
1261 node.level() > self.level() ==> exists|path: TreePath<N>| #[trigger]
1262 path.inv() && path.len() == node.level() - self.level() && self.recursive_visit(
1263 path,
1264 ).last() == node,
1265 {
1266 }
1267
1268 pub broadcast proof fn lemma_not_on_subtree_property(self, node: Self)
1269 requires
1270 self.inv(),
1271 node.inv(),
1272 node.level() < L,
1273 !#[trigger] self.on_subtree(node),
1274 ensures
1275 self != node,
1276 node.level() > self.level() ==> forall|path: TreePath<N>| #[trigger]
1277 path.inv() && path.len() == node.level() - self.level() ==> self.recursive_visit(
1278 path,
1279 ).last() != node,
1280 {
1281 }
1282
1283 pub broadcast proof fn lemma_on_subtree_reflexive(self)
1284 requires
1285 self.inv(),
1286 ensures
1287 #[trigger] self.on_subtree(self),
1288 {
1289 }
1290
1291 pub broadcast proof fn lemma_child_on_subtree(self, key: int)
1292 requires
1293 0 <= key < Self::size(),
1294 self.inv(),
1295 self.has_child(key),
1296 ensures
1297 #[trigger] self.on_subtree(self.child(key)),
1298 {
1299 assert(TreePath::<N>::new(seq![key]).inv());
1300 }
1301
1302 pub broadcast proof fn lemma_insert_on_subtree(self, key: int, node: Self)
1303 requires
1304 0 <= key < Self::size(),
1305 self.inv(),
1306 node.inv(),
1307 self.level() < L - 1,
1308 node.level() == self.level() + 1,
1309 self.value().rel_children(key, Some(node.value())),
1310 ensures
1311 #[trigger] self.insert(key, node).on_subtree(node),
1312 {
1313 self.lemma_insert_child_is_child(key, node);
1314 self.insert(key, node).lemma_child_on_subtree(key);
1315 }
1316
1317 pub open spec fn recursive_remove(self, path: TreePath<N>) -> Self
1323 recommends
1324 self.inv(),
1325 path.inv(),
1326 path.len() < L - self.level(),
1327 decreases path.len(),
1328 {
1329 if path.is_empty() {
1330 self
1331 } else if path.len() == 1 {
1332 self.remove(path[0])
1333 } else {
1334 let (hd, tl) = path.pop_head();
1335 if self.children()[hd as int] is None {
1336 self
1337 } else {
1338 let child = self.child(hd);
1339 let updated_child = child.recursive_remove(tl);
1340 self.insert(hd, updated_child)
1341 }
1342 }
1343 }
1344
1345 pub proof fn lemma_recursive_remove_preserves_level(self, path: TreePath<N>)
1346 requires
1347 self.inv(),
1348 path.inv(),
1349 path.len() < L - self.level(),
1350 ensures
1351 self.recursive_remove(path).level() == self.level(),
1352 decreases path.len(),
1353 {
1354 if path.is_empty() {
1355 } else if path.len() == 1 {
1356 } else {
1357 let (hd, tl) = path.pop_head();
1358 path.lemma_pop_head_preserves_inv();
1359 if self.has_child(hd) {
1360 let c = self.child(hd);
1361 c.lemma_recursive_remove_preserves_level(tl);
1362 }
1363 }
1364 }
1365
1366 pub proof fn lemma_recursive_remove_preserves_value(self, path: TreePath<N>)
1367 requires
1368 self.inv(),
1369 path.inv(),
1370 path.len() < L - self.level(),
1371 ensures
1372 self.recursive_remove(path).value() == self.value(),
1373 decreases path.len(),
1374 {
1375 if path.is_empty() {
1376 } else if path.len() == 1 {
1377 } else {
1378 let (hd, tl) = path.pop_head();
1379 path.lemma_pop_head_preserves_inv();
1380 if self.has_child(hd) {
1381 let c = self.child(hd);
1382 c.lemma_recursive_remove_preserves_value(tl);
1383 }
1384 }
1385 }
1386
1387 pub proof fn lemma_recursive_remove_preserves_inv(self, path: TreePath<N>)
1388 requires
1389 self.inv(),
1390 path.inv(),
1391 path.len() < L - self.level(),
1392 path.len() > 0 ==> self.recursive_seek(path.pop_tail().1) is Some
1393 ==> self.recursive_seek(
1394 path.pop_tail().1,
1395 )->0.children()[path.pop_tail().0 as int] is None || self.recursive_seek(
1396 path.pop_tail().1,
1397 )->0.value().rel_children(path.pop_tail().0 as int, None),
1398 ensures
1399 self.recursive_remove(path).inv(),
1400 decreases path.len(),
1401 {
1402 if path.is_empty() {
1403 } else if path.len() == 1 {
1404 self.lemma_remove_preserves_inv(path[0]);
1405 } else {
1406 let (hd, tl) = path.pop_head();
1407 path.lemma_pop_head_preserves_inv();
1408 if self.has_child(hd) {
1409 let c = self.child(hd);
1410 assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
1411 c.lemma_recursive_remove_preserves_inv(tl);
1412 c.lemma_recursive_remove_preserves_level(tl);
1413 c.lemma_recursive_remove_preserves_value(tl);
1414 let updated_child = c.recursive_remove(tl);
1415 self.lemma_insert_preserves_inv(hd, updated_child);
1416 }
1417 }
1418 }
1419}
1420
1421pub closed spec fn path_between<T: TreeNodeValue<L>, const N: usize, const L: usize>(
1422 src: TreeNode<T, N, L>,
1423 dst: TreeNode<T, N, L>,
1424) -> TreePath<N>
1425 recommends
1426 src.inv(),
1427 dst.inv(),
1428 src.level() <= dst.level(),
1429 src.on_subtree(dst),
1430{
1431 if src.inv() && dst.inv() && dst.level() >= src.level() && dst.level() < L && src.on_subtree(
1432 dst,
1433 ) {
1434 if src == dst {
1435 TreePath::new(seq![])
1436 } else {
1437 choose|path: TreePath<N>| #[trigger]
1438 path.inv() && path.len() > 0 && path.len() == dst.level() - src.level()
1439 && src.recursive_visit(path).last() == dst
1440 }
1441 } else {
1442 vstd::pervasive::arbitrary()
1443 }
1444}
1445
1446pub broadcast proof fn lemma_path_between_properties<
1447 T: TreeNodeValue<L>,
1448 const N: usize,
1449 const L: usize,
1450>(src: TreeNode<T, N, L>, dst: TreeNode<T, N, L>)
1451 requires
1452 src.inv(),
1453 dst.inv(),
1454 src.level() <= dst.level(),
1455 #[trigger] src.on_subtree(dst),
1456 ensures
1457 path_between(src, dst).inv(),
1458 path_between(src, dst).len() == dst.level() - src.level(),
1459 dst.level() == src.level() ==> path_between(src, dst).is_empty() && src == dst,
1460 dst.level() > src.level() ==> src.recursive_visit(path_between(src, dst)).last() == dst,
1461{
1462}
1463
1464} verus! {
1466
1467pub tracked struct Tree<T: TreeNodeValue<L>, const N: usize, const L: usize> {
1468 pub tracked root: TreeNode<T, N, L>,
1469}
1470
1471impl<T: TreeNodeValue<L>, const N: usize, const L: usize> Tree<T, N, L> {
1472 pub open spec fn inv(self) -> bool {
1473 &&& L > 0
1474 &&& N > 0
1475 &&& self.root.inv()
1476 &&& self.root.level() == 0
1477 }
1478
1479 pub open spec fn new() -> Self {
1480 Tree { root: TreeNode::new_default(0) }
1481 }
1482
1483 pub broadcast proof fn lemma_new_preserves_inv()
1484 requires
1485 N > 0,
1486 L > 0,
1487 forall|i: int| 0 <= i < N ==> #[trigger] T::default(0).rel_children(i, None),
1488 ensures
1489 (#[trigger] Self::new()).inv(),
1490 {
1491 TreeNode::<T, N, L>::lemma_new_default_preserves_inv(0);
1492 }
1493
1494 pub open spec fn insert(self, path: TreePath<N>, node: TreeNode<T, N, L>) -> Self
1495 recommends
1496 self.inv(),
1497 path.inv(),
1498 node.inv(),
1499 path.len() < L,
1500 node.level() == path.len() as nat,
1501 decreases path.len(),
1502 {
1503 Tree { root: self.root.recursive_insert(path, node), ..self }
1504 }
1505
1506 pub open spec fn remove(self, path: TreePath<N>) -> Self
1507 recommends
1508 self.inv(),
1509 path.inv(),
1510 path.len() < L,
1511 decreases path.len(),
1512 {
1513 Tree { root: self.root.recursive_remove(path), ..self }
1514 }
1515
1516 pub open spec fn visit(self, path: TreePath<N>) -> Seq<TreeNode<T, N, L>>
1517 recommends
1518 self.inv(),
1519 path.inv(),
1520 path.len() < L,
1521 decreases path.len(),
1522 {
1523 self.root.recursive_visit(path)
1524 }
1525
1526 pub open spec fn trace(self, path: TreePath<N>) -> Seq<T>
1527 recommends
1528 self.inv(),
1529 path.inv(),
1530 path.len() < L,
1531 decreases path.len(),
1532 {
1533 self.root.recursive_trace(path)
1534 }
1535
1536 pub broadcast proof fn lemma_trace_empty_is_head(self, path: TreePath<N>)
1537 requires
1538 path.len() == 0,
1539 ensures
1540 #[trigger] self.trace(path) == seq![self.root.value()],
1541 {
1542 }
1543
1544 pub proof fn lemma_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1545 requires
1546 self.inv(),
1547 path1.inv(),
1548 path2.inv(),
1549 n <= path1.len(),
1550 n <= path2.len(),
1551 forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1552 self.trace(path1).len() > n,
1553 ensures
1554 self.trace(path2).len() > n,
1555 forall|i: int| 0 <= i <= n ==> self.trace(path1)[i] == self.trace(path2)[i],
1556 {
1557 self.root.lemma_recursive_trace_up_to(path1, path2, n)
1558 }
1559
1560 pub broadcast proof fn lemma_trace_length(self, path: TreePath<N>)
1561 requires
1562 self.inv(),
1563 path.inv(),
1564 ensures
1565 #[trigger] self.trace(path).len() <= path.len() + 1,
1566 {
1567 self.root.lemma_recursive_trace_length(path);
1568 }
1569
1570 pub open spec fn seek(self, path: TreePath<N>) -> Option<TreeNode<T, N, L>> {
1571 self.root.recursive_seek(path)
1572 }
1573
1574 pub proof fn lemma_seek_trace_length(self, path: TreePath<N>)
1575 requires
1576 self.inv(),
1577 path.inv(),
1578 path.len() < L,
1579 self.seek(path) is Some,
1580 ensures
1581 self.trace(path).len() == path.len() + 1,
1582 {
1583 self.root.lemma_recursive_seek_trace_length(path)
1584 }
1585
1586 pub proof fn lemma_seek_trace_next(self, path: TreePath<N>, idx: usize)
1587 requires
1588 self.seek(path) is Some,
1589 self.seek(path)->0.has_child(idx as int),
1590 self.inv(),
1591 path.inv(),
1592 path.len() < L,
1593 0 <= idx < N,
1594 ensures
1595 self.trace(path.push_tail(idx as int)).len() == path.len() + 2,
1596 self.seek(path)->0.child(idx as int).value() == self.trace(
1597 path.push_tail(idx as int),
1598 )[path.len() as int + 1],
1599 {
1600 self.root.lemma_recursive_seek_trace_next(path, idx)
1601 }
1602
1603 pub broadcast proof fn lemma_insert_preserves_inv(
1604 self,
1605 path: TreePath<N>,
1606 node: TreeNode<T, N, L>,
1607 )
1608 requires
1609 self.inv(),
1610 path.inv(),
1611 node.inv(),
1612 path.len() < L,
1613 node.level() == path.len() as nat,
1614 self.seek(path.pop_tail().1) is Some ==> self.seek(
1615 path.pop_tail().1,
1616 )->0.value().rel_children(path[path.len() - 1] as int, Some(node.value())),
1617 self.seek(path.pop_tail().1) is None ==> T::default(
1618 (path.len() - 1) as nat,
1619 ).rel_children(path[path.len() - 1] as int, Some(node.value())),
1620 forall|lv: nat, i: int|
1621 lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
1622 ensures
1623 (#[trigger] self.insert(path, node)).inv(),
1624 {
1625 self.root.lemma_recursive_insert_preserves_inv(path, node);
1626 }
1627
1628 pub broadcast proof fn lemma_remove_preserves_inv(self, path: TreePath<N>)
1629 requires
1630 self.inv(),
1631 path.inv(),
1632 path.len() < L,
1633 path.len() > 0 ==> self.seek(path.pop_tail().1) is Some ==> self.seek(
1634 path.pop_tail().1,
1635 )->0.children()[path.pop_tail().0 as int] is None || self.seek(
1636 path.pop_tail().1,
1637 )->0.value().rel_children(path[path.len() - 1] as int, None),
1638 ensures
1639 (#[trigger] self.remove(path)).inv(),
1640 {
1641 self.root.lemma_recursive_remove_preserves_inv(path);
1642 }
1643
1644 pub broadcast proof fn lemma_visited_nodes_inv(self, path: TreePath<N>)
1645 requires
1646 self.inv(),
1647 path.inv(),
1648 path.len() < L,
1649 ensures
1650 #![trigger self.visit(path)]
1651 forall|i: int|
1652 0 <= i < self.visit(path).len() ==> #[trigger] self.visit(path)[i].inv(),
1653 {
1654 self.root.lemma_recursive_visited_node_inv(path);
1655 }
1656
1657 pub open spec fn on_tree(self, node: TreeNode<T, N, L>) -> bool
1658 recommends
1659 self.inv(),
1660 node.inv(),
1661 {
1662 self.root.on_subtree(node)
1663 }
1664
1665 pub broadcast proof fn lemma_on_tree_property(self, node: TreeNode<T, N, L>)
1666 requires
1667 self.inv(),
1668 node.inv(),
1669 #[trigger] self.on_tree(node),
1670 ensures
1671 node.level() == 0 ==> self.root == node,
1672 node.level() > 0 ==> exists|path: TreePath<N>| #[trigger]
1673 path.inv() && path.len() == node.level() && self.visit(path).last() == node,
1674 {
1675 }
1676
1677 pub broadcast proof fn lemma_not_on_tree_property(self, node: TreeNode<T, N, L>)
1678 requires
1679 self.inv(),
1680 node.inv(),
1681 !#[trigger] self.on_tree(node),
1682 ensures
1683 node != self.root,
1684 node.level() > 0 ==> forall|path: TreePath<N>| #[trigger]
1685 path.inv() && path.len() == node.level() ==> self.visit(path).last() != node,
1686 {
1687 }
1688
1689 pub open spec fn get_path(self, node: TreeNode<T, N, L>) -> TreePath<N>
1690 recommends
1691 self.inv(),
1692 node.inv(),
1693 self.on_tree(node),
1694 {
1695 path_between::<T, N, L>(self.root, node)
1696 }
1697
1698 pub broadcast proof fn lemma_get_path_properties(self, node: TreeNode<T, N, L>)
1699 requires
1700 self.inv(),
1701 node.inv(),
1702 self.on_tree(node),
1703 ensures
1704 (#[trigger] self.get_path(node)).inv(),
1705 self.get_path(node).len() == node.level(),
1706 node.level() == 0 ==> self.get_path(node).is_empty(),
1707 node.level() > 0 ==> self.visit(self.get_path(node)).last() == node,
1708 {
1709 lemma_path_between_properties(self.root, node);
1710 }
1711}
1712
1713} verus! {
1715
1716pub broadcast group group_ghost_tree_lemmas {
1717 TreePath::lemma_index_satisfies_elem_inv,
1718 TreePath::lemma_empty_satisfies_inv,
1719 TreePath::lemma_pop_head_preserves_inv,
1720 TreePath::lemma_pop_head_index,
1721 TreePath::lemma_pop_tail_preserves_inv,
1722 TreePath::lemma_pop_tail_index,
1723 TreePath::lemma_push_head_index,
1724 TreePath::lemma_push_head_preserves_inv,
1725 TreePath::lemma_push_tail_len,
1726 TreePath::lemma_push_tail_index,
1727 TreePath::lemma_push_tail_preserves_inv,
1728 TreePath::lemma_new_preserves_inv,
1729 TreeNode::lemma_new_properties,
1730 TreeNode::lemma_new_val_properties,
1731 TreeNode::lemma_ext_equal,
1732 TreeNode::lemma_insert_preserves_inv,
1733 TreeNode::lemma_insert_property,
1734 TreeNode::lemma_remove_preserves_inv,
1735 TreeNode::lemma_remove_property,
1736 TreeNode::lemma_set_value_observable_fields,
1737 TreeNode::lemma_is_leaf_bounded,
1738 TreeNode::lemma_on_subtree_property,
1739 TreeNode::lemma_not_on_subtree_property,
1740 TreeNode::lemma_on_subtree_reflexive,
1741 TreeNode::lemma_child_on_subtree,
1742 TreeNode::lemma_insert_on_subtree,
1743 lemma_path_between_properties,
1744}
1745
1746}