Skip to main content

vstd/
seq_lib.rs

1#[allow(unused_imports)]
2use super::calc_macro::*;
3#[allow(unused_imports)]
4use super::multiset::Multiset;
5#[allow(unused_imports)]
6use super::pervasive::*;
7#[allow(unused_imports)]
8use super::prelude::*;
9#[allow(unused_imports)]
10use super::relations::*;
11#[allow(unused_imports)]
12use super::seq::*;
13#[allow(unused_imports)]
14use super::set::Set;
15
16verus! {
17
18broadcast use group_seq_axioms;
19
20impl<A> Seq<A> {
21    /// Applies the function `f` to each element of the sequence, and returns
22    /// the resulting sequence.
23    /// The `int` parameter of `f` is the index of the element being mapped.
24    // TODO(verus): rename to map_entries, for consistency with Map::map
25    pub open spec fn map<B>(self, f: spec_fn(int, A) -> B) -> Seq<B> {
26        Seq::new(self.len(), |i: int| f(i, self[i]))
27    }
28
29    /// Applies the function `f` to each element of the sequence, and returns
30    /// the resulting sequence.
31    // TODO(verus): rename to map, because this is what everybody wants.
32    pub open spec fn map_values<B>(self, f: spec_fn(A) -> B) -> Seq<B> {
33        Seq::new(self.len(), |i: int| f(self[i]))
34    }
35
36    /// Applies the function `f` to each element of the sequence,
37    /// producing a sequence of sequences, and then concatenates (flattens)
38    /// those into a single flat sequence of `B`.
39    ///
40    /// ## Example
41    ///
42    /// ```rust
43    /// fn example() {
44    ///     let s = seq![1, 2, 3];
45    ///     let result = s.flat_map(|x| seq![x, x]);
46    ///     assert_eq!(result, seq![1, 1, 2, 2, 3, 3]);
47    /// }
48    /// ``
49    pub open spec fn flat_map<B>(self, f: spec_fn(A) -> Seq<B>) -> Seq<B> {
50        self.map_values(f).flatten()
51    }
52
53    /// Add a reference (&) to each element of the sequence
54    pub open spec fn as_ref(&self) -> Seq<&A> {
55        Seq::new(self.len(), |i: int| &self[i])
56    }
57
58    /// Is true if the calling sequence is a prefix of the given sequence 'other'.
59    ///
60    /// ## Example
61    ///
62    /// ```rust
63    /// proof fn prefix_test() {
64    ///     let pre: Seq<int> = seq![1, 2, 3];
65    ///     let whole: Seq<int> = seq![1, 2, 3, 4, 5];
66    ///     assert(pre.is_prefix_of(whole));
67    /// }
68    /// ```
69    pub open spec fn is_prefix_of(self, other: Self) -> bool {
70        self.len() <= other.len() && self =~= other.subrange(0, self.len() as int)
71    }
72
73    /// Is true if the calling sequence is a suffix of the given sequence 'other'.
74    ///
75    /// ## Example
76    ///
77    /// ```rust
78    /// proof fn suffix_test() {
79    ///     let end: Seq<int> = seq![3, 4, 5];
80    ///     let whole: Seq<int> = seq![1, 2, 3, 4, 5];
81    ///     assert(end.is_suffix_of(whole));
82    /// }
83    /// ```
84    pub open spec fn is_suffix_of(self, other: Self) -> bool {
85        self.len() <= other.len() && self =~= other.subrange(
86            (other.len() - self.len()) as int,
87            other.len() as int,
88        )
89    }
90
91    /// Sorts the sequence according to the given leq function
92    ///
93    /// ## Example
94    ///
95    /// ```rust
96    /// {{#include ../../../../examples/multiset.rs:sorted_by_leq}}
97    /// ```
98    pub closed spec fn sort_by(self, leq: spec_fn(A, A) -> bool) -> Seq<A>
99        recommends
100            total_ordering(leq),
101        decreases self.len(),
102    {
103        if self.len() <= 1 {
104            self
105        } else {
106            let split_index = self.len() / 2;
107            let left = self.subrange(0, split_index as int);
108            let right = self.subrange(split_index as int, self.len() as int);
109            let left_sorted = left.sort_by(leq);
110            let right_sorted = right.sort_by(leq);
111            merge_sorted_with(left_sorted, right_sorted, leq)
112        }
113    }
114
115    /// Tests if all elements in the sequence satisfy the predicate.
116    ///
117    /// ## Example
118    ///
119    /// ```rust
120    /// fn example() {
121    ///     let s = seq![2, 4, 6, 8];
122    ///     assert!(s.all(|x| x % 2 == 0));
123    /// }
124    /// ```
125    pub open spec fn all(self, pred: spec_fn(A) -> bool) -> bool {
126        forall|i: int| 0 <= i < self.len() ==> #[trigger] pred(self[i])
127    }
128
129    /// Tests if any element in the sequence satisfies the predicate.
130    ///
131    /// ## Example
132    ///
133    /// ```rust
134    /// fn example() {
135    ///     let s = seq![1, 2, 3, 4];
136    ///     assert!(s.any(|x| x > 3));
137    /// }
138    /// ```
139    pub open spec fn any(self, pred: spec_fn(A) -> bool) -> bool {
140        exists|i: int| 0 <= i < self.len() && #[trigger] pred(self[i])
141    }
142
143    /// Checks that exactly one element in the sequence satisfies the given predicate.
144    /// ## Example
145    ///
146    /// ```rust
147    /// fn example() {
148    ///     let s = seq![1, 2, 3];
149    ///     assert!(s.exactly_one(|x| x == 2));
150    /// }
151    /// ```
152    pub open spec fn exactly_one(self, pred: spec_fn(A) -> bool) -> bool {
153        self.filter(pred).len() == 1
154    }
155
156    pub proof fn lemma_sort_by_ensures(self, leq: spec_fn(A, A) -> bool)
157        requires
158            total_ordering(leq),
159        ensures
160            self.to_multiset() =~= self.sort_by(leq).to_multiset(),
161            sorted_by(self.sort_by(leq), leq),
162            forall|x: A| !self.contains(x) ==> !(#[trigger] self.sort_by(leq).contains(x)),
163        decreases self.len(),
164    {
165        if self.len() <= 1 {
166        } else {
167            let split_index = self.len() / 2;
168            let left = self.subrange(0, split_index as int);
169            let right = self.subrange(split_index as int, self.len() as int);
170            assert(self =~= left + right);
171            let left_sorted = left.sort_by(leq);
172            left.lemma_sort_by_ensures(leq);
173            let right_sorted = right.sort_by(leq);
174            right.lemma_sort_by_ensures(leq);
175            lemma_merge_sorted_with_ensures(left_sorted, right_sorted, leq);
176            lemma_multiset_commutative(left, right);
177            lemma_multiset_commutative(left_sorted, right_sorted);
178            assert forall|x: A| !self.contains(x) implies !(#[trigger] self.sort_by(leq).contains(
179                x,
180            )) by {
181                broadcast use group_to_multiset_ensures;
182
183                assert(!self.contains(x) ==> self.to_multiset().count(x) == 0);
184            }
185        }
186    }
187
188    /// Returns the sequence containing only the elements of the original sequence
189    /// such that pred(element) is true.
190    ///
191    /// ## Example
192    ///
193    /// ```rust
194    /// proof fn filter_test() {
195    ///    let seq: Seq<int> = seq![1, 2, 3, 4, 5];
196    ///    let even: Seq<int> = seq.filter(|x| x % 2 == 0);
197    ///    reveal_with_fuel(Seq::<int>::filter, 6); //Needed for Verus to unfold the recursive definition of filter
198    ///    assert(even =~= seq![2, 4]);
199    /// }
200    /// ```
201    #[verifier::opaque]
202    pub open spec fn filter(self, pred: spec_fn(A) -> bool) -> Self
203        decreases self.len(),
204    {
205        if self.len() == 0 {
206            self
207        } else {
208            let subseq = self.drop_last().filter(pred);
209            if pred(self.last()) {
210                subseq.push(self.last())
211            } else {
212                subseq
213            }
214        }
215    }
216
217    pub broadcast proof fn lemma_filter_len(self, pred: spec_fn(A) -> bool)
218        ensures
219    // the filtered list can't grow
220
221            #[trigger] self.filter(pred).len() <= self.len(),
222        decreases self.len(),
223    {
224        reveal(Seq::filter);
225        let out = self.filter(pred);
226        if 0 < self.len() {
227            self.drop_last().lemma_filter_len(pred);
228        }
229    }
230
231    pub broadcast proof fn lemma_filter_pred(self, pred: spec_fn(A) -> bool, i: int)
232        requires
233            0 <= i < self.filter(pred).len(),
234        ensures
235            pred(#[trigger] self.filter(pred)[i]),
236    {
237        // TODO: remove this after proved filter_lemma is proved
238        #[allow(deprecated)]
239        self.filter_lemma(pred);
240    }
241
242    pub broadcast proof fn lemma_filter_contains(self, pred: spec_fn(A) -> bool, i: int)
243        requires
244            0 <= i < self.len() && pred(self[i]),
245        ensures
246            #[trigger] self.filter(pred).contains(self[i]),
247    {
248        // TODO: remove this after proved filter_lemma is proved
249        #[allow(deprecated)]
250        self.filter_lemma(pred);
251    }
252
253    // deprecated since the triggers inside of 2 of the conjuncts are blocked
254    #[cfg_attr(not(verus_verify_core), deprecated = "Use `broadcast use group_filter_ensures` instead" )]
255    pub proof fn filter_lemma(self, pred: spec_fn(A) -> bool)
256        ensures
257    // we don't keep anything bad
258    // TODO(andrea): recommends didn't catch this error, where i isn't known to be in
259    // self.filter(pred).len()
260    //forall |i: int| 0 <= i < self.len() ==> pred(#[trigger] self.filter(pred)[i]),
261
262            forall|i: int|
263                0 <= i < self.filter(pred).len() ==> pred(#[trigger] self.filter(pred)[i]),
264            // we keep everything we should
265            forall|i: int|
266                0 <= i < self.len() && pred(self[i]) ==> #[trigger] self.filter(pred).contains(
267                    self[i],
268                ),
269            // the filtered list can't grow
270            #[trigger] self.filter(pred).len() <= self.len(),
271        decreases self.len(),
272    {
273        reveal(Seq::filter);
274        let out = self.filter(pred);
275        if 0 < self.len() {
276            self.drop_last().filter_lemma(pred);
277            assert forall|i: int| 0 <= i < out.len() implies pred(out[i]) by {
278                if i < out.len() - 1 {
279                    assert(self.drop_last().filter(pred)[i] == out.drop_last()[i]);  // trigger drop_last
280                    assert(pred(out[i]));  // TODO(andrea): why is this line required? It's the conclusion of the assert-forall.
281                }
282            }
283            assert forall|i: int|
284                0 <= i < self.len() && pred(self[i]) implies #[trigger] out.contains(self[i]) by {
285                if i == self.len() - 1 {
286                    assert(self[i] == out[out.len() - 1]);  // witness to contains
287                } else {
288                    let subseq = self.drop_last().filter(pred);
289                    assert(subseq.contains(self.drop_last()[i]));  // trigger recursive invocation
290                    let j = choose|j| 0 <= j < subseq.len() && subseq[j] == self[i];
291                    assert(out[j] == self[i]);  // TODO(andrea): same, seems needless
292                }
293            }
294        }
295    }
296
297    pub broadcast proof fn filter_distributes_over_add(a: Self, b: Self, pred: spec_fn(A) -> bool)
298        ensures
299            #[trigger] (a + b).filter(pred) == a.filter(pred) + b.filter(pred),
300        decreases b.len(),
301    {
302        reveal(Seq::filter);
303        if 0 < b.len() {
304            Self::drop_last_distributes_over_add(a, b);
305            Self::filter_distributes_over_add(a, b.drop_last(), pred);
306            if pred(b.last()) {
307                Self::push_distributes_over_add(
308                    a.filter(pred),
309                    b.drop_last().filter(pred),
310                    b.last(),
311                );
312            }
313        } else {
314            Self::add_empty_right(a, b);
315            Self::add_empty_right(a.filter(pred), b.filter(pred));
316        }
317    }
318
319    pub broadcast proof fn add_empty_left(a: Self, b: Self)
320        requires
321            a.len() == 0,
322        ensures
323            #[trigger] (a + b) == b,
324    {
325        assert(a + b =~= b);
326    }
327
328    pub broadcast proof fn add_empty_right(a: Self, b: Self)
329        requires
330            b.len() == 0,
331        ensures
332            #[trigger] (a + b) == a,
333    {
334        assert(a + b =~= a);
335    }
336
337    pub broadcast proof fn push_distributes_over_add(a: Self, b: Self, elt: A)
338        ensures
339            #[trigger] (a + b).push(elt) == a + b.push(elt),
340    {
341        assert((a + b).push(elt) =~= a + b.push(elt));
342    }
343
344    /// Returns the maximum value in a non-empty sequence, given sorting function leq
345    pub open spec fn max_via(self, leq: spec_fn(A, A) -> bool) -> A
346        recommends
347            self.len() > 0,
348        decreases self.len(),
349    {
350        if self.len() > 1 {
351            if leq(self[0], self.subrange(1, self.len() as int).max_via(leq)) {
352                self.subrange(1, self.len() as int).max_via(leq)
353            } else {
354                self[0]
355            }
356        } else {
357            self[0]
358        }
359    }
360
361    /// Returns the minimum value in a non-empty sequence, given sorting function leq
362    pub open spec fn min_via(self, leq: spec_fn(A, A) -> bool) -> A
363        recommends
364            self.len() > 0,
365        decreases self.len(),
366    {
367        if self.len() > 1 {
368            let subseq = self.subrange(1, self.len() as int);
369            let elt = subseq.min_via(leq);
370            if leq(elt, self[0]) {
371                elt
372            } else {
373                self[0]
374            }
375        } else {
376            self[0]
377        }
378    }
379
380    // TODO is_sorted -- extract from summer_school e22
381    pub open spec fn contains(self, needle: A) -> bool {
382        exists|i: int| 0 <= i < self.len() && self[i] == needle
383    }
384
385    /// Returns an index where `needle` appears in the sequence.
386    /// Returns an arbitrary value if the sequence does not contain the `needle`.
387    pub open spec fn index_of(self, needle: A) -> int {
388        choose|i: int| 0 <= i < self.len() && self[i] == needle
389    }
390
391    /// For an element that occurs at least once in a sequence, if its first occurence
392    /// is at index i, Some(i) is returned. Otherwise, None is returned
393    pub closed spec fn index_of_first(self, needle: A) -> (result: Option<int>) {
394        if self.contains(needle) {
395            Some(self.first_index_helper(needle))
396        } else {
397            None
398        }
399    }
400
401    // Recursive helper function for index_of_first
402    spec fn first_index_helper(self, needle: A) -> int
403        recommends
404            self.contains(needle),
405        decreases self.len(),
406    {
407        if self.len() <= 0 {
408            -1  //arbitrary, will never get to this case
409
410        } else if self[0] == needle {
411            0
412        } else {
413            1 + self.subrange(1, self.len() as int).first_index_helper(needle)
414        }
415    }
416
417    pub proof fn index_of_first_ensures(self, needle: A)
418        ensures
419            match self.index_of_first(needle) {
420                Some(index) => {
421                    &&& self.contains(needle)
422                    &&& 0 <= index < self.len()
423                    &&& self[index] == needle
424                    &&& forall|j: int| 0 <= j < index < self.len() ==> self[j] != needle
425                },
426                None => { !self.contains(needle) },
427            },
428        decreases self.len(),
429    {
430        if self.contains(needle) {
431            let index = self.index_of_first(needle).unwrap();
432            if self.len() <= 0 {
433            } else if self[0] == needle {
434            } else {
435                assert(Seq::empty().push(self.first()).add(self.drop_first()) =~= self);
436                self.drop_first().index_of_first_ensures(needle);
437            }
438        }
439    }
440
441    /// For an element that occurs at least once in a sequence, if its last occurence
442    /// is at index i, Some(i) is returned. Otherwise, None is returned
443    pub closed spec fn index_of_last(self, needle: A) -> Option<int> {
444        if self.contains(needle) {
445            Some(self.last_index_helper(needle))
446        } else {
447            None
448        }
449    }
450
451    // Recursive helper function for last_index_of
452    spec fn last_index_helper(self, needle: A) -> int
453        recommends
454            self.contains(needle),
455        decreases self.len(),
456    {
457        if self.len() <= 0 {
458            -1  //arbitrary, will never get to this case
459
460        } else if self.last() == needle {
461            self.len() - 1
462        } else {
463            self.drop_last().last_index_helper(needle)
464        }
465    }
466
467    pub proof fn index_of_last_ensures(self, needle: A)
468        ensures
469            match self.index_of_last(needle) {
470                Some(index) => {
471                    &&& self.contains(needle)
472                    &&& 0 <= index < self.len()
473                    &&& self[index] == needle
474                    &&& forall|j: int| 0 <= index < j < self.len() ==> self[j] != needle
475                },
476                None => { !self.contains(needle) },
477            },
478        decreases self.len(),
479    {
480        if self.contains(needle) {
481            let index = self.index_of_last(needle).unwrap();
482            if self.len() <= 0 {
483            } else if self.last() == needle {
484            } else {
485                assert(self.drop_last().push(self.last()) =~= self);
486                self.drop_last().index_of_last_ensures(needle);
487            }
488        }
489    }
490
491    /// Drops the last element of a sequence and returns a sequence whose length is
492    /// thereby 1 smaller.
493    ///
494    /// If the input sequence is empty, the result is meaningless and arbitrary.
495    pub open spec fn drop_last(self) -> Seq<A>
496        recommends
497            self.len() >= 1,
498    {
499        self.subrange(0, self.len() as int - 1)
500    }
501
502    /// Dropping the last element of a concatenation of `a` and `b` is equivalent
503    /// to skipping the last element of `b` and then concatenating `a` and `b`
504    pub proof fn drop_last_distributes_over_add(a: Self, b: Self)
505        requires
506            0 < b.len(),
507        ensures
508            (a + b).drop_last() == a + b.drop_last(),
509    {
510        assert_seqs_equal!((a+b).drop_last(), a+b.drop_last());
511    }
512
513    pub open spec fn drop_first(self) -> Seq<A>
514        recommends
515            self.len() >= 1,
516    {
517        self.subrange(1, self.len() as int)
518    }
519
520    /// returns `true` if the sequence has no duplicate elements
521    pub open spec fn no_duplicates(self) -> bool {
522        forall|i, j| (0 <= i < self.len() && 0 <= j < self.len() && i != j) ==> self[i] != self[j]
523    }
524
525    /// Returns `true` if two sequences are disjoint
526    pub open spec fn disjoint(self, other: Self) -> bool {
527        forall|i: int, j: int| 0 <= i < self.len() && 0 <= j < other.len() ==> self[i] != other[j]
528    }
529
530    /// Converts a sequence into a set
531    pub open spec fn to_set(self) -> Set<A> {
532        Set::new(|a: A| self.contains(a))
533    }
534
535    /// Converts a sequence into a multiset
536    pub closed spec fn to_multiset(self) -> Multiset<A>
537        decreases self.len(),
538    {
539        if self.len() == 0 {
540            Multiset::<A>::empty()
541        } else {
542            Multiset::<A>::empty().insert(self.first()).add(self.drop_first().to_multiset())
543        }
544    }
545
546    // Parts of verified lemma used to be an axiom in the Dafny prelude
547    // Note: the inner triggers in this lemma are blocked by `to_multiset_len`
548    /// Proof of function to_multiset() correctness
549    pub broadcast proof fn to_multiset_ensures(self)
550        ensures
551            forall|a: A| #[trigger] (self.push(a).to_multiset()) =~= self.to_multiset().insert(a),  // to_multiset_build
552            forall|i: int|
553                0 <= i < self.len() ==> #[trigger] (self.remove(i).to_multiset())
554                    =~= self.to_multiset().remove(self[i]),  // to_multiset_remove
555            self.len() == #[trigger] self.to_multiset().len(),  // to_multiset_len
556            forall|a: A|
557                self.contains(a) <==> #[trigger] self.to_multiset().count(a)
558                    > 0,  // to_multiset_contains
559    {
560        broadcast use group_seq_properties;
561
562    }
563
564    /// Insert item a at index i, shifting remaining elements (if any) to the right
565    pub open spec fn insert(self, i: int, a: A) -> Seq<A>
566        recommends
567            0 <= i <= self.len(),
568    {
569        self.subrange(0, i).push(a) + self.subrange(i, self.len() as int)
570    }
571
572    /// Proof of correctness and expected properties of insert function
573    pub proof fn insert_ensures(self, pos: int, elt: A)
574        requires
575            0 <= pos <= self.len(),
576        ensures
577            self.insert(pos, elt).len() == self.len() + 1,
578            forall|i: int| 0 <= i < pos ==> #[trigger] self.insert(pos, elt)[i] == self[i],
579            forall|i: int| pos <= i < self.len() ==> self.insert(pos, elt)[i + 1] == self[i],
580            self.insert(pos, elt)[pos] == elt,
581    {
582    }
583
584    /// Remove item at index i, shifting remaining elements to the left
585    pub open spec fn remove(self, i: int) -> Seq<A>
586        recommends
587            0 <= i < self.len(),
588    {
589        self.subrange(0, i) + self.subrange(i + 1, self.len() as int)
590    }
591
592    /// Proof of function remove() correctness
593    pub proof fn remove_ensures(self, i: int)
594        requires
595            0 <= i < self.len(),
596        ensures
597            self.remove(i).len() == self.len() - 1,
598            forall|index: int| 0 <= index < i ==> #[trigger] self.remove(i)[index] == self[index],
599            forall|index: int|
600                i <= index < self.len() - 1 ==> #[trigger] self.remove(i)[index] == self[index + 1],
601    {
602    }
603
604    /// If a given element occurs at least once in a sequence, the sequence without
605    /// its first occurrence is returned. Otherwise the same sequence is returned.
606    pub open spec fn remove_value(self, val: A) -> Seq<A> {
607        let index = self.index_of_first(val);
608        match index {
609            Some(i) => self.remove(i),
610            None => self,
611        }
612    }
613
614    /// Returns the sequence that is in reverse order to a given sequence.
615    pub open spec fn reverse(self) -> Seq<A>
616        decreases self.len(),
617    {
618        if self.len() == 0 {
619            Seq::empty()
620        } else {
621            Seq::new(self.len(), |i: int| self[self.len() - 1 - i])
622        }
623    }
624
625    /// Zips two sequences of equal length into one sequence that consists of pairs.
626    /// If the two sequences are different lengths, returns an empty sequence
627    pub open spec fn zip_with<B>(self, other: Seq<B>) -> Seq<(A, B)>
628        recommends
629            self.len() == other.len(),
630        decreases self.len(),
631    {
632        if self.len() != other.len() {
633            Seq::empty()
634        } else if self.len() == 0 {
635            Seq::empty()
636        } else {
637            Seq::new(self.len(), |i: int| (self[i], other[i]))
638        }
639    }
640
641    /// Folds the sequence to the left, applying `f` to perform the fold.
642    ///
643    /// Equivalent to `Iterator::fold` in Rust.
644    ///
645    /// Given a sequence `s = [x0, x1, x2, ..., xn]`, applying this function `s.fold_left(b, f)`
646    /// returns `f(...f(f(b, x0), x1), ..., xn)`.
647    pub open spec fn fold_left<B>(self, b: B, f: spec_fn(B, A) -> B) -> (res: B)
648        decreases self.len(),
649    {
650        if self.len() == 0 {
651            b
652        } else {
653            f(self.drop_last().fold_left(b, f), self.last())
654        }
655    }
656
657    /// Equivalent to [`Self::fold_left`] but defined by breaking off the leftmost element when
658    /// recursing, rather than the rightmost. See [`Self::lemma_fold_left_alt`] that proves
659    /// equivalence.
660    pub open spec fn fold_left_alt<B>(self, b: B, f: spec_fn(B, A) -> B) -> (res: B)
661        decreases self.len(),
662    {
663        if self.len() == 0 {
664            b
665        } else {
666            self.subrange(1, self.len() as int).fold_left_alt(f(b, self[0]), f)
667        }
668    }
669
670    /// A lemma that proves how [`Self::fold_left`] distributes over splitting a sequence.
671    pub broadcast proof fn lemma_fold_left_split<B>(self, b: B, f: spec_fn(B, A) -> B, k: int)
672        requires
673            0 <= k <= self.len(),
674        ensures
675            self.subrange(k, self.len() as int).fold_left(
676                (#[trigger] self.subrange(0, k).fold_left(b, f)),
677                f,
678            ) == self.fold_left(b, f),
679        decreases self.len(),
680    {
681        reveal_with_fuel(Seq::fold_left, 2);
682        if k == self.len() {
683            assert(self.subrange(0, self.len() as int) == self);
684        } else {
685            self.drop_last().lemma_fold_left_split(b, f, k);
686            assert_seqs_equal!(
687                self.drop_last().subrange(k, self.drop_last().len() as int) ==
688                self.subrange(k, self.len()-1)
689            );
690            assert_seqs_equal!(
691                self.drop_last().subrange(0, k) ==
692                self.subrange(0, k)
693            );
694            assert_seqs_equal!(
695                self.subrange(k, self.len() as int).drop_last() ==
696                self.subrange(k, self.len() - 1)
697            );
698        }
699    }
700
701    /// An auxiliary lemma for proving [`Self::lemma_fold_left_alt`].
702    proof fn aux_lemma_fold_left_alt<B>(self, b: B, f: spec_fn(B, A) -> B, k: int)
703        requires
704            0 < k <= self.len(),
705        ensures
706            self.subrange(k, self.len() as int).fold_left_alt(
707                self.subrange(0, k).fold_left_alt(b, f),
708                f,
709            ) == self.fold_left_alt(b, f),
710        decreases k,
711    {
712        reveal_with_fuel(Seq::fold_left_alt, 2);
713        if k == 1 {
714            // trivial base case
715        } else {
716            self.subrange(1, self.len() as int).aux_lemma_fold_left_alt(f(b, self[0]), f, k - 1);
717            assert_seqs_equal!(
718                self.subrange(1, self.len() as int)
719                    .subrange(k - 1, self.subrange(1, self.len() as int).len() as int) ==
720                self.subrange(k, self.len() as int)
721            );
722            assert_seqs_equal!(
723                self.subrange(1, self.len() as int).subrange(0, k - 1) ==
724                self.subrange(1, k)
725            );
726            assert_seqs_equal!(
727                self.subrange(0, k).subrange(1, self.subrange(0, k).len() as int) ==
728                self.subrange(1, k)
729            );
730        }
731    }
732
733    /// [`Self::fold_left`] and [`Self::fold_left_alt`] are equivalent.
734    pub proof fn lemma_fold_left_alt<B>(self, b: B, f: spec_fn(B, A) -> B)
735        ensures
736            self.fold_left(b, f) == self.fold_left_alt(b, f),
737        decreases self.len(),
738    {
739        reveal_with_fuel(Seq::fold_left, 2);
740        reveal_with_fuel(Seq::fold_left_alt, 2);
741        if self.len() <= 1 {
742            // trivial base cases
743        } else {
744            self.aux_lemma_fold_left_alt(b, f, self.len() - 1);
745            self.subrange(self.len() - 1, self.len() as int).lemma_fold_left_alt(
746                self.drop_last().fold_left_alt(b, f),
747                f,
748            );
749            self.subrange(0, self.len() - 1).lemma_fold_left_alt(b, f);
750        }
751    }
752
753    /// [`Self::fold_left`] on the reversed sequence is equivalent to
754    /// [`Self::fold_right`] on the original sequence with corresponding folding operator
755    pub proof fn lemma_reverse_fold_left<B>(self, v: B, f: spec_fn(B, A) -> B)
756        ensures
757            self.reverse().fold_left(v, f) == self.fold_right(|a: A, b: B| f(b, a), v),
758    {
759        assert(self.reverse().reverse() =~= self);
760        let g = |a: A, b: B| f(b, a);
761        assert(f =~= |b: B, a: A| g(a, b));
762        self.reverse().lemma_reverse_fold_right(v, |a: A, b: B| f(b, a))
763    }
764
765    /// Folds the sequence to the right, applying `f` to perform the fold.
766    ///
767    /// Equivalent to `DoubleEndedIterator::rfold` in Rust.
768    ///
769    /// Given a sequence `s = [x0, x1, x2, ..., xn]`, applying this function `s.fold_right(b, f)`
770    /// returns `f(x0, f(x1, f(x2, ..., f(xn, b)...)))`.
771    pub open spec fn fold_right<B>(self, f: spec_fn(A, B) -> B, b: B) -> (res: B)
772        decreases self.len(),
773    {
774        if self.len() == 0 {
775            b
776        } else {
777            self.drop_last().fold_right(f, f(self.last(), b))
778        }
779    }
780
781    /// Equivalent to [`Self::fold_right`] but defined by breaking off the leftmost element when
782    /// recursing, rather than the rightmost. See [`Self::lemma_fold_right_alt`] that proves
783    /// equivalence.
784    pub open spec fn fold_right_alt<B>(self, f: spec_fn(A, B) -> B, b: B) -> (res: B)
785        decreases self.len(),
786    {
787        if self.len() == 0 {
788            b
789        } else {
790            f(self[0], self.subrange(1, self.len() as int).fold_right_alt(f, b))
791        }
792    }
793
794    /// A lemma that proves how [`Self::fold_right`] distributes over splitting a sequence.
795    pub broadcast proof fn lemma_fold_right_split<B>(self, f: spec_fn(A, B) -> B, b: B, k: int)
796        requires
797            0 <= k <= self.len(),
798        ensures
799            self.subrange(0, k).fold_right(
800                f,
801                (#[trigger] self.subrange(k, self.len() as int).fold_right(f, b)),
802            ) == self.fold_right(f, b),
803        decreases self.len(),
804    {
805        reveal_with_fuel(Seq::fold_right, 2);
806        if k == self.len() {
807            assert(self.subrange(0, k) == self);
808        } else if k == self.len() - 1 {
809            // trivial base case
810        } else {
811            self.subrange(0, self.len() - 1).lemma_fold_right_split(f, f(self.last(), b), k);
812            assert_seqs_equal!(
813                self.subrange(0, self.len() - 1).subrange(0, k) ==
814                self.subrange(0, k)
815            );
816            assert_seqs_equal!(
817                self.subrange(0, self.len() - 1).subrange(k, self.subrange(0, self.len() - 1).len() as int) ==
818                self.subrange(k, self.len() - 1)
819            );
820            assert_seqs_equal!(
821                self.subrange(k, self.len() as int).drop_last() ==
822                self.subrange(k, self.len() - 1)
823            );
824        }
825    }
826
827    // Lemma that proves it's possible to commute a commutative operator across fold_right.
828    pub proof fn lemma_fold_right_commute_one<B>(self, a: A, f: spec_fn(A, B) -> B, v: B)
829        requires
830            commutative_foldr(f),
831        ensures
832            self.fold_right(f, f(a, v)) == f(a, self.fold_right(f, v)),
833        decreases self.len(),
834    {
835        if self.len() > 0 {
836            self.drop_last().lemma_fold_right_commute_one(a, f, f(self.last(), v));
837        }
838    }
839
840    /// [`Self::fold_right`] and [`Self::fold_right_alt`] are equivalent.
841    pub proof fn lemma_fold_right_alt<B>(self, f: spec_fn(A, B) -> B, b: B)
842        ensures
843            self.fold_right(f, b) == self.fold_right_alt(f, b),
844        decreases self.len(),
845    {
846        reveal_with_fuel(Seq::fold_right, 2);
847        reveal_with_fuel(Seq::fold_right_alt, 2);
848        if self.len() <= 1 {
849            // trivial base cases
850        } else {
851            self.subrange(1, self.len() as int).lemma_fold_right_alt(f, b);
852            self.lemma_fold_right_split(f, b, 1);
853        }
854    }
855
856    /// [`Self::fold_right`] on the reversed sequence is equivalent to
857    /// [`Self::fold_left`] on the original sequence with corresponding folding operator
858    pub proof fn lemma_reverse_fold_right<B>(self, v: B, f: spec_fn(A, B) -> B)
859        ensures
860            self.reverse().fold_right(f, v) == self.fold_left(v, |b: B, a: A| f(a, b)),
861        decreases self.len(),
862    {
863        let g = |b: B, a: A| f(a, b);
864        if self.len() > 0 {
865            let last = self.last();
866            let s0 = self.drop_last();
867            assert(self.reverse() =~= seq![last] + s0.reverse());
868            let res1 = self.reverse().fold_right(f, v);
869            let res2 = self.fold_left(v, g);
870            assert(res1 == self.reverse().fold_right_alt(f, v)) by {
871                self.reverse().lemma_fold_right_alt(f, v)
872            }
873            assert(res2 == g(s0.fold_left(v, g), last));
874            assert(self.reverse().first() == last);
875            assert(self.reverse().subrange(1, self.reverse().len() as int) =~= s0.reverse());
876            assert(res1 == f(last, s0.reverse().fold_right_alt(f, v)));
877            assert(res1 == f(last, s0.reverse().fold_right(f, v))) by {
878                s0.reverse().lemma_fold_right_alt(f, v)
879            }
880            assert(res2 == g(s0.fold_left(v, g), last));
881            s0.lemma_reverse_fold_right(v, f);
882        }
883    }
884
885    // Proven lemmas
886    /// Given a sequence with no duplicates, each element occurs only
887    /// once in its conversion to a multiset
888    pub proof fn lemma_multiset_has_no_duplicates(self)
889        requires
890            self.no_duplicates(),
891        ensures
892            forall|x: A| self.to_multiset().contains(x) ==> self.to_multiset().count(x) == 1,
893        decreases self.len(),
894    {
895        broadcast use super::multiset::group_multiset_axioms;
896
897        if self.len() == 0 {
898            assert(forall|x: A|
899                self.to_multiset().contains(x) ==> self.to_multiset().count(x) == 1);
900        } else {
901            broadcast use group_seq_properties;
902
903            assert(self.drop_last().push(self.last()) =~= self);
904            self.drop_last().lemma_multiset_has_no_duplicates();
905        }
906    }
907
908    /// If, in a sequence's conversion to a multiset, each element occurs only once,
909    /// the sequence has no duplicates.
910    pub proof fn lemma_multiset_has_no_duplicates_conv(self)
911        requires
912            forall|x: A| self.to_multiset().contains(x) ==> self.to_multiset().count(x) == 1,
913        ensures
914            self.no_duplicates(),
915    {
916        broadcast use super::multiset::group_multiset_axioms;
917
918        assert forall|i, j| (0 <= i < self.len() && 0 <= j < self.len() && i != j) implies self[i]
919            != self[j] by {
920            let mut a = if (i < j) {
921                i
922            } else {
923                j
924            };
925            let mut b = if (i < j) {
926                j
927            } else {
928                i
929            };
930
931            if (self[a] == self[b]) {
932                let s0 = self.subrange(0, b);
933                let s1 = self.subrange(b, self.len() as int);
934                assert(self == s0 + s1);
935
936                broadcast use group_to_multiset_ensures;
937
938                lemma_multiset_commutative(s0, s1);
939                assert(self.to_multiset().count(self[a]) >= 2);
940            }
941        }
942    }
943
944    /// Conversion of a sequence to multiset is equivalent to conversion of its reversion to multiset
945    pub proof fn lemma_reverse_to_multiset(self)
946        ensures
947            self.reverse().to_multiset() =~= self.to_multiset(),
948        decreases self.len(),
949    {
950        broadcast use group_seq_properties;
951        broadcast use super::multiset::group_multiset_axioms;
952
953        if self.len() > 0 {
954            let s2 = self.drop_first();
955            let e = self.first();
956            assert(self =~= seq![e] + s2);
957            assert(self.to_multiset() =~= seq![e].to_multiset().add(s2.to_multiset())) by {
958                lemma_multiset_commutative(seq![e], s2)
959            }
960            assert(self.reverse() =~= s2.reverse().push(e));
961            assert(self.reverse().to_multiset() =~= s2.reverse().to_multiset().insert(e));
962            s2.lemma_reverse_to_multiset();
963        }
964    }
965
966    /// The concatenation of two subsequences derived from a non-empty sequence,
967    /// the first obtained from skipping the last element, the second consisting only
968    /// of the last element, is the original sequence.
969    pub proof fn lemma_add_last_back(self)
970        requires
971            0 < self.len(),
972        ensures
973            #[trigger] self.drop_last().push(self.last()) =~= self,
974    {
975    }
976
977    /// If a predicate is true at every index of a sequence,
978    /// it is true for every member of the sequence as a collection.
979    /// Useful for converting quantifiers between the two forms
980    /// to satisfy a precondition in the latter form.
981    pub proof fn lemma_indexing_implies_membership(self, f: spec_fn(A) -> bool)
982        requires
983            forall|i: int| 0 <= i < self.len() ==> #[trigger] f(#[trigger] self[i]),
984        ensures
985            forall|x: A| #[trigger] self.contains(x) ==> #[trigger] f(x),
986    {
987        assert(forall|i: int| 0 <= i < self.len() ==> #[trigger] self.contains(self[i]));
988    }
989
990    /// If a predicate is true for every member of a sequence as a collection,
991    /// it is true at every index of the sequence.
992    /// Useful for converting quantifiers between the two forms
993    /// to satisfy a precondition in the latter form.
994    pub proof fn lemma_membership_implies_indexing(self, f: spec_fn(A) -> bool)
995        requires
996            forall|x: A| #[trigger] self.contains(x) ==> #[trigger] f(x),
997        ensures
998            forall|i: int| 0 <= i < self.len() ==> #[trigger] f(self[i]),
999    {
1000        assert forall|i: int| 0 <= i < self.len() implies #[trigger] f(self[i]) by {
1001            assert(self.contains(self[i]));
1002        }
1003    }
1004
1005    /// A sequence that is sliced at the pos-th element, concatenated
1006    /// with that same sequence sliced from the pos-th element, is equal to the
1007    /// original unsliced sequence.
1008    pub proof fn lemma_split_at(self, pos: int)
1009        requires
1010            0 <= pos <= self.len(),
1011        ensures
1012            self.subrange(0, pos) + self.subrange(pos, self.len() as int) =~= self,
1013    {
1014    }
1015
1016    /// Any element in a slice is included in the original sequence.
1017    pub proof fn lemma_element_from_slice(self, new: Seq<A>, a: int, b: int, pos: int)
1018        requires
1019            0 <= a <= b <= self.len(),
1020            new == self.subrange(a, b),
1021            a <= pos < b,
1022        ensures
1023            pos - a < new.len(),
1024            new[pos - a] == self[pos],
1025    {
1026    }
1027
1028    /// A slice (from s2..e2) of a slice (from s1..e1) of a sequence is equal to just a
1029    /// slice (s1+s2..s1+e2) of the original sequence.
1030    pub proof fn lemma_slice_of_slice(self, s1: int, e1: int, s2: int, e2: int)
1031        requires
1032            0 <= s1 <= e1 <= self.len(),
1033            0 <= s2 <= e2 <= e1 - s1,
1034        ensures
1035            self.subrange(s1, e1).subrange(s2, e2) =~= self.subrange(s1 + s2, s1 + e2),
1036    {
1037    }
1038
1039    /// A sequence of unique items, when converted to a set, produces a set with matching length
1040    pub proof fn unique_seq_to_set(self)
1041        requires
1042            self.no_duplicates(),
1043        ensures
1044            self.len() == self.to_set().len(),
1045        decreases self.len(),
1046    {
1047        broadcast use super::set::group_set_axioms;
1048
1049        seq_to_set_equal_rec::<A>(self);
1050        if self.len() == 0 {
1051        } else {
1052            let rest = self.drop_last();
1053            rest.unique_seq_to_set();
1054            seq_to_set_equal_rec::<A>(rest);
1055            seq_to_set_rec_is_finite::<A>(rest);
1056            assert(!seq_to_set_rec(rest).contains(self.last()));
1057            assert(seq_to_set_rec(rest).insert(self.last()).len() == seq_to_set_rec(rest).len()
1058                + 1);
1059        }
1060    }
1061
1062    /// The cardinality of a set of elements is always less than or
1063    /// equal to that of the full sequence of elements.
1064    pub proof fn lemma_cardinality_of_set(self)
1065        ensures
1066            self.to_set().len() <= self.len(),
1067        decreases self.len(),
1068    {
1069        broadcast use {super::set::group_set_axioms, seq_to_set_is_finite};
1070        broadcast use group_seq_properties;
1071        broadcast use super::set_lib::group_set_properties;
1072
1073        if self.len() == 0 {
1074        } else {
1075            assert(self.drop_last().to_set().insert(self.last()) =~= self.to_set());
1076            self.drop_last().lemma_cardinality_of_set();
1077        }
1078    }
1079
1080    /// A sequence is of length 0 if and only if its conversion to
1081    /// a set results in the empty set.
1082    pub proof fn lemma_cardinality_of_empty_set_is_0(self)
1083        ensures
1084            self.to_set().len() == 0 <==> self.len() == 0,
1085    {
1086        broadcast use {super::set::group_set_axioms, seq_to_set_is_finite};
1087
1088        assert(self.len() == 0 ==> self.to_set().len() == 0) by { self.lemma_cardinality_of_set() }
1089        assert(!(self.len() == 0) ==> !(self.to_set().len() == 0)) by {
1090            if self.len() > 0 {
1091                assert(self.to_set().contains(self[0]));
1092                assert(self.to_set().remove(self[0]).len() <= self.to_set().len());
1093            }
1094        }
1095    }
1096
1097    /// A sequence with cardinality equal to its set has no duplicates.
1098    /// Inverse property of that shown in lemma unique_seq_to_set
1099    pub proof fn lemma_no_dup_set_cardinality(self)
1100        requires
1101            self.to_set().len() == self.len(),
1102        ensures
1103            self.no_duplicates(),
1104        decreases self.len(),
1105    {
1106        broadcast use {super::set::group_set_axioms, seq_to_set_is_finite};
1107
1108        if self.len() == 0 {
1109        } else {
1110            assert(self =~= Seq::empty().push(self.first()).add(self.drop_first()));
1111            if self.drop_first().contains(self.first()) {
1112                // If there is a duplicate, then we show that |s.to_set()| == |s| cannot hold.
1113                assert(self.to_set() =~= self.drop_first().to_set());
1114                assert(self.to_set().len() <= self.drop_first().len()) by {
1115                    self.drop_first().lemma_cardinality_of_set()
1116                }
1117            } else {
1118                assert(self.to_set().len() == 1 + self.drop_first().to_set().len()) by {
1119                    assert(self.drop_first().to_set().insert(self.first()) =~= self.to_set());
1120                }
1121                self.drop_first().lemma_no_dup_set_cardinality();
1122            }
1123        }
1124    }
1125
1126    /// Mapping a function over a sequence and converting to a set is the same
1127    /// as mapping it over the sequence converted to a set.
1128    pub broadcast proof fn lemma_to_set_map_commutes<B>(self, f: spec_fn(A) -> B)
1129        ensures
1130            #[trigger] self.to_set().map(f) =~= self.map_values(f).to_set(),
1131    {
1132        broadcast use crate::vstd::group_vstd_default;
1133
1134        assert forall|elem: B|
1135            self.to_set().map(f).contains(elem) <==> self.map_values(f).to_set().contains(elem) by {
1136            if self.to_set().map(f).contains(elem) {
1137                let x = choose|x: A| self.to_set().contains(x) && f(x) == elem;
1138                let i = choose|i: int| 0 <= i < self.len() && self[i] == x;
1139                assert(self.map_values(f)[i] == elem);
1140            }
1141            if self.map_values(f).to_set().contains(elem) {
1142                let i = choose|i: int|
1143                    0 <= i < self.map_values(f).len() && self.map_values(f)[i] == elem;
1144                let x = self[i];
1145                assert(self.to_set().contains(x));
1146            }
1147        };
1148    }
1149
1150    /// Appending an element to a sequence and converting to set, is equal
1151    /// to converting to set and inserting it.
1152    pub broadcast proof fn lemma_to_set_insert_commutes(sq: Seq<A>, elt: A)
1153        requires
1154        ensures
1155            #[trigger] (sq + seq![elt]).to_set() =~= sq.to_set().insert(elt),
1156    {
1157        broadcast use crate::vstd::group_vstd_default;
1158        broadcast use lemma_seq_concat_contains_all_elements;
1159        broadcast use lemma_seq_empty_contains_nothing;
1160        broadcast use lemma_seq_contains_after_push;
1161        broadcast use super::seq::group_seq_axioms;
1162        broadcast use super::set_lib::group_set_properties;
1163
1164    }
1165
1166    /// Update a subrange of a sequence starting at `off` to values `vs`.
1167    /// Expects that the updated subrange `off` up to `off+vs.len()` fits
1168    /// in the existing sequence.
1169    pub open spec fn update_subrange_with(self, off: int, vs: Self) -> Self
1170        recommends
1171            0 <= off,
1172            off + vs.len() <= self.len(),
1173    {
1174        Seq::new(
1175            self.len(),
1176            |i: int|
1177                if off <= i < off + vs.len() {
1178                    vs[i - off]
1179                } else {
1180                    self[i]
1181                },
1182        )
1183    }
1184
1185    /// Skipping `i` elements and then 1 more is equivalent to skipping `i + 1` elements.
1186    ///
1187    /// ## Example
1188    ///
1189    /// ```rust
1190    /// proof fn example() {
1191    ///     let s = seq![1, 2, 3, 4];
1192    ///     s.lemma_seq_skip_skip(2);
1193    ///     assert(s.skip(2).skip(1) =~= s.skip(3));
1194    /// }
1195    /// ```
1196    pub broadcast proof fn lemma_seq_skip_skip(self, i: int)
1197        ensures
1198            0 <= i < self.len() ==> (self.skip(i)).skip(1) =~= #[trigger] self.skip(i + 1),
1199    {
1200        broadcast use group_seq_properties;
1201
1202    }
1203
1204    /// If an element is contained in a sequence, then there exists an index where that element appears.
1205    ///
1206    /// ## Example
1207    ///
1208    /// ```rust
1209    /// proof fn example() {
1210    ///     let s = seq![10, 20, 30];
1211    ///     assert(s.contains(20));
1212    ///     let idx = s.lemma_contains_to_index(20);
1213    ///     assert(s[idx] == 20);
1214    /// }
1215    /// ```
1216    pub proof fn lemma_contains_to_index(self, elem: A) -> (idx: int)
1217        requires
1218            self.contains(elem),
1219        ensures
1220            0 <= idx < self.len() && self[idx] == elem,
1221        decreases self.len(),
1222    {
1223        broadcast use group_seq_properties;
1224
1225        if self[0] == elem {
1226            0
1227        } else {
1228            let i = self.skip(1).lemma_contains_to_index(elem);
1229            i + 1
1230        }
1231    }
1232
1233    /// If a predicate holds for the first element and for all elements in the tail,
1234    /// then it holds for the entire sequence.
1235    ///
1236    /// ## Example
1237    ///
1238    /// ```rust
1239    /// proof fn example() {
1240    ///     let s = seq![2, 4, 6, 8];
1241    ///     let is_even = |x| x % 2 == 0;
1242    ///     assert(is_even(s[0]));
1243    ///     assert(s.skip(1).all(is_even));
1244    ///     s.lemma_all_from_head_tail(is_even);
1245    ///     assert(s.all(is_even));
1246    /// }
1247    /// ```
1248    pub proof fn lemma_all_from_head_tail(self, pred: spec_fn(A) -> bool)
1249        requires
1250            self.len() > 0,
1251            pred(self[0]) && self.skip(1).all(|x| pred(x)),
1252        ensures
1253            self.all(|x| pred(x)),
1254    {
1255        broadcast use group_seq_properties;
1256
1257        assert(seq![self[0]] + self.skip(1) == self);
1258    }
1259
1260    /// If a predicate holds for any element in the sequence and does not hold for the first element,
1261    /// then the predicate must hold for some element in the tail.
1262    ///
1263    /// ## Example
1264    ///
1265    /// ```rust
1266    /// proof fn example() {
1267    ///     let s = seq![1, 4, 6, 8];
1268    ///     let is_even = |x| x % 2 == 0;
1269    ///     assert(s.any(is_even));
1270    ///     assert(!is_even(s[0]));
1271    ///     s.lemma_any_tail(is_even);
1272    ///     assert(s.skip(1).any(is_even));
1273    /// }
1274    /// ```
1275    pub proof fn lemma_any_tail(self, pred: spec_fn(A) -> bool)
1276        requires
1277            self.any(|x| pred(x)),
1278        ensures
1279            !pred(self[0]) ==> self.skip(1).any(|x| pred(x)),
1280    {
1281        broadcast use group_seq_properties;
1282
1283    }
1284
1285    /// Removes duplicate elements from a sequence, maintaining the order of first appearance.
1286    /// Takes a `seen` sequence parameter to track previously encountered elements.
1287    ///
1288    /// ## Example
1289    ///
1290    /// ```rust
1291    /// fn example() {
1292    ///     let s = seq![1, 2, 1, 3, 2, 4];
1293    ///     let seen = seq![];
1294    ///     let result = s.remove_duplicates(seen);
1295    ///     assert_eq!(result, seq![1, 2, 3, 4]);
1296    ///
1297    ///     let seen2 = seq![2, 3];
1298    ///     let result2 = s.remove_duplicates(seen2);
1299    ///     assert_eq!(result2, seq![1, 4]);
1300    /// }
1301    /// ```
1302    pub open spec fn remove_duplicates(self, seen: Seq<A>) -> Seq<A>
1303        decreases self.len(),
1304    {
1305        if self.len() == 0 {
1306            seen
1307        } else if seen.contains(self[0]) {
1308            self.skip(1).remove_duplicates(seen)
1309        } else {
1310            self.skip(1).remove_duplicates(seen + seq![self[0]])
1311        }
1312    }
1313
1314    /// Properties of remove_duplicates:
1315    /// - The output contains x if and only if x was in the input sequence or seen set
1316    /// - The output length is at most the sum of input and seen lengths
1317    ///
1318    /// ## Example
1319    ///
1320    /// ```rust
1321    /// proof fn example() {
1322    ///     let s = seq![1, 2, 1, 3];
1323    ///     let seen = seq![2];
1324    ///     s.lemma_remove_duplicates_properties(seen);
1325    ///     assert(s.remove_duplicates(seen).contains(1));
1326    ///     assert(s.remove_duplicates(seen).contains(3));
1327    ///     assert(!s.remove_duplicates(seen).contains(2));
1328    ///     assert(s.remove_duplicates(seen).len() <= s.len() + seen.len());
1329    /// }
1330    /// ```
1331    pub broadcast proof fn lemma_remove_duplicates_properties(self, seen: Seq<A>)
1332        ensures
1333            forall|x|
1334                (self + seen).contains(x) <==> #[trigger] self.remove_duplicates(seen).contains(x),
1335            #[trigger] self.remove_duplicates(seen).len() <= self.len() + seen.len(),
1336        decreases self.len(),
1337    {
1338        broadcast use group_seq_properties;
1339
1340        if self.len() == 0 {
1341        } else if seen.contains(self[0]) {
1342            let rest = self.skip(1);
1343            rest.lemma_remove_duplicates_properties(seen);
1344        } else {
1345            let rest = self.skip(1);
1346            rest.lemma_remove_duplicates_properties(seen + seq![self[0]]);
1347        }
1348    }
1349
1350    /// Shows that removing duplicates from a sequence is equivalent to:
1351    /// 1. First removing duplicates from the prefix up to index i (with the given seen set)
1352    /// 2. Using that result as the new seen set for removing duplicates from the suffix after i
1353    ///
1354    /// ## Example
1355    ///
1356    /// ```rust
1357    /// proof fn example() {
1358    ///     let s = seq![1, 2, 1, 3, 2, 4];
1359    ///     let seen = seq![];
1360    ///     s.lemma_remove_duplicates_append_index(seen, 2);
1361    ///     assert(s.remove_duplicates(seen)
1362    ///         =~= seq![1, 3, 2, 4].remove_duplicates(seq![1, 2].remove_duplicates(seen)));
1363    /// }
1364    /// ```
1365    pub proof fn lemma_remove_duplicates_append_index(self, i: int, seen: Seq<A>)
1366        requires
1367            0 <= i < self.len(),
1368        ensures
1369            self.remove_duplicates(seen) == self.skip(i).remove_duplicates(
1370                self.take(i).remove_duplicates(seen),
1371            ),
1372        decreases self.len(),
1373    {
1374        broadcast use {
1375            group_seq_properties,
1376            lemma_seq_skip_of_skip,
1377            Seq::lemma_remove_duplicates_properties,
1378        };
1379
1380        if i == 0 {
1381        } else if i == self.len() {
1382            assert(self.take(i) == self);
1383        } else {
1384            assert(self.skip(1).take(i - 1) == self.subrange(1, i));
1385            assert(self.take(i).skip(1) == self.subrange(1, i));
1386            assert(self.skip(1).take(i - 1) == self.take(i).skip(1));
1387            if seen.contains(self[0]) {
1388                self.skip(1).lemma_remove_duplicates_append_index(i - 1, seen);
1389            } else {
1390                self.skip(1).lemma_remove_duplicates_append_index(i - 1, seen + seq![self[0]]);
1391            }
1392        }
1393    }
1394
1395    /// For two sequences, skipping one element after concatenation equals concatenating
1396    /// the result of skipping one element of the first sequence (which must be non-empty)
1397    /// with the second sequence.
1398    ///
1399    /// ## Example
1400    /// ```rust
1401    /// proof fn example() {
1402    ///     let s1 = seq![1, 2];
1403    ///     let s2 = seq![3, 4, 5];
1404    ///
1405    ///     lemma_skip1_concat(s1, s2);
1406    ///     assert((s1 + s2).skip(1) =~= seq![2, 3, 4, 5]);
1407    /// }
1408    /// ```
1409    proof fn lemma_skip1_concat(xs: Seq<A>, ys: Seq<A>)
1410        requires
1411            xs.len() > 0,
1412        ensures
1413            (xs + ys).skip(1) == xs.skip(1) + ys,
1414    {
1415        broadcast use group_seq_properties;
1416
1417        assert((xs + ys).skip(1) == xs.skip(1) + ys);
1418    }
1419
1420    /// When appending an element `x` to a sequence:
1421    /// - If `x` is in `self + seen`, removing duplicates equals removing duplicates from self
1422    /// - If `x` is not in (self + seen), removing duplicates equals removing duplicates from self,
1423    ///   concatenated with `[x]`
1424    ///
1425    /// ## Example
1426    /// ```rust
1427    /// proof fn example() {
1428    ///     let s1 = seq![1, 2];
1429    ///     let seen = seq![];
1430    ///     assert!(!s1.contains(3));
1431    ///     lemma_remove_duplicates_append(s1, 3, seen);
1432    ///     assert((s1 + seq![3]).remove_duplicates(seen) =~= s1.remove_duplicates(seen) + seq![3]);
1433    /// }
1434    /// ```
1435    pub proof fn lemma_remove_duplicates_append(self, x: A, seen: Seq<A>)
1436        ensures
1437            (self + seen).contains(x) ==> (self + seq![x]).remove_duplicates(seen)
1438                == self.remove_duplicates(seen),
1439            !(self + seen).contains(x) ==> (self + seq![x]).remove_duplicates(seen)
1440                == self.remove_duplicates(seen) + seq![x],
1441        decreases self.len(),
1442    {
1443        broadcast use group_seq_properties;
1444
1445        reveal_with_fuel(Seq::remove_duplicates, 2);
1446
1447        if self.len() != 0 {
1448            let head = self[0];
1449            let tail = self.skip(1);
1450
1451            let seen2 = if seen.contains(head) {
1452                seen
1453            } else {
1454                seen + seq![head]
1455            };
1456            tail.lemma_remove_duplicates_append(x, seen2);
1457            assert((self + seq![x]).skip(1) == tail + seq![x]) by {
1458                Seq::lemma_skip1_concat(self, seq![x]);
1459            };
1460        }
1461    }
1462
1463    /// If all elements in a sequence fail the predicate,
1464    /// filtering by that predicate yields an empty sequence
1465    ///
1466    /// ## Example
1467    /// ```rust
1468    /// proof fn example() {
1469    ///     let s = seq![1, 2, 3];
1470    ///     let pred = |x| x > 5;
1471    ///     lemma_all_neg_filter_empty(s, pred);
1472    ///     assert(s.filter(pred).len() == 0);
1473    /// }
1474    /// ```
1475    pub proof fn lemma_all_neg_filter_empty(self, pred: spec_fn(A) -> bool)
1476        requires
1477            self.all(|x: A| !pred(x)),
1478        ensures
1479            self.filter(pred).len() == 0,
1480        decreases self.len(),
1481    {
1482        broadcast use group_seq_properties;
1483
1484        reveal(Seq::filter);
1485        if self.len() != 0 {
1486            let rest = self.drop_last();
1487            rest.lemma_all_neg_filter_empty(pred);
1488            rest.lemma_filter_len_push(pred, self.last());
1489            let neg_pred = |x| !pred(x);
1490            assert(neg_pred(self.last()));
1491        }
1492    }
1493
1494    /// Applies an Option-returning function to each element, keeping only successful (Some) results
1495    ///
1496    /// ## Example
1497    /// ```rust
1498    /// let s = seq![1, 2, 3];
1499    /// let f = |x| if x % 2 == 0 { Some(x * 2) } else { None };
1500    /// assert(s.filter_map(f) =~= seq![4]);
1501    /// ```
1502    pub open spec fn filter_map<B>(self, f: spec_fn(A) -> Option<B>) -> Seq<B>
1503        decreases self.len(),
1504    {
1505        // We're defining this by starting at the end of the list since it makes it
1506        // easier to reason about in the common case of looping over a vector in the
1507        // implementation.
1508        if self.len() == 0 {
1509            Seq::empty()
1510        } else {
1511            let rest = self.drop_last();
1512            match f(self.last()) {
1513                Option::Some(s) => rest.filter_map(f) + seq![s],
1514                Option::None => rest.filter_map(f),
1515            }
1516        }
1517    }
1518
1519    /// If an element exists in the filtered sequence,
1520    /// it must exist in the original sequence
1521    /// ```
1522    pub broadcast proof fn lemma_filter_contains_rev(self, p: spec_fn(A) -> bool, elem: A)
1523        requires
1524            #[trigger] self.filter(p).contains(elem),
1525        ensures
1526            self.contains(elem),
1527        decreases self.len(),
1528    {
1529        broadcast use group_seq_properties;
1530
1531        reveal(Seq::filter);
1532        if self.len() == 0 {
1533        } else {
1534            let rest = self.drop_last();
1535            let last = self.last();
1536            if !p(last) || last != elem {
1537                rest.lemma_filter_contains_rev(p, elem);
1538            }
1539        }
1540    }
1541
1542    /// If an element exists in filter_map's output,
1543    /// there must be an input element that mapped to it
1544    /// ```
1545    pub broadcast proof fn lemma_filter_map_contains<B>(self, f: spec_fn(A) -> Option<B>, elt: B)
1546        requires
1547            #[trigger] self.filter_map(f).contains(elt),
1548        ensures
1549            exists|t: A| #[trigger] self.contains(t) && f(t) == Some(elt),
1550        decreases self.len(),
1551    {
1552        broadcast use group_seq_properties;
1553
1554        if self.len() == 0 {
1555        } else {
1556            let last = self.last();
1557            let rest = self.drop_last();
1558            if f(last) == Some(elt) {
1559                assert(self.contains(last));
1560            } else {
1561                rest.lemma_filter_map_contains(f, elt);
1562                let t = choose|t: A| #[trigger] rest.contains(t) && f(t) == Some(elt);
1563                assert(self.contains(t));
1564            }
1565        }
1566    }
1567
1568    /// Taking k+1 elements is the same as taking k elements plus the kth element
1569    ///
1570    /// ## Example
1571    /// ```rust
1572    /// let s = seq![1, 2, 3];
1573    /// lemma_take_plus_one(s, 1);
1574    /// seq![1, 2] == seq![1] + seq![2]
1575    /// ```
1576    pub proof fn lemma_take_succ(xs: Seq<A>, k: int)
1577        requires
1578            0 <= k < xs.len(),
1579        ensures
1580            xs.take(k + 1) =~= xs.take(k) + seq![xs[k]],
1581    {
1582        broadcast use group_seq_properties;
1583
1584    }
1585
1586    /// filter_map on a single element sequence
1587    /// either produces a new single element sequence (if f returns Some)
1588    /// or an empty sequence (if f returns None)
1589    pub proof fn lemma_filter_map_singleton<B>(a: A, f: spec_fn(A) -> Option<B>)
1590        ensures
1591            seq![a].filter_map(f) =~= match f(a) {
1592                Option::Some(b) => seq![b],
1593                Option::None => Seq::empty(),
1594            },
1595    {
1596        reveal_with_fuel(Seq::filter_map, 2);
1597    }
1598
1599    /// filter_map of take(i+1) equals
1600    /// filter_map of take(i) plus maybe the mapped i'th element
1601    ///
1602    /// ## Example
1603    /// ```rust
1604    /// let s = seq![1, 2, 3];
1605    /// let f = |x| if x % 2 == 0 { Some(x * 2) } else { None };
1606    /// s.lemma_filter_map_take_succ(s, f, 1);
1607    /// assert(s.take(2).filter_map(f) == s.take(1).filter_map(f) + seq![f(s[1]).unwrap()]);
1608    /// assert(s.take(2).filter_map(f) == seq![] + seq![4]);
1609    /// ```
1610    pub broadcast proof fn lemma_filter_map_take_succ<B>(self, f: spec_fn(A) -> Option<B>, i: int)
1611        requires
1612            0 <= i < self.len(),
1613        ensures
1614            #[trigger] self.take(i + 1).filter_map(f) =~= self.take(i).filter_map(f) + (match f(
1615                self[i],
1616            ) {
1617                Option::Some(s) => seq![s],
1618                Option::None => Seq::empty(),
1619            }),
1620        decreases self.len(),
1621    {
1622        broadcast use group_seq_properties;
1623
1624        if i != 0 {
1625            self.drop_last().lemma_filter_map_take_succ(f, i - 1);
1626            assert(self.take(i + 1).drop_last() == self.take(i));
1627        }
1628    }
1629
1630    /// An alternative implementation of filter that processes the sequence recursively from
1631    /// left to right, in contrast to the standard filter which processes from right to left.
1632    pub open spec fn filter_alt(self, p: spec_fn(A) -> bool) -> Seq<A> {
1633        if self.len() == 0 {
1634            Seq::empty()
1635        } else {
1636            let rest = self.drop_first().filter(p);
1637            let first = self.first();
1638            if p(first) {
1639                seq![first] + rest
1640            } else {
1641                rest
1642            }
1643        }
1644    }
1645
1646    /// When filtering (x + sequence), if x satisfies the predicate, x is prepended to
1647    /// the filtered sequence. Otherwise, only the filtered sequence remains.
1648    ///
1649    /// ## Example
1650    /// ```rust
1651    /// proof fn filter_prepend_test() {
1652    ///     let s = seq![2, 3, 4];
1653    ///     let is_even = |x: int| x % 2 == 0;
1654    ///     let with_five = seq![5] + s;
1655    ///     assert(with_five.filter(is_even) =~= seq![2, 4]); // 5 filtered out
1656    ///     let with_six = seq![6] + s;
1657    ///     assert(with_six.filter(is_even) =~= seq![6, 2, 4]); // 6 included
1658    /// }
1659    /// ```
1660    pub broadcast proof fn lemma_filter_prepend(self, x: A, p: spec_fn(A) -> bool)
1661        ensures
1662            #[trigger] (seq![x] + self).filter(p) == (if p(x) {
1663                seq![x]
1664            } else {
1665                Seq::empty()
1666            }) + self.filter(p),
1667        decreases self.len(),
1668    {
1669        broadcast use group_seq_properties;
1670
1671        reveal(Seq::filter);
1672        let lhs = (seq![x] + self).filter(p);
1673        let rhs = (if p(x) {
1674            seq![x]
1675        } else {
1676            Seq::empty()
1677        }) + self.filter(p);
1678
1679        if self.len() == 0 {
1680            assert(lhs =~= rhs);
1681        } else {
1682            let tail_seq = if p(self.last()) {
1683                seq![self.last()]
1684            } else {
1685                Seq::empty()
1686            };
1687
1688            assert(((seq![x] + self).drop_last()) =~= seq![x] + self.drop_last());
1689            let sub = (seq![x] + self.drop_last()).filter(p);
1690            assert(lhs =~= sub + tail_seq);
1691            assert(rhs =~= (if p(x) {
1692                seq![x]
1693            } else {
1694                Seq::empty()
1695            }) + self.drop_last().filter(p) + tail_seq);
1696            self.drop_last().lemma_filter_prepend(x, p);
1697        }
1698    }
1699
1700    /// The filter() and filter_alt() methods produce equivalent results for any sequence
1701    pub proof fn lemma_filter_eq_filter_alt(self, p: spec_fn(A) -> bool)
1702        ensures
1703            self.filter(p) =~= self.filter_alt(p),
1704        decreases self.len(),
1705    {
1706        broadcast use group_seq_properties;
1707        broadcast use Seq::lemma_filter_prepend;
1708
1709        reveal(Seq::filter);
1710        if self.len() == 0 {
1711        } else {
1712            let first = self.first();
1713            let but_first = self.drop_first();
1714            assert(self =~= seq![first] + but_first);
1715            self.drop_first().lemma_filter_eq_filter_alt(p);
1716        }
1717    }
1718
1719    /// Filtering preserves the prefix relationship between sequences.
1720    ///
1721    /// ## Example
1722    /// ```rust
1723    /// proof fn filter_monotone_test() {
1724    ///     let s = seq![1, 2, 3];
1725    ///     let ys = seq![1, 2, 3, 4, 5];
1726    ///     let is_even = |x: int| x % 2 == 0;
1727    ///     assert(s.is_prefix_of(ys));
1728    ///     assert(s.filter(is_even).is_prefix_of(ys.filter(is_even)));
1729    ///     assert(s.filter(is_even) =~= seq![2]);
1730    ///     assert(ys.filter(is_even) =~= seq![2, 4]);
1731    /// }
1732    /// ```
1733    pub proof fn lemma_filter_monotone(self, ys: Seq<A>, p: spec_fn(A) -> bool)
1734        requires
1735            self.is_prefix_of(ys),
1736        ensures
1737            self.filter(p).is_prefix_of(ys.filter(p)),
1738        decreases self.len(),
1739    {
1740        broadcast use group_seq_properties;
1741
1742        self.lemma_filter_eq_filter_alt(p);
1743        ys.lemma_filter_eq_filter_alt(p);
1744        if self.len() == 0 {
1745        } else {
1746            self.drop_first().lemma_filter_monotone(ys.drop_first(), p);
1747        }
1748    }
1749
1750    /// The length of filter(take(i)) is never greater than the length of filter(entire_sequence).
1751    ///
1752    /// ## Example
1753    /// ```rust
1754    /// proof fn filter_take_len_test() {
1755    ///     let s = seq![1, 2, 3, 4, 5];
1756    ///     let is_even = |x: int| x % 2 == 0;
1757    ///     let i = 3;
1758    ///     assert(s.take(i) =~= seq![1, 2, 3]);
1759    ///     assert(s.take(i).filter(is_even) =~= seq![2]);
1760    ///     assert(s.filter(is_even) =~= seq![2, 4]);
1761    ///     assert(s.filter(is_even).len() >= s.take(i).filter(is_even).len());
1762    /// }
1763    /// ```
1764    pub proof fn lemma_filter_take_len(self, p: spec_fn(A) -> bool, i: int)
1765        requires
1766            0 <= i <= self.len(),
1767        ensures
1768            self.filter(p).len() >= self.take(i).filter(p).len(),
1769        decreases i,
1770    {
1771        broadcast use group_seq_properties;
1772        broadcast use Seq::lemma_filter_len_push;
1773        broadcast use Seq::lemma_filter_push;
1774
1775        self.take(i).lemma_filter_monotone(self, p);
1776    }
1777
1778    /// Filtering a prefix of a sequence produces the same number or fewer elements
1779    /// as filtering the entire sequence.
1780    ///
1781    /// ## Example
1782    /// ```rust
1783    /// proof fn filter_take_len_test() {
1784    ///     let s = seq![1, 2, 3, 4, 5];
1785    ///     let is_even = |x: int| x % 2 == 0;
1786    ///     assert(s.filter(is_even).len() >= s.take(3).filter(is_even).len());
1787    /// }
1788    /// ```
1789    pub broadcast proof fn lemma_filter_len_push(self, p: spec_fn(A) -> bool, elem: A)
1790        ensures
1791            #[trigger] self.push(elem).filter(p).len() == self.filter(p).len() + (if p(elem) {
1792                1int
1793            } else {
1794                0int
1795            }),
1796    {
1797        broadcast use group_seq_properties;
1798        broadcast use Seq::lemma_filter_push;
1799
1800    }
1801
1802    /// If an index i is valid for a sequence (0 ≤ i < len), then the element at that index
1803    /// is contained in the sequence.
1804    pub broadcast proof fn lemma_index_contains(self, i: int)
1805        requires
1806            0 <= i < self.len(),
1807        ensures
1808            self.contains(#[trigger] self[i]),
1809    {
1810    }
1811
1812    /// Taking i+1 elements from a sequence is equivalent to taking i elements
1813    /// and then pushing the element at index i.
1814    pub broadcast proof fn lemma_take_succ_push(self, i: int)
1815        requires
1816            0 <= i < self.len(),
1817        ensures
1818            #[trigger] self.take(i + 1) =~= self.take(i).push(self[i]),
1819    {
1820        broadcast use group_seq_properties;
1821
1822    }
1823
1824    /// Taking the full length of a sequence returns the sequence itself.
1825    pub broadcast proof fn lemma_take_len(self)
1826        ensures
1827            #[trigger] self.take(self.len() as int) == self,
1828    {
1829        broadcast use group_seq_properties;
1830
1831    }
1832
1833    /// Taking i+1 elements and checking if any element satisfies predicate p is equivalent to:
1834    /// either taking i elements and checking if any satisfies p, OR checking if the i-th element satisfies p.
1835    ///
1836    /// ## Example
1837    /// ```rust
1838    /// proof fn take_any_succ_test() {
1839    ///     let s = seq![1, 2, 3];
1840    ///     let is_even = |x| x % 2 == 0;
1841    ///     let i = 1;
1842    ///     assert(s.take(i + 1).any(is_even) == (s.take(i).any(is_even) || is_even(s[i])));
1843    /// }
1844    /// ```
1845    pub broadcast proof fn lemma_take_any_succ(self, p: spec_fn(A) -> bool, i: int)
1846        requires
1847            0 <= i < self.len(),
1848        ensures
1849            #[trigger] self.take(i + 1).any(p) <==> self.take(i).any(p) || p(self[i]),
1850    {
1851        broadcast use group_seq_properties;
1852
1853        self.lemma_take_succ_push(i);
1854        if self.take(i + 1).any(p) {
1855            let x = choose|x: A| self.take(i + 1).contains(x) && #[trigger] p(x);
1856            assert(self.take(i).contains(x) || x == self[i]);
1857        }
1858        if self.take(i).any(p) {
1859            let x = choose|x: A| self.take(i).contains(x) && #[trigger] p(x);
1860            assert(self.take(i + 1).contains(x));
1861        }
1862        if p(self[i]) {
1863            assert(self.take(i + 1).contains(self[i]));
1864        }
1865    }
1866
1867    /// A sequence has no duplicates iff mapping an injective function over it
1868    /// produces a sequence with no duplicates.
1869    ///
1870    /// ## Example
1871    /// ```rust
1872    /// proof fn no_duplicates_injective_test() {
1873    ///     let s = seq![1, 2];
1874    ///     let f = |x| x + 1;  // injective function
1875    ///     assert(s.no_duplicates() == s.map_values(f).no_duplicates());
1876    /// }
1877    /// ```
1878    pub proof fn lemma_no_duplicates_injective<B>(self, f: spec_fn(A) -> B)
1879        requires
1880            injective(f),
1881        ensures
1882            self.no_duplicates() <==> self.map_values(f).no_duplicates(),
1883    {
1884        broadcast use group_seq_properties;
1885        broadcast use super::set_lib::group_set_properties;
1886
1887        let mapped = self.map_values(f);
1888        assert(mapped.len() == self.len());
1889        if mapped.no_duplicates() {
1890            assert forall|i: int, j: int| 0 <= i < j < mapped.len() implies self[i] != self[j] by {
1891                assert(mapped[i] == f(self[i]));
1892                assert(mapped[j] == f(self[j]));
1893            }
1894        }
1895    }
1896
1897    /// Pushing an element and then mapping a function over a sequence is equivalent to
1898    /// mapping the function over the sequence and then pushing the function applied to that element.
1899    ///
1900    /// ## Example
1901    /// ```rust
1902    /// proof fn push_map_test() {
1903    ///     let s = seq![1, 2];
1904    ///     let f = |x| x + 1;
1905    ///     assert(s.push(3).map_values(f) =~= s.map_values(f).push(f(3)));
1906    /// }
1907    /// ```
1908    pub broadcast proof fn lemma_push_map_commute<B>(self, f: spec_fn(A) -> B, x: A)
1909        ensures
1910            self.map_values(f).push(f(x)) =~= #[trigger] self.push(x).map_values(f),
1911        decreases self.len(),
1912    {
1913        broadcast use group_seq_properties;
1914
1915    }
1916
1917    /// Converting a sequence to a set after pushing an element is equivalent to
1918    /// converting to a set first and then inserting that element.
1919    ///
1920    /// ## Example
1921    /// ```rust
1922    /// proof fn push_to_set_test() {
1923    ///     let s = seq![1, 2];
1924    ///     assert(s.push(3).to_set() =~= s.to_set().insert(3));
1925    /// }
1926    /// ```
1927    pub broadcast proof fn lemma_push_to_set_commute(self, elem: A)
1928        ensures
1929            #[trigger] self.push(elem).to_set() =~= self.to_set().insert(elem),
1930    {
1931        broadcast use group_seq_properties;
1932        broadcast use super::set::group_set_axioms;
1933
1934        let lhs = self.push(elem).to_set();
1935        let rhs = self.to_set().insert(elem);
1936
1937        assert(lhs.subset_of(rhs));
1938        assert forall|x: A| rhs.contains(x) implies lhs.contains(x) by {
1939            lemma_seq_contains_after_push(self, elem, x);
1940            if x == elem {
1941            } else {
1942                lemma_seq_contains_after_push(self, elem, x);
1943            }
1944        }
1945    }
1946
1947    /// Filtering a sequence after pushing an element is equivalent to:
1948    /// if the element satisfies the predicate, filter the sequence and push the element
1949    /// otherwise, just filter the sequence without the element.
1950    ///
1951    /// ## Example
1952    /// ```rust
1953    /// proof fn filter_push_test() {
1954    ///     let s = seq![1, 2];
1955    ///     let is_even = |x| x % 2 == 0;
1956    ///     assert(s.push(4).filter(is_even) == s.filter(is_even).push(4));
1957    ///     assert(s.push(3).filter(is_even) == s.filter(is_even));
1958    /// }
1959    /// ```
1960    pub broadcast proof fn lemma_filter_push(self, elem: A, pred: spec_fn(A) -> bool)
1961        ensures
1962            #[trigger] self.push(elem).filter(pred) == if pred(elem) {
1963                self.filter(pred).push(elem)
1964            } else {
1965                self.filter(pred)
1966            },
1967    {
1968        broadcast use group_seq_properties;
1969
1970        reveal(Seq::filter);
1971        assert(self.push(elem).drop_last() =~= self);
1972    }
1973
1974    /// If two sequences have the same length and `i` is a valid index,
1975    /// then the pair `(a[i], b[i])` is contained in their zip.
1976    ///
1977    /// ## Example
1978    /// ```rust
1979    /// proof fn zip_contains_test() {
1980    ///     let a = seq![1, 2];
1981    ///     let b = seq!["a", "b"];
1982    ///     assert(a.zip_with(b).contains((a[0], b[0])));
1983    ///     assert(a.zip_with(b).contains((a[1], b[1])));
1984    /// }
1985    /// ```
1986    pub proof fn lemma_zip_with_contains_index<B>(self, b: Seq<B>, i: int)
1987        requires
1988            0 <= i < self.len(),
1989            self.len() == b.len(),
1990        ensures
1991            self.zip_with(b).contains((self[i], b[i])),
1992    {
1993        assert(self.zip_with(b)[i] == (self[i], b[i]));
1994    }
1995
1996    /// Proves equivalence between checking a predicate over zipped sequences and checking
1997    /// corresponding elements by index. Requires sequences of equal length.
1998    ///
1999    /// # Example
2000    /// ```rust
2001    /// proof fn example() {
2002    ///     let xs = seq![1, 2];
2003    ///     let ys = seq![2, 3];
2004    ///     let f = |x, y| x < y;
2005    ///     assert(xs.zip_with(ys).all(|(x, y)| f(x, y)) <==>
2006    ///            forall|i| 0 <= i < xs.len() ==> f(xs[i], ys[i]));
2007    ///     // We can now prove specific index relationships
2008    ///     assert(xs[0] < ys[0]); // 1 < 2
2009    ///     assert(xs[1] < ys[1]); // 2 < 3
2010    /// }
2011    /// ```
2012    pub proof fn lemma_zip_with_uncurry_all<B>(self, b: Seq<B>, f: spec_fn(A, B) -> bool)
2013        requires
2014            self.len() == b.len(),
2015        ensures
2016            self.zip_with(b).all(|p: (A, B)| f(p.0, p.1)) <==> forall|i: int|
2017                0 <= i < self.len() ==> f(self[i], b[i]),
2018    {
2019        broadcast use group_seq_properties;
2020
2021        let zipped = self.zip_with(b);
2022        let f_uncurr = |p: (A, B)| f(p.0, p.1);
2023        let lhs = zipped.all(f_uncurr);
2024        let rhs = (forall|i: int| 0 <= i < self.len() ==> f(self[i], b[i]));
2025        if lhs {
2026            assert forall|i: int| 0 <= i < self.len() implies f(self[i], b[i]) by {
2027                self.lemma_zip_with_contains_index(b, i);
2028                assert(forall|j| 0 <= j < zipped.len() ==> f_uncurr(zipped[j]));
2029            }
2030        }
2031    }
2032
2033    /// flat_mapping after pushing an element is the same as
2034    /// flat_mapping first and then appending f of that element.
2035    ///
2036    /// # Example
2037    /// ```rust
2038    /// proof fn example() {
2039    ///     let xs = seq![1, 2];
2040    ///     let f = |x| seq![x, x + 1];
2041    ///     assert(xs.push(3).flat_map(f) =~= xs.flat_map(f) + f(3));
2042    ///     // xs.push(3).flat_map(f)    = [1,2,2,3,3,4]
2043    ///     // xs.flat_map(f) + f(3)     = [1,2,2,3] + [3,4]
2044    /// }
2045    /// ```
2046    pub proof fn lemma_flat_map_push<B>(self, f: spec_fn(A) -> Seq<B>, elem: A)
2047        ensures
2048            self.push(elem).flat_map(f) =~= self.flat_map(f) + f(elem),
2049        decreases self.len(),
2050    {
2051        broadcast use group_seq_properties;
2052        broadcast use Seq::lemma_flatten_push;
2053        broadcast use Seq::lemma_push_map_commute;
2054
2055    }
2056
2057    /// flat_mapping a sequence up to index i+1 is equivalent to
2058    /// flat_mapping up to index i and appending f of the element at index i.
2059    ///
2060    /// # Example
2061    /// ```rust
2062    /// proof fn example() {
2063    ///     let xs = seq![1, 2, 3];
2064    ///     let f = |x| seq![x, x + 1];
2065    ///
2066    ///     assert(xs.take(2).flat_map(f) =~= xs.take(1).flat_map(f) + f(xs[1]));
2067    ///     // xs.take(2).flat_map(f)        = [1,2,2,3]
2068    ///     // xs.take(1).flat_map(f) + f(2) = [1,2] + [2,3]
2069    /// }
2070    /// ```
2071    pub broadcast proof fn lemma_flat_map_take_append<B>(self, f: spec_fn(A) -> Seq<B>, i: int)
2072        requires
2073            0 <= i < self.len(),
2074        ensures
2075            #[trigger] self.take(i + 1).flat_map(f) =~= self.take(i).flat_map(f) + f(self[i]),
2076        decreases i,
2077    {
2078        broadcast use group_seq_properties;
2079
2080        self.lemma_take_succ_push(i);
2081        self.take(i).lemma_flat_map_push(f, self[i]);
2082    }
2083
2084    /// flat_mapping a sequence with a single element
2085    /// is equivalent to applying the function f to that element.
2086    pub broadcast proof fn lemma_flat_map_singleton<B>(self, f: spec_fn(A) -> Seq<B>)
2087        requires
2088            #[trigger] self.len() == 1,
2089        ensures
2090            #[trigger] self.flat_map(f) == f(self[0]),
2091    {
2092        broadcast use Seq::lemma_flatten_singleton;
2093
2094    }
2095
2096    /// Mapping a sequence's first i+1 elements equals
2097    /// mapping its first i elements plus f of the i-th element.
2098    ///
2099    /// # Example
2100    /// ```rust
2101    /// proof fn example() {
2102    ///     let xs = seq![1, 2, 3];
2103    ///     let f = |x| x * 2;
2104    ///
2105    ///     assert(xs.take(2).map_values(f) =~= xs.take(1).map_values(f).push(f(xs[1])));
2106    ///     // Left:  [1,2].map(f)          = [2,4]
2107    ///     // Right: [1].map(f).push(f(2)) = [2].push(4)
2108    /// }
2109    /// ```
2110    pub broadcast proof fn lemma_map_take_succ<B>(self, f: spec_fn(A) -> B, i: int)
2111        requires
2112            0 <= i < self.len(),
2113        ensures
2114            #[trigger] self.take(i + 1).map_values(f) =~= self.take(i).map_values(f).push(
2115                f(self[i]),
2116            ),
2117    {
2118        broadcast use group_seq_properties;
2119
2120        self.lemma_take_succ_push(i);
2121    }
2122
2123    /// If a sequence is a prefix of another sequence,
2124    /// their elements match at all indices within the prefix length.
2125    ///
2126    /// # Example
2127    /// ```rust
2128    /// proof fn example() {
2129    ///     let xs = seq![1, 2, 3];
2130    ///     let prefix = seq![1, 2];
2131    ///     assert(prefix.is_prefix_of(xs));
2132    ///     assert(prefix[0] == xs[0] && prefix[1] == xs[1]);
2133    /// }
2134    /// ```
2135    pub broadcast proof fn lemma_prefix_index_eq(self, prefix: Seq<A>)
2136        requires
2137            #[trigger] prefix.is_prefix_of(self),
2138        ensures
2139            forall|i: int| 0 <= i < prefix.len() ==> prefix[i] == self[i],
2140    {
2141    }
2142
2143    /// If a concatenated sequence (prefix1 + prefix2) is a prefix of another sequence,
2144    /// then prefix1 by itself is also a prefix of that sequence.
2145    ///
2146    /// # Example
2147    /// ```rust
2148    /// proof fn example() {
2149    ///     let xs = seq![1, 2, 3, 4];
2150    ///     let prefix1 = seq![1, 2];
2151    ///     let prefix2 = seq![3];
2152    ///     assert((prefix1 + prefix2).is_prefix_of(xs));
2153    ///     assert(prefix1.is_prefix_of(xs));
2154    /// }
2155    /// ```
2156    pub broadcast proof fn lemma_prefix_concat(self, prefix1: Seq<A>, prefix2: Seq<A>)
2157        requires
2158            #[trigger] (prefix1 + prefix2).is_prefix_of(self),
2159        ensures
2160            prefix1.is_prefix_of(self),
2161    {
2162        broadcast use Seq::lemma_prefix_index_eq;
2163
2164    }
2165
2166    /// If `prefix1 + [t]` is a prefix of a sequence,
2167    /// `prefix1` is a prefix of `prefix2`,
2168    /// `prefix2` is a prefix of the sequence,
2169    /// `prefix1` and `prefix2` are different, and
2170    /// `prefix1` doesn't contain `t`,
2171    /// then `prefix2` must contain t.
2172    ///
2173    /// # Example
2174    /// ```rust
2175    /// proof fn example() {
2176    ///     let xs = seq![1, 2, 3, 4];
2177    ///     let prefix1 = seq![1];
2178    ///     let prefix2 = seq![1, 2];
2179    ///     let t = 2;
2180    ///     assert((prefix1 + seq![t]).is_prefix_of(xs));
2181    ///     assert(prefix1.is_prefix_of(prefix2));
2182    ///     assert(prefix2.is_prefix_of(xs));
2183    ///     assert(prefix2.contains(t));
2184    /// }
2185    /// ```
2186    pub broadcast proof fn lemma_prefix_chain_contains(self, prefix1: Seq<A>, prefix2: Seq<A>, t: A)
2187        requires
2188            #[trigger] (prefix1 + seq![t]).is_prefix_of(self),
2189            #[trigger] prefix1.is_prefix_of(prefix2),
2190            prefix2.is_prefix_of(self),
2191            prefix1 != prefix2,
2192            !prefix1.contains(t),
2193        ensures
2194            prefix2.contains(t),
2195    {
2196        broadcast use Seq::lemma_prefix_concat;
2197        broadcast use Seq::lemma_prefix_index_eq;
2198
2199        assert(prefix2[prefix1.len() as int] == t);
2200    }
2201
2202    /// If `prefix1 + [t]` and `prefix2 + [t]` are both prefixes of a sequence,
2203    /// and neither `prefix1` nor `prefix2` contains `t`,
2204    /// then `prefix1` equals `prefix2`.
2205    pub broadcast proof fn lemma_prefix_append_unique(self, prefix1: Seq<A>, prefix2: Seq<A>, t: A)
2206        requires
2207            #[trigger] (prefix1 + seq![t]).is_prefix_of(self),
2208            #[trigger] (prefix2 + seq![t]).is_prefix_of(self),
2209            !prefix1.contains(t),
2210            !prefix2.contains(t),
2211        ensures
2212            prefix1 == prefix2,
2213    {
2214        broadcast use Seq::lemma_prefix_concat;
2215        broadcast use Seq::lemma_prefix_index_eq;
2216        broadcast use Seq::lemma_prefix_chain_contains;
2217
2218        if prefix1 != prefix2 {
2219            assert(prefix1.is_prefix_of(prefix2) || prefix2.is_prefix_of(prefix1));
2220        }
2221    }
2222
2223    /// If a predicate `p` is true for all elements in a sequence,
2224    /// and `p` is true for an element `e`, then `p` remains true for all elements
2225    /// after pushing `e` to the sequence.
2226    ///
2227    /// # Example
2228    /// ```rust
2229    /// proof fn example() {
2230    ///     let xs = seq![2, 4, 6];
2231    ///     let is_even = |x| x % 2 == 0;
2232    ///     assert(xs.all(is_even));
2233    ///     assert(is_even(8));
2234    ///     assert(xs.push(8).all(is_even));
2235    /// }
2236    /// ```
2237    pub broadcast proof fn lemma_all_push(self, p: spec_fn(A) -> bool, elem: A)
2238        requires
2239            self.all(p),
2240            p(elem),
2241        ensures
2242            #[trigger] self.push(elem).all(p),
2243    {
2244        broadcast use group_seq_properties;
2245
2246        assert forall|x: A| self.push(elem).contains(x) implies p(x) by {
2247            lemma_seq_contains_after_push(self, elem, x);
2248        }
2249    }
2250
2251    /// Two sequences are equal when concatenated with the same prefix
2252    /// iff those two sequences are equal.
2253    pub proof fn lemma_concat_injective(self, s1: Seq<A>, s2: Seq<A>)
2254        ensures
2255            (self + s1 == self + s2) <==> (s1 == s2),
2256    {
2257        broadcast use group_seq_properties;
2258
2259        assert((self + s1).skip(self.len() as int) == s1);
2260    }
2261
2262    pub broadcast group group_seq_extra {
2263        Seq::<_>::lemma_seq_skip_skip,
2264        Seq::<_>::lemma_remove_duplicates_properties,
2265        Seq::<_>::lemma_filter_contains_rev,
2266        Seq::<_>::lemma_filter_map_take_succ,
2267        Seq::<_>::lemma_filter_prepend,
2268        Seq::<_>::lemma_filter_len_push,
2269        Seq::<_>::lemma_take_len,
2270        Seq::<_>::lemma_take_any_succ,
2271        Seq::<_>::lemma_push_map_commute,
2272        Seq::<_>::lemma_push_to_set_commute,
2273        Seq::<_>::lemma_filter_push,
2274        Seq::<_>::lemma_flat_map_take_append,
2275        Seq::<_>::lemma_flat_map_singleton,
2276        Seq::<_>::lemma_map_take_succ,
2277        Seq::<_>::lemma_prefix_index_eq,
2278        Seq::<_>::lemma_prefix_concat,
2279        Seq::<_>::lemma_prefix_chain_contains,
2280        Seq::<_>::lemma_prefix_append_unique,
2281        Seq::<_>::lemma_all_push,
2282    }
2283}
2284
2285impl<A> Seq<&A> {
2286    /// Dereference each element of the sequence
2287    pub open spec fn unref(self) -> Seq<A> {
2288        Seq::new(self.len(), |i: int| *self[i])
2289    }
2290}
2291
2292impl<A, B> Seq<(&A, &B)> {
2293    /// Dereference each element of each tuple in the sequence
2294    pub open spec fn unref(self) -> Seq<(A, B)> {
2295        Seq::new(self.len(), |i: int| (*self[i].0, *self[i].1))
2296    }
2297}
2298
2299/// Filtering a sequence and then viewing its elements produces the same result as
2300/// viewing the elements first and then filtering with the corresponding predicate.
2301/// The predicates p and sp must be equivalent under view.
2302///
2303/// # Example
2304/// ```rust
2305/// proof fn example() {
2306///     let s = seq!["hello".to_string(), "world".to_string()];
2307///     let p = |x: String| x.len() > 4;
2308///     let sp = |x: Seq<char>| x.len() > 4;
2309///
2310///     let way1 = s.filter(p).map_values(|x| x.view());
2311///     let way2 = s.map_values(|x| x.view()).filter(sp);
2312///     assert(way1 == way2);
2313/// }
2314/// ```
2315pub proof fn lemma_filter_view_commute<S: View>(
2316    s: Seq<S>,
2317    p: spec_fn(S) -> bool,
2318    sp: spec_fn(S::V) -> bool,
2319)
2320    requires
2321        forall|s: S| p(s) <==> sp(s.view()),
2322    ensures
2323        s.filter(p).map_values(|x: S| x.view()) == s.map_values(|x: S| x.view()).filter(sp),
2324    decreases s.len(),
2325{
2326    broadcast use group_seq_properties;
2327    broadcast use Seq::lemma_push_map_commute;
2328    broadcast use Seq::lemma_filter_push;
2329
2330    reveal(Seq::filter);
2331    let view = |x: S| x.view();
2332    if s.len() > 0 {
2333        let rest = s.drop_last();
2334        let last = s.last();
2335        assert(s =~= rest.push(last));
2336        assert(s.map_values(view).last() == view(last));
2337        lemma_filter_view_commute(rest, p, sp);
2338    }
2339}
2340
2341/// A sequence has exactly one element satisfying a predicate iff
2342/// viewing all elements and filtering with the corresponding predicate
2343/// produces a sequence with exactly one element.
2344///
2345/// # Example
2346/// ```rust
2347/// proof fn example() {
2348///     let s = seq!["hello".to_string(), "world".to_string()];
2349///     let p = |x: String| x.len() == 5;
2350///     let sp = |x: Seq<char>| x.len() == 5;
2351///
2352///     assert(s.exactly_one(p) <==> s.map_values(|x| x.view()).exactly_one(sp));
2353/// }
2354/// ```
2355pub proof fn lemma_exactly_one_view<S: View>(
2356    s: Seq<S>,
2357    p: spec_fn(S) -> bool,
2358    sp: spec_fn(S::V) -> bool,
2359)
2360    requires
2361        forall|s: S| p(s) <==> sp(s.view()),
2362        injective(|x: S| x.view()),
2363    ensures
2364        s.exactly_one(p) <==> s.map_values(|x: S| x.view()).exactly_one(sp),
2365{
2366    lemma_filter_view_commute(s, p, sp);
2367}
2368
2369impl<A, B> Seq<(A, B)> {
2370    /// Unzips a sequence that contains pairs into two separate sequences.
2371    pub closed spec fn unzip(self) -> (Seq<A>, Seq<B>) {
2372        (Seq::new(self.len(), |i: int| self[i].0), Seq::new(self.len(), |i: int| self[i].1))
2373    }
2374
2375    /// Proof of correctness and expected properties of unzip function
2376    pub proof fn unzip_ensures(self)
2377        ensures
2378            self.unzip().0.len() == self.unzip().1.len(),
2379            self.unzip().0.len() == self.len(),
2380            self.unzip().1.len() == self.len(),
2381            forall|i: int|
2382                0 <= i < self.len() ==> (#[trigger] self.unzip().0[i], #[trigger] self.unzip().1[i])
2383                    == self[i],
2384        decreases self.len(),
2385    {
2386        if self.len() > 0 {
2387            self.drop_last().unzip_ensures();
2388        }
2389    }
2390
2391    /// Unzipping a sequence of sequences and then zipping the resulting two sequences
2392    /// back together results in the original sequence of sequences.
2393    pub proof fn lemma_zip_of_unzip(self)
2394        ensures
2395            self.unzip().0.zip_with(self.unzip().1) =~= self,
2396    {
2397    }
2398}
2399
2400impl<A> Seq<Seq<A>> {
2401    /// Flattens a sequence of sequences into a single sequence by concatenating
2402    /// subsequences, starting from the first element.
2403    ///
2404    /// ## Example
2405    ///
2406    /// ```rust
2407    /// proof fn flatten_test() {
2408    ///    let seq: Seq<Seq<int>> = seq![seq![1, 2, 3], seq![4, 5, 6], seq![7, 8, 9]];
2409    ///    let flat: Seq<int> = seq.flatten();
2410    ///    reveal_with_fuel(Seq::<Seq<int>>::flatten, 5); //Needed for Verus to unfold the recursive definition of flatten
2411    ///    assert(flat =~= seq![1, 2, 3, 4, 5, 6, 7, 8, 9]);
2412    /// }
2413    /// ```
2414    pub open spec fn flatten(self) -> Seq<A>
2415        decreases self.len(),
2416    {
2417        if self.len() == 0 {
2418            Seq::empty()
2419        } else {
2420            self.first().add(self.drop_first().flatten())
2421        }
2422    }
2423
2424    /// Flattens a sequence of sequences into a single sequence by concatenating
2425    /// subsequences in reverse order, i.e. starting from the last element.
2426    /// This is equivalent to a call to `flatten`, but with concatenation operation
2427    /// applied along the oppositive associativity for the sake of proof reasoning in that direction.
2428    pub open spec fn flatten_alt(self) -> Seq<A>
2429        decreases self.len(),
2430    {
2431        if self.len() == 0 {
2432            Seq::empty()
2433        } else {
2434            self.drop_last().flatten_alt().add(self.last())
2435        }
2436    }
2437
2438    /// Flattening a sequence of a sequence x, where x has length 1,
2439    /// results in a sequence equivalent to the single element of x
2440    pub proof fn lemma_flatten_one_element(self)
2441        ensures
2442            self.len() == 1 ==> self.flatten() == self.first(),
2443    {
2444        broadcast use Seq::add_empty_right;
2445
2446        if self.len() == 1 {
2447            assert(self.flatten() =~= self.first().add(self.drop_first().flatten()));
2448        }
2449    }
2450
2451    /// The length of a flattened sequence of sequences x is greater than or
2452    /// equal to any of the lengths of the elements of x.
2453    pub proof fn lemma_flatten_length_ge_single_element_length(self, i: int)
2454        requires
2455            0 <= i < self.len(),
2456        ensures
2457            self.flatten_alt().len() >= self[i].len(),
2458        decreases self.len(),
2459    {
2460        if self.len() == 1 {
2461            self.lemma_flatten_one_element();
2462            self.lemma_flatten_and_flatten_alt_are_equivalent();
2463        } else if i < self.len() - 1 {
2464            self.drop_last().lemma_flatten_length_ge_single_element_length(i);
2465        } else {
2466            assert(self.flatten_alt() == self.drop_last().flatten_alt().add(self.last()));
2467        }
2468    }
2469
2470    /// The length of a flattened sequence of sequences x is less than or equal
2471    /// to the length of x multiplied by a number greater than or equal to the
2472    /// length of the longest sequence in x.
2473    pub proof fn lemma_flatten_length_le_mul(self, j: int)
2474        requires
2475            forall|i: int| 0 <= i < self.len() ==> (#[trigger] self[i]).len() <= j,
2476        ensures
2477            self.flatten_alt().len() <= self.len() * j,
2478        decreases self.len(),
2479    {
2480        broadcast use group_seq_properties;
2481
2482        if self.len() == 0 {
2483        } else {
2484            self.drop_last().lemma_flatten_length_le_mul(j);
2485            assert((self.len() - 1) * j == (self.len() * j) - (1 * j)) by (nonlinear_arith);  //TODO: use math library after imported
2486        }
2487    }
2488
2489    /// Flattening sequences of sequences in order (starting from the beginning)
2490    /// and in reverse order (starting from the end) results in the same sequence.
2491    pub proof fn lemma_flatten_and_flatten_alt_are_equivalent(self)
2492        ensures
2493            self.flatten() =~= self.flatten_alt(),
2494        decreases self.len(),
2495    {
2496        broadcast use {Seq::add_empty_right, Seq::push_distributes_over_add};
2497
2498        if self.len() != 0 {
2499            self.drop_last().lemma_flatten_and_flatten_alt_are_equivalent();
2500            // let s = self.drop_last().flatten();
2501            // let s2 = self.drop_last().flatten_alt();
2502            // assert(s == s2);
2503            seq![self.last()].lemma_flatten_one_element();
2504            assert(seq![self.last()].flatten() == self.last());
2505            lemma_flatten_concat(self.drop_last(), seq![self.last()]);
2506            assert((self.drop_last() + seq![self.last()]).flatten() == self.drop_last().flatten()
2507                + self.last());
2508            assert(self.drop_last() + seq![self.last()] =~= self);
2509            assert(self.flatten_alt() == self.drop_last().flatten_alt() + self.last());
2510        }
2511    }
2512
2513    /// Flattening a sequence of sequences after pushing a new sequence is equivalent to
2514    /// concatenating that sequence to the original flattened result.
2515    pub broadcast proof fn lemma_flatten_push(self, elem: Seq<A>)
2516        ensures
2517            #[trigger] self.push(elem).flatten() =~= self.flatten() + elem,
2518        decreases self.len(),
2519    {
2520        broadcast use group_seq_properties;
2521
2522        assert(self.push(elem).last() == elem);
2523        assert(self.push(elem).drop_last() =~= self);
2524        calc! {
2525            (==)
2526            self.push(elem).flatten(); {
2527                self.push(elem).lemma_flatten_and_flatten_alt_are_equivalent();
2528            }
2529            self.push(elem).flatten_alt(); {}
2530            self.flatten_alt() + elem; {
2531                self.lemma_flatten_and_flatten_alt_are_equivalent();
2532            }
2533            self.flatten() + elem;
2534        }
2535    }
2536
2537    /// Flattening a sequence containing a single sequence yields that inner sequence.
2538    pub broadcast proof fn lemma_flatten_singleton(self)
2539        requires
2540            #[trigger] self.len() == 1,
2541        ensures
2542            #[trigger] self.flatten() == self[0],
2543    {
2544        assert(self.flatten() == self[0] + self.drop_first().flatten());
2545        assert(self.flatten() == self[0]);
2546    }
2547
2548    pub broadcast group group_seq_flatten {
2549        Seq::<_>::lemma_flatten_push,
2550        Seq::<_>::lemma_flatten_singleton,
2551    }
2552}
2553
2554/********************************* Extrema in Sequences *********************************/
2555
2556impl Seq<int> {
2557    /// Returns the maximum integer value in a non-empty sequence of integers.
2558    pub open spec fn max(self) -> int
2559        recommends
2560            0 < self.len(),
2561        decreases self.len(),
2562    {
2563        if self.len() == 1 {
2564            self[0]
2565        } else if self.len() == 0 {
2566            0
2567        } else {
2568            let later_max = self.drop_first().max();
2569            if self[0] >= later_max {
2570                self[0]
2571            } else {
2572                later_max
2573            }
2574        }
2575    }
2576
2577    /// Proof of correctness and expected properties for max function
2578    pub proof fn max_ensures(self)
2579        ensures
2580            forall|x: int| self.contains(x) ==> x <= self.max(),
2581            forall|i: int| 0 <= i < self.len() ==> self[i] <= self.max(),
2582            self.len() == 0 || self.contains(self.max()),
2583        decreases self.len(),
2584    {
2585        if self.len() <= 1 {
2586        } else {
2587            let elt = self.drop_first().max();
2588            assert(self.drop_first().contains(elt)) by { self.drop_first().max_ensures() }
2589            assert forall|i: int| 0 <= i < self.len() implies self[i] <= self.max() by {
2590                assert(i == 0 || self[i] == self.drop_first()[i - 1]);
2591                assert(forall|j: int|
2592                    0 <= j < self.drop_first().len() ==> self.drop_first()[j]
2593                        <= self.drop_first().max()) by { self.drop_first().max_ensures() }
2594            }
2595        }
2596    }
2597
2598    /// Returns the minimum integer value in a non-empty sequence of integers.
2599    pub open spec fn min(self) -> int
2600        recommends
2601            0 < self.len(),
2602        decreases self.len(),
2603    {
2604        if self.len() == 1 {
2605            self[0]
2606        } else if self.len() == 0 {
2607            0
2608        } else {
2609            let later_min = self.drop_first().min();
2610            if self[0] <= later_min {
2611                self[0]
2612            } else {
2613                later_min
2614            }
2615        }
2616    }
2617
2618    /// Proof of correctness and expected properties for min function
2619    pub proof fn min_ensures(self)
2620        ensures
2621            forall|x: int| self.contains(x) ==> self.min() <= x,
2622            forall|i: int| 0 <= i < self.len() ==> self.min() <= self[i],
2623            self.len() == 0 || self.contains(self.min()),
2624        decreases self.len(),
2625    {
2626        if self.len() <= 1 {
2627        } else {
2628            let elt = self.drop_first().min();
2629            assert(self.subrange(1, self.len() as int).contains(elt)) by {
2630                self.drop_first().min_ensures()
2631            }
2632            assert forall|i: int| 0 <= i < self.len() implies self.min() <= self[i] by {
2633                assert(i == 0 || self[i] == self.drop_first()[i - 1]);
2634                assert(forall|j: int|
2635                    0 <= j < self.drop_first().len() ==> self.drop_first().min()
2636                        <= self.drop_first()[j]) by { self.drop_first().min_ensures() }
2637            }
2638        }
2639    }
2640
2641    pub closed spec fn sort(self) -> Self {
2642        self.sort_by(|x: int, y: int| x <= y)
2643    }
2644
2645    pub proof fn lemma_sort_ensures(self)
2646        ensures
2647            self.to_multiset() =~= self.sort().to_multiset(),
2648            sorted_by(self.sort(), |x: int, y: int| x <= y),
2649    {
2650        self.lemma_sort_by_ensures(|x: int, y: int| x <= y);
2651    }
2652
2653    /// The maximum element in a non-empty sequence is greater than or equal to
2654    /// the maxima of its non-empty subsequences.
2655    pub proof fn lemma_subrange_max(self, from: int, to: int)
2656        requires
2657            0 <= from < to <= self.len(),
2658        ensures
2659            self.subrange(from, to).max() <= self.max(),
2660    {
2661        self.max_ensures();
2662        self.subrange(from, to).max_ensures();
2663    }
2664
2665    /// The minimum element in a non-empty sequence is less than or equal to
2666    /// the minima of its non-empty subsequences.
2667    pub proof fn lemma_subrange_min(self, from: int, to: int)
2668        requires
2669            0 <= from < to <= self.len(),
2670        ensures
2671            self.subrange(from, to).min() >= self.min(),
2672    {
2673        self.min_ensures();
2674        self.subrange(from, to).min_ensures();
2675    }
2676}
2677
2678// Helper function to aid with merge sort
2679spec fn merge_sorted_with<A>(left: Seq<A>, right: Seq<A>, leq: spec_fn(A, A) -> bool) -> Seq<A>
2680    recommends
2681        sorted_by(left, leq),
2682        sorted_by(right, leq),
2683        total_ordering(leq),
2684    decreases left.len(), right.len(),
2685{
2686    if left.len() == 0 {
2687        right
2688    } else if right.len() == 0 {
2689        left
2690    } else if leq(left.first(), right.first()) {
2691        Seq::<A>::empty().push(left.first()) + merge_sorted_with(left.drop_first(), right, leq)
2692    } else {
2693        Seq::<A>::empty().push(right.first()) + merge_sorted_with(left, right.drop_first(), leq)
2694    }
2695}
2696
2697proof fn lemma_merge_sorted_with_ensures<A>(left: Seq<A>, right: Seq<A>, leq: spec_fn(A, A) -> bool)
2698    requires
2699        sorted_by(left, leq),
2700        sorted_by(right, leq),
2701        total_ordering(leq),
2702    ensures
2703        (left + right).to_multiset() =~= merge_sorted_with(left, right, leq).to_multiset(),
2704        sorted_by(merge_sorted_with(left, right, leq), leq),
2705    decreases left.len(), right.len(),
2706{
2707    // TODO: lemma_seq_skip_of_skip and lemma_seq_skip_index2 cause a lot of QIs
2708    broadcast use group_seq_properties;
2709
2710    if left.len() == 0 {
2711        assert(left + right =~= right);
2712    } else if right.len() == 0 {
2713        assert(left + right =~= left);
2714    } else if leq(left.first(), right.first()) {
2715        let result = Seq::<A>::empty().push(left.first()) + merge_sorted_with(
2716            left.drop_first(),
2717            right,
2718            leq,
2719        );
2720        lemma_merge_sorted_with_ensures(left.drop_first(), right, leq);
2721        let rest = merge_sorted_with(left.drop_first(), right, leq);
2722        assert(rest.len() == 0 || rest.first() == left.drop_first().first() || rest.first()
2723            == right.first()) by {
2724            if left.drop_first().len() == 0 {
2725            } else if leq(left.drop_first().first(), right.first()) {
2726                assert(rest =~= Seq::<A>::empty().push(left.drop_first().first())
2727                    + merge_sorted_with(left.drop_first().drop_first(), right, leq));
2728            } else {
2729                assert(rest =~= Seq::<A>::empty().push(right.first()) + merge_sorted_with(
2730                    left.drop_first(),
2731                    right.drop_first(),
2732                    leq,
2733                ));
2734            }
2735        }
2736        lemma_new_first_element_still_sorted_by(left.first(), rest, leq);
2737        assert((left.drop_first() + right) =~= (left + right).drop_first());
2738    } else {
2739        let result = Seq::<A>::empty().push(right.first()) + merge_sorted_with(
2740            left,
2741            right.drop_first(),
2742            leq,
2743        );
2744        lemma_merge_sorted_with_ensures(left, right.drop_first(), leq);
2745        let rest = merge_sorted_with(left, right.drop_first(), leq);
2746        assert(rest.len() == 0 || rest.first() == left.first() || rest.first()
2747            == right.drop_first().first()) by {
2748            assert(left.len() > 0);
2749            if right.drop_first().len() == 0 {  /*assert(rest =~= left);*/
2750            } else if leq(left.first(), right.drop_first().first()) {  //right might be length 1
2751                assert(rest =~= Seq::<A>::empty().push(left.first()) + merge_sorted_with(
2752                    left.drop_first(),
2753                    right.drop_first(),
2754                    leq,
2755                ));
2756            } else {
2757                assert(rest =~= Seq::<A>::empty().push(right.drop_first().first())
2758                    + merge_sorted_with(left, right.drop_first().drop_first(), leq));
2759            }
2760        }
2761        lemma_new_first_element_still_sorted_by(
2762            right.first(),
2763            merge_sorted_with(left, right.drop_first(), leq),
2764            leq,
2765        );
2766        lemma_seq_union_to_multiset_commutative(left, right);
2767        assert((right.drop_first() + left) =~= (right + left).drop_first());
2768        lemma_seq_union_to_multiset_commutative(right.drop_first(), left);
2769    }
2770}
2771
2772/// The maximum of the concatenation of two non-empty sequences is greater than or
2773/// equal to the maxima of its two non-empty subsequences.
2774pub proof fn lemma_max_of_concat(x: Seq<int>, y: Seq<int>)
2775    requires
2776        0 < x.len() && 0 < y.len(),
2777    ensures
2778        x.max() <= (x + y).max(),
2779        y.max() <= (x + y).max(),
2780        forall|elt: int| (x + y).contains(elt) ==> elt <= (x + y).max(),
2781    decreases x.len(),
2782{
2783    broadcast use group_seq_properties;
2784
2785    x.max_ensures();
2786    y.max_ensures();
2787    (x + y).max_ensures();
2788    assert(x.drop_first().len() == x.len() - 1);
2789    if x.len() == 1 {
2790        assert(y.max() <= (x + y).max()) by {
2791            assert((x + y).contains(y.max()));
2792        }
2793    } else {
2794        assert(x.max() <= (x + y).max()) by {
2795            assert(x.contains(x.max()));
2796            assert((x + y).contains(x.max()));
2797        }
2798        assert(x.drop_first() + y =~= (x + y).drop_first());
2799        lemma_max_of_concat(x.drop_first(), y);
2800    }
2801}
2802
2803/// The minimum of the concatenation of two non-empty sequences is less than or
2804/// equal to the minimum of its two non-empty subsequences.
2805pub proof fn lemma_min_of_concat(x: Seq<int>, y: Seq<int>)
2806    requires
2807        0 < x.len() && 0 < y.len(),
2808    ensures
2809        (x + y).min() <= x.min(),
2810        (x + y).min() <= y.min(),
2811        forall|elt: int| (x + y).contains(elt) ==> (x + y).min() <= elt,
2812    decreases x.len(),
2813{
2814    x.min_ensures();
2815    y.min_ensures();
2816    (x + y).min_ensures();
2817    broadcast use group_seq_properties;
2818
2819    if x.len() == 1 {
2820        assert((x + y).min() <= y.min()) by {
2821            assert((x + y).contains(y.min()));
2822        }
2823    } else {
2824        assert((x + y).min() <= x.min()) by {
2825            assert((x + y).contains(x.min()));
2826        }
2827        assert((x + y).min() <= y.min()) by {
2828            assert((x + y).contains(y.min()));
2829        }
2830        assert(x.drop_first() + y =~= (x + y).drop_first());
2831        lemma_max_of_concat(x.drop_first(), y)
2832    }
2833}
2834
2835/************************* Sequence to Multiset Conversion **************************/
2836
2837/// push(a) o to_multiset = to_multiset o insert(a)
2838pub broadcast proof fn to_multiset_build<A>(s: Seq<A>, a: A)
2839    ensures
2840        #![trigger s.push(a).to_multiset()]
2841        s.push(a).to_multiset() =~= s.to_multiset().insert(a),
2842    decreases s.len(),
2843{
2844    broadcast use super::multiset::group_multiset_axioms;
2845
2846    if s.len() == 0 {
2847        assert(s.to_multiset() =~= Multiset::<A>::empty());
2848        assert(s.push(a).drop_first() =~= Seq::<A>::empty());
2849        assert(s.push(a).to_multiset() =~= Multiset::<A>::empty().insert(a).add(
2850            Seq::<A>::empty().to_multiset(),
2851        ));
2852    } else {
2853        to_multiset_build(s.drop_first(), a);
2854        assert(s.drop_first().push(a).to_multiset() =~= s.drop_first().to_multiset().insert(a));
2855        assert(s.push(a).drop_first() =~= s.drop_first().push(a));
2856    }
2857}
2858
2859pub broadcast proof fn to_multiset_remove<A>(s: Seq<A>, i: int)
2860    requires
2861        0 <= i < s.len(),
2862    ensures
2863        #![trigger s.remove(i).to_multiset()]
2864        s.remove(i).to_multiset() == s.to_multiset().remove(s[i]),
2865{
2866    broadcast use super::multiset::group_multiset_axioms;
2867
2868    let s0 = s.subrange(0, i);
2869    let s1 = s.subrange(i, s.len() as int);
2870    let s2 = s.subrange(i + 1, s.len() as int);
2871    lemma_seq_union_to_multiset_commutative(s0, s2);
2872    lemma_seq_union_to_multiset_commutative(s0, s1);
2873    assert(s == s0 + s1);
2874    assert(s2 + s0 == (s1 + s0).drop_first());
2875    assert(s.remove(i).to_multiset() =~= s.to_multiset().remove(s[i]));
2876}
2877
2878pub broadcast proof fn to_multiset_insert<A>(s: Seq<A>, i: int, a: A)
2879    requires
2880        0 <= i <= s.len(),
2881    ensures
2882        #![trigger s.insert(i, a).to_multiset()]
2883        s.insert(i, a).to_multiset() == s.to_multiset().insert(a),
2884    decreases s.len(),
2885{
2886    broadcast use super::multiset::group_multiset_axioms;
2887
2888    let s0 = s.subrange(0, i);
2889    let s1 = s.subrange(i, s.len() as int);
2890
2891    assert(s =~= s0 + s1);
2892    assert(s.insert(i, a) =~= s0 + seq![a] + s1);
2893    assert(((s0 + seq![a]) + s1).to_multiset() =~= ((seq![a] + s0) + s1).to_multiset()) by {
2894        broadcast use lemma_multiset_commutative;
2895
2896    };
2897    assert((seq![a] + s0 + s1).drop_first() == s0 + s1);
2898    assert(s.insert(i, a).to_multiset() =~= s.to_multiset().insert(a));
2899}
2900
2901/// to_multiset() preserves length
2902pub broadcast proof fn to_multiset_len<A>(s: Seq<A>)
2903    ensures
2904        s.len() == #[trigger] s.to_multiset().len(),
2905    decreases s.len(),
2906{
2907    broadcast use super::multiset::group_multiset_axioms;
2908
2909    if s.len() == 0 {
2910        assert(s.to_multiset() =~= Multiset::<A>::empty());
2911        assert(s.len() == 0);
2912    } else {
2913        to_multiset_len(s.drop_first());
2914        assert(s.len() == s.drop_first().len() + 1);
2915        assert(s.to_multiset().len() == s.drop_first().to_multiset().len() + 1);
2916    }
2917}
2918
2919/// to_multiset() contains only the elements of the sequence
2920pub broadcast proof fn to_multiset_contains<A>(s: Seq<A>, a: A)
2921    ensures
2922        #![trigger s.to_multiset().count(a)]
2923        s.contains(a) <==> s.to_multiset().count(a) > 0,
2924    decreases s.len(),
2925{
2926    broadcast use super::multiset::group_multiset_axioms;
2927
2928    if s.len() != 0 {
2929        // ==>
2930        if s.contains(a) {
2931            if s.first() == a {
2932                to_multiset_build(s, a);
2933                assert(s.to_multiset() =~= Multiset::<A>::empty().insert(s.first()).add(
2934                    s.drop_first().to_multiset(),
2935                ));
2936                assert(Multiset::<A>::empty().insert(s.first()).contains(s.first()));
2937            } else {
2938                to_multiset_contains(s.drop_first(), a);
2939                assert(s.skip(1) =~= s.drop_first());
2940                lemma_seq_skip_contains(s, 1, a);
2941                assert(s.to_multiset().count(a) == s.drop_first().to_multiset().count(a));
2942                assert(s.contains(a) <==> s.to_multiset().count(a) > 0);
2943            }
2944        }
2945        // <==
2946
2947        if s.to_multiset().count(a) > 0 {
2948            to_multiset_contains(s.drop_first(), a);
2949            assert(s.contains(a) <==> s.to_multiset().count(a) > 0);
2950        } else {
2951            assert(s.contains(a) <==> s.to_multiset().count(a) > 0);
2952        }
2953    }
2954}
2955
2956pub broadcast proof fn to_multiset_update<A>(s: Seq<A>, i: int, a: A)
2957    requires
2958        0 <= i < s.len(),
2959    ensures
2960        #[trigger] s.update(i, a).to_multiset() == s.to_multiset().insert(a).remove(s[i]),
2961    decreases s.len(),
2962{
2963    broadcast use {
2964        super::seq_lib::lemma_seq_take_len,
2965        super::multiset::group_multiset_properties,
2966        super::multiset::group_multiset_axioms,
2967        to_multiset_insert,
2968        to_multiset_remove,
2969        to_multiset_contains,
2970        lemma_update_is_remove_insert,
2971    };
2972
2973    assert(s.update(i, a).to_multiset() =~= s.to_multiset().insert(a).remove(s[i]));
2974
2975}
2976
2977/// Lemma showing that update is equivalent to a remove followed by an insertae
2978pub broadcast proof fn lemma_update_is_remove_insert<A>(s: Seq<A>, i: int, a: A)
2979    requires
2980        0 <= i < s.len(),
2981    ensures
2982        #[trigger] s.update(i, a) =~= s.remove(i).insert(i, a),
2983    decreases s.len(),
2984{
2985}
2986
2987/// The last element of two concatenated sequences, the second one being non-empty, will be the
2988/// last element of the latter sequence.
2989pub proof fn lemma_append_last<A>(s1: Seq<A>, s2: Seq<A>)
2990    requires
2991        0 < s2.len(),
2992    ensures
2993        (s1 + s2).last() == s2.last(),
2994{
2995}
2996
2997/// The concatenation of sequences is associative
2998pub proof fn lemma_concat_associative<A>(s1: Seq<A>, s2: Seq<A>, s3: Seq<A>)
2999    ensures
3000        s1.add(s2.add(s3)) =~= s1.add(s2).add(s3),
3001{
3002}
3003
3004/// Recursive definition of seq to set conversion
3005spec fn seq_to_set_rec<A>(seq: Seq<A>) -> Set<A>
3006    decreases seq.len(),
3007{
3008    if seq.len() == 0 {
3009        Set::empty()
3010    } else {
3011        seq_to_set_rec(seq.drop_last()).insert(seq.last())
3012    }
3013}
3014
3015// Helper function showing that the recursive definition of set_to_seq produces a finite set
3016proof fn seq_to_set_rec_is_finite<A>(seq: Seq<A>)
3017    ensures
3018        seq_to_set_rec(seq).finite(),
3019    decreases seq.len(),
3020{
3021    broadcast use super::set::group_set_axioms;
3022
3023    if seq.len() > 0 {
3024        let sub_seq = seq.drop_last();
3025        assert(seq_to_set_rec(sub_seq).finite()) by {
3026            seq_to_set_rec_is_finite(sub_seq);
3027        }
3028    }
3029}
3030
3031// Helper function showing that the resulting set contains all elements of the sequence
3032proof fn seq_to_set_rec_contains<A>(seq: Seq<A>)
3033    ensures
3034        forall|a| #[trigger] seq.contains(a) <==> seq_to_set_rec(seq).contains(a),
3035    decreases seq.len(),
3036{
3037    broadcast use super::set::group_set_axioms;
3038
3039    if seq.len() > 0 {
3040        assert(forall|a| #[trigger]
3041            seq.drop_last().contains(a) <==> seq_to_set_rec(seq.drop_last()).contains(a)) by {
3042            seq_to_set_rec_contains(seq.drop_last());
3043        }
3044        assert(seq =~= seq.drop_last().push(seq.last()));
3045        assert forall|a| #[trigger] seq.contains(a) <==> seq_to_set_rec(seq).contains(a) by {
3046            if !seq.drop_last().contains(a) {
3047                if a == seq.last() {
3048                    assert(seq.contains(a));
3049                    assert(seq_to_set_rec(seq).contains(a));
3050                } else {
3051                    assert(!seq_to_set_rec(seq).contains(a));
3052                }
3053            }
3054        }
3055    }
3056}
3057
3058// Helper function showing that the recursive definition matches the set comprehension one
3059proof fn seq_to_set_equal_rec<A>(seq: Seq<A>)
3060    ensures
3061        seq.to_set() == seq_to_set_rec(seq),
3062{
3063    broadcast use super::set::group_set_axioms;
3064
3065    assert(forall|n| #[trigger] seq.contains(n) <==> seq_to_set_rec(seq).contains(n)) by {
3066        seq_to_set_rec_contains(seq);
3067    }
3068    assert(forall|n| #[trigger] seq.contains(n) <==> seq.to_set().contains(n));
3069    assert(seq.to_set() =~= seq_to_set_rec(seq));
3070}
3071
3072/// The set obtained from a sequence is finite
3073pub broadcast proof fn seq_to_set_is_finite<A>(seq: Seq<A>)
3074    ensures
3075        #[trigger] seq.to_set().finite(),
3076{
3077    broadcast use super::set::group_set_axioms;
3078
3079    assert(seq.to_set().finite()) by {
3080        seq_to_set_equal_rec(seq);
3081        seq_to_set_rec_is_finite(seq);
3082    }
3083}
3084
3085pub proof fn seq_to_set_distributes_over_add<T>(s1: Seq<T>, s2: Seq<T>)
3086    ensures
3087        s1.to_set() + s2.to_set() =~= (s1 + s2).to_set(),
3088{
3089    broadcast use super::group_vstd_default;
3090    broadcast use super::set_lib::group_set_properties;
3091    broadcast use group_seq_properties;
3092
3093}
3094
3095/// If sequences a and b don't have duplicates, and there are no
3096/// elements in common between them, then the concatenated sequence
3097/// a + b will not contain duplicates either.
3098pub proof fn lemma_no_dup_in_concat<A>(a: Seq<A>, b: Seq<A>)
3099    requires
3100        a.no_duplicates(),
3101        b.no_duplicates(),
3102        forall|i: int, j: int| 0 <= i < a.len() && 0 <= j < b.len() ==> a[i] != b[j],
3103    ensures
3104        #[trigger] (a + b).no_duplicates(),
3105{
3106}
3107
3108/// Flattening sequences of sequences is distributive over concatenation. That is, concatenating
3109/// the flattening of two sequences of sequences is the same as flattening the
3110/// concatenation of two sequences of sequences.
3111pub proof fn lemma_flatten_concat<A>(x: Seq<Seq<A>>, y: Seq<Seq<A>>)
3112    ensures
3113        (x + y).flatten() =~= x.flatten() + y.flatten(),
3114    decreases x.len(),
3115{
3116    if x.len() == 0 {
3117        assert(x + y =~= y);
3118    } else {
3119        assert((x + y).drop_first() =~= x.drop_first() + y);
3120        assert(x.first() + (x.drop_first() + y).flatten() =~= x.first() + x.drop_first().flatten()
3121            + y.flatten()) by {
3122            lemma_flatten_concat(x.drop_first(), y);
3123        }
3124    }
3125}
3126
3127/// Flattening sequences of sequences in reverse order is distributive over concatentation.
3128/// That is, concatenating the flattening of two sequences of sequences in reverse
3129/// order is the same as flattening the concatenation of two sequences of sequences
3130/// in reverse order.
3131pub proof fn lemma_flatten_alt_concat<A>(x: Seq<Seq<A>>, y: Seq<Seq<A>>)
3132    ensures
3133        (x + y).flatten_alt() =~= x.flatten_alt() + y.flatten_alt(),
3134    decreases y.len(),
3135{
3136    if y.len() == 0 {
3137        assert(x + y =~= x);
3138    } else {
3139        assert((x + y).drop_last() =~= x + y.drop_last());
3140        assert((x + y.drop_last()).flatten_alt() + y.last() =~= x.flatten_alt()
3141            + y.drop_last().flatten_alt() + y.last()) by {
3142            lemma_flatten_alt_concat(x, y.drop_last());
3143        }
3144    }
3145}
3146
3147/// The multiset of a concatenated sequence `a + b` is equivalent to the multiset of the
3148/// concatenated sequence `b + a`.
3149pub broadcast proof fn lemma_seq_union_to_multiset_commutative<A>(a: Seq<A>, b: Seq<A>)
3150    ensures
3151        #[trigger] (a + b).to_multiset() =~= (b + a).to_multiset(),
3152{
3153    broadcast use super::multiset::group_multiset_axioms;
3154
3155    lemma_multiset_commutative(a, b);
3156    lemma_multiset_commutative(b, a);
3157}
3158
3159/// The multiset of a concatenated sequence `a + b` is equivalent to the multiset of just
3160/// sequence `a` added to the multiset of just sequence `b`.
3161pub broadcast proof fn lemma_multiset_commutative<A>(a: Seq<A>, b: Seq<A>)
3162    ensures
3163        #[trigger] (a + b).to_multiset() =~= a.to_multiset().add(b.to_multiset()),
3164    decreases a.len(),
3165{
3166    broadcast use super::multiset::group_multiset_axioms;
3167
3168    if a.len() == 0 {
3169        assert(a + b =~= b);
3170    } else {
3171        lemma_multiset_commutative(a.drop_first(), b);
3172        assert(a.drop_first() + b =~= (a + b).drop_first());
3173    }
3174}
3175
3176/// Any two sequences that are sorted by a total order and that have the same elements are equal.
3177pub proof fn lemma_sorted_unique<A>(x: Seq<A>, y: Seq<A>, leq: spec_fn(A, A) -> bool)
3178    requires
3179        sorted_by(x, leq),
3180        sorted_by(y, leq),
3181        total_ordering(leq),
3182        x.to_multiset() == y.to_multiset(),
3183    ensures
3184        x =~= y,
3185    decreases x.len(), y.len(),
3186{
3187    broadcast use super::multiset::group_multiset_axioms;
3188    broadcast use group_to_multiset_ensures;
3189
3190    if x.len() == 0 || y.len() == 0 {
3191    } else {
3192        assert(x.to_multiset().contains(x[0]));
3193        assert(x.to_multiset().contains(y[0]));
3194        let i = choose|i: int| #![trigger x.spec_index(i) ] 0 <= i < x.len() && x[i] == y[0];
3195        assert(leq(x[i], x[0]));
3196        assert(leq(x[0], x[i]));
3197        assert(x.drop_first().to_multiset() =~= x.to_multiset().remove(x[0]));
3198        assert(y.drop_first().to_multiset() =~= y.to_multiset().remove(y[0]));
3199        lemma_sorted_unique(x.drop_first(), y.drop_first(), leq);
3200        assert(x.drop_first() =~= y.drop_first());
3201        assert(x.first() == y.first());
3202        assert(x =~= Seq::<A>::empty().push(x.first()).add(x.drop_first()));
3203        assert(x =~= y);
3204    }
3205}
3206
3207// This verified lemma used to be an axiom in the Dafny prelude
3208pub broadcast proof fn lemma_seq_contains<A>(s: Seq<A>, x: A)
3209    ensures
3210        #[trigger] s.contains(x) <==> exists|i: int| 0 <= i < s.len() && #[trigger] s[i] == x,
3211{
3212}
3213
3214// This verified lemma used to be an axiom in the Dafny prelude
3215/// The empty sequence contains nothing
3216pub broadcast proof fn lemma_seq_empty_contains_nothing<A>(x: A)
3217    ensures
3218        !(#[trigger] Seq::<A>::empty().contains(x)),
3219{
3220}
3221
3222// This verified lemma used to be an axiom in the Dafny prelude
3223// Note: Dafny only does one way implication, but theoretically it could go both ways
3224/// A sequence with length 0 is equivalent to the empty sequence
3225pub broadcast proof fn lemma_seq_empty_equality<A>(s: Seq<A>)
3226    ensures
3227        #[trigger] s.len() == 0 ==> s =~= Seq::<A>::empty(),
3228{
3229}
3230
3231// This verified lemma used to be an axiom in the Dafny prelude
3232/// The concatenation of two sequences contains only the elements
3233/// of the two sequences
3234pub broadcast proof fn lemma_seq_concat_contains_all_elements<A>(x: Seq<A>, y: Seq<A>, elt: A)
3235    ensures
3236        #[trigger] (x + y).contains(elt) <==> x.contains(elt) || y.contains(elt),
3237    decreases x.len(),
3238{
3239    if x.len() == 0 && y.len() > 0 {
3240        assert((x + y) =~= y);
3241    } else {
3242        assert forall|elt: A| #[trigger] x.contains(elt) implies #[trigger] (x + y).contains(
3243            elt,
3244        ) by {
3245            let index = choose|i: int| 0 <= i < x.len() && x[i] == elt;
3246            assert((x + y)[index] == elt);
3247        }
3248        assert forall|elt: A| #[trigger] y.contains(elt) implies #[trigger] (x + y).contains(
3249            elt,
3250        ) by {
3251            let index = choose|i: int| 0 <= i < y.len() && y[i] == elt;
3252            assert((x + y)[index + x.len()] == elt);
3253        }
3254    }
3255}
3256
3257// This verified lemma used to be an axiom in the Dafny prelude
3258/// After pushing an element onto a sequence, the sequence contains that element
3259pub broadcast proof fn lemma_seq_contains_after_push<A>(s: Seq<A>, v: A, x: A)
3260    ensures
3261        #[trigger] s.push(v).contains(x) <==> v == x || s.contains(x),
3262{
3263    assert forall|elt: A| #[trigger] s.contains(elt) implies #[trigger] s.push(v).contains(elt) by {
3264        let index = choose|i: int| 0 <= i < s.len() && s[i] == elt;
3265        assert(s.push(v)[index] == elt);
3266    }
3267    assert(s.push(v)[s.len() as int] == v);
3268}
3269
3270// This verified lemma used to be an axiom in the Dafny prelude
3271/// The subrange of a sequence contains only the elements within the indices `start` and `stop`
3272/// of the original sequence.
3273pub broadcast proof fn lemma_seq_subrange_elements<A>(s: Seq<A>, start: int, stop: int, x: A)
3274    requires
3275        0 <= start <= stop <= s.len(),
3276    ensures
3277        #[trigger] s.subrange(start, stop).contains(x) <==> (exists|i: int|
3278            0 <= start <= i < stop <= s.len() && #[trigger] s[i] == x),
3279{
3280    assert((exists|i: int| 0 <= start <= i < stop <= s.len() && s[i] == x) ==> s.subrange(
3281        start,
3282        stop,
3283    ).contains(x)) by {
3284        if exists|i: int| 0 <= start <= i < stop <= s.len() && s[i] == x {
3285            let index = choose|i: int| 0 <= start <= i < stop <= s.len() && s[i] == x;
3286            assert(s.subrange(start, stop)[index - start] == s[index]);
3287        }
3288    }
3289}
3290
3291// Definition of a commutative fold_right operator.
3292pub open spec fn commutative_foldr<A, B>(f: spec_fn(A, B) -> B) -> bool {
3293    forall|x: A, y: A, v: B| #[trigger] f(x, f(y, v)) == f(y, f(x, v))
3294}
3295
3296// Definition of a commutative fold_left operator.
3297pub open spec fn commutative_foldl<A, B>(f: spec_fn(B, A) -> B) -> bool {
3298    forall|x: A, y: A, v: B| #[trigger] f(f(v, x), y) == f(f(v, y), x)
3299}
3300
3301// For a commutative fold_right operator, any folding order
3302// (i.e., any permutation) produces the same result.
3303pub proof fn lemma_fold_right_permutation<A, B>(l1: Seq<A>, l2: Seq<A>, f: spec_fn(A, B) -> B, v: B)
3304    requires
3305        commutative_foldr(f),
3306        l1.to_multiset() == l2.to_multiset(),
3307    ensures
3308        l1.fold_right(f, v) == l2.fold_right(f, v),
3309    decreases l1.len(),
3310{
3311    broadcast use group_to_multiset_ensures;
3312
3313    if l1.len() > 0 {
3314        let a = l1.last();
3315        let i = l2.index_of(a);
3316        let l2r = l2.subrange(i + 1, l2.len() as int).fold_right(f, v);
3317
3318        assert(l1.to_multiset().count(a) > 0);
3319        l1.drop_last().lemma_fold_right_commute_one(a, f, v);
3320        l2.subrange(0, i).lemma_fold_right_commute_one(a, f, l2r);
3321
3322        l2.lemma_fold_right_split(f, v, i + 1);
3323        l2.remove(i).lemma_fold_right_split(f, v, i);
3324
3325        assert(l2.subrange(0, i + 1).drop_last() == l2.subrange(0, i));
3326        assert(l1.drop_last() == l1.remove(l1.len() - 1));
3327
3328        assert(l2.remove(i).subrange(0, i) == l2.subrange(0, i));
3329        assert(l2.remove(i).subrange(i, l2.remove(i).len() as int) == l2.subrange(
3330            i + 1,
3331            l2.len() as int,
3332        ));
3333
3334        lemma_fold_right_permutation(l1.drop_last(), l2.remove(i), f, v);
3335    } else {
3336        assert(l2.to_multiset().len() == 0);
3337    }
3338}
3339
3340// For a commutative fold_left operator, any folding order
3341// (i.e., any permutation) produces the same result.
3342pub proof fn lemma_fold_left_permutation<A, B>(l1: Seq<A>, l2: Seq<A>, f: spec_fn(B, A) -> B, v: B)
3343    requires
3344        commutative_foldl(f),
3345        l1.to_multiset() == l2.to_multiset(),
3346    ensures
3347        l1.fold_left(v, f) == l2.fold_left(v, f),
3348{
3349    let g = |a: A, b: B| f(b, a);
3350    assert(f =~= |b: B, a: A| g(a, b));
3351    assert(l1.fold_left(v, f) == l1.reverse().fold_right(g, v)) by {
3352        l1.lemma_reverse_fold_right(v, g)
3353    };
3354    assert(l2.fold_left(v, f) == l2.reverse().fold_right(g, v)) by {
3355        l2.lemma_reverse_fold_right(v, g)
3356    };
3357    assert(l1.reverse().to_multiset() =~= l2.reverse().to_multiset()) by {
3358        l1.lemma_reverse_to_multiset();
3359        l2.lemma_reverse_to_multiset();
3360    }
3361    assert(forall|x: A| #[trigger] l1.reverse().contains(x) ==> l1.contains(x));
3362    assert(forall|x: A| #[trigger] l2.reverse().contains(x) ==> l2.contains(x));
3363    lemma_fold_right_permutation(l1.reverse(), l2.reverse(), g, v);
3364}
3365
3366/************************** Lemmas about Take/Skip ***************************/
3367
3368// This verified lemma used to be an axiom in the Dafny prelude
3369/// Taking the first `n` elements of a sequence results in a sequence of length `n`,
3370/// as long as `n` is within the bounds of the original sequence.
3371pub broadcast proof fn lemma_seq_take_len<A>(s: Seq<A>, n: int)
3372    ensures
3373        0 <= n <= s.len() ==> #[trigger] s.take(n).len() == n,
3374{
3375}
3376
3377// This verified lemma used to be an axiom in the Dafny prelude
3378/// The resulting sequence after taking the first `n` elements from sequence `s` contains
3379/// element `x` if and only if `x` is contained in the first `n` elements of `s`.
3380pub broadcast proof fn lemma_seq_take_contains<A>(s: Seq<A>, n: int, x: A)
3381    requires
3382        0 <= n <= s.len(),
3383    ensures
3384        #[trigger] s.take(n).contains(x) <==> (exists|i: int|
3385            0 <= i < n <= s.len() && #[trigger] s[i] == x),
3386{
3387    assert((exists|i: int| 0 <= i < n <= s.len() && #[trigger] s[i] == x) ==> s.take(n).contains(x))
3388        by {
3389        if exists|i: int| 0 <= i < n <= s.len() && #[trigger] s[i] == x {
3390            let index = choose|i: int| 0 <= i < n <= s.len() && #[trigger] s[i] == x;
3391            assert(s.take(n)[index] == s[index]);
3392        }
3393    }
3394}
3395
3396// This verified lemma used to be an axiom in the Dafny prelude
3397/// If `j` is a valid index less than `n`, then the `j`th element of the sequence `s`
3398/// is the same as `j`th element of the sequence after taking the first `n` elements of `s`.
3399pub broadcast proof fn lemma_seq_take_index<A>(s: Seq<A>, n: int, j: int)
3400    ensures
3401        0 <= j < n <= s.len() ==> #[trigger] s.take(n)[j] == s[j],
3402{
3403}
3404
3405pub proof fn subrange_of_matching_take<T>(a: Seq<T>, b: Seq<T>, s: int, e: int, l: int)
3406    requires
3407        a.take(l) == b.take(l),
3408        l <= a.len(),
3409        l <= b.len(),
3410        0 <= s <= e <= l,
3411    ensures
3412        a.subrange(s, e) == b.subrange(s, e),
3413{
3414    assert forall|i| 0 <= i < e - s implies a.subrange(s, e)[i] == b.subrange(s, e)[i] by {
3415        assert(a.subrange(s, e)[i] == a.take(l)[i + s]);
3416        //             assert( b.subrange(s, e)[i] == b.take(l)[i + s] );   // either trigger will do
3417    }
3418    // trigger extn equality (verus issue #1257)
3419
3420    assert(a.subrange(s, e) == b.subrange(s, e));
3421}
3422
3423// This verified lemma used to be an axiom in the Dafny prelude
3424/// Skipping the first `n` elements of a sequence gives a sequence of length `n` less than
3425/// the original sequence's length.
3426pub broadcast proof fn lemma_seq_skip_len<A>(s: Seq<A>, n: int)
3427    ensures
3428        0 <= n <= s.len() ==> #[trigger] s.skip(n).len() == s.len() - n,
3429{
3430}
3431
3432// This verified lemma used to be an axiom in the Dafny prelude
3433/// The resulting sequence after skipping the first `n` elements from sequence `s` contains
3434/// element `x` if and only if `x` is contained in `s` before index `n`.
3435pub broadcast proof fn lemma_seq_skip_contains<A>(s: Seq<A>, n: int, x: A)
3436    requires
3437        0 <= n <= s.len(),
3438    ensures
3439        #[trigger] s.skip(n).contains(x) <==> (exists|i: int|
3440            0 <= n <= i < s.len() && #[trigger] s[i] == x),
3441{
3442    assert((exists|i: int| 0 <= n <= i < s.len() && #[trigger] s[i] == x) ==> s.skip(n).contains(x))
3443        by {
3444        let index = choose|i: int| 0 <= n <= i < s.len() && #[trigger] s[i] == x;
3445        lemma_seq_skip_index(s, n, index - n);
3446    }
3447}
3448
3449// This verified lemma used to be an axiom in the Dafny prelude
3450/// If `j` is a valid index less than `s.len() - n`, then the `j`th element of the sequence
3451/// `s.skip(n)` is the same as the `j+n`th element of the sequence `s`.
3452pub broadcast proof fn lemma_seq_skip_index<A>(s: Seq<A>, n: int, j: int)
3453    ensures
3454        0 <= n && 0 <= j < (s.len() - n) ==> #[trigger] s.skip(n)[j] == s[j + n],
3455{
3456}
3457
3458// This verified lemma used to be an axiom in the Dafny prelude
3459/// If `k` is a valid index between `n` (inclusive) and the length of sequence `s` (exclusive),
3460/// then the `k-n`th element of the sequence `s.skip(n)` is the same as the `k`th element of the
3461/// original sequence `s`.
3462pub broadcast proof fn lemma_seq_skip_index2<A>(s: Seq<A>, n: int, k: int)
3463    ensures
3464        0 <= n <= k < s.len() ==> (#[trigger] s.skip(n))[k - n] == #[trigger] s[k],
3465{
3466}
3467
3468// This verified lemma used to be an axiom in the Dafny prelude
3469/// If `n` is the length of sequence `a`, then taking the first `n` elements of the concatenation
3470/// `a + b` is equivalent to the sequence `a` and skipping the first `n` elements of the concatenation
3471/// `a + b` is equivalent to the sequence `b`.
3472pub broadcast proof fn lemma_seq_append_take_skip<A>(a: Seq<A>, b: Seq<A>, n: int)
3473    ensures
3474        #![trigger (a + b).take(n)]
3475        #![trigger (a + b).skip(n)]
3476        n == a.len() ==> ((a + b).take(n) =~= a && (a + b).skip(n) =~= b),
3477{
3478}
3479
3480/************* Lemmas about the Commutability of Take and Skip with Update ************/
3481
3482// This verified lemma used to be an axiom in the Dafny prelude
3483/// If `i` is in the first `n` indices of sequence `s`, updating sequence `s` at index `i` with
3484/// value `v` and then taking the first `n` elements is equivalent to first taking the first `n`
3485/// elements of `s` and then updating index `i` to value `v`.
3486pub broadcast proof fn lemma_seq_take_update_commut1<A>(s: Seq<A>, i: int, v: A, n: int)
3487    ensures
3488        #![trigger s.update(i, v).take(n)]
3489        0 <= i < n <= s.len() ==> #[trigger] s.update(i, v).take(n) =~= s.take(n).update(i, v),
3490{
3491}
3492
3493// This verified lemma used to be an axiom in the Dafny prelude
3494/// If `i` is a valid index after the first `n` indices of sequence `s`, updating sequence `s` at
3495/// index `i` with value `v` and then taking the first `n` elements is equivalent to just taking the first `n`
3496/// elements of `s` without the update.
3497pub broadcast proof fn lemma_seq_take_update_commut2<A>(s: Seq<A>, i: int, v: A, n: int)
3498    ensures
3499        0 <= n <= i < s.len() ==> #[trigger] s.update(i, v).take(n) =~= s.take(n),
3500{
3501}
3502
3503// This verified lemma used to be an axiom in the Dafny prelude
3504/// If `i` is a valid index after the first `n` indices of sequence `s`, updating sequence `s` at
3505/// index `i` with value `v` and then skipping the first `n` elements is equivalent to skipping the first `n`
3506/// elements of `s` and then updating index `i-n` to value `v`.
3507pub broadcast proof fn lemma_seq_skip_update_commut1<A>(s: Seq<A>, i: int, v: A, n: int)
3508    ensures
3509        0 <= n <= i < s.len() ==> #[trigger] s.update(i, v).skip(n) =~= s.skip(n).update(i - n, v),
3510{
3511}
3512
3513// This verified lemma used to be an axiom in the Dafny prelude
3514/// If `i` is a valid index in the first `n` indices of sequence `s`, updating sequence `s` at
3515/// index `i` with value `v` and then skipping the first `n` elements is equivalent to just skipping
3516/// the first `n` elements without the update.
3517pub broadcast proof fn lemma_seq_skip_update_commut2<A>(s: Seq<A>, i: int, v: A, n: int)
3518    ensures
3519        0 <= i < n <= s.len() ==> #[trigger] s.update(i, v).skip(n) =~= s.skip(n),
3520{
3521}
3522
3523// This verified lemma used to be an axiom in the Dafny prelude
3524/// Pushing element `v` onto the end of sequence `s` and then skipping the first `n` elements is
3525/// equivalent to skipping the first `n` elements of `s` and then pushing `v` onto the end.
3526pub broadcast proof fn lemma_seq_skip_build_commut<A>(s: Seq<A>, v: A, n: int)
3527    ensures
3528        #![trigger s.push(v).skip(n)]
3529        0 <= n <= s.len() ==> s.push(v).skip(n) =~= s.skip(n).push(v),
3530{
3531}
3532
3533// This verified lemma used to be an axiom in the Dafny prelude
3534/// `s.skip(0)` is equivalent to `s`.
3535pub broadcast proof fn lemma_seq_skip_nothing<A>(s: Seq<A>, n: int)
3536    ensures
3537        n == 0 ==> #[trigger] s.skip(n) =~= s,
3538{
3539}
3540
3541// This verified lemma used to be an axiom in the Dafny prelude
3542/// `s.take(0)` is equivalent to the empty sequence.
3543pub broadcast proof fn lemma_seq_take_nothing<A>(s: Seq<A>, n: int)
3544    ensures
3545        n == 0 ==> #[trigger] s.take(n) =~= Seq::<A>::empty(),
3546{
3547}
3548
3549// This verified lemma used to be an axiom in the Dafny prelude
3550/// If `m + n` is less than or equal to the length of sequence `s`, then skipping the first `m` elements
3551/// and then skipping the first `n` elements of the resulting sequence is equivalent to just skipping
3552/// the first `m + n` elements.
3553pub broadcast proof fn lemma_seq_skip_of_skip<A>(s: Seq<A>, m: int, n: int)
3554    ensures
3555        (0 <= m && 0 <= n && m + n <= s.len()) ==> #[trigger] s.skip(m).skip(n) =~= s.skip(m + n),
3556{
3557}
3558
3559#[doc(hidden)]
3560#[verifier::inline]
3561pub open spec fn check_argument_is_seq<A>(s: Seq<A>) -> Seq<A> {
3562    s
3563}
3564
3565/// Prove two sequences `s1` and `s2` are equal by proving that their elements are equal at each index.
3566///
3567/// More precisely, `assert_seqs_equal!` requires:
3568///  * `s1` and `s2` have the same length (`s1.len() == s2.len()`), and
3569///  * for all `i` in the range `0 <= i < s1.len()`, we have `s1[i] == s2[i]`.
3570///
3571/// The property that equality follows from these facts is often called _extensionality_.
3572///
3573/// `assert_seqs_equal!` can handle many trivial-looking
3574/// identities without any additional help:
3575///
3576/// ```rust
3577/// proof fn subrange_concat(s: Seq<u64>, i: int) {
3578///     requires([
3579///         0 <= i && i <= s.len(),
3580///     ]);
3581///
3582///     let t1 = s.subrange(0, i);
3583///     let t2 = s.subrange(i, s.len());
3584///     let t = t1.add(t2);
3585///
3586///     assert_seqs_equal!(s == t);
3587///
3588///     assert(s == t);
3589/// }
3590/// ```
3591///
3592/// In more complex cases, a proof may be required for the equality of each element pair.
3593/// For example,
3594///
3595/// ```rust
3596/// proof fn bitvector_seqs() {
3597///     let s = Seq::<u64>::new(5, |i| i as u64);
3598///     let t = Seq::<u64>::new(5, |i| i as u64 | 0);
3599///
3600///     assert_seqs_equal!(s == t, i => {
3601///         // Need to show that s[i] == t[i]
3602///         // Prove that the elements are equal by appealing to a bitvector solver:
3603///         let j = i as u64;
3604///         assert_bit_vector(j | 0 == j);
3605///         assert(s[i] == t[i]);
3606///     });
3607/// }
3608/// ```
3609#[macro_export]
3610macro_rules! assert_seqs_equal {
3611    [$($tail:tt)*] => {
3612        $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::seq_lib::assert_seqs_equal_internal!($($tail)*))
3613    };
3614}
3615
3616#[macro_export]
3617#[doc(hidden)]
3618macro_rules! assert_seqs_equal_internal {
3619    (::vstd::spec_eq($s1:expr, $s2:expr)) => {
3620        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2)
3621    };
3622    (::vstd::prelude::spec_eq($s1:expr, $s2:expr)) => {
3623        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2)
3624    };
3625    (::vstd::prelude::spec_eq($s1:expr, $s2:expr), $idx:ident => $bblock:block) => {
3626        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2, $idx => $bblock)
3627    };
3628    (crate::prelude::spec_eq($s1:expr, $s2:expr)) => {
3629        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2)
3630    };
3631    (crate::prelude::spec_eq($s1:expr, $s2:expr), $idx:ident => $bblock:block) => {
3632        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2, $idx => $bblock)
3633    };
3634    (crate::verus_builtin::spec_eq($s1:expr, $s2:expr)) => {
3635        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2)
3636    };
3637    (crate::verus_builtin::spec_eq($s1:expr, $s2:expr), $idx:ident => $bblock:block) => {
3638        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2, $idx => $bblock)
3639    };
3640    ($s1:expr, $s2:expr $(,)?) => {
3641        $crate::vstd::seq_lib::assert_seqs_equal_internal!($s1, $s2, idx => { })
3642    };
3643    ($s1:expr, $s2:expr, $idx:ident => $bblock:block) => {
3644        #[verifier::spec] let s1 = $crate::vstd::seq_lib::check_argument_is_seq($s1);
3645        #[verifier::spec] let s2 = $crate::vstd::seq_lib::check_argument_is_seq($s2);
3646        $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(s1, s2), {
3647            $crate::vstd::prelude::assert_(s1.len() == s2.len());
3648            $crate::vstd::prelude::assert_forall_by(|$idx : $crate::vstd::prelude::int| {
3649                $crate::vstd::prelude::requires($crate::vstd::prelude::verus_proof_expr!(0 <= $idx && $idx < s1.len()));
3650                $crate::vstd::prelude::ensures($crate::vstd::prelude::equal(s1.index($idx), s2.index($idx)));
3651                { $bblock }
3652            });
3653            $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(s1, s2));
3654        });
3655    }
3656}
3657
3658pub broadcast group group_filter_ensures {
3659    Seq::lemma_filter_len,
3660    Seq::lemma_filter_pred,
3661    Seq::lemma_filter_contains,
3662}
3663
3664pub broadcast group group_seq_lib_default {
3665    group_filter_ensures,
3666    Seq::add_empty_left,
3667    Seq::add_empty_right,
3668    Seq::push_distributes_over_add,
3669    Seq::filter_distributes_over_add,
3670    seq_to_set_is_finite,
3671    Seq::lemma_fold_right_split,
3672    Seq::lemma_fold_left_split,
3673}
3674
3675pub broadcast group group_to_multiset_ensures {
3676    to_multiset_build,
3677    to_multiset_remove,
3678    to_multiset_len,
3679    to_multiset_contains,
3680    to_multiset_insert,
3681    to_multiset_update,
3682}
3683
3684// include all the Dafny prelude lemmas
3685pub broadcast group group_seq_properties {
3686    lemma_seq_contains,
3687    lemma_seq_empty_contains_nothing,
3688    lemma_seq_empty_equality,
3689    lemma_seq_concat_contains_all_elements,
3690    lemma_seq_contains_after_push,
3691    lemma_seq_subrange_elements,
3692    lemma_seq_take_len,
3693    lemma_seq_take_contains,
3694    lemma_seq_take_index,
3695    lemma_seq_skip_len,
3696    lemma_seq_skip_contains,
3697    lemma_seq_skip_index,
3698    lemma_seq_skip_index2,
3699    lemma_seq_append_take_skip,
3700    lemma_seq_take_update_commut1,
3701    lemma_seq_take_update_commut2,
3702    lemma_seq_skip_update_commut1,
3703    lemma_seq_skip_update_commut2,
3704    lemma_seq_skip_build_commut,
3705    lemma_seq_skip_nothing,
3706    lemma_seq_take_nothing,
3707    // Removed the following from group due to bad verification performance
3708    // for `lemma_merge_sorted_with_ensures`
3709    // lemma_seq_skip_of_skip,
3710    group_to_multiset_ensures,
3711}
3712
3713#[doc(hidden)]
3714pub use assert_seqs_equal_internal;
3715pub use assert_seqs_equal;
3716
3717} // verus!