vstd_extra/
ghost_tree.rs

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