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]->Some_0.tree_predicate_map(path.push_tail(i as usize), f)
407        } else {
408            &&& f(self.value, path)
409        }
410    }
411
412    pub proof fn map_unroll_once(
413        self,
414        path: TreePath<N>,
415        f: spec_fn(T, TreePath<N>) -> bool,
416        i: int,
417    )
418        requires
419            self.inv(),
420            self.level < L - 1,
421            0 <= i < self.children.len(),
422            self.children[i] is Some,
423            self.tree_predicate_map(path, f),
424        ensures
425            self.children[i]->Some_0.tree_predicate_map(path.push_tail(i as usize), f),
426    {
427    }
428
429    pub open spec fn implies(
430        f: spec_fn(T, TreePath<N>) -> bool,
431        g: spec_fn(T, TreePath<N>) -> bool,
432    ) -> bool {
433        forall|value: T, path: TreePath<N>|
434            value.inv() ==> f(value, path) ==> #[trigger] g(value, path)
435    }
436
437    pub proof fn map_implies(
438        self,
439        path: TreePath<N>,
440        f: spec_fn(T, TreePath<N>) -> bool,
441        g: spec_fn(T, TreePath<N>) -> bool,
442    )
443        requires
444            self.inv(),
445            Self::implies(f, g),
446            Self::tree_predicate_map(self, path, f),
447        ensures
448            Self::tree_predicate_map(self, path, g),
449        decreases L - self.level,
450    {
451        if self.level < L - 1 {
452            assert forall|i: int|
453                #![trigger self.children[i]->Some_0]
454                0 <= i < self.children.len()
455                    && self.children[i] is Some implies self.children[i]->Some_0.tree_predicate_map(
456                path.push_tail(i as usize),
457                g,
458            ) by {
459                self.children[i]->Some_0.map_implies(path.push_tail(i as usize), f, g);
460            }
461        }
462    }
463
464    /// `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]->Some_0]
519                0 <= i < self.children.len()
520                    && self.children[i] is Some implies self.children[i]->Some_0.tree_predicate_map(
521                path.push_tail(i as usize),
522                g,
523            ) by {
524                self.children[i]->Some_0.map_implies_and(path.push_tail(i as usize), f1, f2, g);
525            }
526        }
527    }
528
529    pub open spec fn inv_node(self) -> bool {
530        &&& self.value.inv()
531        &&& self.value.la_inv(self.level)
532        &&& self.level < L
533        &&& self.children.len() == Self::size()
534    }
535
536    pub open spec fn inv_children(self) -> bool {
537        if self.level == L - 1 {
538            forall|i: int| 0 <= i < Self::size() ==> #[trigger] self.children[i] is None
539        } else {
540            forall|i: int|
541                0 <= i < Self::size() ==> match #[trigger] self.children[i] {
542                    Some(child) => {
543                        &&& child.level == self.level + 1
544                        &&& self.value.rel_children(i, Some(child.value))
545                    },
546                    None => self.value.rel_children(i, None),
547                }
548        }
549    }
550
551    pub open spec fn inv(self) -> bool
552        decreases (L - self.level),
553    {
554        &&& L > 0
555        &&& N > 0
556        &&& self.inv_node()
557        &&& self.inv_children()
558        &&& if L - self.level == 1 {
559            // 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)->Some_0.level == self.level + 1 && self.child(
720                key,
721            )->Some_0.inv(),
722    {
723    }
724
725    pub proof fn child_some_properties(self, key: usize)
726        requires
727            0 <= key < Self::size(),
728            self.inv(),
729            self.child(key) is Some,
730        ensures
731            self.level < L - 1,
732            self.child(key)->Some_0.level == self.level + 1,
733            self.child(key)->Some_0.inv(),
734    {
735        self.child_property(key);
736        self.child_property_cases(key);
737    }
738
739    pub broadcast proof fn lemma_insert_child_is_child(self, key: usize, node: Self)
740        requires
741            0 <= key < Self::size(),
742            self.inv(),
743            node.inv(),
744            self.level < L - 1,
745            node.level == self.level + 1,
746        ensures
747            #[trigger] self.insert(key, node).child(key) == Some(node),
748    {
749        self.insert_property(key, node);
750        self.child_property(key);
751    }
752
753    pub broadcast proof fn lemma_remove_child_is_none(self, key: usize)
754        requires
755            0 <= key < Self::size(),
756            self.inv(),
757        ensures
758            #[trigger] self.remove(key).child(key) is None,
759    {
760        self.remove_property(key);
761        self.child_property(key);
762    }
763
764    pub open spec fn get_value(self) -> T {
765        self.value
766    }
767
768    pub broadcast proof fn get_value_property(self)
769        requires
770            self.inv(),
771        ensures
772            #[trigger] self.get_value() == self.value,
773            self.get_value().inv(),
774    {
775    }
776
777    pub open spec fn set_value(self, value: T) -> Self
778        recommends
779            self.inv(),
780            value.inv(),
781    {
782        Node { value: value, ..self }
783    }
784
785    pub broadcast proof fn set_value_property(self, value: T)
786        requires
787            self.inv(),
788            value.inv(),
789            value.la_inv(self.level),
790            forall|i: int|
791                0 <= i < N ==> #[trigger] self.children[i] is Some ==> value.rel_children(
792                    i,
793                    Some(self.children[i]->Some_0.value),
794                ),
795            forall|i: int|
796                0 <= i < N ==> #[trigger] self.children[i] is None ==> value.rel_children(i, None),
797        ensures
798            #[trigger] self.set_value(value).value == value,
799            self.set_value(value).children == self.children,
800            self.set_value(value).inv(),
801    {
802        let n = self.set_value(value);
803
804        if n.level == L - 1 {
805        } else {
806            assert forall|i: int| 0 <= i < Self::size() implies match #[trigger] n.children[i] {
807                Some(child) => {
808                    &&& child.level == n.level + 1
809                    &&& n.value.rel_children(i, Some(child.value))
810                },
811                None => n.value.rel_children(i, None),
812            } by {
813                if n.children[i] is Some {
814                    let child = n.children[i]->Some_0;
815                }
816            }
817        }
818    }
819
820    pub open spec fn is_leaf(self) -> bool {
821        forall|i: int| 0 <= i < Self::size() ==> self.children[i] is None
822    }
823
824    pub broadcast proof fn is_leaf_bounded(self)
825        requires
826            self.inv(),
827            self.level == L - 1,
828        ensures
829            #[trigger] self.is_leaf(),
830    {
831    }
832
833    pub open spec fn recursive_insert(self, path: TreePath<N>, node: Self) -> Self
834        recommends
835            self.inv(),
836            path.inv(),
837            node.inv(),
838            path.len() < L - self.level,
839            node.level == self.level + path.len() as nat,
840        decreases path.len(),
841    {
842        if path.is_empty() {
843            self
844        } else if path.len() == 1 {
845            self.insert(path.index(0), node)
846        } else {
847            let (hd, tl) = path.pop_head();
848            let child = match self.child(hd) {
849                Some(child) => child,
850                None => Node::new(self.level + 1),
851            };
852            let updated_child = child.recursive_insert(tl, node);
853            self.insert(hd, updated_child)
854        }
855    }
856
857    pub broadcast proof fn lemma_recursive_insert_path_empty_identical(
858        self,
859        path: TreePath<N>,
860        node: Self,
861    )
862        requires
863            self.inv(),
864            node.inv(),
865            path.inv(),
866            path.is_empty(),
867        ensures
868            #[trigger] self.recursive_insert(path, node) == self,
869    {
870    }
871
872    pub broadcast proof fn lemma_recursive_insert_path_len_1(self, path: TreePath<N>, node: Self)
873        requires
874            self.inv(),
875            node.inv(),
876            path.inv(),
877            path.len() == 1,
878            1 < L - self.level,
879            node.level == self.level + 1,
880        ensures
881            #[trigger] self.recursive_insert(path, node) == self.insert(path.index(0), node),
882    {
883    }
884
885    pub broadcast proof fn lemma_recursive_insert_path_len_step(self, path: TreePath<N>, node: Self)
886        requires
887            self.inv(),
888            path.inv(),
889            node.inv(),
890            path.len() < L - self.level,
891            node.level == self.level + path.len() as nat,
892            path.len() > 1,
893        ensures
894            self.child(path.index(0)) is Some ==> #[trigger] self.recursive_insert(path, node)
895                == self.insert(
896                path.index(0),
897                self.child(path.index(0))->Some_0.recursive_insert(path.pop_head().1, node),
898            ),
899            self.child(path.index(0)) is None ==> #[trigger] self.recursive_insert(path, node)
900                == self.insert(
901                path.index(0),
902                Node::new(self.level + 1).recursive_insert(path.pop_head().1, node),
903            ),
904    {
905    }
906
907    pub broadcast proof fn lemma_recursive_insert_preserves_level(
908        self,
909        path: TreePath<N>,
910        node: Self,
911    )
912        requires
913            self.inv(),
914            path.inv(),
915            node.inv(),
916            path.len() < L - self.level,
917            node.level == self.level + path.len() as nat,
918            forall|lv: nat|
919                lv < L ==> #[trigger] T::default(lv).rel_children(path.pop_tail().0 as int, None),
920        ensures
921            #[trigger] self.recursive_insert(path, node).level == self.level,
922        decreases path.len(),
923    {
924        if path.is_empty() {
925            self.lemma_recursive_insert_path_empty_identical(path, node);
926        } else if path.len() == 1 {
927            path.index_satisfies_elem_inv(0);
928            self.lemma_recursive_insert_path_len_1(path, node);
929            assert(self.insert(path.index(0), node).level == self.level);
930        } else {
931            self.lemma_recursive_insert_path_len_step(path, node);
932            let (hd, tl) = path.pop_head();
933            path.pop_head_preserves_inv();
934            if self.child(hd) is Some {
935                let c = self.child(hd)->Some_0;
936                self.child_some_properties(hd);
937                assert(self.insert(hd, c.recursive_insert(tl, node)).level == self.level);
938            } else {
939                let c = Node::new(self.level + 1);
940                assert(self.insert(hd, c.recursive_insert(tl, node)).level == self.level);
941            }
942        }
943    }
944
945    pub broadcast proof fn lemma_recursive_insert_preserves_value(
946        self,
947        path: TreePath<N>,
948        node: Self,
949    )
950        requires
951            self.inv(),
952            path.inv(),
953            node.inv(),
954            path.len() < L - self.level,
955            node.level == self.level + path.len() as nat,
956            forall|lv: nat, i: int|
957                lv < L && 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
958        ensures
959            #[trigger] self.recursive_insert(path, node).value == self.value,
960        decreases path.len(),
961    {
962        if path.is_empty() {
963            self.lemma_recursive_insert_path_empty_identical(path, node);
964        } else if path.len() == 1 {
965            path.index_satisfies_elem_inv(0);
966            self.lemma_recursive_insert_path_len_1(path, node);
967        } else {
968            self.lemma_recursive_insert_path_len_step(path, node);
969            let (hd, tl) = path.pop_head();
970            path.pop_head_preserves_inv();
971            if self.child(hd) is Some {
972                let c = self.child(hd)->Some_0;
973                self.child_some_properties(hd);
974                c.lemma_recursive_insert_preserves_value(tl, node);
975                let updated_child = c.recursive_insert(tl, node);
976            } else {
977                let c = Node::new(self.level + 1);
978                Self::new_preserves_inv(self.level + 1);
979                c.lemma_recursive_insert_preserves_value(tl, node);
980                let updated_child = c.recursive_insert(tl, node);
981            }
982        }
983    }
984
985    pub broadcast proof fn lemma_recursive_insert_preserves_inv(self, path: TreePath<N>, node: Self)
986        requires
987            self.inv(),
988            path.inv(),
989            node.inv(),
990            path.len() < L - self.level,
991            node.level == self.level + path.len() as nat,
992            self.recursive_seek(path.pop_tail().1) is Some ==> self.recursive_seek(
993                path.pop_tail().1,
994            )->Some_0.value.rel_children(path.pop_tail().0 as int, Some(node.value)),
995            self.recursive_seek(path.pop_tail().1) is None ==> T::default(
996                (node.level - 1) as nat,
997            ).rel_children(path.pop_tail().0 as int, Some(node.value)),
998            forall|lv: nat, i: int|
999                lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
1000        ensures
1001            #[trigger] self.recursive_insert(path, node).inv(),
1002        decreases path.len(),
1003    {
1004        if path.is_empty() {
1005            self.lemma_recursive_insert_path_empty_identical(path, node);
1006        } else if path.len() == 1 {
1007            path.index_satisfies_elem_inv(0);
1008            self.lemma_recursive_insert_path_len_1(path, node);
1009            self.insert_preserves_inv(path.index(0), node);
1010        } else {
1011            self.lemma_recursive_insert_path_len_step(path, node);
1012            let (hd, tl) = path.pop_head();
1013            path.pop_head_preserves_inv();
1014            if self.child(hd) is Some {
1015                let c = self.child(hd)->Some_0;
1016                self.child_some_properties(hd);
1017                assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
1018                c.lemma_recursive_insert_preserves_inv(tl, node);
1019                c.lemma_recursive_insert_preserves_level(tl, node);
1020                c.lemma_recursive_insert_preserves_value(tl, node);
1021                let updated_child = c.recursive_insert(tl, node);
1022                self.insert_preserves_inv(hd, updated_child);
1023            } else {
1024                let c = Node::new(self.level + 1);
1025                Self::new_preserves_inv(self.level + 1);
1026                self.value.default_preserves_rel_children(self.level);
1027                c.lemma_recursive_insert_preserves_inv(tl, node);
1028                c.lemma_recursive_insert_preserves_level(tl, node);
1029                c.lemma_recursive_insert_preserves_value(tl, node);
1030                let updated_child = c.recursive_insert(tl, node);
1031                self.insert_preserves_inv(hd, updated_child);
1032            }
1033        }
1034    }
1035
1036    /// Visit the tree node recursively based on the path
1037    /// Returns a sequence of visited node values, including the initial one
1038    /// If the path does not correspond to a node, stop the traverse, and return the
1039    /// previously visited nodes.
1040    pub open spec fn recursive_trace(self, path: TreePath<N>) -> Seq<T>
1041        recommends
1042            self.inv(),
1043            path.inv(),
1044            path.len() < L - self.level,
1045        decreases path.len(),
1046    {
1047        if path.is_empty() {
1048            seq![self.value]
1049        } else {
1050            let (hd, tl) = path.pop_head();
1051            match self.child(hd) {
1052                Some(child) => seq![self.value].add(child.recursive_trace(tl)),
1053                None => seq![self.value],
1054            }
1055        }
1056    }
1057
1058    pub proof fn lemma_recursive_trace_length(self, path: TreePath<N>)
1059        requires
1060            self.inv(),
1061            path.inv(),
1062        ensures
1063            #[trigger] self.recursive_trace(path).len() <= path.len() + 1,
1064        decreases path.len(),
1065    {
1066        if path.len() == 0 {
1067        } else {
1068            let (hd, tl) = path.pop_head();
1069            path.pop_head_preserves_inv();
1070            match self.child(hd) {
1071                None => {},
1072                Some(child) => {
1073                    child.lemma_recursive_trace_length(tl);
1074                },
1075            }
1076        }
1077    }
1078
1079    pub proof fn lemma_recursive_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1080        requires
1081            self.inv(),
1082            path1.inv(),
1083            path2.inv(),
1084            n <= path1.len(),
1085            n <= path2.len(),
1086            forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1087            self.recursive_trace(path1).len() > n,
1088        ensures
1089            self.recursive_trace(path2).len() > n,
1090            forall|i: int|
1091                0 <= i <= n ==> self.recursive_trace(path1)[i] == self.recursive_trace(path2)[i],
1092        decreases n,
1093    {
1094        if n <= 0 {
1095        } else {
1096            let (hd1, tl1) = path1.pop_head();
1097            let (hd2, tl2) = path2.pop_head();
1098            match self.child(hd1) {
1099                None => {},
1100                Some(child) => {
1101                    path1.pop_head_preserves_inv();
1102                    path2.pop_head_preserves_inv();
1103                    child.lemma_recursive_trace_up_to(tl1, tl2, n - 1);
1104                },
1105            }
1106        }
1107    }
1108
1109    /// Walk to the end of a path and return the subtree at the end
1110    /// Returns a single node (with its children)
1111    /// If the path does not correspond to a node, return None
1112    pub open spec fn recursive_seek(self, path: TreePath<N>) -> Option<Self>
1113        recommends
1114            self.inv(),
1115            path.inv(),
1116            path.len() < L - self.level,
1117        decreases path.len(),
1118    {
1119        if path.is_empty() {
1120            Some(self)
1121        } else {
1122            let (hd, tl) = path.pop_head();
1123            match self.child(hd) {
1124                Some(child) => child.recursive_seek(tl),
1125                None => None,
1126            }
1127        }
1128    }
1129
1130    pub proof fn lemma_recursive_seek_trace_length(self, path: TreePath<N>)
1131        requires
1132            self.inv(),
1133            path.inv(),
1134            path.len() < L - self.level,
1135            self.recursive_seek(path) is Some,
1136        ensures
1137            self.recursive_trace(path).len() == path.len() + 1,
1138        decreases path.len(),
1139    {
1140        if path.len() == 0 {
1141        } else {
1142            let (hd, tl) = path.pop_head();
1143            match self.child(hd) {
1144                None => {},
1145                Some(child) => {
1146                    path.pop_head_preserves_inv();
1147                    child.lemma_recursive_seek_trace_length(tl)
1148                },
1149            }
1150        }
1151    }
1152
1153    pub proof fn lemma_recursive_seek_trace_next(self, path: TreePath<N>, idx: usize)
1154        requires
1155            self.recursive_seek(path) is Some,
1156            self.recursive_seek(path)->Some_0.children[idx as int] is Some,
1157            self.inv(),
1158            path.inv(),
1159            path.len() < L - self.level,
1160            0 <= idx < N,
1161        ensures
1162            self.recursive_trace(path.push_tail(idx)).len() == path.len() + 2,
1163            self.recursive_seek(path)->Some_0.children[idx as int]->Some_0.value
1164                == self.recursive_trace(path.push_tail(idx))[path.len() as int + 1],
1165        decreases path.len(),
1166    {
1167        let path2 = path.push_tail(idx);
1168
1169        if path.len() == 0 {
1170            assert(self.recursive_trace(path2) =~= seq![
1171                self.value,
1172                self.children[idx as int]->Some_0.value,
1173            ]) by { reveal_with_fuel(Node::recursive_trace, 2) }
1174        } else {
1175            let (hd1, tl1) = path.pop_head();
1176            let (hd2, tl2) = path2.pop_head();
1177            assert(tl2 == tl1.push_tail(idx)) by {}
1178            assert(tl1.inv()) by { path.pop_head_preserves_inv() }
1179            match self.child(hd2) {
1180                None => {},
1181                Some(child) => {
1182                    child.lemma_recursive_seek_trace_next(tl1, idx);
1183
1184                },
1185            }
1186        }
1187    }
1188
1189    /// Visit the tree node recursively based on the path
1190    /// Returns a sequence of visited nodes, exclude the given one
1191    /// If the path is empty, return an empty sequence
1192    /// If the tree node is absent, stop the traverse, and return the
1193    /// previously visited nodes.
1194    pub open spec fn recursive_visit(self, path: TreePath<N>) -> Seq<Self>
1195        recommends
1196            self.inv(),
1197            path.inv(),
1198            path.len() < L - self.level,
1199        decreases path.len(),
1200    {
1201        if path.is_empty() {
1202            Seq::empty()
1203        } else if path.len() == 1 {
1204            match self.child(path.index(0)) {
1205                Some(child) => seq![child],
1206                None => Seq::empty(),
1207            }
1208        } else {
1209            let (hd, tl) = path.pop_head();
1210            match self.child(hd) {
1211                Some(child) => seq![child].add(child.recursive_visit(tl)),
1212                None => Seq::empty(),
1213            }
1214        }
1215    }
1216
1217    pub broadcast proof fn lemma_recursive_visited_node_inv(self, path: TreePath<N>)
1218        requires
1219            #[trigger] self.inv(),
1220            #[trigger] path.inv(),
1221            path.len() < L - self.level,
1222        ensures
1223            forall|i: int|
1224                0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1225                    path,
1226                ).index(i).inv(),
1227        decreases path.len(),
1228    {
1229        if path.is_empty() {
1230        } else if path.len() == 1 {
1231            if self.child(path.index(0)) is Some {
1232            }
1233        } else {
1234            let (hd, tl) = path.pop_head();
1235            path.pop_head_preserves_inv();
1236            if self.child(hd) is Some {
1237                let c = self.child(hd)->Some_0;
1238                assert(self.recursive_visit(path) =~= seq![c].add(c.recursive_visit(tl)));
1239                c.lemma_recursive_visited_node_inv(tl);
1240            }
1241        }
1242    }
1243
1244    pub broadcast proof fn lemma_recursive_visited_node_levels(self, path: TreePath<N>)
1245        requires
1246            #[trigger] self.inv(),
1247            #[trigger] path.inv(),
1248            path.len() < L - self.level,
1249        ensures
1250            forall|i: int|
1251                0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1252                    path,
1253                ).index(i).level == self.level + i + 1,
1254        decreases path.len(),
1255    {
1256        if path.is_empty() {
1257        } else if path.len() == 1 {
1258            if self.child(path.index(0)) is Some {
1259            }
1260        } else {
1261            let (hd, tl) = path.pop_head();
1262            path.pop_head_preserves_inv();
1263            if self.child(hd) is Some {
1264                let c = self.child(hd)->Some_0;
1265                assert(self.recursive_visit(path) =~= seq![c].add(c.recursive_visit(tl)));
1266                c.lemma_recursive_visited_node_levels(tl);
1267            }
1268        }
1269    }
1270
1271    pub broadcast proof fn lemma_recursive_visit_head(self, path: TreePath<N>)
1272        requires
1273            #[trigger] self.inv(),
1274            #[trigger] path.inv(),
1275            path.len() < L - self.level,
1276            !path.is_empty(),
1277            self.recursive_visit(path).len() > 0,
1278        ensures
1279            self.recursive_visit(path).index(0) == self.child(path.index(0))->Some_0,
1280    {
1281        if path.len() == 0 {
1282        } else if path.len() == 1 {
1283            if self.child(path.index(0)) is None {
1284            }
1285        } else {
1286            if self.child(path.index(0)) is None {
1287            }
1288        }
1289    }
1290
1291    pub broadcast proof fn lemma_recursive_visit_induction(self, path: TreePath<N>)
1292        requires
1293            self.inv(),
1294            path.inv(),
1295            path.len() < L - self.level,
1296            !path.is_empty(),
1297            self.recursive_visit(path).len() > 0,
1298        ensures
1299            #[trigger] self.recursive_visit(path) == seq![
1300                self.child(path.pop_head().0)->Some_0,
1301            ].add(self.child(path.pop_head().0)->Some_0.recursive_visit(path.pop_head().1)),
1302    {
1303        if path.len() == 1 {
1304            let (hd, tl) = path.pop_head();
1305            path.pop_head_preserves_inv();
1306            path.pop_head_property();
1307            let c = self.child(hd);
1308            if c is None {
1309            } else {
1310                let c = c->Some_0;
1311            }
1312        } else {
1313            let (hd, tl) = path.pop_head();
1314            path.pop_head_preserves_inv();
1315            path.pop_head_property();
1316
1317            let c = self.child(hd);
1318            if c is None {
1319            } else {
1320                let c = c->Some_0;
1321                self.lemma_recursive_visit_head(path);
1322            }
1323        }
1324    }
1325
1326    pub broadcast proof fn lemma_recursive_visit_one_is_child(self, path: TreePath<N>)
1327        requires
1328            self.inv(),
1329            path.inv(),
1330            path.len() < L - self.level,
1331            path.len() == 1,
1332        ensures
1333            self.child(path.index(0)) is Some ==> #[trigger] self.recursive_visit(path) =~= seq![
1334                self.child(path.index(0))->Some_0,
1335            ],
1336            self.child(path.index(0)) is None ==> #[trigger] self.recursive_visit(path) =~= seq![],
1337    {
1338    }
1339
1340    pub open spec fn on_subtree(self, node: Self) -> bool
1341        recommends
1342            self.inv(),
1343            node.inv(),
1344            node.level >= self.level,
1345            node.level < L,
1346    {
1347        node == self || exists|path: TreePath<N>| #[trigger]
1348            path.inv() && path.len() > 0 && path.len() == node.level - self.level
1349                && self.recursive_visit(path).last() == node
1350    }
1351
1352    pub broadcast proof fn on_subtree_property(self, node: Self)
1353        requires
1354            self.inv(),
1355            node.inv(),
1356            node.level >= self.level,
1357            node.level < L,
1358            #[trigger] self.on_subtree(node),
1359        ensures
1360            node.level == self.level ==> self == node,
1361            node.level > self.level ==> exists|path: TreePath<N>| #[trigger]
1362                path.inv() && path.len() == node.level - self.level && self.recursive_visit(
1363                    path,
1364                ).last() == node,
1365    {
1366    }
1367
1368    pub broadcast proof fn not_on_subtree_property(self, node: Self)
1369        requires
1370            self.inv(),
1371            node.inv(),
1372            node.level < L,
1373            !#[trigger] self.on_subtree(node),
1374        ensures
1375            self != node,
1376            node.level > self.level ==> forall|path: TreePath<N>| #[trigger]
1377                path.inv() && path.len() == node.level - self.level ==> self.recursive_visit(
1378                    path,
1379                ).last() != node,
1380    {
1381    }
1382
1383    pub broadcast proof fn lemma_on_subtree_reflexive(self)
1384        requires
1385            self.inv(),
1386        ensures
1387            #[trigger] self.on_subtree(self),
1388    {
1389    }
1390
1391    pub broadcast proof fn lemma_child_on_subtree(self, key: usize)
1392        requires
1393            0 <= key < Self::size(),
1394            self.inv(),
1395            self.child(key) is Some,
1396        ensures
1397            #[trigger] self.on_subtree(self.child(key)->Some_0),
1398    {
1399        let path = TreePath::<N>::new(seq![key]);
1400        let c = self.child(key)->Some_0;
1401        assert(path.inv());
1402    }
1403
1404    pub broadcast proof fn lemma_insert_on_subtree(self, key: usize, node: Self)
1405        requires
1406            0 <= key < Self::size(),
1407            self.inv(),
1408            node.inv(),
1409            self.level < L - 1,
1410            node.level == self.level + 1,
1411            self.value.rel_children(key as int, Some(node.value)),
1412        ensures
1413            #[trigger] self.insert(key, node).on_subtree(node),
1414    {
1415        self.lemma_insert_child_is_child(key, node);
1416        self.insert(key, node).lemma_child_on_subtree(key);
1417    }
1418
1419    /// Remove the tree node at the end of the path
1420    /// If the path is empty or any node in the path is absent,
1421    /// return the original tree node (no change)
1422    /// Otherwise, remove the node at the end of the path, and
1423    /// update the node recursively
1424    pub open spec fn recursive_remove(self, path: TreePath<N>) -> Self
1425        recommends
1426            self.inv(),
1427            path.inv(),
1428            path.len() < L - self.level,
1429        decreases path.len(),
1430    {
1431        if path.is_empty() {
1432            self
1433        } else if path.len() == 1 {
1434            self.remove(path.index(0))
1435        } else {
1436            let (hd, tl) = path.pop_head();
1437            if self.child(hd) is None {
1438                self
1439            } else {
1440                let child = self.child(hd)->Some_0;
1441                let updated_child = child.recursive_remove(tl);
1442                self.insert(hd, updated_child)
1443            }
1444        }
1445    }
1446
1447    pub broadcast proof fn lemma_recursive_remove_preserves_level(self, path: TreePath<N>)
1448        requires
1449            self.inv(),
1450            path.inv(),
1451            path.len() < L - self.level,
1452        ensures
1453            #[trigger] self.recursive_remove(path).level == self.level,
1454        decreases path.len(),
1455    {
1456        if path.is_empty() {
1457        } else if path.len() == 1 {
1458            path.index_satisfies_elem_inv(0);
1459        } else {
1460            let (hd, tl) = path.pop_head();
1461            path.pop_head_preserves_inv();
1462            if self.child(hd) is Some {
1463                let c = self.child(hd)->Some_0;
1464                self.child_some_properties(hd);
1465                c.lemma_recursive_remove_preserves_level(tl);
1466            }
1467        }
1468    }
1469
1470    pub broadcast proof fn lemma_recursive_remove_preserves_value(self, path: TreePath<N>)
1471        requires
1472            self.inv(),
1473            path.inv(),
1474            path.len() < L - self.level,
1475        ensures
1476            #[trigger] self.recursive_remove(path).value == self.value,
1477        decreases path.len(),
1478    {
1479        if path.is_empty() {
1480        } else if path.len() == 1 {
1481            path.index_satisfies_elem_inv(0);
1482        } else {
1483            let (hd, tl) = path.pop_head();
1484            path.pop_head_preserves_inv();
1485            if self.child(hd) is Some {
1486                let c = self.child(hd)->Some_0;
1487                self.child_some_properties(hd);
1488                c.lemma_recursive_remove_preserves_value(tl);
1489            }
1490        }
1491    }
1492
1493    pub broadcast proof fn lemma_recursive_remove_preserves_inv(self, path: TreePath<N>)
1494        requires
1495            self.inv(),
1496            path.inv(),
1497            path.len() < L - self.level,
1498            path.len() > 0 ==> self.recursive_seek(path.pop_tail().1) is Some
1499                ==> self.recursive_seek(
1500                path.pop_tail().1,
1501            )->Some_0.children[path.pop_tail().0 as int] is None || self.recursive_seek(
1502                path.pop_tail().1,
1503            )->Some_0.value.rel_children(path.pop_tail().0 as int, None),
1504        ensures
1505            #[trigger] self.recursive_remove(path).inv(),
1506        decreases path.len(),
1507    {
1508        if path.is_empty() {
1509        } else if path.len() == 1 {
1510            path.index_satisfies_elem_inv(0);
1511
1512            self.remove_preserves_inv(path.index(0));
1513        } else {
1514            let (hd, tl) = path.pop_head();
1515            path.pop_head_preserves_inv();
1516            if self.child(hd) is Some {
1517                let c = self.child(hd)->Some_0;
1518                self.child_some_properties(hd);
1519                assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
1520                c.lemma_recursive_remove_preserves_inv(tl);
1521                c.lemma_recursive_remove_preserves_level(tl);
1522                c.lemma_recursive_remove_preserves_value(tl);
1523                let updated_child = c.recursive_remove(tl);
1524                self.insert_preserves_inv(hd, updated_child);
1525            }
1526        }
1527    }
1528}
1529
1530} // verus!
1531verus! {
1532
1533pub closed spec fn path_between<T: TreeNodeValue<L>, const N: usize, const L: usize>(
1534    src: Node<T, N, L>,
1535    dst: Node<T, N, L>,
1536) -> TreePath<N>
1537    recommends
1538        src.inv(),
1539        dst.inv(),
1540        src.level <= dst.level,
1541        src.on_subtree(dst),
1542{
1543    if src.inv() && dst.inv() && dst.level >= src.level && dst.level < L && src.on_subtree(dst) {
1544        if src == dst {
1545            TreePath::new(seq![])
1546        } else {
1547            choose|path: TreePath<N>| #[trigger]
1548                path.inv() && path.len() > 0 && path.len() == dst.level - src.level
1549                    && src.recursive_visit(path).last() == dst
1550        }
1551    } else {
1552        vstd::pervasive::arbitrary()
1553    }
1554}
1555
1556pub broadcast proof fn path_between_properties<T: TreeNodeValue<L>, const N: usize, const L: usize>(
1557    src: Node<T, N, L>,
1558    dst: Node<T, N, L>,
1559)
1560    requires
1561        src.inv(),
1562        dst.inv(),
1563        src.level <= dst.level,
1564        #[trigger] src.on_subtree(dst),
1565    ensures
1566        path_between(src, dst).inv(),
1567        path_between(src, dst).len() == dst.level - src.level,
1568        dst.level == src.level ==> path_between(src, dst).is_empty() && src == dst,
1569        dst.level > src.level ==> src.recursive_visit(path_between(src, dst)).last() == dst,
1570{
1571}
1572
1573} // verus!
1574verus! {
1575
1576pub tracked struct Tree<T: TreeNodeValue<L>, const N: usize, const L: usize> {
1577    pub tracked root: Node<T, N, L>,
1578}
1579
1580impl<T: TreeNodeValue<L>, const N: usize, const L: usize> Tree<T, N, L> {
1581    pub open spec fn inv(self) -> bool {
1582        &&& L > 0
1583        &&& N > 0
1584        &&& self.root.inv()
1585        &&& self.root.level == 0
1586    }
1587
1588    pub open spec fn new() -> Self {
1589        Tree { root: Node::new(0) }
1590    }
1591
1592    pub broadcast proof fn new_preserves_inv()
1593        requires
1594            N > 0,
1595            L > 0,
1596            forall|i: int| 0 <= i < N ==> #[trigger] T::default(0).rel_children(i, None),
1597        ensures
1598            #[trigger] Self::new().inv(),
1599    {
1600        let t = Self::new();
1601        Node::<T, N, L>::new_preserves_inv(0);
1602    }
1603
1604    pub open spec fn insert(self, path: TreePath<N>, node: Node<T, N, L>) -> Self
1605        recommends
1606            self.inv(),
1607            path.inv(),
1608            node.inv(),
1609            path.len() < L,
1610            node.level == path.len() as nat,
1611        decreases path.len(),
1612    {
1613        Tree { root: self.root.recursive_insert(path, node), ..self }
1614    }
1615
1616    pub open spec fn remove(self, path: TreePath<N>) -> Self
1617        recommends
1618            self.inv(),
1619            path.inv(),
1620            path.len() < L,
1621        decreases path.len(),
1622    {
1623        Tree { root: self.root.recursive_remove(path), ..self }
1624    }
1625
1626    pub open spec fn visit(self, path: TreePath<N>) -> Seq<Node<T, N, L>>
1627        recommends
1628            self.inv(),
1629            path.inv(),
1630            path.len() < L,
1631        decreases path.len(),
1632    {
1633        self.root.recursive_visit(path)
1634    }
1635
1636    pub broadcast proof fn visit_is_recursive_visit(self, path: TreePath<N>)
1637        requires
1638            self.inv(),
1639            path.inv(),
1640            path.len() < L,
1641        ensures
1642            #[trigger] self.visit(path) == self.root.recursive_visit(path),
1643    {
1644    }
1645
1646    pub open spec fn trace(self, path: TreePath<N>) -> Seq<T>
1647        recommends
1648            self.inv(),
1649            path.inv(),
1650            path.len() < L,
1651        decreases path.len(),
1652    {
1653        self.root.recursive_trace(path)
1654    }
1655
1656    pub broadcast proof fn trace_empty_is_head(self, path: TreePath<N>)
1657        requires
1658            path.len() == 0,
1659        ensures
1660            #[trigger] self.trace(path) == seq![self.root.value],
1661    {
1662    }
1663
1664    pub proof fn lemma_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1665        requires
1666            self.inv(),
1667            path1.inv(),
1668            path2.inv(),
1669            n <= path1.len(),
1670            n <= path2.len(),
1671            forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1672            self.trace(path1).len() > n,
1673        ensures
1674            self.trace(path2).len() > n,
1675            forall|i: int| 0 <= i <= n ==> self.trace(path1)[i] == self.trace(path2)[i],
1676    {
1677        self.root.lemma_recursive_trace_up_to(path1, path2, n)
1678    }
1679
1680    pub broadcast proof fn lemma_trace_length(self, path: TreePath<N>)
1681        requires
1682            self.inv(),
1683            path.inv(),
1684        ensures
1685            #[trigger] self.trace(path).len() <= path.len() + 1,
1686    {
1687        self.root.lemma_recursive_trace_length(path);
1688    }
1689
1690    pub open spec fn seek(self, path: TreePath<N>) -> Option<Node<T, N, L>> {
1691        self.root.recursive_seek(path)
1692    }
1693
1694    pub proof fn lemma_seek_trace_length(self, path: TreePath<N>)
1695        requires
1696            self.inv(),
1697            path.inv(),
1698            path.len() < L,
1699            self.seek(path) is Some,
1700        ensures
1701            self.trace(path).len() == path.len() + 1,
1702    {
1703        self.root.lemma_recursive_seek_trace_length(path)
1704    }
1705
1706    pub proof fn lemma_seek_trace_next(self, path: TreePath<N>, idx: usize)
1707        requires
1708            self.seek(path) is Some,
1709            self.seek(path)->Some_0.children[idx as int] is Some,
1710            self.inv(),
1711            path.inv(),
1712            path.len() < L,
1713            0 <= idx < N,
1714        ensures
1715            self.trace(path.push_tail(idx)).len() == path.len() + 2,
1716            self.seek(path)->Some_0.children[idx as int]->Some_0.value == self.trace(
1717                path.push_tail(idx),
1718            )[path.len() as int + 1],
1719    {
1720        self.root.lemma_recursive_seek_trace_next(path, idx)
1721    }
1722
1723    pub broadcast proof fn insert_preserves_inv(self, path: TreePath<N>, node: Node<T, N, L>)
1724        requires
1725            self.inv(),
1726            path.inv(),
1727            node.inv(),
1728            path.len() < L,
1729            node.level == path.len() as nat,
1730            self.seek(path.pop_tail().1) is Some ==> self.seek(
1731                path.pop_tail().1,
1732            )->Some_0.value.rel_children(path.index(path.len() - 1) as int, Some(node.value)),
1733            self.seek(path.pop_tail().1) is None ==> T::default(
1734                (path.len() - 1) as nat,
1735            ).rel_children(path.index(path.len() - 1) as int, Some(node.value)),
1736            forall|lv: nat, i: int|
1737                lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
1738        ensures
1739            #[trigger] self.insert(path, node).inv(),
1740    {
1741        self.root.lemma_recursive_insert_preserves_inv(path, node);
1742    }
1743
1744    pub broadcast proof fn remove_preserves_inv(self, path: TreePath<N>)
1745        requires
1746            self.inv(),
1747            path.inv(),
1748            path.len() < L,
1749            path.len() > 0 ==> self.seek(path.pop_tail().1) is Some ==> self.seek(
1750                path.pop_tail().1,
1751            )->Some_0.children[path.pop_tail().0 as int] is None || self.seek(
1752                path.pop_tail().1,
1753            )->Some_0.value.rel_children(path.index(path.len() - 1) as int, None),
1754        ensures
1755            #[trigger] self.remove(path).inv(),
1756    {
1757        self.root.lemma_recursive_remove_preserves_inv(path);
1758    }
1759
1760    pub broadcast proof fn visited_nodes_inv(self, path: TreePath<N>)
1761        requires
1762            #[trigger] self.inv(),
1763            #[trigger] path.inv(),
1764            path.len() < L,
1765        ensures
1766            forall|i: int|
1767                0 <= i < self.visit(path).len() ==> #[trigger] self.visit(path).index(i).inv(),
1768    {
1769        self.root.lemma_recursive_visited_node_inv(path);
1770    }
1771
1772    #[verifier::inline]
1773    pub open spec fn on_tree(self, node: Node<T, N, L>) -> bool
1774        recommends
1775            self.inv(),
1776            node.inv(),
1777    {
1778        self.root.on_subtree(node)
1779    }
1780
1781    pub broadcast proof fn on_tree_property(self, node: Node<T, N, L>)
1782        requires
1783            self.inv(),
1784            node.inv(),
1785            #[trigger] self.on_tree(node),
1786        ensures
1787            node.level == 0 ==> self.root == node,
1788            node.level > 0 ==> exists|path: TreePath<N>| #[trigger]
1789                path.inv() && path.len() == node.level && self.visit(path).last() == node,
1790    {
1791    }
1792
1793    pub broadcast proof fn not_on_tree_property(self, node: Node<T, N, L>)
1794        requires
1795            self.inv(),
1796            node.inv(),
1797            !#[trigger] self.on_tree(node),
1798        ensures
1799            node != self.root,
1800            node.level > 0 ==> forall|path: TreePath<N>| #[trigger]
1801                path.inv() && path.len() == node.level ==> self.visit(path).last() != node,
1802    {
1803    }
1804
1805    #[verifier::inline]
1806    pub open spec fn get_path(self, node: Node<T, N, L>) -> TreePath<N>
1807        recommends
1808            self.inv(),
1809            node.inv(),
1810            self.on_tree(node),
1811    {
1812        path_between::<T, N, L>(self.root, node)
1813    }
1814
1815    pub broadcast proof fn get_path_properties(self, node: Node<T, N, L>)
1816        requires
1817            self.inv(),
1818            node.inv(),
1819            self.on_tree(node),
1820        ensures
1821            #[trigger] self.get_path(node).inv(),
1822            #[trigger] self.get_path(node).len() == node.level,
1823            node.level == 0 ==> #[trigger] self.get_path(node).is_empty(),
1824            node.level > 0 ==> #[trigger] self.visit(self.get_path(node)).last() == node,
1825    {
1826        path_between_properties(self.root, node);
1827    }
1828}
1829
1830} // verus!
1831verus! {
1832
1833pub broadcast group group_ghost_tree {
1834    TreePath::inv_property,
1835    TreePath::index_satisfies_elem_inv,
1836    TreePath::empty_satisfies_inv,
1837    TreePath::drop_head_property,
1838    TreePath::drop_last_property,
1839    TreePath::pop_head_preserves_inv,
1840    TreePath::pop_head_decreases_len,
1841    TreePath::pop_head_head_satisfies_inv,
1842    TreePath::pop_head_property,
1843    TreePath::pop_tail_preserves_inv,
1844    TreePath::pop_tail_decreases_len,
1845    TreePath::pop_tail_tail_satisfies_inv,
1846    TreePath::pop_tail_property,
1847    TreePath::push_head_property,
1848    TreePath::new_empty_preserves_inv,
1849    TreePath::new_preserves_inv,
1850    Node::insert_preserves_inv,
1851    Node::insert_property,
1852    Node::insert_same_child_identical,
1853    Node::remove_preserves_inv,
1854    Node::remove_property,
1855    Node::child_property,
1856    Node::child_property_cases,
1857    Node::lemma_insert_child_is_child,
1858    Node::lemma_remove_child_is_none,
1859    Node::get_value_property,
1860    Node::set_value_property,
1861    Node::is_leaf_bounded,
1862    Node::lemma_recursive_visited_node_inv,
1863    Node::lemma_recursive_visited_node_levels,
1864    Node::lemma_recursive_visit_head,
1865    Node::lemma_recursive_visit_induction,
1866    Node::lemma_recursive_visit_one_is_child,
1867    Node::on_subtree_property,
1868    Node::not_on_subtree_property,
1869    Node::lemma_on_subtree_reflexive,
1870    Node::lemma_child_on_subtree,
1871    Node::lemma_insert_on_subtree,
1872    // Node::lemma_remove_not_on_subtree,
1873    // Node::lemma_recursive_insert_on_subtree,
1874    // Node::lemma_recursive_remove_not_on_subtree,
1875    // Node::lemma_recursive_visit_on_subtree,
1876    // Node::remaining_level_decreases,
1877    Node::lemma_recursive_remove_preserves_inv,
1878    path_between_properties,
1879    Tree::new_preserves_inv,
1880    Tree::visit_is_recursive_visit,
1881    Tree::insert_preserves_inv,
1882    Tree::remove_preserves_inv,
1883    Tree::visited_nodes_inv,
1884    Tree::on_tree_property,
1885    Tree::not_on_tree_property,
1886}
1887
1888} // verus!