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