use super::map::Map;
#[allow(unused_imports)]
use super::pervasive::*;
#[allow(unused_imports)]
use super::prelude::*;
use super::set::*;
#[cfg(verus_keep_ghost)]
use super::set_lib::*;
verus! {
broadcast use super::map::group_map_axioms, super::set::group_set_axioms;
impl<K, V> Map<K, V> {
#[verifier::inline]
pub open spec fn is_full(self) -> bool {
self.dom().is_full()
}
#[verifier::inline]
pub open spec fn is_empty(self) -> (b: bool) {
self.dom().is_empty()
}
#[verifier::inline]
pub open spec fn contains_key(self, k: K) -> bool {
self.dom().contains(k)
}
pub open spec fn contains_value(self, v: V) -> bool {
exists|i: K| #[trigger] self.dom().contains(i) && self[i] == v
}
pub open spec fn values(self) -> Set<V> {
Set::<V>::new(|v: V| self.contains_value(v))
}
pub open spec fn contains_pair(self, k: K, v: V) -> bool {
self.dom().contains(k) && self[k] == v
}
pub open spec fn submap_of(self, m2: Self) -> bool {
forall|k: K| #[trigger]
self.dom().contains(k) ==> #[trigger] m2.dom().contains(k) && self[k] == m2[k]
}
#[verifier::inline]
pub open spec fn spec_le(self, m2: Self) -> bool {
self.submap_of(m2)
}
#[verifier::inline]
#[cfg_attr(not(verus_verify_core), deprecated = "use m1.submap_of(m2) or m1 <= m2 instead")]
pub open spec fn le(self, m2: Self) -> bool {
self.submap_of(m2)
}
pub open spec fn union_prefer_right(self, m2: Self) -> Self {
Self::new(
|k: K| self.dom().contains(k) || m2.dom().contains(k),
|k: K|
if m2.dom().contains(k) {
m2[k]
} else {
self[k]
},
)
}
pub open spec fn remove_keys(self, keys: Set<K>) -> Self {
Self::new(|k: K| self.dom().contains(k) && !keys.contains(k), |k: K| self[k])
}
pub open spec fn restrict(self, keys: Set<K>) -> Self {
Self::new(|k: K| self.dom().contains(k) && keys.contains(k), |k: K| self[k])
}
pub open spec fn is_equal_on_key(self, m2: Self, key: K) -> bool {
||| (!self.dom().contains(key) && !m2.dom().contains(key))
||| (self.dom().contains(key) && m2.dom().contains(key) && self[key] == m2[key])
}
pub open spec fn agrees(self, m2: Self) -> bool {
forall|k| #![auto] self.dom().contains(k) && m2.dom().contains(k) ==> self[k] == m2[k]
}
pub open spec fn map_entries<W>(self, f: spec_fn(K, V) -> W) -> Map<K, W> {
Map::new(|k: K| self.contains_key(k), |k: K| f(k, self[k]))
}
pub open spec fn map_values<W>(self, f: spec_fn(V) -> W) -> Map<K, W> {
Map::new(|k: K| self.contains_key(k), |k: K| f(self[k]))
}
pub open spec fn is_injective(self) -> bool {
forall|x: K, y: K|
x != y && self.dom().contains(x) && self.dom().contains(y) ==> #[trigger] self[x]
!= #[trigger] self[y]
}
pub open spec fn invert(self) -> Map<V, K> {
Map::<V, K>::new(
|v: V| self.contains_value(v),
|v: V| choose|k: K| self.contains_pair(k, v),
)
}
pub proof fn lemma_remove_key_len(self, key: K)
requires
self.dom().contains(key),
self.dom().finite(),
ensures
self.dom().len() == 1 + self.remove(key).dom().len(),
{
}
pub proof fn lemma_remove_equivalency(self, key: K)
ensures
self.remove(key).dom() == self.dom().remove(key),
{
}
pub proof fn lemma_remove_keys_len(self, keys: Set<K>)
requires
forall|k: K| #[trigger] keys.contains(k) ==> self.contains_key(k),
keys.finite(),
self.dom().finite(),
ensures
self.remove_keys(keys).dom().len() == self.dom().len() - keys.len(),
decreases keys.len(),
{
lemma_set_properties::<K>();
if keys.len() > 0 {
let key = keys.choose();
let val = self[key];
self.remove(key).lemma_remove_keys_len(keys.remove(key));
assert(self.remove(key).remove_keys(keys.remove(key)) =~= self.remove_keys(keys));
} else {
assert(self.remove_keys(keys) =~= self);
}
}
pub proof fn lemma_invert_is_injective(self)
ensures
self.invert().is_injective(),
{
assert forall|x: V, y: V|
x != y && self.invert().dom().contains(x) && self.invert().dom().contains(
y,
) implies #[trigger] self.invert()[x] != #[trigger] self.invert()[y] by {
let i = choose|i: K| #[trigger] self.dom().contains(i) && self[i] == x;
assert(self.contains_pair(i, x));
let j = choose|j: K| self.contains_pair(j, x) && self.invert()[x] == j;
let k = choose|k: K| #[trigger] self.dom().contains(k) && self[k] == y;
assert(self.contains_pair(k, y));
let l = choose|l: K| self.contains_pair(l, y) && self.invert()[y] == l && l != j;
}
}
}
impl Map<int, int> {
pub open spec fn is_monotonic(self) -> bool {
forall|x: int, y: int|
self.dom().contains(x) && self.dom().contains(y) && x <= y ==> #[trigger] self[x]
<= #[trigger] self[y]
}
pub open spec fn is_monotonic_from(self, start: int) -> bool {
forall|x: int, y: int|
self.dom().contains(x) && self.dom().contains(y) && start <= x <= y
==> #[trigger] self[x] <= #[trigger] self[y]
}
}
pub proof fn lemma_disjoint_union_size<K, V>(m1: Map<K, V>, m2: Map<K, V>)
requires
m1.dom().disjoint(m2.dom()),
m1.dom().finite(),
m2.dom().finite(),
ensures
m1.union_prefer_right(m2).dom().len() == m1.dom().len() + m2.dom().len(),
{
let u = m1.union_prefer_right(m2);
assert(u.dom() =~= m1.dom() + m2.dom()); assert(u.remove_keys(m1.dom()).dom() =~= m2.dom());
assert(u.remove_keys(m1.dom()).dom().len() == u.dom().len() - m1.dom().len()) by {
u.lemma_remove_keys_len(m1.dom());
}
}
pub proof fn lemma_map_new_domain<K, V>(fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V)
ensures
Map::<K, V>::new(fk, fv).dom() == Set::<K>::new(|k: K| fk(k)),
{
assert(Set::new(fk) =~= Set::<K>::new(|k: K| fk(k)));
}
pub proof fn lemma_map_new_values<K, V>(fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V)
ensures
Map::<K, V>::new(fk, fv).values() == Set::<V>::new(
|v: V| (exists|k: K| #[trigger] fk(k) && #[trigger] fv(k) == v),
),
{
let keys = Set::<K>::new(fk);
let values = Map::<K, V>::new(fk, fv).values();
let map = Map::<K, V>::new(fk, fv);
assert(map.dom() =~= keys);
assert(forall|k: K| #[trigger] fk(k) ==> keys.contains(k));
assert(values =~= Set::<V>::new(
|v: V| (exists|k: K| #[trigger] fk(k) && #[trigger] fv(k) == v),
));
}
pub proof fn lemma_map_properties<K, V>()
ensures
forall|fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V| #[trigger]
Map::<K, V>::new(fk, fv).dom() == Set::<K>::new(|k: K| fk(k)), forall|fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V| #[trigger]
Map::<K, V>::new(fk, fv).values() == Set::<V>::new(
|v: V| exists|k: K| #[trigger] fk(k) && #[trigger] fv(k) == v,
), {
assert forall|fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V| #[trigger]
Map::<K, V>::new(fk, fv).dom() == Set::<K>::new(|k: K| fk(k)) by {
lemma_map_new_domain(fk, fv);
}
assert forall|fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V| #[trigger]
Map::<K, V>::new(fk, fv).values() == Set::<V>::new(
|v: V| exists|k: K| #[trigger] fk(k) && #[trigger] fv(k) == v,
) by {
lemma_map_new_values(fk, fv);
}
}
pub proof fn lemma_values_finite<K, V>(m: Map<K, V>)
requires
m.dom().finite(),
ensures
m.values().finite(),
decreases m.len(),
{
if m.len() > 0 {
let k = m.dom().choose();
let v = m[k];
let m1 = m.remove(k);
assert(m.contains_key(k));
assert(m.contains_value(v));
let mv = m.values();
let m1v = m1.values();
assert_sets_equal!(mv == m1v.insert(v), v0 => {
if m.contains_value(v0) {
if v0 != v {
let k0 = choose|k0| #![auto] m.contains_key(k0) && m[k0] == v0;
assert(k0 != k);
assert(m1.contains_key(k0));
assert(mv.contains(v0) ==> m1v.insert(v).contains(v0));
assert(mv.contains(v0) <== m1v.insert(v).contains(v0));
}
}
});
assert(m1.len() < m.len());
lemma_values_finite(m1);
axiom_set_insert_finite(m1.values(), v);
} else {
assert(m.values() =~= Set::<V>::empty());
}
}
}