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