// Finite maps. // (Originally from Dafny Prelude: Copyright (c) Microsoft) // Map type type Map U V; // Map domain function Map#Domain(Map U V): Set U; // Mapping from keys to values function Map#Elements(Map U V): [U]V; // // Map constructed from domain and elements // function Map#Glue([U] bool, [U]V): Map U V; // axiom (forall a: [U] bool, b:[U]V :: // { Map#Domain(Map#Glue(a, b)) } // Map#Domain(Map#Glue(a, b)) == a); // axiom (forall a: [U] bool, b:[U]V :: // { Map#Elements(Map#Glue(a, b)) } // Map#Elements(Map#Glue(a, b)) == b); // Map cardinality function Map#Card(Map U V): int; axiom (forall m: Map U V :: { Map#Card(m) } 0 <= Map#Card(m)); axiom (forall m: Map U V :: { Map#Card(m), Map#Domain(m) } Map#Card(m) == Set#Card(Map#Domain(m))); // Empty map function Map#Empty(): Map U V; axiom (forall u: U :: { Map#Domain(Map#Empty(): Map U V)[u] } !Map#Domain(Map#Empty(): Map U V)[u]); axiom (forall m: Map U V :: { Map#Card(m) } Map#Card(m) == 0 <==> m == Map#Empty()); axiom (forall f: Field (Map U V) :: { Default(f) } Default(f) == Map#Empty() : Map U V); // Singleton map function {: inline } Map#Singleton(k: U, x: V): Map U V { Map#Update(Map#Empty(), k, x) } // Does the map contain value x? function {: inline } Map#Has(m: Map U V, x: V): bool { Map#Range(m)[x] } // Is the map empty? function {: inline } Map#IsEmpty(m: Map U V): bool { Map#Equal(m, Map#Empty()) } // Are all values in m equal to c? function Map#IsConstant(m: Map U V, c: V): bool { (forall k: U :: Map#Domain(m)[k] ==> Map#Elements(m)[k] == c) } // Element at a given key function {: inline } Map#Item(m: Map U V, k: U): V { Map#Elements(m)[k] } // Map Range function {: inline } Map#Range(m: Map U V): Set V { Map#Image(m, Map#Domain(m)) } // Image of a set function Map#Image(m: Map U V, s: Set U): Set V; axiom (forall m: Map U V, s: Set U, x: V :: { Map#Image(m, s)[x] } Map#Image(m, s)[x] <==> (exists k: U :: s[k] && Map#Elements(m)[k] == x)); axiom (forall m: Map U V, s: Set U, k: U :: { Map#Image(m, s)[Map#Elements(m)[k]] } s[k] ==> Map#Image(m, s)[Map#Elements(m)[k]]); // Image of a sequence function Map#SequenceImage(m: Map U V, s: Seq U): Seq V; axiom (forall m: Map U V, s: Seq U :: { Seq#Length(Map#SequenceImage(m, s)) } Seq#Length(Map#SequenceImage(m, s)) == Seq#Length(s)); axiom (forall m: Map U V, s: Seq U, i: int :: { Seq#Item(Map#SequenceImage(m, s), i) } Seq#Item(Map#SequenceImage(m, s), i) == Map#Elements(m)[Seq#Item(s, i)]); // Bag of map values function Map#ToBag(m: Map U V): Bag V; axiom (forall m: Map U V :: { Map#ToBag(m) } Bag#IsValid(Map#ToBag(m))); // axiom (forall m: Map U V :: { Bag#Equal(Map#ToBag(m), Bag#Empty()) } // Bag#Equal(Map#ToBag(m), Bag#Empty() : Bag V) <==> Map#Equal (m, Map#Empty() : Map U V)); axiom (forall :: Map#ToBag(Map#Empty() : Map U V) == Bag#Empty() : Bag V); axiom (forall m: Map U V, x: V :: { Map#ToBag(m)[x] } Map#ToBag(m)[x] > 0 <==> Map#Range(m)[x]); // update axiom axiom (forall m: Map U V, k: U, x: V :: { Map#ToBag(Map#Update(m, k, x)) } !Map#Domain(m)[k] ==> Map#ToBag(Map#Update(m, k, x)) == Bag#Extended(Map#ToBag(m), x)); axiom (forall m: Map U V, k: U, x: V :: { Map#ToBag(Map#Update(m, k, x)) } Map#Domain(m)[k] ==> Map#ToBag(Map#Update(m, k, x)) == Bag#Extended(Bag#Removed(Map#ToBag(m), Map#Elements(m)[k]), x)); // removed axiom axiom (forall m: Map U V, k: U :: { Map#ToBag(Map#Removed(m, k)) } Map#Domain(m)[k] ==> Map#ToBag(Map#Removed(m, k)) == Bag#Removed(Map#ToBag(m), Map#Elements(m)[k])); // cardinality axiom axiom (forall m: Map U V :: { Bag#Card(Map#ToBag(m)) } Bag#Card(Map#ToBag(m)) == Map#Card(m)); // disjoint union axiom axiom (forall a: Map U V, b: Map U V, x: V :: { Map#ToBag(Map#Override(a, b))[x] } Set#Disjoint(Map#Domain(a), Map#Domain(b)) ==> Map#ToBag(Map#Override(a, b))[x] == Map#ToBag(a)[x] + Map#ToBag(b)[x] ); // Equality function Map#Equal(Map U V, Map U V): bool; axiom (forall m: Map U V, m': Map U V:: { Map#Equal(m, m') } Map#Equal(m, m') <==> (forall u : U :: Map#Domain(m)[u] == Map#Domain(m')[u]) && (forall u : U :: Map#Domain(m)[u] ==> Map#Elements(m)[u] == Map#Elements(m')[u])); // extensionality axiom (forall m: Map U V, m': Map U V:: { Map#Equal(m, m') } Map#Equal(m, m') ==> m == m'); // Dow two maps have disjoint domains? function Map#Disjoint(Map U V, Map U V): bool; axiom (forall m: Map U V, m': Map U V :: { Map#Disjoint(m, m') } Map#Disjoint(m, m') <==> (forall o: U :: {Map#Domain(m)[o]} {Map#Domain(m')[o]} !Map#Domain(m)[o] || !Map#Domain(m')[o])); // Map with a key-value pair updated function Map#Update(Map U V, U, V): Map U V; /*axiom (forall m: Map U V, u: U, v: V :: { Map#Domain(Map#Update(m, u, v))[u] } { Map#Elements(Map#Update(m, u, v))[u] } Map#Domain(Map#Update(m, u, v))[u] && Map#Elements(Map#Update(m, u, v))[u] == v);*/ axiom (forall m: Map U V, u: U, u': U, v: V :: { Map#Domain(Map#Update(m, u, v))[u'] } { Map#Elements(Map#Update(m, u, v))[u'] } (u' == u ==> Map#Domain(Map#Update(m, u, v))[u'] && Map#Elements(Map#Update(m, u, v))[u'] == v) && (u' != u ==> Map#Domain(Map#Update(m, u, v))[u'] == Map#Domain(m)[u'] && Map#Elements(Map#Update(m, u, v))[u'] == Map#Elements(m)[u'])); axiom (forall m: Map U V, u: U, v: V :: { Map#Card(Map#Update(m, u, v)) } Map#Domain(m)[u] ==> Map#Card(Map#Update(m, u, v)) == Map#Card(m)); axiom (forall m: Map U V, u: U, v: V :: { Map#Card(Map#Update(m, u, v)) } !Map#Domain(m)[u] ==> Map#Card(Map#Update(m, u, v)) == Map#Card(m) + 1); // Map with a key removed function Map#Removed(Map U V, U): Map U V; axiom (forall m: Map U V, k: U :: { Map#Domain(Map#Removed(m, k)) } Map#Domain(Map#Removed(m, k)) == Set#Removed(Map#Domain(m), k)); axiom (forall m: Map U V, k: U, i: U :: { Map#Elements(Map#Removed(m, k))[i] } Map#Elements(Map#Removed(m, k))[i] == Map#Elements(m)[i]); axiom (forall m: Map U V, k: U :: { Map#Domain(m)[k], Map#Removed(m, k) } !Map#Domain(m)[k] ==> Map#Removed(m, k) == m); // Map restricted to a subdomain function Map#Restricted(Map U V, Set U): Map U V; axiom (forall m: Map U V, s: Set U :: { Map#Domain(Map#Restricted(m, s)) } Map#Domain(Map#Restricted(m, s)) == Set#Intersection(Map#Domain(m), s)); axiom (forall m: Map U V, s: Set U, i: U :: { Map#Elements(Map#Restricted(m, s))[i] } Map#Elements(Map#Restricted(m, s))[i] == Map#Elements(m)[i]); // Map override (right-biased union) function Map#Override(Map U V, Map U V): Map U V; axiom (forall a: Map U V, b: Map U V :: { Map#Domain(Map#Override(a, b)) } Map#Domain(Map#Override(a, b)) == Set#Union(Map#Domain(a), Map#Domain(b))); axiom (forall a: Map U V, b: Map U V, i: U :: { Map#Elements(Map#Override(a, b))[i] } Map#Elements(Map#Override(a, b))[i] == if Map#Domain(b)[i] then Map#Elements(b)[i] else Map#Elements(a)[i]); // Inverse function Map#Inverse(Map U V): Rel V U; axiom (forall a: Map U V, u: U, v: V :: { Map#Inverse(a)[v, u] } Map#Inverse(a)[v, u] <==> Map#Domain(a)[u] && Map#Elements(a)[u] == v); axiom (forall a: Map U V :: { Rel#Card(Map#Inverse(a)) } Rel#Card(Map#Inverse(a)) == Map#Card(a)); axiom (forall a: Map U V :: { Rel#Domain(Map#Inverse(a)) } Rel#Domain(Map#Inverse(a)) == Map#Range(a)); axiom (forall a: Map U V :: { Rel#Range(Map#Inverse(a)) } Rel#Range(Map#Inverse(a)) == Map#Domain(a)); // Type properties function {: inline } Map#DomainType(heap: HeapType, m: Map ref T, t: Type): bool { (forall o: ref :: { Map#Domain(m)[o] } Map#Domain(m)[o] ==> detachable(heap, o, t)) } function {: inline } Map#RangeType(heap: HeapType, m: Map T ref, t: Type): bool { (forall i: T :: { Map#Domain(m)[i] } Map#Domain(m)[i] ==> detachable(heap, Map#Elements(m)[i], t)) }