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    /// Constructs a tracked node with the given value and no children.
597    pub proof fn tracked_new_val(tracked val: T, lv: nat) -> (tracked res: Self)
598        requires
599            0 <= lv < L,
600            N > 0,
601            val.inv(),
602            val.la_inv(lv),
603            forall|i: int| 0 <= i < N ==> #[trigger] val.rel_children(i, None),
604        ensures
605            res.inv(),
606        returns
607            Self::new_val(val, lv),
608    {
609        proof fn tracked_none_seq<A>(n: nat) -> (tracked res: Seq<Option<A>>)
610            ensures
611                res == Seq::new(n, |i| None),
612            decreases n,
613        {
614            if n == 0 {
615                Seq::tracked_empty()
616            } else {
617                let tracked mut res = tracked_none_seq((n - 1) as nat);
618                res.tracked_push(None);
619                res
620            }
621        }
622        let tracked children = tracked_none_seq(N as nat);
623        Self::tracked_new(val, lv, children)
624    }
625
626    pub proof fn lemma_new_default_preserves_inv(lv: nat)
627        requires
628            0 <= lv < L,
629            N > 0,
630            forall|i: int| 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
631        ensures
632            Self::new_default(lv).inv(),
633    {
634        T::lemma_default_preserves_inv();
635        T::lemma_default_preserves_la_inv();
636    }
637
638    /// Insert the child at the given index.
639    pub open spec fn insert(self, key: int, node: Self) -> Self
640        recommends
641            0 <= key < Self::size(),
642            node.level() == self.level() + 1,
643    {
644        Self::new(self.value(), self.level(), self.children().update(key, Some(node)))
645    }
646
647    pub broadcast proof fn lemma_insert_preserves_inv(self, key: int, node: Self)
648        requires
649            self.inv(),
650            node.inv(),
651            node.level() == self.level() + 1,
652            self.value().rel_children(key, Some(node.value())),
653        ensures
654            #![trigger self.insert(key, node)]
655            self.insert(key, node).inv(),
656    {
657    }
658
659    pub broadcast proof fn lemma_insert_property(self, key: int, node: Self)
660        requires
661            0 <= key < Self::size(),
662            self.inv(),
663        ensures
664            #![trigger self.insert(key, node)]
665            self.insert(key, node).value() == self.value(),
666            self.insert(key, node).children()[key] == Some(node),
667            self.insert(key, node).children() == self.children().update(key, Some(node)),
668    {
669    }
670
671    pub proof fn lemma_insert_same_child_identical(self, key: int, node: Self)
672        requires
673            0 <= key < Self::size(),
674            self.inv(),
675            self.has_child(key),
676            self.child(key) == node,
677        ensures
678            self.insert(key, node) == self,
679    {
680        self.lemma_insert_property(key, node);
681        assert(self.insert(key, node).children() == self.children());
682    }
683
684    pub open spec fn remove(self, key: int) -> Self
685        recommends
686            0 <= key < Self::size(),
687    {
688        Self::new(self.value(), self.level(), self.children().update(key, None))
689    }
690
691    pub broadcast proof fn lemma_remove_preserves_inv(self, key: int)
692        requires
693            0 <= key < Self::size(),
694            self.inv(),
695            self.children()[key] is None || self.value().rel_children(key, None),
696        ensures
697            (#[trigger] self.remove(key)).inv(),
698    {
699    }
700
701    pub broadcast proof fn lemma_remove_property(self, key: int)
702        requires
703            0 <= key < Self::size(),
704            self.inv(),
705        ensures
706            #![trigger self.remove(key)]
707            self.remove(key).value() == self.value(),
708            self.remove(key).children()[key] is None,
709            self.remove(key).children() == self.children().update(key, None),
710    {
711    }
712
713    pub proof fn lemma_insert_child_is_child(self, key: int, node: Self)
714        requires
715            0 <= key < Self::size(),
716            self.inv(),
717            node.inv(),
718            self.level() < L - 1,
719            node.level() == self.level() + 1,
720        ensures
721            self.insert(key, node).has_child(key),
722            self.insert(key, node).child(key) == node,
723    {
724        self.lemma_insert_property(key, node);
725    }
726
727    pub proof fn lemma_remove_child_is_none(self, key: int)
728        requires
729            0 <= key < Self::size(),
730            self.inv(),
731        ensures
732            !self.remove(key).has_child(key),
733    {
734        self.lemma_remove_property(key);
735    }
736
737    pub open spec fn set_value(self, value: T) -> Self
738        recommends
739            self.inv(),
740            value.inv(),
741    {
742        Self::new(value, self.level(), self.children())
743    }
744
745    /// Exposes the observable fields changed and preserved by `set_value`.
746    pub broadcast proof fn lemma_set_value_observable_fields(self, value: T)
747        ensures
748            #![trigger self.set_value(value)]
749            (#[trigger] self.set_value(value)).value() == value,
750            self.set_value(value).level() == self.level(),
751            self.set_value(value).children() == self.children(),
752    {
753        Self::lemma_new_properties(value, self.level(), self.children());
754    }
755
756    /// Replacing the value of a childless node preserves its `new_val` shape.
757    pub proof fn lemma_set_value_preserves_new_val_shape(self, value: T)
758        requires
759            self == Self::new_val(self.value(), self.level()),
760        ensures
761            self.set_value(value) == Self::new_val(value, self.level()),
762    {
763        self.lemma_set_value_observable_fields(value);
764        Self::lemma_new_properties(value, self.level(), Seq::new(N as nat, |i| None));
765        Self::lemma_ext_equal(self.set_value(value), Self::new_val(value, self.level()));
766    }
767
768    pub open spec fn is_leaf(self) -> bool {
769        forall|i: int| 0 <= i < Self::size() ==> !#[trigger] self.has_child(i)
770    }
771
772    pub broadcast proof fn lemma_is_leaf_bounded(self)
773        requires
774            self.inv(),
775            self.level() == L - 1,
776        ensures
777            #[trigger] self.is_leaf(),
778    {
779    }
780
781    pub open spec fn recursive_insert(self, path: TreePath<N>, node: Self) -> Self
782        recommends
783            self.inv(),
784            path.inv(),
785            path.len() < L - self.level(),
786            node.level() == self.level() + path.len() as nat,
787        decreases path.len(),
788    {
789        if path.is_empty() {
790            self
791        } else if path.len() == 1 {
792            self.insert(path[0], node)
793        } else {
794            let (hd, tl) = path.pop_head();
795            let child = if self.has_child(hd) {
796                self.child(hd)
797            } else {
798                TreeNode::new_default(self.level() + 1)
799            };
800            let updated_child = child.recursive_insert(tl, node);
801            self.insert(hd, updated_child)
802        }
803    }
804
805    pub proof fn lemma_recursive_insert_path_empty_identical(self, path: TreePath<N>, node: Self)
806        requires
807            self.inv(),
808            node.inv(),
809            path.inv(),
810            path.is_empty(),
811        ensures
812            self.recursive_insert(path, node) == self,
813    {
814    }
815
816    pub proof fn lemma_recursive_insert_path_len_1(self, path: TreePath<N>, node: Self)
817        requires
818            self.inv(),
819            node.inv(),
820            path.inv(),
821            path.len() == 1,
822            1 < L - self.level(),
823            node.level() == self.level() + 1,
824        ensures
825            self.recursive_insert(path, node) == self.insert(path[0], node),
826    {
827    }
828
829    pub proof fn lemma_recursive_insert_path_len_step(self, path: TreePath<N>, node: Self)
830        requires
831            self.inv(),
832            path.inv(),
833            node.inv(),
834            path.len() < L - self.level(),
835            node.level() == self.level() + path.len() as nat,
836            path.len() > 1,
837        ensures
838            self.has_child(path[0]) ==> self.recursive_insert(path, node) == self.insert(
839                path[0],
840                self.child(path[0]).recursive_insert(path.pop_head().1, node),
841            ),
842            !self.has_child(path[0]) ==> self.recursive_insert(path, node) == self.insert(
843                path[0],
844                TreeNode::new_default(self.level() + 1).recursive_insert(path.pop_head().1, node),
845            ),
846    {
847    }
848
849    pub proof fn lemma_recursive_insert_preserves_level(self, path: TreePath<N>, node: Self)
850        requires
851            self.inv(),
852            path.inv(),
853            node.inv(),
854            path.len() < L - self.level(),
855            node.level() == self.level() + path.len() as nat,
856            forall|lv: nat|
857                lv < L ==> #[trigger] T::default(lv).rel_children(path.pop_tail().0 as int, None),
858        ensures
859            self.recursive_insert(path, node).level() == self.level(),
860        decreases path.len(),
861    {
862        if path.is_empty() {
863            self.lemma_recursive_insert_path_empty_identical(path, node);
864        } else if path.len() == 1 {
865            path.lemma_index_satisfies_elem_inv(0);
866            self.lemma_recursive_insert_path_len_1(path, node);
867            assert(self.insert(path[0], node).level() == self.level());
868        } else {
869            self.lemma_recursive_insert_path_len_step(path, node);
870            let (hd, tl) = path.pop_head();
871            path.lemma_pop_head_preserves_inv();
872            if self.has_child(hd) {
873                let c = self.child(hd);
874                assert(self.insert(hd, c.recursive_insert(tl, node)).level() == self.level());
875            } else {
876                let c = TreeNode::new_default(self.level() + 1);
877                assert(self.insert(hd, c.recursive_insert(tl, node)).level() == self.level());
878            }
879        }
880    }
881
882    pub proof fn lemma_recursive_insert_preserves_value(self, path: TreePath<N>, node: Self)
883        requires
884            self.inv(),
885            path.inv(),
886            node.inv(),
887            path.len() < L - self.level(),
888            node.level() == self.level() + path.len() as nat,
889            forall|lv: nat, i: int|
890                lv < L && 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
891        ensures
892            self.recursive_insert(path, node).value() == self.value(),
893        decreases path.len(),
894    {
895        if path.is_empty() {
896            self.lemma_recursive_insert_path_empty_identical(path, node);
897        } else if path.len() == 1 {
898            path.lemma_index_satisfies_elem_inv(0);
899            self.lemma_recursive_insert_path_len_1(path, node);
900        } else {
901            self.lemma_recursive_insert_path_len_step(path, node);
902            let (hd, tl) = path.pop_head();
903            path.lemma_pop_head_preserves_inv();
904            if self.has_child(hd) {
905                let c = self.child(hd);
906                c.lemma_recursive_insert_preserves_value(tl, node);
907            } else {
908                let c = TreeNode::new_default(self.level() + 1);
909                Self::lemma_new_default_preserves_inv(self.level() + 1);
910                c.lemma_recursive_insert_preserves_value(tl, node);
911            }
912        }
913    }
914
915    pub proof fn lemma_recursive_insert_preserves_inv(self, path: TreePath<N>, node: Self)
916        requires
917            self.inv(),
918            path.inv(),
919            node.inv(),
920            path.len() < L - self.level(),
921            node.level() == self.level() + path.len() as nat,
922            self.recursive_seek(path.pop_tail().1) is Some ==> self.recursive_seek(
923                path.pop_tail().1,
924            )->0.value().rel_children(path.pop_tail().0 as int, Some(node.value())),
925            self.recursive_seek(path.pop_tail().1) is None ==> T::default(
926                (node.level() - 1) as nat,
927            ).rel_children(path.pop_tail().0 as int, Some(node.value())),
928            forall|lv: nat, i: int|
929                lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
930        ensures
931            self.recursive_insert(path, node).inv(),
932        decreases path.len(),
933    {
934        if path.is_empty() {
935            self.lemma_recursive_insert_path_empty_identical(path, node);
936        } else if path.len() == 1 {
937            path.lemma_index_satisfies_elem_inv(0);
938            self.lemma_recursive_insert_path_len_1(path, node);
939            self.lemma_insert_preserves_inv(path[0], node);
940        } else {
941            self.lemma_recursive_insert_path_len_step(path, node);
942            let (hd, tl) = path.pop_head();
943            path.lemma_pop_head_preserves_inv();
944            if self.has_child(hd) {
945                let c = self.child(hd);
946                assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
947                c.lemma_recursive_insert_preserves_inv(tl, node);
948                c.lemma_recursive_insert_preserves_level(tl, node);
949                c.lemma_recursive_insert_preserves_value(tl, node);
950                let updated_child = c.recursive_insert(tl, node);
951                self.lemma_insert_preserves_inv(hd, updated_child);
952            } else {
953                let c = TreeNode::new_default(self.level() + 1);
954                Self::lemma_new_default_preserves_inv(self.level() + 1);
955                self.value().lemma_default_preserves_rel_children(self.level());
956                c.lemma_recursive_insert_preserves_inv(tl, node);
957                c.lemma_recursive_insert_preserves_level(tl, node);
958                c.lemma_recursive_insert_preserves_value(tl, node);
959                let updated_child = c.recursive_insert(tl, node);
960                self.lemma_insert_preserves_inv(hd, updated_child);
961            }
962        }
963    }
964
965    /// Visit the tree node recursively based on the path
966    /// Returns a sequence of visited node values, including the initial one
967    /// If the path does not correspond to a node, stop the traverse, and return the
968    /// previously visited nodes.
969    pub open spec fn recursive_trace(self, path: TreePath<N>) -> Seq<T>
970        recommends
971            self.inv(),
972            path.inv(),
973            path.len() < L - self.level(),
974        decreases path.len(),
975    {
976        if path.is_empty() {
977            seq![self.value()]
978        } else {
979            let (hd, tl) = path.pop_head();
980            if self.has_child(hd) {
981                seq![self.value()].add(self.child(hd).recursive_trace(tl))
982            } else {
983                seq![self.value()]
984            }
985        }
986    }
987
988    pub proof fn lemma_recursive_trace_length(self, path: TreePath<N>)
989        requires
990            self.inv(),
991            path.inv(),
992        ensures
993            #[trigger] self.recursive_trace(path).len() <= path.len() + 1,
994        decreases path.len(),
995    {
996        if path.len() == 0 {
997        } else {
998            let (hd, tl) = path.pop_head();
999            path.lemma_pop_head_preserves_inv();
1000            if self.has_child(hd) {
1001                self.child(hd).lemma_recursive_trace_length(tl);
1002            }
1003        }
1004    }
1005
1006    pub proof fn lemma_recursive_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1007        requires
1008            self.inv(),
1009            path1.inv(),
1010            path2.inv(),
1011            n <= path1.len(),
1012            n <= path2.len(),
1013            forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1014            self.recursive_trace(path1).len() > n,
1015        ensures
1016            self.recursive_trace(path2).len() > n,
1017            forall|i: int|
1018                0 <= i <= n ==> self.recursive_trace(path1)[i] == self.recursive_trace(path2)[i],
1019        decreases n,
1020    {
1021        if n <= 0 {
1022        } else {
1023            let (hd1, tl1) = path1.pop_head();
1024            let (hd2, tl2) = path2.pop_head();
1025            if self.has_child(hd1) {
1026                path1.lemma_pop_head_preserves_inv();
1027                path2.lemma_pop_head_preserves_inv();
1028                self.child(hd1).lemma_recursive_trace_up_to(tl1, tl2, n - 1);
1029            }
1030        }
1031    }
1032
1033    /// Walk to the end of a path and return the subtree at the end
1034    /// Returns a single node (with its children)
1035    /// If the path does not correspond to a node, return None
1036    pub open spec fn recursive_seek(self, path: TreePath<N>) -> Option<Self>
1037        recommends
1038            self.inv(),
1039            path.inv(),
1040            path.len() < L - self.level(),
1041        decreases path.len(),
1042    {
1043        if path.is_empty() {
1044            Some(self)
1045        } else {
1046            let (hd, tl) = path.pop_head();
1047            if self.has_child(hd) {
1048                self.child(hd).recursive_seek(tl)
1049            } else {
1050                None
1051            }
1052        }
1053    }
1054
1055    pub proof fn lemma_recursive_seek_trace_length(self, path: TreePath<N>)
1056        requires
1057            self.inv(),
1058            path.inv(),
1059            path.len() < L - self.level(),
1060            self.recursive_seek(path) is Some,
1061        ensures
1062            self.recursive_trace(path).len() == path.len() + 1,
1063        decreases path.len(),
1064    {
1065        if path.len() == 0 {
1066        } else {
1067            let (hd, tl) = path.pop_head();
1068            if self.has_child(hd) {
1069                path.lemma_pop_head_preserves_inv();
1070                self.child(hd).lemma_recursive_seek_trace_length(tl)
1071            }
1072        }
1073    }
1074
1075    pub proof fn lemma_recursive_seek_trace_next(self, path: TreePath<N>, idx: usize)
1076        requires
1077            self.recursive_seek(path) is Some,
1078            self.recursive_seek(path)->0.has_child(idx as int),
1079            self.inv(),
1080            path.inv(),
1081            path.len() < L - self.level(),
1082            0 <= idx < N,
1083        ensures
1084            self.recursive_trace(path.push_tail(idx as int)).len() == path.len() + 2,
1085            self.recursive_seek(path)->0.child(idx as int).value() == self.recursive_trace(
1086                path.push_tail(idx as int),
1087            )[path.len() as int + 1],
1088        decreases path.len(),
1089    {
1090        let path2 = path.push_tail(idx as int);
1091
1092        if path.len() == 0 {
1093            assert(self.recursive_trace(path2) == seq![
1094                self.value(),
1095                self.child(idx as int).value(),
1096            ]) by { reveal_with_fuel(TreeNode::recursive_trace, 2) }
1097        } else {
1098            let (_, tl1) = path.pop_head();
1099            let (hd2, tl2) = path2.pop_head();
1100            assert(tl2 == tl1.push_tail(idx as int)) by {}
1101            assert(tl1.inv()) by { path.lemma_pop_head_preserves_inv() }
1102            if self.has_child(hd2) {
1103                self.child(hd2).lemma_recursive_seek_trace_next(tl1, idx);
1104            }
1105        }
1106    }
1107
1108    /// Visit the tree node recursively based on the path
1109    /// Returns a sequence of visited nodes, exclude the given one
1110    /// If the path is empty, return an empty sequence
1111    /// If the tree node is absent, stop the traverse, and return the
1112    /// previously visited nodes.
1113    pub open spec fn recursive_visit(self, path: TreePath<N>) -> Seq<Self>
1114        recommends
1115            self.inv(),
1116            path.inv(),
1117            path.len() < L - self.level(),
1118        decreases path.len(),
1119    {
1120        if path.is_empty() {
1121            Seq::empty()
1122        } else if path.len() == 1 {
1123            if self.has_child(path[0]) {
1124                seq![self.child(path[0])]
1125            } else {
1126                Seq::empty()
1127            }
1128        } else {
1129            let (hd, tl) = path.pop_head();
1130            if self.has_child(hd) {
1131                let child = self.child(hd);
1132                seq![child].add(child.recursive_visit(tl))
1133            } else {
1134                Seq::empty()
1135            }
1136        }
1137    }
1138
1139    pub proof fn lemma_recursive_visited_node_inv(self, path: TreePath<N>)
1140        requires
1141            self.inv(),
1142            path.inv(),
1143            path.len() < L - self.level(),
1144        ensures
1145            forall|i: int|
1146                0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1147                    path,
1148                )[i].inv(),
1149        decreases path.len(),
1150    {
1151        if path.is_empty() {
1152        } else if path.len() == 1 {
1153            if self.has_child(path[0]) {
1154            }
1155        } else {
1156            let (hd, tl) = path.pop_head();
1157            path.lemma_pop_head_preserves_inv();
1158            if self.has_child(hd) {
1159                let c = self.child(hd);
1160                assert(self.recursive_visit(path) == seq![c].add(c.recursive_visit(tl)));
1161                c.lemma_recursive_visited_node_inv(tl);
1162            }
1163        }
1164    }
1165
1166    pub proof fn lemma_recursive_visited_node_levels(self, path: TreePath<N>)
1167        requires
1168            self.inv(),
1169            path.inv(),
1170            path.len() < L - self.level(),
1171        ensures
1172            forall|i: int|
1173                0 <= i < self.recursive_visit(path).len() ==> #[trigger] self.recursive_visit(
1174                    path,
1175                )[i].level() == self.level() + i + 1,
1176        decreases path.len(),
1177    {
1178        if path.is_empty() {
1179        } else if path.len() == 1 {
1180            if self.has_child(path[0]) {
1181            }
1182        } else {
1183            let (hd, tl) = path.pop_head();
1184            path.lemma_pop_head_preserves_inv();
1185            if self.has_child(hd) {
1186                let c = self.child(hd);
1187                assert(self.recursive_visit(path) == seq![c].add(c.recursive_visit(tl)));
1188                c.lemma_recursive_visited_node_levels(tl);
1189            }
1190        }
1191    }
1192
1193    pub proof fn lemma_recursive_visit_head(self, path: TreePath<N>)
1194        requires
1195            self.inv(),
1196            path.inv(),
1197            path.len() < L - self.level(),
1198            !path.is_empty(),
1199            self.recursive_visit(path).len() > 0,
1200        ensures
1201            self.recursive_visit(path)[0] == self.child(path[0]),
1202    {
1203    }
1204
1205    pub proof fn lemma_recursive_visit_induction(self, path: TreePath<N>)
1206        requires
1207            self.inv(),
1208            path.inv(),
1209            path.len() < L - self.level(),
1210            !path.is_empty(),
1211            self.recursive_visit(path).len() > 0,
1212        ensures
1213            self.recursive_visit(path) == seq![self.child(path.pop_head().0)].add(
1214                self.child(path.pop_head().0).recursive_visit(path.pop_head().1),
1215            ),
1216    {
1217        if path.len() == 1 {
1218            path.lemma_pop_head_preserves_inv();
1219        } else {
1220            let (hd, _) = path.pop_head();
1221            path.lemma_pop_head_preserves_inv();
1222            if self.has_child(hd) {
1223                self.lemma_recursive_visit_head(path);
1224            }
1225        }
1226    }
1227
1228    pub proof fn lemma_recursive_visit_one_is_child(self, path: TreePath<N>)
1229        requires
1230            self.inv(),
1231            path.inv(),
1232            path.len() < L - self.level(),
1233            path.len() == 1,
1234        ensures
1235            self.has_child(path[0]) ==> self.recursive_visit(path) == seq![self.child(path[0])],
1236            !self.has_child(path[0]) ==> self.recursive_visit(path) == seq![],
1237    {
1238    }
1239
1240    pub open spec fn on_subtree(self, node: Self) -> bool
1241        recommends
1242            self.inv(),
1243            node.inv(),
1244            node.level() >= self.level(),
1245            node.level() < L,
1246    {
1247        node == self || exists|path: TreePath<N>| #[trigger]
1248            path.inv() && path.len() > 0 && path.len() == node.level() - self.level()
1249                && self.recursive_visit(path).last() == node
1250    }
1251
1252    pub broadcast proof fn lemma_on_subtree_property(self, node: Self)
1253        requires
1254            self.inv(),
1255            node.inv(),
1256            node.level() >= self.level(),
1257            node.level() < L,
1258            #[trigger] self.on_subtree(node),
1259        ensures
1260            node.level() == self.level() ==> self == node,
1261            node.level() > self.level() ==> exists|path: TreePath<N>| #[trigger]
1262                path.inv() && path.len() == node.level() - self.level() && self.recursive_visit(
1263                    path,
1264                ).last() == node,
1265    {
1266    }
1267
1268    pub broadcast proof fn lemma_not_on_subtree_property(self, node: Self)
1269        requires
1270            self.inv(),
1271            node.inv(),
1272            node.level() < L,
1273            !#[trigger] self.on_subtree(node),
1274        ensures
1275            self != node,
1276            node.level() > self.level() ==> forall|path: TreePath<N>| #[trigger]
1277                path.inv() && path.len() == node.level() - self.level() ==> self.recursive_visit(
1278                    path,
1279                ).last() != node,
1280    {
1281    }
1282
1283    pub broadcast proof fn lemma_on_subtree_reflexive(self)
1284        requires
1285            self.inv(),
1286        ensures
1287            #[trigger] self.on_subtree(self),
1288    {
1289    }
1290
1291    pub broadcast proof fn lemma_child_on_subtree(self, key: int)
1292        requires
1293            0 <= key < Self::size(),
1294            self.inv(),
1295            self.has_child(key),
1296        ensures
1297            #[trigger] self.on_subtree(self.child(key)),
1298    {
1299        assert(TreePath::<N>::new(seq![key]).inv());
1300    }
1301
1302    pub broadcast proof fn lemma_insert_on_subtree(self, key: int, node: Self)
1303        requires
1304            0 <= key < Self::size(),
1305            self.inv(),
1306            node.inv(),
1307            self.level() < L - 1,
1308            node.level() == self.level() + 1,
1309            self.value().rel_children(key, Some(node.value())),
1310        ensures
1311            #[trigger] self.insert(key, node).on_subtree(node),
1312    {
1313        self.lemma_insert_child_is_child(key, node);
1314        self.insert(key, node).lemma_child_on_subtree(key);
1315    }
1316
1317    /// Remove the tree node at the end of the path
1318    /// If the path is empty or any node in the path is absent,
1319    /// return the original tree node (no change)
1320    /// Otherwise, remove the node at the end of the path, and
1321    /// update the node recursively
1322    pub open spec fn recursive_remove(self, path: TreePath<N>) -> Self
1323        recommends
1324            self.inv(),
1325            path.inv(),
1326            path.len() < L - self.level(),
1327        decreases path.len(),
1328    {
1329        if path.is_empty() {
1330            self
1331        } else if path.len() == 1 {
1332            self.remove(path[0])
1333        } else {
1334            let (hd, tl) = path.pop_head();
1335            if self.children()[hd as int] is None {
1336                self
1337            } else {
1338                let child = self.child(hd);
1339                let updated_child = child.recursive_remove(tl);
1340                self.insert(hd, updated_child)
1341            }
1342        }
1343    }
1344
1345    pub proof fn lemma_recursive_remove_preserves_level(self, path: TreePath<N>)
1346        requires
1347            self.inv(),
1348            path.inv(),
1349            path.len() < L - self.level(),
1350        ensures
1351            self.recursive_remove(path).level() == self.level(),
1352        decreases path.len(),
1353    {
1354        if path.is_empty() {
1355        } else if path.len() == 1 {
1356        } else {
1357            let (hd, tl) = path.pop_head();
1358            path.lemma_pop_head_preserves_inv();
1359            if self.has_child(hd) {
1360                let c = self.child(hd);
1361                c.lemma_recursive_remove_preserves_level(tl);
1362            }
1363        }
1364    }
1365
1366    pub proof fn lemma_recursive_remove_preserves_value(self, path: TreePath<N>)
1367        requires
1368            self.inv(),
1369            path.inv(),
1370            path.len() < L - self.level(),
1371        ensures
1372            self.recursive_remove(path).value() == self.value(),
1373        decreases path.len(),
1374    {
1375        if path.is_empty() {
1376        } else if path.len() == 1 {
1377        } else {
1378            let (hd, tl) = path.pop_head();
1379            path.lemma_pop_head_preserves_inv();
1380            if self.has_child(hd) {
1381                let c = self.child(hd);
1382                c.lemma_recursive_remove_preserves_value(tl);
1383            }
1384        }
1385    }
1386
1387    pub proof fn lemma_recursive_remove_preserves_inv(self, path: TreePath<N>)
1388        requires
1389            self.inv(),
1390            path.inv(),
1391            path.len() < L - self.level(),
1392            path.len() > 0 ==> self.recursive_seek(path.pop_tail().1) is Some
1393                ==> self.recursive_seek(
1394                path.pop_tail().1,
1395            )->0.children()[path.pop_tail().0 as int] is None || self.recursive_seek(
1396                path.pop_tail().1,
1397            )->0.value().rel_children(path.pop_tail().0 as int, None),
1398        ensures
1399            self.recursive_remove(path).inv(),
1400        decreases path.len(),
1401    {
1402        if path.is_empty() {
1403        } else if path.len() == 1 {
1404            self.lemma_remove_preserves_inv(path[0]);
1405        } else {
1406            let (hd, tl) = path.pop_head();
1407            path.lemma_pop_head_preserves_inv();
1408            if self.has_child(hd) {
1409                let c = self.child(hd);
1410                assert(path.pop_tail().1.pop_head().1 == path.pop_head().1.pop_tail().1);
1411                c.lemma_recursive_remove_preserves_inv(tl);
1412                c.lemma_recursive_remove_preserves_level(tl);
1413                c.lemma_recursive_remove_preserves_value(tl);
1414                let updated_child = c.recursive_remove(tl);
1415                self.lemma_insert_preserves_inv(hd, updated_child);
1416            }
1417        }
1418    }
1419}
1420
1421pub closed spec fn path_between<T: TreeNodeValue<L>, const N: usize, const L: usize>(
1422    src: TreeNode<T, N, L>,
1423    dst: TreeNode<T, N, L>,
1424) -> TreePath<N>
1425    recommends
1426        src.inv(),
1427        dst.inv(),
1428        src.level() <= dst.level(),
1429        src.on_subtree(dst),
1430{
1431    if src.inv() && dst.inv() && dst.level() >= src.level() && dst.level() < L && src.on_subtree(
1432        dst,
1433    ) {
1434        if src == dst {
1435            TreePath::new(seq![])
1436        } else {
1437            choose|path: TreePath<N>| #[trigger]
1438                path.inv() && path.len() > 0 && path.len() == dst.level() - src.level()
1439                    && src.recursive_visit(path).last() == dst
1440        }
1441    } else {
1442        vstd::pervasive::arbitrary()
1443    }
1444}
1445
1446pub broadcast proof fn lemma_path_between_properties<
1447    T: TreeNodeValue<L>,
1448    const N: usize,
1449    const L: usize,
1450>(src: TreeNode<T, N, L>, dst: TreeNode<T, N, L>)
1451    requires
1452        src.inv(),
1453        dst.inv(),
1454        src.level() <= dst.level(),
1455        #[trigger] src.on_subtree(dst),
1456    ensures
1457        path_between(src, dst).inv(),
1458        path_between(src, dst).len() == dst.level() - src.level(),
1459        dst.level() == src.level() ==> path_between(src, dst).is_empty() && src == dst,
1460        dst.level() > src.level() ==> src.recursive_visit(path_between(src, dst)).last() == dst,
1461{
1462}
1463
1464} // verus!
1465verus! {
1466
1467pub tracked struct Tree<T: TreeNodeValue<L>, const N: usize, const L: usize> {
1468    pub tracked root: TreeNode<T, N, L>,
1469}
1470
1471impl<T: TreeNodeValue<L>, const N: usize, const L: usize> Tree<T, N, L> {
1472    pub open spec fn inv(self) -> bool {
1473        &&& L > 0
1474        &&& N > 0
1475        &&& self.root.inv()
1476        &&& self.root.level() == 0
1477    }
1478
1479    pub open spec fn new() -> Self {
1480        Tree { root: TreeNode::new_default(0) }
1481    }
1482
1483    pub broadcast proof fn lemma_new_preserves_inv()
1484        requires
1485            N > 0,
1486            L > 0,
1487            forall|i: int| 0 <= i < N ==> #[trigger] T::default(0).rel_children(i, None),
1488        ensures
1489            (#[trigger] Self::new()).inv(),
1490    {
1491        TreeNode::<T, N, L>::lemma_new_default_preserves_inv(0);
1492    }
1493
1494    pub open spec fn insert(self, path: TreePath<N>, node: TreeNode<T, N, L>) -> Self
1495        recommends
1496            self.inv(),
1497            path.inv(),
1498            node.inv(),
1499            path.len() < L,
1500            node.level() == path.len() as nat,
1501        decreases path.len(),
1502    {
1503        Tree { root: self.root.recursive_insert(path, node), ..self }
1504    }
1505
1506    pub open spec fn remove(self, path: TreePath<N>) -> Self
1507        recommends
1508            self.inv(),
1509            path.inv(),
1510            path.len() < L,
1511        decreases path.len(),
1512    {
1513        Tree { root: self.root.recursive_remove(path), ..self }
1514    }
1515
1516    pub open spec fn visit(self, path: TreePath<N>) -> Seq<TreeNode<T, N, L>>
1517        recommends
1518            self.inv(),
1519            path.inv(),
1520            path.len() < L,
1521        decreases path.len(),
1522    {
1523        self.root.recursive_visit(path)
1524    }
1525
1526    pub open spec fn trace(self, path: TreePath<N>) -> Seq<T>
1527        recommends
1528            self.inv(),
1529            path.inv(),
1530            path.len() < L,
1531        decreases path.len(),
1532    {
1533        self.root.recursive_trace(path)
1534    }
1535
1536    pub broadcast proof fn lemma_trace_empty_is_head(self, path: TreePath<N>)
1537        requires
1538            path.len() == 0,
1539        ensures
1540            #[trigger] self.trace(path) == seq![self.root.value()],
1541    {
1542    }
1543
1544    pub proof fn lemma_trace_up_to(self, path1: TreePath<N>, path2: TreePath<N>, n: int)
1545        requires
1546            self.inv(),
1547            path1.inv(),
1548            path2.inv(),
1549            n <= path1.len(),
1550            n <= path2.len(),
1551            forall|i: int| 0 <= i < n ==> path1.0[i] == path2.0[i],
1552            self.trace(path1).len() > n,
1553        ensures
1554            self.trace(path2).len() > n,
1555            forall|i: int| 0 <= i <= n ==> self.trace(path1)[i] == self.trace(path2)[i],
1556    {
1557        self.root.lemma_recursive_trace_up_to(path1, path2, n)
1558    }
1559
1560    pub broadcast proof fn lemma_trace_length(self, path: TreePath<N>)
1561        requires
1562            self.inv(),
1563            path.inv(),
1564        ensures
1565            #[trigger] self.trace(path).len() <= path.len() + 1,
1566    {
1567        self.root.lemma_recursive_trace_length(path);
1568    }
1569
1570    pub open spec fn seek(self, path: TreePath<N>) -> Option<TreeNode<T, N, L>> {
1571        self.root.recursive_seek(path)
1572    }
1573
1574    pub proof fn lemma_seek_trace_length(self, path: TreePath<N>)
1575        requires
1576            self.inv(),
1577            path.inv(),
1578            path.len() < L,
1579            self.seek(path) is Some,
1580        ensures
1581            self.trace(path).len() == path.len() + 1,
1582    {
1583        self.root.lemma_recursive_seek_trace_length(path)
1584    }
1585
1586    pub proof fn lemma_seek_trace_next(self, path: TreePath<N>, idx: usize)
1587        requires
1588            self.seek(path) is Some,
1589            self.seek(path)->0.has_child(idx as int),
1590            self.inv(),
1591            path.inv(),
1592            path.len() < L,
1593            0 <= idx < N,
1594        ensures
1595            self.trace(path.push_tail(idx as int)).len() == path.len() + 2,
1596            self.seek(path)->0.child(idx as int).value() == self.trace(
1597                path.push_tail(idx as int),
1598            )[path.len() as int + 1],
1599    {
1600        self.root.lemma_recursive_seek_trace_next(path, idx)
1601    }
1602
1603    pub broadcast proof fn lemma_insert_preserves_inv(
1604        self,
1605        path: TreePath<N>,
1606        node: TreeNode<T, N, L>,
1607    )
1608        requires
1609            self.inv(),
1610            path.inv(),
1611            node.inv(),
1612            path.len() < L,
1613            node.level() == path.len() as nat,
1614            self.seek(path.pop_tail().1) is Some ==> self.seek(
1615                path.pop_tail().1,
1616            )->0.value().rel_children(path[path.len() - 1] as int, Some(node.value())),
1617            self.seek(path.pop_tail().1) is None ==> T::default(
1618                (path.len() - 1) as nat,
1619            ).rel_children(path[path.len() - 1] as int, Some(node.value())),
1620            forall|lv: nat, i: int|
1621                lv < L ==> 0 <= i < N ==> #[trigger] T::default(lv).rel_children(i, None),
1622        ensures
1623            (#[trigger] self.insert(path, node)).inv(),
1624    {
1625        self.root.lemma_recursive_insert_preserves_inv(path, node);
1626    }
1627
1628    pub broadcast proof fn lemma_remove_preserves_inv(self, path: TreePath<N>)
1629        requires
1630            self.inv(),
1631            path.inv(),
1632            path.len() < L,
1633            path.len() > 0 ==> self.seek(path.pop_tail().1) is Some ==> self.seek(
1634                path.pop_tail().1,
1635            )->0.children()[path.pop_tail().0 as int] is None || self.seek(
1636                path.pop_tail().1,
1637            )->0.value().rel_children(path[path.len() - 1] as int, None),
1638        ensures
1639            (#[trigger] self.remove(path)).inv(),
1640    {
1641        self.root.lemma_recursive_remove_preserves_inv(path);
1642    }
1643
1644    pub broadcast proof fn lemma_visited_nodes_inv(self, path: TreePath<N>)
1645        requires
1646            self.inv(),
1647            path.inv(),
1648            path.len() < L,
1649        ensures
1650            #![trigger self.visit(path)]
1651            forall|i: int|
1652                0 <= i < self.visit(path).len() ==> #[trigger] self.visit(path)[i].inv(),
1653    {
1654        self.root.lemma_recursive_visited_node_inv(path);
1655    }
1656
1657    pub open spec fn on_tree(self, node: TreeNode<T, N, L>) -> bool
1658        recommends
1659            self.inv(),
1660            node.inv(),
1661    {
1662        self.root.on_subtree(node)
1663    }
1664
1665    pub broadcast proof fn lemma_on_tree_property(self, node: TreeNode<T, N, L>)
1666        requires
1667            self.inv(),
1668            node.inv(),
1669            #[trigger] self.on_tree(node),
1670        ensures
1671            node.level() == 0 ==> self.root == node,
1672            node.level() > 0 ==> exists|path: TreePath<N>| #[trigger]
1673                path.inv() && path.len() == node.level() && self.visit(path).last() == node,
1674    {
1675    }
1676
1677    pub broadcast proof fn lemma_not_on_tree_property(self, node: TreeNode<T, N, L>)
1678        requires
1679            self.inv(),
1680            node.inv(),
1681            !#[trigger] self.on_tree(node),
1682        ensures
1683            node != self.root,
1684            node.level() > 0 ==> forall|path: TreePath<N>| #[trigger]
1685                path.inv() && path.len() == node.level() ==> self.visit(path).last() != node,
1686    {
1687    }
1688
1689    pub open spec fn get_path(self, node: TreeNode<T, N, L>) -> TreePath<N>
1690        recommends
1691            self.inv(),
1692            node.inv(),
1693            self.on_tree(node),
1694    {
1695        path_between::<T, N, L>(self.root, node)
1696    }
1697
1698    pub broadcast proof fn lemma_get_path_properties(self, node: TreeNode<T, N, L>)
1699        requires
1700            self.inv(),
1701            node.inv(),
1702            self.on_tree(node),
1703        ensures
1704            (#[trigger] self.get_path(node)).inv(),
1705            self.get_path(node).len() == node.level(),
1706            node.level() == 0 ==> self.get_path(node).is_empty(),
1707            node.level() > 0 ==> self.visit(self.get_path(node)).last() == node,
1708    {
1709        lemma_path_between_properties(self.root, node);
1710    }
1711}
1712
1713} // verus!
1714verus! {
1715
1716pub broadcast group group_ghost_tree_lemmas {
1717    TreePath::lemma_index_satisfies_elem_inv,
1718    TreePath::lemma_empty_satisfies_inv,
1719    TreePath::lemma_pop_head_preserves_inv,
1720    TreePath::lemma_pop_head_index,
1721    TreePath::lemma_pop_tail_preserves_inv,
1722    TreePath::lemma_pop_tail_index,
1723    TreePath::lemma_push_head_index,
1724    TreePath::lemma_push_head_preserves_inv,
1725    TreePath::lemma_push_tail_len,
1726    TreePath::lemma_push_tail_index,
1727    TreePath::lemma_push_tail_preserves_inv,
1728    TreePath::lemma_new_preserves_inv,
1729    TreeNode::lemma_new_properties,
1730    TreeNode::lemma_new_val_properties,
1731    TreeNode::lemma_ext_equal,
1732    TreeNode::lemma_insert_preserves_inv,
1733    TreeNode::lemma_insert_property,
1734    TreeNode::lemma_remove_preserves_inv,
1735    TreeNode::lemma_remove_property,
1736    TreeNode::lemma_set_value_observable_fields,
1737    TreeNode::lemma_is_leaf_bounded,
1738    TreeNode::lemma_on_subtree_property,
1739    TreeNode::lemma_not_on_subtree_property,
1740    TreeNode::lemma_on_subtree_reflexive,
1741    TreeNode::lemma_child_on_subtree,
1742    TreeNode::lemma_insert_on_subtree,
1743    lemma_path_between_properties,
1744}
1745
1746} // verus!