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