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