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