pub struct Multiset<V> { /* private fields */ }
Expand description
Multiset<V>
is an abstract multiset type for specifications.
Multiset<V>
can be encoded as a (total) map from elements to natural numbers,
where the number of nonzero entries is finite.
Multisets can be constructed in a few different ways:
Multiset::empty()
constructs an empty multiset.Multiset::singleton
constructs a multiset that contains a single element with multiplicity 1.Multiset::new
constructs a multiset from a map of elements to multiplicities.- By manipulating existings multisets with
Multiset::add
,Multiset::insert
,Multiset::sub
,Multiset::remove
,Multiset::update
, orMultiset::filter
. - TODO:
multiset!
constructor macro, multiset from set, from map, etc.
To prove that two multisets are equal, it is usually easiest to use the
extensionality operator =~=
.
Implementations§
source§impl<V> Multiset<V>
impl<V> Multiset<V>
sourcepub spec fn count(self, value: V) -> nat
pub spec fn count(self, value: V) -> nat
Returns the count, or multiplicity of a single value within the multiset.
sourcepub spec fn len(self) -> nat
pub spec fn len(self) -> nat
The total size of the multiset, i.e., the sum of all multiplicities over all values.
sourcepub open spec fn from_map(m: Map<V, nat>) -> Self
pub open spec fn from_map(m: Map<V, nat>) -> Self
{}
Creates a multiset whose elements are given by the domain of the map m
and whose
multiplicities are given by the corresponding values of m[element]
. The map m
must be finite, or else this multiset is arbitrary.
sourcepub open spec fn new(m: Map<V, nat>) -> Self
👎Deprecated: use from_map instead
pub open spec fn new(m: Map<V, nat>) -> Self
{ Self::from_map(m) }
sourcepub open spec fn from_set(m: Set<V>) -> Self
pub open spec fn from_set(m: Set<V>) -> Self
{ Self::from_map(Map::new(|k| m.contains(k), |v| 1)) }
sourcepub spec fn singleton(v: V) -> Self
pub spec fn singleton(v: V) -> Self
A singleton multiset, i.e., a multiset with a single element of multiplicity 1.
sourcepub spec fn add(self, m2: Self) -> Self
pub spec fn add(self, m2: Self) -> Self
Takes the union of two multisets. For a given element, its multiplicity in the resulting multiset is the sum of its multiplicities in the operands.
sourcepub spec fn sub(self, m2: Self) -> Self
pub spec fn sub(self, m2: Self) -> Self
Takes the difference of two multisets.
The multiplicities of m2
are subtracted from those of self
; if any element
occurs more in m2
then the resulting multiplicity bottoms out at 0.
(See axiom_multiset_sub
for the precise definition.)
Note in particular that self == self.sub(m).add(m)
only holds if
m
is included in self
.
sourcepub open spec fn insert(self, v: V) -> Self
pub open spec fn insert(self, v: V) -> Self
{ self.add(Self::singleton(v)) }
Inserts one instance the value v
into the multiset.
This always increases the total size of the multiset by 1.
sourcepub open spec fn remove(self, v: V) -> Self
pub open spec fn remove(self, v: V) -> Self
{ self.sub(Self::singleton(v)) }
Removes one instance of the value v
from the multiset.
If v
was absent from the multiset, then the multiset is unchanged.
sourcepub open spec fn update(self, v: V, mult: nat) -> Self
pub open spec fn update(self, v: V, mult: nat) -> Self
{
let map = Map::new(
|key: V| (self.contains(key) || key == v),
|key: V| if key == v { mult } else { self.count(key) },
);
Self::from_map(map)
}
Updates the multiplicity of the value v
in the multiset to mult
.
sourcepub open spec fn subset_of(self, m2: Self) -> bool
pub open spec fn subset_of(self, m2: Self) -> bool
{ forall |v: V| self.count(v) <= m2.count(v) }
Returns true
is the left argument is contained in the right argument,
that is, if for each value v
, the number of occurences in the left
is at most the number of occurences in the right.
sourcepub open spec fn le(self, m2: Self) -> bool
👎Deprecated: use m1.subset_of(m2) or m1 <= m2 instead
pub open spec fn le(self, m2: Self) -> bool
{ self.subset_of(m2) }
sourcepub open spec fn ext_equal(self, m2: Self) -> bool
👎Deprecated: use =~= or =~~= instead
pub open spec fn ext_equal(self, m2: Self) -> bool
{ self =~= m2 }
DEPRECATED: use =~= or =~~= instead.
Returns true if the two multisets are pointwise equal, i.e.,
for every value v: V
, the counts are the same in each multiset.
This is equivalent to the multisets actually being equal
by axiom_multiset_ext_equal
.
To prove that two maps are equal via extensionality, it may be easier
to use the general-purpose =~=
or =~~=
or
to use the assert_multisets_equal!
macro, rather than using ext_equal
directly.
sourcepub open spec fn choose(self) -> V
pub open spec fn choose(self) -> V
{ choose |v: V| self.count(v) > 0 }
Chooses an arbitrary value of the multiset.
This is often useful for proofs by induction.
(Note that, although the result is arbitrary, it is still a deterministic function
like any other spec
function.)
sourcepub open spec fn contains(self, v: V) -> bool
pub open spec fn contains(self, v: V) -> bool
{ self.count(v) > 0 }
Predicate indicating if the multiset contains the given value.
sourcepub open spec fn spec_has(self, v: V) -> bool
pub open spec fn spec_has(self, v: V) -> bool
{ self.contains(v) }
Predicate indicating if the set contains the given element: supports self has a
syntax.
sourcepub open spec fn intersection_with(self, other: Self) -> Self
pub open spec fn intersection_with(self, other: Self) -> Self
{
let m = Map::<
V,
nat,
>::new(
|v: V| self.contains(v),
|v: V| min(self.count(v) as int, other.count(v) as int) as nat,
);
Self::from_map(m)
}
Returns a multiset containing the lower count of a given element between the two sets. In other words, returns a multiset with only the elements that “overlap”.
sourcepub open spec fn difference_with(self, other: Self) -> Self
pub open spec fn difference_with(self, other: Self) -> Self
{
let m = Map::<
V,
nat,
>::new(|v: V| self.contains(v), |v: V| clip(self.count(v) - other.count(v)));
Self::from_map(m)
}
Returns a multiset containing the difference between the count of a given element of the two sets.
sourcepub open spec fn is_disjoint_from(self, other: Self) -> bool
pub open spec fn is_disjoint_from(self, other: Self) -> bool
{ forall |x: V| self.count(x) == 0 || other.count(x) == 0 }
Returns true if there exist no elements that have a count greater than 0 in both multisets. In other words, returns true if the two multisets have no elements in common.
source§impl<A> Multiset<A>
impl<A> Multiset<A>
sourcepub open spec fn is_empty(self) -> b : bool
pub open spec fn is_empty(self) -> b : bool
{ self.len() == 0 }
Is true
if called by an “empty” multiset, i.e., a set containing no elements and has length 0
sourcepub open spec fn is_singleton(self) -> bool
pub open spec fn is_singleton(self) -> bool
{
&&& self.len() > 0
&&& (forall |x: A| self.contains(x) ==> self.count(x) == 1)
&&& (forall |x: A, y: A| self.contains(x) && self.contains(y) ==> x == y)
}
A singleton multiset has at least one element with multiplicity 1 and any two elements are equal.
sourcepub proof fn lemma_is_singleton_contains_elem_equal_singleton(self, x: A)
pub proof fn lemma_is_singleton_contains_elem_equal_singleton(self, x: A)
self.is_singleton(),
self.contains(x),
ensuresself =~= Multiset::singleton(x),
A singleton multiset that contains an alement is equivalent to the singleton multiset with that element.
sourcepub proof fn lemma_singleton_size(self)
pub proof fn lemma_singleton_size(self)
self.is_singleton(),
ensuresself.len() == 1,
A singleton multiset has length 1.
sourcepub proof fn lemma_is_singleton(s: Multiset<A>)
pub proof fn lemma_is_singleton(s: Multiset<A>)
s.is_singleton() <==> (s.len() == 1),
A multiset has exactly one element, if and only if, it has at least one element with multiplicity 1 and any two elements are equal.