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