Skip to main content

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