vstd_extra/
ghost_tree.rs

1use vstd::prelude::*;
2
3use vstd::seq::*;
4use vstd::seq_lib::*;
5
6use super::ownership::*;
7use super::seq_extra::*;
8
9verus! {
10
11/// Path from the current node to the leaf of the tree
12/// `N` is the maximum number of children of a tree node
13/// `TreePath.index(i)` returns the `i`-th element of the path
14#[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!
334verus! {
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
362/// A ghost tree node with maximum `N` children,
363/// the maximum depth of the tree is `L`
364/// Each tree node has a value of type `T` and a sequence of children
365pub 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            // leaf nodes
498            true
499        } else {
500            // pass invariants to children
501            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    /// Visit the tree node recursively based on the path
988    /// Returns a sequence of visited node values, including the initial one
989    /// If the path does not correspond to a node, stop the traverse, and return the
990    /// previously visited nodes.
991    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    /// Walk to the end of a path and return the subtree at the end
1061    /// Returns a single node (with its children)
1062    /// If the path does not correspond to a node, return None
1063    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    /// Visit the tree node recursively based on the path
1141    /// Returns a sequence of visited nodes, exclude the given one
1142    /// If the path is empty, return an empty sequence
1143    /// If the tree node is absent, stop the traverse, and return the
1144    /// previously visited nodes.
1145    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    // #[verifier::external_body]
1243    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 broadcast proof fn lemma_recursive_visit_step(self, path: TreePath<N>)
1293    //     requires
1294    //         self.inv(),
1295    //         path.inv(),
1296    //         path.len() < L - self.level,
1297    //         path.len() > 1,
1298    //         self.recursive_visit(path).len() == path.len(),
1299    //     ensures
1300    //         #[trigger]
1301    //         self.recursive_visit(path.pop_tail().1) =~= self.recursive_visit(path).drop_last(),
1302    //         self.recursive_visit(path.pop_tail().1).last().child(path.pop_tail().0) == Some(self.recursive_visit(path).last()),
1303    // {
1304    //     admit();
1305    // }
1306    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 broadcast proof fn lemma_remove_not_on_subtree(self, key: usize, node: Self)
1386    //     requires
1387    //         0 <= key < Self::size(),
1388    //         self.inv(),
1389    //         node.inv(),
1390    //         node.level == self.level + 1,
1391    //         self.child(key) == Some(node),
1392    //     ensures
1393    //         !#[trigger] self.remove(key).on_subtree(node),
1394    // {
1395    //     admit();  // TODO
1396    // }
1397    // pub broadcast proof fn lemma_recursive_insert_on_subtree(self, path: TreePath<N>, node: Self)
1398    //     requires
1399    //         self.inv(),
1400    //         path.inv(),
1401    //         node.inv(),
1402    //         path.len() < L - self.level,
1403    //         node.level == self.level + path.len() as nat,
1404    //     ensures
1405    //         #[trigger] self.recursive_insert(path, node).on_subtree(node),
1406    //     decreases path.len(),
1407    // {
1408    //     admit();  // TODO
1409    // }
1410    // pub broadcast proof fn lemma_recursive_remove_not_on_subtree(
1411    //     self,
1412    //     path: TreePath<N>,
1413    //     node: Self,
1414    // )
1415    //     requires
1416    //         self.inv(),
1417    //         path.inv(),
1418    //         node.inv(),
1419    //         path.len() < L - self.level,
1420    //         node.level == self.level + path.len() as nat,
1421    //         self.recursive_visit(path).last() == node,
1422    //     ensures
1423    //         !#[trigger] self.recursive_remove(path).on_subtree(node),
1424    //     decreases path.len(),
1425    // {
1426    //     admit();  // TODO
1427    // }
1428    // pub broadcast proof fn lemma_recursive_visit_on_subtree(self, path: TreePath<N>)
1429    //     requires
1430    //         self.inv(),
1431    //         path.inv(),
1432    //         path.len() < L - self.level,
1433    //         path.len() > 0,
1434    //         #[trigger] self.recursive_visit(path).len() > 0,
1435    //     ensures
1436    //         forall|i: int|
1437    //             0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.on_subtree(
1438    //                 self.recursive_visit(path)[i],
1439    //             ),
1440    // {
1441    //     admit();  // TODO
1442    // }
1443    // pub proof fn level_increases(self)
1444    //     requires
1445    //         self.inv(),
1446    //         self.level < L,
1447    //     ensures
1448    //         forall|i: int|
1449    //             0 <= i < Self::size() && #[trigger] self.children[i] is Some
1450    //                 ==> self.children[i]->Some_0.level > self.level,
1451    // {
1452    //     if self.level == Self::max_depth() - 1 {
1453    //         assert(self.is_leaf());
1454    //     }
1455    // }
1456    // pub broadcast proof fn remaining_level_decreases(self)
1457    //     requires
1458    //         #[trigger] self.inv(),
1459    //         #[trigger] self.level < L,
1460    //     ensures
1461    //         forall|i: int|
1462    //             0 <= i < Self::size() && #[trigger] self.children[i] is Some ==> (L
1463    //                 - self.children[i]->Some_0.level) < (L - self.level),
1464    // {
1465    //     self.level_increases();
1466    // }
1467    /// Remove the tree node at the end of the path
1468    /// If the path is empty or any node in the path is absent,
1469    /// return the original tree node (no change)
1470    /// Otherwise, remove the node at the end of the path, and
1471    /// update the node recursively
1472    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!
1579verus! {
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!
1622verus! {
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!
1888verus! {
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_remove_not_on_subtree,
1930    // Node::lemma_recursive_insert_on_subtree,
1931    // Node::lemma_recursive_remove_not_on_subtree,
1932    // Node::lemma_recursive_visit_on_subtree,
1933    // Node::remaining_level_decreases,
1934    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} // verus!