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