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