Skip to main content

vstd/
seq_lib.rs

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