pub struct Seq<A> { /* private fields */ }
Expand description
Seq<A>
is a sequence type for specifications.
To use a “sequence” in compiled code, use an exec
type like vec::Vec
that has Seq<A>
as its specification type.
An object seq: Seq<A>
has a length, given by seq.len()
,
and a value at each i
for 0 <= i < seq.len()
, given by seq[i]
.
Sequences can be constructed in a few different ways:
Seq::empty
construct an empty sequence (len() == 0
)Seq::new
construct a sequence of a given length, initialized according to a given function mapping indicesi
to valuesA
.- The
seq!
macro, to construct small sequences of a fixed size (analagous to thestd::vec!
macro). - By manipulating an existing sequence with
Seq::push
,Seq::update
, orSeq::add
.
To prove that two sequences are equal, it is usually easiest to use the
extensional equality operator =~=
.
Implementations§
source§impl<A> Seq<A>
impl<A> Seq<A>
sourcepub spec fn new(len: nat, f: impl Fn(int) -> A) -> Seq<A>
pub spec fn new(len: nat, f: impl Fn(int) -> A) -> Seq<A>
Construct a sequence s
of length len
where entry s[i]
is given by f(i)
.
sourcepub spec fn index(self, i: int) -> A
pub spec fn index(self, i: int) -> A
0 <= i < self.len(),
Gets the value at the given index i
.
If i
is not in the range [0, self.len())
, then the resulting value
is meaningless and arbitrary.
sourcepub open spec fn spec_index(self, i: int) -> A
pub open spec fn spec_index(self, i: int) -> A
0 <= i < self.len(),
{ self.index(i) }
[]
operator, synonymous with index
sourcepub spec fn push(self, a: A) -> Seq<A>
pub spec fn push(self, a: A) -> Seq<A>
Appends the value a
to the end of the sequence.
This always increases the length of the sequence by 1.
This often requires annotating the type of the element literal in the sequence,
e.g., 10int
.
§Example
proof fn push_test() {
assert(seq![10int, 11, 12].push(13) =~= seq![10, 11, 12, 13]);
}
sourcepub spec fn update(self, i: int, a: A) -> Seq<A>
pub spec fn update(self, i: int, a: A) -> Seq<A>
0 <= i < self.len(),
Updates the sequence at the given index, replacing the element with the given value, and leaves all other entries unchanged.
§Example
proof fn update_test() {
let s = seq![10, 11, 12, 13, 14];
let t = s.update(2, -5);
assert(t =~= seq![10, 11, -5, 13, 14]);
}
sourcepub open spec fn ext_equal(self, s2: Seq<A>) -> bool
👎Deprecated: use =~= or =~~= instead
pub open spec fn ext_equal(self, s2: Seq<A>) -> bool
{ self =~= s2 }
DEPRECATED: use =~= or =~~= instead.
Returns true
if the two sequences are pointwise equal, i.e.,
they have the same length and the corresponding values are equal
at each index. This is equivalent to the sequences being actually equal
by axiom_seq_ext_equal
.
To prove that two sequences are equal via extensionality, it may be easier
to use the general-purpose =~=
or =~~=
or
to use the assert_seqs_equal!
macro,
rather than using .ext_equal
directly.
sourcepub spec fn subrange(self, start_inclusive: int, end_exclusive: int) -> Seq<A>
pub spec fn subrange(self, start_inclusive: int, end_exclusive: int) -> Seq<A>
0 <= start_inclusive <= end_exclusive <= self.len(),
Returns a sequence for the given subrange.
§Example
proof fn subrange_test() {
let s = seq![10int, 11, 12, 13, 14];
// ^-------^
// 0 1 2 3 4 5
let sub = s.subrange(2, 4);
assert(sub =~= seq![12, 13]);
}
sourcepub open spec fn take(self, n: int) -> Seq<A>
pub open spec fn take(self, n: int) -> Seq<A>
{ self.subrange(0, n) }
Returns a sequence containing only the first n elements of the original sequence
sourcepub open spec fn skip(self, n: int) -> Seq<A>
pub open spec fn skip(self, n: int) -> Seq<A>
{ self.subrange(n, self.len() as int) }
Returns a sequence without the first n elements of the original sequence
sourcepub spec fn add(self, rhs: Seq<A>) -> Seq<A>
pub spec fn add(self, rhs: Seq<A>) -> Seq<A>
Concatenates the sequences.
§Example
proof fn add_test() {
assert(seq![10int, 11].add(seq![12, 13, 14])
=~= seq![10, 11, 12, 13, 14]);
}
sourcepub open spec fn spec_add(self, rhs: Seq<A>) -> Seq<A>
pub open spec fn spec_add(self, rhs: Seq<A>) -> Seq<A>
{ self.add(rhs) }
+
operator, synonymous with add
source§impl<A> Seq<A>
impl<A> Seq<A>
sourcepub open spec fn map<B>(self, f: FnSpec<(int, A), B>) -> Seq<B>
pub open spec fn map<B>(self, f: FnSpec<(int, A), B>) -> Seq<B>
{ Seq::new(self.len(), |i: int| f(i, self[i])) }
Applies the function f
to each element of the sequence, and returns
the resulting sequence.
The int
parameter of f
is the index of the element being mapped.
sourcepub open spec fn map_values<B>(self, f: FnSpec<(A,), B>) -> Seq<B>
pub open spec fn map_values<B>(self, f: FnSpec<(A,), B>) -> Seq<B>
{ Seq::new(self.len(), |i: int| f(self[i])) }
Applies the function f
to each element of the sequence, and returns
the resulting sequence.
sourcepub open spec fn is_prefix_of(self, other: Self) -> bool
pub open spec fn is_prefix_of(self, other: Self) -> bool
{ self.len() <= other.len() && self =~= other.subrange(0, self.len() as int) }
Is true if the calling sequence is a prefix of the given sequence ‘other’.
§Example
proof fn prefix_test() {
let pre: Seq<int> = seq![1, 2, 3];
let whole: Seq<int> = seq![1, 2, 3, 4, 5];
assert(pre.is_prefix_of(whole));
}
sourcepub open spec fn is_suffix_of(self, other: Self) -> bool
pub open spec fn is_suffix_of(self, other: Self) -> bool
{
self.len() <= other.len()
&& self =~= other.subrange((other.len() - self.len()) as int, other.len() as int)
}
Is true if the calling sequence is a suffix of the given sequence ‘other’.
§Example
proof fn suffix_test() {
let end: Seq<int> = seq![3, 4, 5];
let whole: Seq<int> = seq![1, 2, 3, 4, 5];
assert(end.is_suffix_of(whole));
}
sourcepub closed spec fn sort_by(self, leq: FnSpec<(A, A), bool>) -> Seq<A>
pub closed spec fn sort_by(self, leq: FnSpec<(A, A), bool>) -> Seq<A>
total_ordering(leq),
Sorts the sequence according to the given leq function
§Example
{{#include ../../../rust_verify/example/multiset.rs:sorted_by_leq}}
sourcepub proof fn lemma_sort_by_ensures(self, leq: FnSpec<(A, A), bool>)
pub proof fn lemma_sort_by_ensures(self, leq: FnSpec<(A, A), bool>)
total_ordering(leq),
ensuresself.to_multiset() =~= self.sort_by(leq).to_multiset(),
sorted_by(self.sort_by(leq), leq),
forall |x: A| !self.contains(x) ==> !(#[trigger] self.sort_by(leq).contains(x)),
sourcepub open spec fn filter(self, pred: FnSpec<(A,), bool>) -> Self
pub open spec fn filter(self, pred: FnSpec<(A,), bool>) -> Self
{
if self.len() == 0 {
self
} else {
let subseq = self.drop_last().filter(pred);
if pred(self.last()) { subseq.push(self.last()) } else { subseq }
}
}
Returns the sequence containing only the elements of the original sequence such that pred(element) is true.
§Example
proof fn filter_test() {
let seq: Seq<int> = seq![1, 2, 3, 4, 5];
let even: Seq<int> = seq.filter(|x| x % 2 == 0);
reveal_with_fuel(Seq::<int>::filter, 6); //Needed for Verus to unfold the recursive definition of filter
assert(even =~= seq![2, 4]);
}
sourcepub broadcast proof fn filter_lemma(self, pred: FnSpec<(A,), bool>)
pub broadcast proof fn filter_lemma(self, pred: FnSpec<(A,), bool>)
forall |i: int| {
0 <= i < self.filter(pred).len() ==> pred(#[trigger] self.filter(pred)[i])
},
forall |i: int| {
0 <= i < self.len() && pred(self[i]) ==> #[trigger]
self.filter(pred).contains(self[i])
},
#[trigger] self.filter(pred).len() <= self.len(),
sourcepub broadcast proof fn filter_distributes_over_add(a: Self, b: Self, pred: FnSpec<(A,), bool>)
pub broadcast proof fn filter_distributes_over_add(a: Self, b: Self, pred: FnSpec<(A,), bool>)
#[trigger] (a + b).filter(pred) == a.filter(pred) + b.filter(pred),
sourcepub broadcast proof fn add_empty_left(a: Self, b: Self)
pub broadcast proof fn add_empty_left(a: Self, b: Self)
a.len() == 0,
ensures#[trigger] (a + b) == b,
sourcepub broadcast proof fn add_empty_right(a: Self, b: Self)
pub broadcast proof fn add_empty_right(a: Self, b: Self)
b.len() == 0,
ensures#[trigger] (a + b) == a,
sourcepub broadcast proof fn push_distributes_over_add(a: Self, b: Self, elt: A)
pub broadcast proof fn push_distributes_over_add(a: Self, b: Self, elt: A)
#[trigger] (a + b).push(elt) == a + b.push(elt),
sourcepub open spec fn max_via(self, leq: FnSpec<(A, A), bool>) -> A
pub open spec fn max_via(self, leq: FnSpec<(A, A), bool>) -> A
self.len() > 0,
{
if self.len() > 1 {
if leq(self[0], self.subrange(1, self.len() as int).max_via(leq)) {
self.subrange(1, self.len() as int).max_via(leq)
} else {
self[0]
}
} else {
self[0]
}
}
Returns the maximum value in a non-empty sequence, given sorting function leq
sourcepub open spec fn min_via(self, leq: FnSpec<(A, A), bool>) -> A
pub open spec fn min_via(self, leq: FnSpec<(A, A), bool>) -> A
self.len() > 0,
{
if self.len() > 1 {
let subseq = self.subrange(1, self.len() as int);
let elt = subseq.min_via(leq);
if leq(elt, self[0]) { elt } else { self[0] }
} else {
self[0]
}
}
Returns the minimum value in a non-empty sequence, given sorting function leq
sourcepub open spec fn contains(self, needle: A) -> bool
pub open spec fn contains(self, needle: A) -> bool
{ exists |i: int| 0 <= i < self.len() && self[i] == needle }
sourcepub open spec fn index_of(self, needle: A) -> int
pub open spec fn index_of(self, needle: A) -> int
{ choose |i: int| 0 <= i < self.len() && self[i] == needle }
Returns an index where needle
appears in the sequence.
Returns an arbitrary value if the sequence does not contain the needle
.
sourcepub closed spec fn index_of_first(self, needle: A) -> result : Option<int>
pub closed spec fn index_of_first(self, needle: A) -> result : Option<int>
For an element that occurs at least once in a sequence, if its first occurence is at index i, Some(i) is returned. Otherwise, None is returned
sourcepub proof fn index_of_first_ensures(self, needle: A)
pub proof fn index_of_first_ensures(self, needle: A)
match self.index_of_first(needle) {
Some(index) => {
&&& self.contains(needle)
&&& 0 <= index < self.len()
&&& self[index] == needle
&&& forall |j: int| 0 <= j < index < self.len() ==> self[j] != needle
}
None => !self.contains(needle),
},
sourcepub closed spec fn index_of_last(self, needle: A) -> Option<int>
pub closed spec fn index_of_last(self, needle: A) -> Option<int>
For an element that occurs at least once in a sequence, if its last occurence is at index i, Some(i) is returned. Otherwise, None is returned
sourcepub proof fn index_of_last_ensures(self, needle: A)
pub proof fn index_of_last_ensures(self, needle: A)
match self.index_of_last(needle) {
Some(index) => {
&&& self.contains(needle)
&&& 0 <= index < self.len()
&&& self[index] == needle
&&& forall |j: int| 0 <= index < j < self.len() ==> self[j] != needle
}
None => !self.contains(needle),
},
sourcepub open spec fn drop_last(self) -> Seq<A>
pub open spec fn drop_last(self) -> Seq<A>
self.len() >= 1,
{ self.subrange(0, self.len() as int - 1) }
Drops the last element of a sequence and returns a sequence whose length is thereby 1 smaller.
If the input sequence is empty, the result is meaningless and arbitrary.
sourcepub proof fn drop_last_distributes_over_add(a: Self, b: Self)
pub proof fn drop_last_distributes_over_add(a: Self, b: Self)
0 < b.len(),
ensures(a + b).drop_last() == a + b.drop_last(),
Dropping the last element of a concatenation of a
and b
is equivalent
to skipping the last element of b
and then concatenating a
and b
sourcepub open spec fn drop_first(self) -> Seq<A>
pub open spec fn drop_first(self) -> Seq<A>
self.len() >= 1,
{ self.subrange(1, self.len() as int) }
sourcepub open spec fn no_duplicates(self) -> bool
pub open spec fn no_duplicates(self) -> bool
{
forall |i, j| {
(0 <= i < self.len() && 0 <= j < self.len() && i != j) ==> self[i] != self[j]
}
}
returns true
if the sequence has no duplicate elements
sourcepub open spec fn disjoint(self, other: Self) -> bool
pub open spec fn disjoint(self, other: Self) -> bool
{
forall |i: int, j: int| {
0 <= i < self.len() && 0 <= j < other.len() ==> self[i] != other[j]
}
}
Returns true
if two sequences are disjoint
sourcepub open spec fn to_set(self) -> Set<A>
pub open spec fn to_set(self) -> Set<A>
{ Set::new(|a: A| self.contains(a)) }
Converts a sequence into a set
sourcepub closed spec fn to_multiset(self) -> Multiset<A>
pub closed spec fn to_multiset(self) -> Multiset<A>
Converts a sequence into a multiset
sourcepub proof fn to_multiset_ensures(self)
pub proof fn to_multiset_ensures(self)
forall |a: A| #[trigger] (self.push(a).to_multiset()) =~= self.to_multiset().insert(a),
forall |i: int| {
0 <= i < self.len()
==> #[trigger] (self.remove(i).to_multiset())
=~= self.to_multiset().remove(self[i])
},
self.len() == self.to_multiset().len(),
forall |a: A| self.contains(a) <==> #[trigger] self.to_multiset().count(a) > 0,
Proof of function to_multiset() correctness
sourcepub open spec fn insert(self, i: int, a: A) -> Seq<A>
pub open spec fn insert(self, i: int, a: A) -> Seq<A>
0 <= i <= self.len(),
{ self.subrange(0, i).push(a) + self.subrange(i, self.len() as int) }
Insert item a at index i, shifting remaining elements (if any) to the right
sourcepub proof fn insert_ensures(self, pos: int, elt: A)
pub proof fn insert_ensures(self, pos: int, elt: A)
0 <= pos <= self.len(),
ensuresself.insert(pos, elt).len() == self.len() + 1,
forall |i: int| 0 <= i < pos ==> #[trigger] self.insert(pos, elt)[i] == self[i],
forall |i: int| pos <= i < self.len() ==> self.insert(pos, elt)[i + 1] == self[i],
self.insert(pos, elt)[pos] == elt,
Proof of correctness and expected properties of insert function
sourcepub open spec fn remove(self, i: int) -> Seq<A>
pub open spec fn remove(self, i: int) -> Seq<A>
0 <= i < self.len(),
{ self.subrange(0, i) + self.subrange(i + 1, self.len() as int) }
Remove item at index i, shifting remaining elements to the left
sourcepub proof fn remove_ensures(self, i: int)
pub proof fn remove_ensures(self, i: int)
0 <= i < self.len(),
ensuresself.remove(i).len() == self.len() - 1,
forall |index: int| 0 <= index < i ==> #[trigger] self.remove(i)[index] == self[index],
forall |index: int| {
i <= index < self.len() - 1 ==> #[trigger] self.remove(i)[index] == self[index + 1]
},
Proof of function remove() correctness
sourcepub open spec fn remove_value(self, val: A) -> Seq<A>
pub open spec fn remove_value(self, val: A) -> Seq<A>
{
let index = self.index_of_first(val);
match index {
Some(i) => self.remove(i),
None => self,
}
}
If a given element occurs at least once in a sequence, the sequence without its first occurrence is returned. Otherwise the same sequence is returned.
sourcepub open spec fn reverse(self) -> Seq<A>
pub open spec fn reverse(self) -> Seq<A>
{
if self.len() == 0 {
Seq::empty()
} else {
Seq::new(self.len(), |i: int| self[self.len() - 1 - i])
}
}
Returns the sequence that is in reverse order to a given sequence.
sourcepub open spec fn zip_with<B>(self, other: Seq<B>) -> Seq<(A, B)>
pub open spec fn zip_with<B>(self, other: Seq<B>) -> Seq<(A, B)>
self.len() == other.len(),
{
if self.len() != other.len() {
Seq::empty()
} else if self.len() == 0 {
Seq::empty()
} else {
Seq::new(self.len(), |i: int| (self[i], other[i]))
}
}
Zips two sequences of equal length into one sequence that consists of pairs. If the two sequences are different lengths, returns an empty sequence
sourcepub open spec fn fold_left<B>(self, b: B, f: FnSpec<(B, A), B>) -> res : B
pub open spec fn fold_left<B>(self, b: B, f: FnSpec<(B, A), B>) -> res : B
{ if self.len() == 0 { b } else { f(self.drop_last().fold_left(b, f), self.last()) } }
Folds the sequence to the left, applying f
to perform the fold.
Equivalent to Iterator::fold
in Rust.
Given a sequence s = [x0, x1, x2, ..., xn]
, applying this function s.fold_left(b, f)
returns f(...f(f(b, x0), x1), ..., xn)
.
sourcepub open spec fn fold_left_alt<B>(self, b: B, f: FnSpec<(B, A), B>) -> res : B
pub open spec fn fold_left_alt<B>(self, b: B, f: FnSpec<(B, A), B>) -> res : B
{
if self.len() == 0 {
b
} else {
self.subrange(1, self.len() as int).fold_left_alt(f(b, self[0]), f)
}
}
Equivalent to Self::fold_left
but defined by breaking off the leftmost element when
recursing, rather than the rightmost. See Self::lemma_fold_left_alt
that proves
equivalence.
sourcepub proof fn lemma_fold_left_alt<B>(self, b: B, f: FnSpec<(B, A), B>)
pub proof fn lemma_fold_left_alt<B>(self, b: B, f: FnSpec<(B, A), B>)
self.fold_left(b, f) == self.fold_left_alt(b, f),
Self::fold_left
and Self::fold_left_alt
are equivalent.
sourcepub open spec fn fold_right<B>(self, f: FnSpec<(A, B), B>, b: B) -> res : B
pub open spec fn fold_right<B>(self, f: FnSpec<(A, B), B>, b: B) -> res : B
{ if self.len() == 0 { b } else { self.drop_last().fold_right(f, f(self.last(), b)) } }
Folds the sequence to the right, applying f
to perform the fold.
Equivalent to DoubleEndedIterator::rfold
in Rust.
Given a sequence s = [x0, x1, x2, ..., xn]
, applying this function s.fold_right(b, f)
returns f(x0, f(x1, f(x2, ..., f(xn, b)...)))
.
sourcepub open spec fn fold_right_alt<B>(self, f: FnSpec<(A, B), B>, b: B) -> res : B
pub open spec fn fold_right_alt<B>(self, f: FnSpec<(A, B), B>, b: B) -> res : B
{
if self.len() == 0 {
b
} else {
f(self[0], self.subrange(1, self.len() as int).fold_right_alt(f, b))
}
}
Equivalent to Self::fold_right
but defined by breaking off the leftmost element when
recursing, rather than the rightmost. See Self::lemma_fold_right_alt
that proves
equivalence.
sourcepub proof fn lemma_fold_right_split<B>(self, f: FnSpec<(A, B), B>, b: B, k: int)
pub proof fn lemma_fold_right_split<B>(self, f: FnSpec<(A, B), B>, b: B, k: int)
0 <= k <= self.len(),
ensuresself.subrange(0, k).fold_right(f, self.subrange(k, self.len() as int).fold_right(f, b))
== self.fold_right(f, b),
A lemma that proves how Self::fold_right
distributes over splitting a sequence.
sourcepub proof fn lemma_fold_right_commute_one<B>(self, a: A, f: FnSpec<(A, B), B>, v: B)
pub proof fn lemma_fold_right_commute_one<B>(self, a: A, f: FnSpec<(A, B), B>, v: B)
commutative_foldr(f),
ensuresself.fold_right(f, f(a, v)) == f(a, self.fold_right(f, v)),
sourcepub proof fn lemma_fold_right_alt<B>(self, f: FnSpec<(A, B), B>, b: B)
pub proof fn lemma_fold_right_alt<B>(self, f: FnSpec<(A, B), B>, b: B)
self.fold_right(f, b) == self.fold_right_alt(f, b),
Self::fold_right
and Self::fold_right_alt
are equivalent.
sourcepub proof fn lemma_multiset_has_no_duplicates(self)
pub proof fn lemma_multiset_has_no_duplicates(self)
self.no_duplicates(),
ensuresforall |x: A| self.to_multiset().contains(x) ==> self.to_multiset().count(x) == 1,
Given a sequence with no duplicates, each element occurs only once in its conversion to a multiset
sourcepub proof fn lemma_multiset_has_no_duplicates_conv(self)
pub proof fn lemma_multiset_has_no_duplicates_conv(self)
forall |x: A| self.to_multiset().contains(x) ==> self.to_multiset().count(x) == 1,
ensuresself.no_duplicates(),
If, in a sequence’s conversion to a multiset, each element occurs only once, the sequence has no duplicates.
sourcepub proof fn lemma_add_last_back(self)
pub proof fn lemma_add_last_back(self)
0 < self.len(),
ensures#[trigger] self.drop_last().push(self.last()) =~= self,
The concatenation of two subsequences derived from a non-empty sequence, the first obtained from skipping the last element, the second consisting only of the last element, is the original sequence.
sourcepub proof fn lemma_indexing_implies_membership(self, f: FnSpec<(A,), bool>)
pub proof fn lemma_indexing_implies_membership(self, f: FnSpec<(A,), bool>)
forall |i: int| 0 <= i < self.len() ==> #[trigger] f(#[trigger] self[i]),
ensuresforall |x: A| #[trigger] self.contains(x) ==> #[trigger] f(x),
If a predicate is true at every index of a sequence, it is true for every member of the sequence as a collection. Useful for converting quantifiers between the two forms to satisfy a precondition in the latter form.
sourcepub proof fn lemma_membership_implies_indexing(self, f: FnSpec<(A,), bool>)
pub proof fn lemma_membership_implies_indexing(self, f: FnSpec<(A,), bool>)
forall |x: A| #[trigger] self.contains(x) ==> #[trigger] f(x),
ensuresforall |i: int| 0 <= i < self.len() ==> #[trigger] f(self[i]),
If a predicate is true for every member of a sequence as a collection, it is true at every index of the sequence. Useful for converting quantifiers between the two forms to satisfy a precondition in the latter form.
sourcepub proof fn lemma_split_at(self, pos: int)
pub proof fn lemma_split_at(self, pos: int)
0 <= pos <= self.len(),
ensuresself.subrange(0, pos) + self.subrange(pos, self.len() as int) =~= self,
A sequence that is sliced at the pos-th element, concatenated with that same sequence sliced from the pos-th element, is equal to the original unsliced sequence.
sourcepub proof fn lemma_element_from_slice(self, new: Seq<A>, a: int, b: int, pos: int)
pub proof fn lemma_element_from_slice(self, new: Seq<A>, a: int, b: int, pos: int)
0 <= a <= b <= self.len(),
new == self.subrange(a, b),
a <= pos < b,
ensurespos - a < new.len(),
new[pos - a] == self[pos],
Any element in a slice is included in the original sequence.
sourcepub proof fn lemma_slice_of_slice(self, s1: int, e1: int, s2: int, e2: int)
pub proof fn lemma_slice_of_slice(self, s1: int, e1: int, s2: int, e2: int)
0 <= s1 <= e1 <= self.len(),
0 <= s2 <= e2 <= e1 - s1,
ensuresself.subrange(s1, e1).subrange(s2, e2) =~= self.subrange(s1 + s2, s1 + e2),
A slice (from s2..e2) of a slice (from s1..e1) of a sequence is equal to just a slice (s1+s2..s1+e2) of the original sequence.
sourcepub proof fn unique_seq_to_set(self)
pub proof fn unique_seq_to_set(self)
self.no_duplicates(),
ensuresself.len() == self.to_set().len(),
A sequence of unique items, when converted to a set, produces a set with matching length
sourcepub proof fn lemma_cardinality_of_set(self)
pub proof fn lemma_cardinality_of_set(self)
self.to_set().len() <= self.len(),
The cardinality of a set of elements is always less than or equal to that of the full sequence of elements.
sourcepub proof fn lemma_cardinality_of_empty_set_is_0(self)
pub proof fn lemma_cardinality_of_empty_set_is_0(self)
self.to_set().len() == 0 <==> self.len() == 0,
A sequence is of length 0 if and only if its conversion to a set results in the empty set.
sourcepub proof fn lemma_no_dup_set_cardinality(self)
pub proof fn lemma_no_dup_set_cardinality(self)
self.to_set().len() == self.len(),
ensuresself.no_duplicates(),
A sequence with cardinality equal to its set has no duplicates. Inverse property of that shown in lemma unique_seq_to_set
source§impl<A, B> Seq<(A, B)>
impl<A, B> Seq<(A, B)>
sourcepub closed spec fn unzip(self) -> (Seq<A>, Seq<B>)
pub closed spec fn unzip(self) -> (Seq<A>, Seq<B>)
Unzips a sequence that contains pairs into two separate sequences.
sourcepub proof fn unzip_ensures(self)
pub proof fn unzip_ensures(self)
self.unzip().0.len() == self.unzip().1.len(),
self.unzip().0.len() == self.len(),
self.unzip().1.len() == self.len(),
forall |i: int| {
0 <= i < self.len()
==> (#[trigger] self.unzip().0[i], #[trigger] self.unzip().1[i]) == self[i]
},
Proof of correctness and expected properties of unzip function
sourcepub proof fn lemma_zip_of_unzip(self)
pub proof fn lemma_zip_of_unzip(self)
self.unzip().0.zip_with(self.unzip().1) =~= self,
Unzipping a sequence of sequences and then zipping the resulting two sequences back together results in the original sequence of sequences.
source§impl<A> Seq<Seq<A>>
impl<A> Seq<Seq<A>>
sourcepub open spec fn flatten(self) -> Seq<A>
pub open spec fn flatten(self) -> Seq<A>
{
if self.len() == 0 {
Seq::empty()
} else {
self.first().add(self.drop_first().flatten())
}
}
Flattens a sequence of sequences into a single sequence by concatenating subsequences, starting from the first element.
§Example
proof fn flatten_test() {
let seq: Seq<Seq<int>> = seq![seq![1, 2, 3], seq![4, 5, 6], seq![7, 8, 9]];
let flat: Seq<int> = seq.flatten();
reveal_with_fuel(Seq::<Seq<int>>::flatten, 5); //Needed for Verus to unfold the recursive definition of flatten
assert(flat =~= seq![1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
sourcepub open spec fn flatten_alt(self) -> Seq<A>
pub open spec fn flatten_alt(self) -> Seq<A>
{
if self.len() == 0 {
Seq::empty()
} else {
self.drop_last().flatten_alt().add(self.last())
}
}
Flattens a sequence of sequences into a single sequence by concatenating
subsequences in reverse order, i.e. starting from the last element.
This is equivalent to a call to flatten
, but with concatenation operation
applied along the oppositive associativity for the sake of proof reasoning in that direction.
sourcepub proof fn lemma_flatten_one_element(self)
pub proof fn lemma_flatten_one_element(self)
self.len() == 1 ==> self.flatten() == self.first(),
Flattening a sequence of a sequence x, where x has length 1, results in a sequence equivalent to the single element of x
sourcepub proof fn lemma_flatten_length_ge_single_element_length(self, i: int)
pub proof fn lemma_flatten_length_ge_single_element_length(self, i: int)
0 <= i < self.len(),
ensuresself.flatten_alt().len() >= self[i].len(),
The length of a flattened sequence of sequences x is greater than or equal to any of the lengths of the elements of x.
sourcepub proof fn lemma_flatten_length_le_mul(self, j: int)
pub proof fn lemma_flatten_length_le_mul(self, j: int)
forall |i: int| 0 <= i < self.len() ==> (#[trigger] self[i]).len() <= j,
ensuresself.flatten_alt().len() <= self.len() * j,
The length of a flattened sequence of sequences x is less than or equal to the length of x multiplied by a number greater than or equal to the length of the longest sequence in x.
sourcepub proof fn lemma_flatten_and_flatten_alt_are_equivalent(self)
pub proof fn lemma_flatten_and_flatten_alt_are_equivalent(self)
self.flatten() =~= self.flatten_alt(),
Flattening sequences of sequences in order (starting from the beginning) and in reverse order (starting from the end) results in the same sequence.
source§impl Seq<int>
impl Seq<int>
sourcepub open spec fn max(self) -> int
pub open spec fn max(self) -> int
0 < self.len(),
{
if self.len() == 1 {
self[0]
} else if self.len() == 0 {
0
} else {
let later_max = self.drop_first().max();
if self[0] >= later_max { self[0] } else { later_max }
}
}
Returns the maximum integer value in a non-empty sequence of integers.
sourcepub proof fn max_ensures(self)
pub proof fn max_ensures(self)
forall |x: int| self.contains(x) ==> x <= self.max(),
forall |i: int| 0 <= i < self.len() ==> self[i] <= self.max(),
self.len() == 0 || self.contains(self.max()),
Proof of correctness and expected properties for max function
sourcepub open spec fn min(self) -> int
pub open spec fn min(self) -> int
0 < self.len(),
{
if self.len() == 1 {
self[0]
} else if self.len() == 0 {
0
} else {
let later_min = self.drop_first().min();
if self[0] <= later_min { self[0] } else { later_min }
}
}
Returns the minimum integer value in a non-empty sequence of integers.
sourcepub proof fn min_ensures(self)
pub proof fn min_ensures(self)
forall |x: int| self.contains(x) ==> self.min() <= x,
forall |i: int| 0 <= i < self.len() ==> self.min() <= self[i],
self.len() == 0 || self.contains(self.min()),
Proof of correctness and expected properties for min function
sourcepub proof fn lemma_sort_ensures(self)
pub proof fn lemma_sort_ensures(self)
self.to_multiset() =~= self.sort().to_multiset(),
sorted_by(self.sort(), |x: int, y: int| x <= y),
sourcepub proof fn lemma_subrange_max(self, from: int, to: int)
pub proof fn lemma_subrange_max(self, from: int, to: int)
0 <= from < to <= self.len(),
ensuresself.subrange(from, to).max() <= self.max(),
The maximum element in a non-empty sequence is greater than or equal to the maxima of its non-empty subsequences.
sourcepub proof fn lemma_subrange_min(self, from: int, to: int)
pub proof fn lemma_subrange_min(self, from: int, to: int)
0 <= from < to <= self.len(),
ensuresself.subrange(from, to).min() >= self.min(),
The minimum element in a non-empty sequence is less than or equal to the minima of its non-empty subsequences.