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