Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
Probabilistic Functions and Cryptographic Oracles
in Higher Order Logic
Andreas Lochbihler
March 2, 2016
Contents
1 Auxiliary material 51.0.1 Countable . . . . . . . . . . . . . . . . . . . . . . . . . 51.0.2 Extended naturals . . . . . . . . . . . . . . . . . . . . 51.0.3 Indicator function . . . . . . . . . . . . . . . . . . . . 51.0.4 Integrals . . . . . . . . . . . . . . . . . . . . . . . . . . 51.0.5 Measures . . . . . . . . . . . . . . . . . . . . . . . . . 61.0.6 Sequence space . . . . . . . . . . . . . . . . . . . . . . 61.0.7 PMF . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.0.8 Streams . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1 Transfer rules . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.2 Algebraic stuff . . . . . . . . . . . . . . . . . . . . . . . . . . 81.3 Option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.1 Orders on option . . . . . . . . . . . . . . . . . . . . . 91.3.2 filter for option . . . . . . . . . . . . . . . . . . . . . . 111.3.3 map for the combination of set and option . . . . . . . 121.3.4 join on options . . . . . . . . . . . . . . . . . . . . . . 131.3.5 Zip on options . . . . . . . . . . . . . . . . . . . . . . 14
1.4 Predicator for function relator with relation op = on the domain 151.5 A relator for sets that treats sets like predicates . . . . . . . . 161.6 List of a given length . . . . . . . . . . . . . . . . . . . . . . . 161.7 Corecursor for products . . . . . . . . . . . . . . . . . . . . . 181.8 If . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2 Monomorphic monads and monad transformers 252.1 Plain monads . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.1.1 Identity monad . . . . . . . . . . . . . . . . . . . . . . 282.2 Monads with failure . . . . . . . . . . . . . . . . . . . . . . . 282.3 The option monad . . . . . . . . . . . . . . . . . . . . . . . . 302.4 The set monad . . . . . . . . . . . . . . . . . . . . . . . . . . 312.5 Monad homomorphism . . . . . . . . . . . . . . . . . . . . . . 32
1
3 Monad transformers 333.1 The state monad transformer . . . . . . . . . . . . . . . . . . 33
3.1.1 Transformation of homomorphisms . . . . . . . . . . . 373.2 The reader/environment monad transformer . . . . . . . . . . 39
3.2.1 Transformation of homomorphisms . . . . . . . . . . . 43
4 Subprobability mass functions 464.1 Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494.2 Functorial structure . . . . . . . . . . . . . . . . . . . . . . . 514.3 Monad operations . . . . . . . . . . . . . . . . . . . . . . . . 53
4.3.1 Return . . . . . . . . . . . . . . . . . . . . . . . . . . . 534.3.2 Bind . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.4 Relator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574.5 From ′a pmf to ′a spmf . . . . . . . . . . . . . . . . . . . . . 594.6 Weight of a subprobability . . . . . . . . . . . . . . . . . . . . 604.7 From density to spmfs . . . . . . . . . . . . . . . . . . . . . . 634.8 Ordering on spmfs . . . . . . . . . . . . . . . . . . . . . . . . 644.9 Restrictions on spmfs . . . . . . . . . . . . . . . . . . . . . . . 804.10 Integral over spmf . . . . . . . . . . . . . . . . . . . . . . . . 84
4.10.1 Non-negative integral . . . . . . . . . . . . . . . . . . 844.10.2 Lebesgue integral . . . . . . . . . . . . . . . . . . . . . 86
4.11 Bounded functions . . . . . . . . . . . . . . . . . . . . . . . . 884.12 Subprobability distributions . . . . . . . . . . . . . . . . . . . 944.13 Losslessness . . . . . . . . . . . . . . . . . . . . . . . . . . . . 984.14 Scaling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1004.15 Conditional spmfs . . . . . . . . . . . . . . . . . . . . . . . . 1054.16 Product spmf . . . . . . . . . . . . . . . . . . . . . . . . . . . 1064.17 Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1104.18 Try . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1104.19 Embedding of ′a option into ′a spmf . . . . . . . . . . . . . . 113
5 The IO monad 1205.1 The real world . . . . . . . . . . . . . . . . . . . . . . . . . . 1205.2 Setup for lifting and transfer . . . . . . . . . . . . . . . . . . 1225.3 Code generator setup . . . . . . . . . . . . . . . . . . . . . . . 1255.4 Semantics of the IO monad . . . . . . . . . . . . . . . . . . . 126
6 The resumption monad 1296.1 setup for partial-function . . . . . . . . . . . . . . . . . . . . 1346.2 Execution resumption . . . . . . . . . . . . . . . . . . . . . . 1406.3 Code generator setup . . . . . . . . . . . . . . . . . . . . . . . 1476.4 Setup for lifting and transfer . . . . . . . . . . . . . . . . . . 147
6.4.1 Single-step generative . . . . . . . . . . . . . . . . . . 153
2
7 Generative probabilistic values 1577.1 Type definition . . . . . . . . . . . . . . . . . . . . . . . . . . 1597.2 Simple, derived operations . . . . . . . . . . . . . . . . . . . . 1627.3 Monad structure . . . . . . . . . . . . . . . . . . . . . . . . . 1657.4 Embedding ′a spmf as a monad . . . . . . . . . . . . . . . . . 1727.5 Embedding ′a option as a monad . . . . . . . . . . . . . . . . 1767.6 Embedding resumptions . . . . . . . . . . . . . . . . . . . . . 1787.7 Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1797.8 Executing gpv: possibilistic trace semantics . . . . . . . . . . 1807.9 Order for ( ′a, ′out , ′in) gpv . . . . . . . . . . . . . . . . . . . 1887.10 Bounds on interaction . . . . . . . . . . . . . . . . . . . . . . 1907.11 Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
7.11.1 Interface between gpvs and rpvs . . . . . . . . . . . . 1947.11.2 Type judgements . . . . . . . . . . . . . . . . . . . . . 198
7.12 Sub-gpvs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2027.13 Losslessness . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2037.14 Inlining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2077.15 Running GPVs . . . . . . . . . . . . . . . . . . . . . . . . . . 2257.16 Bisimulation for oracles . . . . . . . . . . . . . . . . . . . . . 233
8 Oracle combinators 2398.1 Combining oracles . . . . . . . . . . . . . . . . . . . . . . . . 240
9 Negligibility 241
10 Applicative Functors 26510.1 The basic operations of applicative functors . . . . . . . . . . 26510.2 Applicative functors with combinatorial structure . . . . . . . 26510.3 The environment functor . . . . . . . . . . . . . . . . . . . . . 26610.4 lifting predicates to the environment functor . . . . . . . . . . 266
11 Cyclic groups 268
12 Bitstrings 271
13 Examples 27313.1 The IND-CPA security game for public-key encryption with
oracle access . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27313.2 The IND-CPA security game (public key, single instance) . . 27513.3 The IND-CPA security game . . . . . . . . . . . . . . . . . . 27613.4 The DDH security game . . . . . . . . . . . . . . . . . . . . . 27813.5 The LCDH security game . . . . . . . . . . . . . . . . . . . . 27813.6 Random function construction . . . . . . . . . . . . . . . . . 27913.7 Pseudo-random functions . . . . . . . . . . . . . . . . . . . . 28013.8 The bernoulli distribution built from coin flips . . . . . . . . 281
3
13.9 Elgamal encryption scheme . . . . . . . . . . . . . . . . . . . 28313.10Formalisation of Hashed Elgamal in the Random Oracle Model28613.11IND-CPA from PRF . . . . . . . . . . . . . . . . . . . . . . . 295
4
theory Probability-More imports ∼∼/src/HOL/Probability/Probability begin
1 Auxiliary material
lemma cSUP-singleton [simp]: (SUP x :x. f x :: - :: conditionally-complete-lattice)= f xunfolding SUP-def by simp
1.0.1 Countable
lemma countable-lfp:assumes step:
∧Y . countable Y =⇒ countable (F Y )
and cont : Order-Continuity .sup-continuous Fshows countable (lfp F )
by(subst sup-continuous-lfp[OF cont ])(simp add : countable-funpow [OF step])
lemma countable-lfp-apply :assumes step:
∧Y x . (
∧x . countable (Y x )) =⇒ countable (F Y x )
and cont : Order-Continuity .sup-continuous Fshows countable (lfp F x )
proof − fix n
have∧
x . countable ((F ˆˆ n) bot x )by(induct n)(auto intro: step)
thus ?thesis using cont by(simp add : sup-continuous-lfp)qed
1.0.2 Extended naturals
lemma idiff-enat-eq-enat-iff : x − enat n = enat m ←→ (∃ k . x = enat k ∧ k −n = m)by(cases x ) simp-all
1.0.3 Indicator function
lemma indicator-single-Some: indicator Some x (Some y) = indicator x yby(simp split : split-indicator)
1.0.4 Integrals
lemma (in finite-measure) nn-integral-indicator-neq-infty :f −‘ A ∈ sets M =⇒ (
∫+ x . indicator A (f x ) ∂M ) 6= ∞
unfolding ereal-indicator [symmetric]apply(rule integrableD)apply(rule integrable-const-bound [where B=1 ])apply(simp-all add : indicator-vimage[symmetric])done
lemma nn-integral-indicator-map:
5
assumes [measurable]: f ∈ measurable M N x∈space N . P x ∈ sets Nshows (
∫+x . indicator x∈space N . P x (f x ) ∂M ) = emeasure M x∈space
M . P (f x )using assms(1 )[THEN measurable-space]by (subst nn-integral-indicator [symmetric])
(auto intro!: nn-integral-cong split : split-indicator simp del : nn-integral-indicator)
1.0.5 Measures
declare sets-restrict-space-count-space [measurable-cong ]
lemma (in sigma-algebra) sets-Collect-countable-Ex1 :(∧
i :: ′i :: countable. x ∈ Ω. P i x ∈ M ) =⇒ x ∈ Ω. ∃ !i . P i x ∈ Musing sets-Collect-countable-Ex1 ′[of UNIV :: ′i set ] by simp
lemma pred-countable-Ex1 [measurable]:(∧
i :: - :: countable. Measurable.pred M (λx . P i x ))=⇒ Measurable.pred M (λx . ∃ !i . P i x )
unfolding pred-def by(rule sets.sets-Collect-countable-Ex1 )
lemma measurable-snd-count-space [measurable]:A ⊆ B =⇒ snd ∈ measurable (M1
⊗M count-space A) (count-space B)
by(auto simp add : measurable-def space-pair-measure snd-vimage-eq-Times times-Int-times)
1.0.6 Sequence space
lemma (in sequence-space) nn-integral-split :assumes f [measurable]: f ∈ borel-measurable Sshows (
∫+ω. f ω ∂S ) = (
∫+ω. (
∫+ω ′. f (comb-seq i ω ω ′) ∂S ) ∂S )
by (subst PiM-comb-seq [symmetric, where i=i ])(simp add : nn-integral-distr P .nn-integral-fst [symmetric])
lemma (in sequence-space) prob-Collect-split :assumes f [measurable]: x∈space S . P x ∈ sets Sshows P(x in S . P x ) = (
∫+x . P(x ′ in S . P (comb-seq i x x ′)) ∂S )
proof −have P(x in S . P x ) = (
∫+x . (
∫+x ′. indicator x∈space S . P x (comb-seq i x
x ′) ∂S ) ∂S )using nn-integral-split [of indicator x∈space S . P x] by (auto simp: emeasure-eq-measure)also have . . . = (
∫+x . P(x ′ in S . P (comb-seq i x x ′)) ∂S )
by (intro nn-integral-cong) (auto simp: emeasure-eq-measure nn-integral-indicator-map)finally show ?thesis .
qed
1.0.7 PMF
adhoc-overloading Monad-Syntax .bind bind-pmf
lemma measure-map-pmf-conv-distr :measure-pmf (map-pmf f p) = distr (measure-pmf p) (count-space UNIV ) f
6
by(fact map-pmf-rep-eq)
1.0.8 Streams
primrec sprefix :: ′a list ⇒ ′a stream ⇒ bool wheresprefix-Nil : sprefix [] ys = True| sprefix-Cons: sprefix (x # xs) ys ←→ x = shd ys ∧ sprefix xs (stl ys)
lemma sprefix-append : sprefix (xs @ ys) zs ←→ sprefix xs zs ∧ sprefix ys (sdrop(length xs) zs)by(induct xs arbitrary : zs) simp-all
lemma sprefix-stake-same [simp]: sprefix (stake n xs) xsby(induct n arbitrary : xs) simp-all
lemma sprefix-same-imp-eq :assumes sprefix xs ys sprefix xs ′ ysand length xs = length xs ′
shows xs = xs ′
using assms(3 ,1 ,2 ) by(induct arbitrary : ys rule: list-induct2 ) auto
lemma sprefix-shift-same [simp]:sprefix xs (xs @− ys)
by(induct xs) simp-all
lemma snth-sdrop: sdrop n xs !! m = xs !! (n + m)by(induct n arbitrary : xs) simp-all
lemma sprefix-shift [simp]:length xs ≤ length ys =⇒ sprefix xs (ys @− zs) ←→ prefixeq xs ys
by(induct xs arbitrary : ys)(simp, case-tac ys, auto)
lemma prefixeq-stake2 [simp]: prefixeq xs (stake n ys) ←→ length xs ≤ n ∧ sprefixxs ysproof(induct xs arbitrary : n ys)
case (Cons x xs)thus ?case by(cases ys n rule: stream.exhaust [case-product nat .exhaust ]) auto
qed simp
lemma sdrop-shift : sdrop n (xs @− ys) = drop n xs @− sdrop (n − length xs) ysby(induct xs arbitrary : n)(simp, case-tac n, simp-all)
endtheory Misc imports
Complex-Main∼∼/src/HOL/Eisbach/Eisbach∼∼/src/HOL/Library/Rewrite∼∼/src/HOL/Library/Simps-Case-Conv
begin
7
lemma Least-le-Least :fixes x :: ′a :: wellorderassumes Q xand Q :
∧x . Q x =⇒ ∃ y≤x . P y
shows Least P ≤ Least Qproof −
obtain f :: ′a ⇒ ′a where ∀ a. ¬ Q a ∨ f a ≤ a ∧ P (f a) using Q by mouramoreover have Q (Least Q) using 〈Q x 〉 by(rule LeastI )ultimately show ?thesis by (metis (full-types) le-cases le-less less-le-trans not-less-Least)
qed
1.1 Transfer rules
context begin interpretation lifting-syntax .
lemma monotone-parametric [transfer-rule]:assumes [transfer-rule]: bi-total Ashows ((A ===> A ===> op =) ===> (B ===> B ===> op =) ===>
(A ===> B) ===> op =) monotone monotoneunfolding monotone-def [abs-def ] by transfer-prover
lemma fun-ord-parametric [transfer-rule]:assumes [transfer-rule]: bi-total Cshows ((A ===> B ===> op =) ===> (C ===> A) ===> (C ===>
B) ===> op =) fun-ord fun-ordunfolding fun-ord-def [abs-def ] by transfer-prover
lemma fun-lub-parametric [transfer-rule]:assumes [transfer-rule]: bi-total A bi-unique Ashows ((rel-set A ===> B) ===> rel-set (C ===> A) ===> C ===> B)
fun-lub fun-lubunfolding fun-lub-def [abs-def ] by transfer-prover
lemma Ex1-parametric [transfer-rule]:assumes [transfer-rule]: bi-unique A bi-total Ashows ((A ===> op =) ===> op =) Ex1 Ex1
unfolding Ex1-def [abs-def ] by transfer-prover
end
1.2 Algebraic stuff
lemma abs-diff-triangle-ineq2 : |a − b :: - :: ordered-ab-group-add-abs| ≤ |a − c|+ |c − b|by(rule order-trans[OF - abs-diff-triangle-ineq ]) simp
lemma (in ordered-ab-semigroup-add) add-left-mono-trans:[[ x ≤ a + b; b ≤ c ]] =⇒ x ≤ a + c
8
by(erule order-trans)(rule add-left-mono)
lemma of-nat-le-one-cancel-iff [simp]:fixes n :: nat shows real n ≤ 1 ←→ n ≤ 1
by linarith
lemma (in linordered-semidom) mult-right-le: c ≤ 1 =⇒ 0 ≤ a =⇒ c ∗ a ≤ aby(subst mult .commute)(rule mult-left-le)
1.3 Option
declare is-none-bind [simp]
lemma None-in-map-option-image [simp]: None ∈ map-option f ‘ A ←→ None ∈Aby auto
lemma Some-in-map-option-image [simp]: Some x ∈ map-option f ‘ A ←→ (∃ y .x = f y ∧ Some y ∈ A)by(auto intro: rev-image-eqI dest : sym)
lemma case-option-collapse: case-option x (λ-. x ) y = xby(simp split : option.split)
lemma case-option-id : case-option None Some = idby(rule ext)(simp split : option.split)
1.3.1 Orders on option
inductive ord-option :: ( ′a ⇒ ′b ⇒ bool) ⇒ ′a option ⇒ ′b option ⇒ boolfor ord :: ′a ⇒ ′b ⇒ bool
whereNone: ord-option ord None x| Some: ord x y =⇒ ord-option ord (Some x ) (Some y)
inductive-simps ord-option-simps [simp]:ord-option ord None xord-option ord x Noneord-option ord (Some x ) (Some y)ord-option ord (Some x ) None
inductive-simps ord-option-eq-simps [simp]:ord-option op = None yord-option op = (Some x ) y
lemma ord-option-reflI : (∧
y . y ∈ set-option x =⇒ ord y y) =⇒ ord-option ord xxby(cases x ) simp-all
lemma reflp-ord-option: reflp ord =⇒ reflp (ord-option ord)
9
by(simp add : reflp-def ord-option-reflI )
lemma ord-option-trans:[[ ord-option ord x y ; ord-option ord y z ;∧
a b c. [[ a ∈ set-option x ; b ∈ set-option y ; c ∈ set-option z ; ord a b; ord b c]] =⇒ ord a c ]]
=⇒ ord-option ord x zby(auto elim!: ord-option.cases)
lemma transp-ord-option: transp ord =⇒ transp (ord-option ord)unfolding transp-def by(blast intro: ord-option-trans)
lemma antisymP-ord-option: antisymP ord =⇒ antisymP (ord-option ord)by(auto intro!: antisymI elim!: ord-option.cases dest : antisymD)
lemma ord-option-chainD :Complete-Partial-Order .chain (ord-option ord) Y=⇒ Complete-Partial-Order .chain ord x . Some x ∈ Y
by(rule chainI )(auto dest : chainD)
definition lub-option :: ( ′a set ⇒ ′b) ⇒ ′a option set ⇒ ′b optionwhere lub-option lub Y = (if Y ⊆ None then None else Some (lub x . Some x∈ Y ))
lemma map-lub-option: map-option f (lub-option lub Y ) = lub-option (f lub) Yby(simp add : lub-option-def )
lemma lub-option-upper :assumes Complete-Partial-Order .chain (ord-option ord) Y x ∈ Yand lub-upper :
∧Y x . [[ Complete-Partial-Order .chain ord Y ; x ∈ Y ]] =⇒ ord
x (lub Y )shows ord-option ord x (lub-option lub Y )
using assms(1−2 )by(cases x )(auto simp add : lub-option-def intro: lub-upper [OF ord-option-chainD ])
lemma lub-option-least :assumes Y : Complete-Partial-Order .chain (ord-option ord) Yand upper :
∧x . x ∈ Y =⇒ ord-option ord x y
assumes lub-least :∧
Y y . [[ Complete-Partial-Order .chain ord Y ;∧
x . x ∈ Y=⇒ ord x y ]] =⇒ ord (lub Y ) y
shows ord-option ord (lub-option lub Y ) yusing Yby(cases y)(auto 4 3 simp add : lub-option-def intro: lub-least [OF ord-option-chainD ]dest : upper)
lemma lub-map-option: lub-option lub (map-option f ‘ Y ) = lub-option (lub op‘ f ) Yapply(auto simp add : lub-option-def )apply(erule notE )
10
apply(rule arg-cong [where f =lub])apply(auto intro: rev-image-eqI dest : sym)done
lemma ord-option-mono: [[ ord-option A x y ;∧
x y . A x y =⇒ B x y ]] =⇒ord-option B x yby(auto elim: ord-option.cases)
lemma ord-option-mono ′ [mono]:(∧
x y . A x y −→ B x y) =⇒ ord-option A x y −→ ord-option B x yby(blast intro: ord-option-mono)
lemma ord-option-compp: ord-option (A OO B) = ord-option A OO ord-option Bby(auto simp add : fun-eq-iff elim!: ord-option.cases intro: ord-option.intros)
lemma ord-option-inf : inf (ord-option A) (ord-option B) = ord-option (inf A B)(is ?lhs = ?rhs)proof(rule antisym)
show ?lhs ≤ ?rhs by(auto elim!: ord-option.cases)qed(auto elim: ord-option-mono)
lemma ord-option-map2 : ord-option ord x (map-option f y) = ord-option (λx y .ord x (f y)) x yby(auto elim: ord-option.cases)
lemma ord-option-map1 : ord-option ord (map-option f x ) y = ord-option (λx y .ord (f x ) y) x yby(auto elim: ord-option.cases)
lemma option-ord-Some1-iff : option-ord (Some x ) y ←→ y = Some xby(auto simp add : flat-ord-def )
We need a polymorphic constant for the empty map such that transfer-provercan use a custom transfer rule for Map.empty
definition Map-empty where [simp]: Map-empty ≡ Map.empty
1.3.2 filter for option
fun filter-option :: ( ′a ⇒ bool) ⇒ ′a option ⇒ ′a optionwhere
filter-option P None = None| filter-option P (Some x ) = (if P x then Some x else None)
lemma set-filter-option [simp]: set-option (filter-option P x ) = y ∈ set-option x .P yby(cases x ) auto
lemma filter-map-option: filter-option P (map-option f x ) = map-option f (filter-option(P f ) x )
11
by(cases x ) simp-all
lemma is-none-filter-option [simp]: Option.is-none (filter-option P x ) ←→ Op-tion.is-none x ∨ ¬ P (the x )by(cases x ) simp-all
lemma filter-option-eq-Some-iff [simp]: filter-option P x = Some y ←→ x = Somey ∧ P yby(cases x ) auto
lemma Some-eq-filter-option-iff [simp]: Some y = filter-option P x ←→ x = Somey ∧ P yby(cases x ) auto
lemma filter-conv-bind-option: filter-option P x = Option.bind x (λy . if P y thenSome y else None)by(cases x ) simp-all
1.3.3 map for the combination of set and option
fun map-option-set :: ( ′a ⇒ ′b option set) ⇒ ′a option ⇒ ′b option setwhere
map-option-set f None = None| map-option-set f (Some x ) = f x
lemma None-in-map-option-set :None ∈ map-option-set f x ←→ None ∈ Set .bind (set-option x ) f ∨ x = None
by(cases x ) simp-all
lemma None-in-map-option-set-None [intro!]: None ∈ map-option-set f Noneby simp
lemma None-in-map-option-set-Some [intro!]: None ∈ f x =⇒ None ∈ map-option-setf (Some x )by simp
lemma Some-in-map-option-set [intro!]: Some y ∈ f x =⇒ Some y ∈ map-option-setf (Some x )by simp
lemma map-option-set-singleton [simp]: map-option-set (λx . f x) y = Option.bindy f by(cases y) simp-all
lemma Some-eq-bind-conv : Some y = Option.bind x f ←→ (∃ z . x = Some z ∧ fz = Some y)by(cases x ) auto
lemma map-option-set-bind : map-option-set f (Option.bind x g) = map-option-set
12
(map-option-set f g) xby(cases x ) simp-all
lemma Some-in-map-option-set-conv : Some y ∈ map-option-set f x ←→ (∃ z . x =Some z ∧ Some y ∈ f z )by(cases x ) auto
1.3.4 join on options
definition join-option :: ′a option option ⇒ ′a optionwhere join-option x = (case x of Some y ⇒ y | None ⇒ None)
simps-of-case join-simps [simp, code]: join-option-def
lemma set-join-option [simp]: set-option (join-option x ) =⋃
(set-option ‘ set-optionx )by(cases x )(simp-all)
lemma in-set-join-option: x ∈ set-option (join-option (Some (Some x )))by simp
lemma map-join-option: map-option f (join-option x ) = join-option (map-option(map-option f ) x )by(cases x ) simp-all
lemma bind-conv-join-option: Option.bind x f = join-option (map-option f x )by(cases x ) simp-all
lemma join-conv-bind-option: join-option x = Option.bind x idby(cases x ) simp-all
context begin interpretation lifting-syntax .lemma join-option-parametric [transfer-rule]:
(rel-option (rel-option R) ===> rel-option R) join-option join-optionunfolding join-conv-bind-option[abs-def ] by transfer-proverend
lemma join-option-eq-Some [simp]: join-option x = Some y ←→ x = Some (Somey)by(cases x ) simp-all
lemma Some-eq-join-option [simp]: Some y = join-option x ←→ x = Some (Somey)by(cases x ) auto
lemma join-option-eq-None: join-option x = None ←→ x = None ∨ x = SomeNoneby(cases x ) simp-all
13
lemma None-eq-join-option: None = join-option x ←→ x = None ∨ x = SomeNoneby(cases x ) auto
1.3.5 Zip on options
function zip-option :: ′a option ⇒ ′b option ⇒ ( ′a × ′b) optionwhere
zip-option (Some x ) (Some y) = Some (x , y)| zip-option - None = None| zip-option None - = Noneby pat-completeness autotermination by lexicographic-order
lemma zip-option-eq-Some-iff [iff ]:zip-option x y = Some (a, b) ←→ x = Some a ∧ y = Some b
by(cases (x , y) rule: zip-option.cases) simp-all
lemma set-zip-option [simp]:set-option (zip-option x y) = set-option x × set-option y
by auto
lemma zip-map-option1 : zip-option (map-option f x ) y = map-option (apfst f )(zip-option x y)by(cases (x , y) rule: zip-option.cases) simp-all
lemma zip-map-option2 : zip-option x (map-option g y) = map-option (apsnd g)(zip-option x y)by(cases (x , y) rule: zip-option.cases) simp-all
lemma map-zip-option:map-option (map-prod f g) (zip-option x y) = zip-option (map-option f x ) (map-option
g y)by(simp add : zip-map-option1 zip-map-option2 option.map-comp apfst-def apsnd-defo-def prod .map-comp)
lemma zip-conv-bind-option:zip-option x y = Option.bind x (λx . Option.bind y (λy . Some (x , y)))
by(cases (x , y) rule: zip-option.cases) simp-all
context begin interpretation lifting-syntax .lemma zip-option-parametric [transfer-rule]:
(rel-option R ===> rel-option Q ===> rel-option (rel-prod R Q)) zip-optionzip-optionunfolding zip-conv-bind-option[abs-def ] by transfer-proverend
14
1.4 Predicator for function relator with relation op = on thedomain
definition fun-eq-pred :: ( ′b ⇒ bool) ⇒ ( ′a ⇒ ′b) ⇒ boolwhere fun-eq-pred P f ←→ (∀ x . P (f x ))
context begin interpretation lifting-syntax .
lemma fun-rel-eq-OO : (op = ===> A) OO (op = ===> B) = (op = ===>A OO B)by(clarsimp simp add : rel-fun-def fun-eq-iff relcompp.simps) metis
lemma Domainp-fun-rel-eq :Domainp (op = ===> A) = fun-eq-pred (Domainp A)
by(simp add : rel-fun-def Domainp.simps fun-eq-pred-def fun-eq-iff ) metis
lemma Domainp-eq : Domainp op = = (λ-. True)by(simp add : Domainp.simps fun-eq-iff )
lemma invariant-True: eq-onp (λ-. True) = op =by(simp add : eq-onp-def )
lemma fun-eq-invariant [relator-eq-onp]:op = ===> eq-onp P = eq-onp (fun-eq-pred P)
by(simp add : rel-fun-def eq-onp-def fun-eq-iff fun-eq-pred-def ) metis
lemma Quotient-set-rel-eq :assumes Quotient R Abs Rep Tshows (rel-set T ===> rel-set T ===> op =) (rel-set R) op =
proof(rule rel-funI iffI )+fix A B C Dassume AB : rel-set T A B and CD : rel-set T C Dhave ∗:
∧x y . R x y = (T x (Abs x ) ∧ T y (Abs y) ∧ Abs x = Abs y)∧
a b. T a b =⇒ Abs a = busing assms unfolding Quotient-alt-def by simp-all
assume [simp]: B = Dthus rel-set R A C
by(auto 4 4 intro!: rel-setI dest : rel-setD1 [OF AB , simplified ] rel-setD2 [OFAB , simplified ] rel-setD2 [OF CD ] rel-setD1 [OF CD ] simp add : ∗ elim!: rev-bexI )
nextassume AC : rel-set R A Cshow B = D
apply safeapply(drule rel-setD2 [OF AB ], erule bexE )apply(drule rel-setD1 [OF AC ], erule bexE )apply(drule rel-setD1 [OF CD ], erule bexE )apply(simp add : ∗)
apply(drule rel-setD2 [OF CD ], erule bexE )apply(drule rel-setD2 [OF AC ], erule bexE )
15
apply(drule rel-setD1 [OF AB ], erule bexE )apply(simp add : ∗)done
qed
lemma fun-eq-pred-parametric [transfer-rule]:assumes [transfer-rule]: bi-total Ashows ((B ===> op =) ===> (A ===> B) ===> op =) fun-eq-pred
fun-eq-predunfolding fun-eq-pred-def [abs-def ] by transfer-prover
end
1.5 A relator for sets that treats sets like predicates
context begin interpretation lifting-syntax .definition rel-pred :: ( ′a ⇒ ′b ⇒ bool) ⇒ ′a set ⇒ ′b set ⇒ boolwhere rel-pred R A B = (R ===> op =) (λx . x ∈ A) (λy . y ∈ B)
lemma rel-predI : (R ===> op =) (λx . x ∈ A) (λy . y ∈ B) =⇒ rel-pred R A Bby(simp add : rel-pred-def )
lemma rel-predD : [[ rel-pred R A B ; R x y ]] =⇒ x ∈ A ←→ y ∈ Bby(simp add : rel-pred-def rel-fun-def )
lemma Collect-parametric [transfer-rule]: ((A ===> op =) ===> rel-pred A)Collect Collectby(simp add : rel-funI rel-predI )end
1.6 List of a given length
inductive-set nlists :: ′a set ⇒ nat ⇒ ′a list set for A nwhere nlists: [[ set xs ⊆ A; length xs = n ]] =⇒ xs ∈ nlists A nhide-fact (open) nlists
lemma nlists-alt-def : nlists A n = xs. set xs ⊆ A ∧ length xs = nby(auto simp add : nlists.simps)
lemma nlists-empty : nlists n = (if n = 0 then [] else )by(auto simp add : nlists-alt-def )
lemma nlists-empty-gt0 [simp]: n > 0 =⇒ nlists n = by(simp add : nlists-empty)
lemma nlists-0 [simp]: nlists A 0 = []by(auto simp add : nlists-alt-def )
16
lemma Cons-in-nlists-Suc [simp]: x # xs ∈ nlists A (Suc n) ←→ x ∈ A ∧ xs ∈nlists A nby(simp add : nlists-alt-def )
lemma Nil-in-nlists [simp]: [] ∈ nlists A n ←→ n = 0by(auto simp add : nlists-alt-def )
lemma Cons-in-nlists-iff : x # xs ∈ nlists A n ←→ (∃n ′. n = Suc n ′ ∧ x ∈ A ∧xs ∈ nlists A n ′)by(cases n) simp-all
lemma in-nlists-Suc-iff : xs ∈ nlists A (Suc n) ←→ (∃ x xs ′. xs = x # xs ′ ∧ x ∈A ∧ xs ′ ∈ nlists A n)by(cases xs) simp-all
lemma nlists-Suc: nlists A (Suc n) = (⋃
x∈A. op # x ‘ nlists A n)by(auto 4 3 simp add : in-nlists-Suc-iff intro: rev-image-eqI )
lemma replicate-in-nlists [simp, intro]: x ∈ A =⇒ replicate n x ∈ nlists A nby(simp add : nlists-alt-def set-replicate-conv-if )
lemma nlists-eq-empty-iff [simp]: nlists A n = ←→ n > 0 ∧ A = using replicate-in-nlists by(cases n)(auto)
lemma finite-nlists [simp]: finite A =⇒ finite (nlists A n)by(induction n)(simp-all add : nlists-Suc)
lemma finite-nlistsD :assumes finite (nlists A n)shows finite A ∨ n = 0
proof(rule disjCI )assume n 6= 0then obtain n ′ where n: n = Suc n ′ by(cases n)autothen have A = hd ‘ nlists A n by(auto 4 4 simp add : nlists-Suc intro: rev-image-eqI
rev-bexI )also have finite . . . using assms ..finally show finite A .
qed
lemma finite-nlists-iff : finite (nlists A n) ←→ finite A ∨ n = 0by(auto dest : finite-nlistsD)
lemma card-nlists: card (nlists A n) = card A ˆ nproof(induction n)
case (Suc n)have card (
⋃x∈A. op # x ‘ nlists A n) = card A ∗ card (nlists A n)
proof(cases finite A)case True
then show ?thesis by(subst card-UN-disjoint)(auto simp add : card-image
17
inj-on-def )next
case Falsehence ¬ finite (
⋃x∈A. op # x ‘ nlists A n)
unfolding nlists-Suc[symmetric] by(auto dest : finite-nlistsD)then show ?thesis using False by simp
qedthen show ?case using Suc.IH by(simp add : nlists-Suc)
qed simp
lemma in-nlists-UNIV : xs ∈ nlists UNIV n ←→ length xs = nby(simp add : nlists-alt-def )
1.7 Corecursor for products
definition corec-prod :: ( ′s ⇒ ′a) ⇒ ( ′s ⇒ ′b) ⇒ ′s ⇒ ′a × ′bwhere corec-prod f g = (λs. (f s, g s))
lemma corec-prod-apply : corec-prod f g s = (f s, g s)by(simp add : corec-prod-def )
lemma corec-prod-sel [simp]:shows fst-corec-prod : fst (corec-prod f g s) = f sand snd-corec-prod : snd (corec-prod f g s) = g s
by(simp-all add : corec-prod-apply)
lemma apfst-corec-prod [simp]: apfst h (corec-prod f g s) = corec-prod (h f ) g sby(simp add : corec-prod-apply)
lemma apsnd-corec-prod [simp]: apsnd h (corec-prod f g s) = corec-prod f (h g)sby(simp add : corec-prod-apply)
lemma map-corec-prod [simp]: map-prod f g (corec-prod h k s) = corec-prod (f h) (g k) sby(simp add : corec-prod-apply)
lemma split-corec-prod [simp]: case-prod h (corec-prod f g s) = h (f s) (g s)by(simp add : corec-prod-apply)
1.8 If
named-theorems if-distribs Distributivity theorems for If
lemma if-mono-cong : [[b =⇒ x ≤ x ′; ¬ b =⇒ y ≤ y ′ ]] =⇒ If b x y ≤ If b x ′ y ′
by simp
endtheory PF-Set imports Main begin
18
lemma (in complete-lattice) lattice-partial-function-definition:partial-function-definitions (op ≤) Sup
by(unfold-locales)(auto intro: Sup-upper Sup-least)
interpretation set : partial-function-definitions op ⊆ Unionby(rule lattice-partial-function-definition)
lemma fun-lub-Sup: fun-lub Sup = (Sup :: - ⇒ - :: complete-lattice)by(fastforce simp add : fun-lub-def fun-eq-iff Sup-fun-def intro: Sup-eqI SUP-upperSUP-least)
lemma set-admissible: set .admissible (λf :: ′a ⇒ ′b set . ∀ x y . y ∈ f x −→ P x y)by(rule ccpo.admissibleI )(auto simp add : fun-lub-Sup)
abbreviation mono-set ≡ monotone (fun-ord op ⊆) op ⊆
lemma fixp-induct-set-scott :fixes F :: ′c ⇒ ′cand U :: ′c ⇒ ′b ⇒ ′a setand C :: ( ′b ⇒ ′a set) ⇒ ′cand P :: ′b ⇒ ′a ⇒ booland x and yassumes mono:
∧x . mono-set (λf . U (F (C f )) x )
and eq : f ≡ C (ccpo.fixp (fun-lub Sup) (fun-ord op ≤) (λf . U (F (C f ))))and inverse2 :
∧f . U (C f ) = f
and step:∧
f x y . [[∧
x y . y ∈ U f x =⇒ P x y ; y ∈ U (F f ) x ]] =⇒ P x yand enforce-variable-ordering : x = xand elem: y ∈ U f xshows P x y
using step elem set .fixp-induct-uc[of U F C , OF mono eq inverse2 set-admissible,of P ]by blast
lemma fixp-Sup-le:defines le ≡ (op ≤ :: - :: complete-lattice ⇒ -)shows ccpo.fixp Sup le = ccpo-class.fixp
proof −have class.ccpo Sup le op < unfolding le-def by unfold-localesthus ?thesisby(simp add : ccpo.fixp-def fixp-def ccpo.iterates-def iterates-def ccpo.iteratesp-def
iteratesp-def fun-eq-iff le-def )qed
lemma fun-ord-le: fun-ord op ≤ = op ≤by(auto simp add : fun-ord-def fun-eq-iff le-fun-def )
lemma monotone-le-le: monotone op ≤ op ≤ = monoby(simp add : monotone-def [abs-def ] mono-def [abs-def ])
19
lemma fixp-induct-set :fixes F :: ′c ⇒ ′cand U :: ′c ⇒ ′b ⇒ ′a setand C :: ( ′b ⇒ ′a set) ⇒ ′cand P :: ′b ⇒ ′a ⇒ booland x and yassumes mono:
∧x . mono-set (λf . U (F (C f )) x )
and eq : f ≡ C (ccpo.fixp (fun-lub Sup) (fun-ord op ≤) (λf . U (F (C f ))))and inverse2 :
∧f . U (C f ) = f
and step:∧
f ′ x y . [[∧
x . U f ′ x = U f ′ x ; y ∈ U (F (C (inf (U f ) (λx . y . Px y)))) x ]] =⇒ P x y
— partial function requires a quantifier over f’, so let’s have a fake oneand elem: y ∈ U f xshows P x y
proof −from monohave mono ′: mono (λf . U (F (C f )))
by(simp add : fun-ord-le monotone-le-le mono-def le-fun-def )hence eq ′: f ≡ C (lfp (λf . U (F (C f ))))using eq unfolding fun-ord-le fun-lub-Sup fixp-Sup-le by(simp add : lfp-eq-fixp)
let ?f = C (lfp (λf . U (F (C f ))))have step ′:
∧x y . [[ y ∈ U (F (C (inf (U ?f ) (λx . y . P x y)))) x ]] =⇒ P x y
unfolding eq ′[symmetric] by(rule step[OF refl ])
let ?P = λx . y . P x yfrom mono ′ have lfp (λf . U (F (C f ))) ≤ ?P
by(rule lfp-induct)(auto intro!: le-funI step ′ simp add : inverse2 )with elem show ?thesis
by(subst (asm) eq ′)(auto simp add : inverse2 le-fun-def )qed
declaration 〈〈 Partial-Function.init set @term set .fixp-fun@term set .mono-body @thm set .fixp-rule-uc @thm set .fixp-induct-uc(SOME @thm fixp-induct-set) 〉〉
lemma [partial-function-mono]:shows insert-mono: mono-set A =⇒ mono-set (λf . insert x (A f ))and UNION-mono: [[mono-set B ;
∧y . mono-set (λf . C y f )]] =⇒ mono-set (λf .⋃
y∈B f . C y f )and set-bind-mono: [[mono-set B ;
∧y . mono-set (λf . C y f )]] =⇒ mono-set (λf .
Set .bind (B f ) (λy . C y f ))and Un-mono: [[ mono-set A; mono-set B ]] =⇒ mono-set (λf . A f ∪ B f )and Int-mono: [[ mono-set A; mono-set B ]] =⇒ mono-set (λf . A f ∩ B f )and Diff-mono1 : mono-set A =⇒ mono-set (λf . A f − X )and image-mono: mono-set A =⇒ mono-set (λf . g ‘ A f )and vimage-mono: mono-set A =⇒ mono-set (λf . g −‘ A f )
20
unfolding bind-UNIONby(blast intro!: monotoneI dest : monotoneD)+
partial-function (set) test :: ′a list ⇒ nat ⇒ bool ⇒ int setwhere
test xs i j = insert 4 (test [] 0 j ∪ test [] 1 True ∩ test [] 2 False − 5 ∪ uminus‘ test [undefined ] 0 True ∪ uminus −‘ test [] 1 False)
interpretation coset : partial-function-definitions op ⊇ Interby(rule complete-lattice.lattice-partial-function-definition[OF dual-complete-lattice])
lemma fun-lub-Inf : fun-lub Inf = (Inf :: - ⇒ - :: complete-lattice)by(auto simp add : fun-lub-def fun-eq-iff Inf-fun-def intro: Inf-eqI INF-lower INF-greatest)
lemma fun-ord-ge: fun-ord op ≥ = op ≥by(auto simp add : fun-ord-def fun-eq-iff le-fun-def )
lemma coset-admissible: coset .admissible (λf :: ′a ⇒ ′b set . ∀ x y . P x y −→ y ∈f x )by(rule ccpo.admissibleI )(auto simp add : fun-lub-Inf )
abbreviation mono-coset ≡ monotone (fun-ord op ⊇) op ⊇
lemma gfp-eq-fixp:fixes f :: ′a :: complete-lattice ⇒ ′aassumes f : monotone op ≥ op ≥ fshows gfp f = ccpo.fixp Inf op ≥ f
proof (rule antisym)from f have f ′: mono f by(simp add : mono-def monotone-def )
interpret ccpo Inf op ≥ mk-less op ≥ :: ′a ⇒ -by(rule ccpo)(rule complete-lattice.lattice-partial-function-definition[OF dual-complete-lattice])show ccpo.fixp Inf op ≥ f ≤ gfp f
by(rule gfp-upperbound)(subst fixp-unfold [OF f ], rule order-refl)
show gfp f ≤ ccpo.fixp Inf op ≥ fby(rule fixp-lowerbound [OF f ])(subst gfp-unfold [OF f ′], rule order-refl)
qed
lemma fixp-coinduct-set :fixes F :: ′c ⇒ ′cand U :: ′c ⇒ ′b ⇒ ′a setand C :: ( ′b ⇒ ′a set) ⇒ ′cand P :: ′b ⇒ ′a ⇒ booland x and yassumes mono:
∧x . mono-coset (λf . U (F (C f )) x )
and eq : f ≡ C (ccpo.fixp (fun-lub Inter) (fun-ord op ≥) (λf . U (F (C f ))))and inverse2 :
∧f . U (C f ) = f
21
and step:∧
f ′ x y . [[∧
x . U f ′ x = U f ′ x ; ¬ P x y ]] =⇒ y ∈ U (F (C (sup(λx . y . ¬ P x y) (U f )))) x
— partial function requires a quantifier over f’, so let’s have a fake oneand elem: y /∈ U f xshows P x y
using elemproof(rule contrapos-np)
have mono ′: monotone (op ≥) (op ≥) (λf . U (F (C f )))and mono ′′: mono (λf . U (F (C f )))using mono by(simp-all add : monotone-def fun-ord-def le-fun-def mono-def )
hence eq ′: U f = gfp (λf . U (F (C f )))apply(subst eq) by(simp add : fun-lub-Inf fun-ord-ge gfp-eq-fixp inverse2 )
let ?P = λx . y . ¬ P x yhave ?P ≤ gfp (λf . U (F (C f )))
using mono ′′ by(rule coinduct)(auto intro!: le-funI dest : step[OF refl ] simpadd : eq ′)
moreoverassume ¬ P x yultimately show y ∈ U f x by(auto simp add : le-fun-def eq ′)
qed
declaration 〈〈 Partial-Function.init coset @term coset .fixp-fun@term coset .mono-body @thm coset .fixp-rule-uc @thm coset .fixp-induct-uc(SOME @thm fixp-coinduct-set) 〉〉
abbreviation mono-set ′ ≡ monotone (fun-ord op ⊇) op ⊇
lemma [partial-function-mono]:shows insert-mono ′: mono-set ′ A =⇒ mono-set ′ (λf . insert x (A f ))and UNION-mono ′: [[mono-set ′ B ;
∧y . mono-set ′ (λf . C y f )]] =⇒ mono-set ′
(λf .⋃
y∈B f . C y f )and set-bind-mono ′: [[mono-set ′ B ;
∧y . mono-set ′ (λf . C y f )]] =⇒ mono-set ′
(λf . Set .bind (B f ) (λy . C y f ))and Un-mono ′: [[ mono-set ′ A; mono-set ′ B ]] =⇒ mono-set ′ (λf . A f ∪ B f )and Int-mono ′: [[ mono-set ′ A; mono-set ′ B ]] =⇒ mono-set ′ (λf . A f ∩ B f )
unfolding bind-UNIONby(blast intro!: monotoneI dest : monotoneD)+
partial-function (coset) test2 :: nat ⇒ nat setwhere test2 x = insert x (test2 (Suc x ))
lemma test2-coinduct :assumes P x yand ∗:
∧x y . P x y =⇒ y = x ∨ (P (Suc x ) y ∨ y ∈ test2 (Suc x ))
shows y ∈ test2 xusing 〈P x y〉
apply(rule contrapos-pp)apply(erule test2 .raw-induct [rotated ])
22
apply(simp add : ∗)done
endtheory Monad-Locale imports
Misc∼∼/src/HOL/Library/Monad-Syntax
begin
context begin interpretation lifting-syntax .lemma rel-fun-conversep:
(Aˆ−−1 ===> Bˆ−−1 ) = (A ===> B)ˆ−−1by(auto simp add : rel-fun-def fun-eq-iff )end
lemma left-unique-Grp [iff ]:left-unique (BNF-Def .Grp A f ) ←→ inj-on f A
unfolding Grp-def left-unique-def by(auto simp add : inj-on-def )
lemma right-unique-Grp [simp, intro!]: right-unique (BNF-Def .Grp A f )by(simp add : Grp-def right-unique-def )
lemma bi-unique-Grp [iff ]:bi-unique (BNF-Def .Grp A f ) ←→ inj-on f A
by(simp add : bi-unique-alt-def )
lemma left-total-Grp [iff ]:left-total (BNF-Def .Grp A f ) ←→ A = UNIV
by(auto simp add : left-total-def Grp-def )
lemma right-total-Grp [iff ]:right-total (BNF-Def .Grp A f ) ←→ f ‘ A = UNIV
by(auto simp add : right-total-def BNF-Def .Grp-def image-def )
lemma bi-total-Grp [iff ]:bi-total (BNF-Def .Grp A f ) ←→ A = UNIV ∧ surj f
by(auto simp add : bi-total-alt-def )
lemma left-unique-vimage2p [simp]:[[ left-unique P ; inj f ]] =⇒ left-unique (BNF-Def .vimage2p f g P)
unfolding vimage2p-Grp by(intro left-unique-OO) simp-all
lemma right-unique-vimage2p [simp]:[[ right-unique P ; inj g ]] =⇒ right-unique (BNF-Def .vimage2p f g P)
unfolding vimage2p-Grp by(intro right-unique-OO) simp-all
lemma bi-unique-vimage2p [simp]:[[ bi-unique P ; inj f ; inj g ]] =⇒ bi-unique (BNF-Def .vimage2p f g P)
unfolding bi-unique-alt-def by simp
23
lemma left-total-vimage2p [simp]:[[ left-total P ; surj g ]] =⇒ left-total (BNF-Def .vimage2p f g P)
unfolding vimage2p-Grp by(intro left-total-OO) simp-all
lemma right-total-vimage2p [simp]:[[ right-total P ; surj f ]] =⇒ right-total (BNF-Def .vimage2p f g P)
unfolding vimage2p-Grp by(intro right-total-OO) simp-all
lemma bi-total-vimage2p [simp]:[[ bi-total P ; surj f ; surj g ]] =⇒ bi-total (BNF-Def .vimage2p f g P)
unfolding bi-total-alt-def by simp
lemma vimage2p-eq [simp]:inj f =⇒ BNF-Def .vimage2p f f op = = op =
by(auto simp add : vimage2p-def fun-eq-iff inj-on-def )
lemma vimage2p-conversep: BNF-Def .vimage2p f g Rˆ−−1 = (BNF-Def .vimage2pg f R)ˆ−−1by(simp add : vimage2p-def fun-eq-iff )
named-theorems record-parametricity unfold theorems for record-parametricitynamed-theorems record-typedef type definition theorems for record parametricity
context begin interpretation lifting-syntax .lemma vimage2p-abs-rep:
assumes h: (Y ===> X1 ===> X2 ) h1 h2and 1 : type-definition f1 g1 UNIVand 2 : type-definition f2 g2 UNIVshows (Y ===> BNF-Def .vimage2p f1 f2 X1 ===> BNF-Def .vimage2p f1 f2
X2 ) (λx . g1 (h1 x f1 )) (λx . g2 (h2 x f2 ))apply(rule rel-funI )apply(rule comp-transfer [THEN rel-funD , THEN rel-funD ])apply(rule Abs-transfer [OF 1 2 ])
apply(rule comp-transfer [THEN rel-funD , THEN rel-funD ])apply(erule rel-funD [OF h])
apply(rule vimage2p-rel-fun)done
lemma apsnd-parametric [transfer-rule]:((A ===> B) ===> rel-prod C A ===> rel-prod C B) apsnd apsnd
unfolding apsnd-def [abs-def ] by transfer-prover
endmethod record-parametricity uses unfold typedefs =
(unfold unfold record-parametricityiso-tuple-fst-def iso-tuple-snd-def tuple-iso-tuple-defiso-tuple-fst-update-def [abs-def ] iso-tuple-snd-update-def [abs-def ]
24
iso-tuple-cons-defrepr .simps abst .simps o-assoc[symmetric] id-o o-id ,
((assumption | ruletypedefs record-typedeffst-transfer [THEN comp-transfer [THEN rel-funD , THEN rel-funD ]]snd-transfer [THEN comp-transfer [THEN rel-funD , THEN rel-funD ]]comp-transfer [THEN rel-funD , THEN rel-funD ]apfst-parametricapsnd-parametriccurry-transfer [THEN rel-funD , THEN rel-funD ]
curry-transfer [THEN rel-funD , THEN rel-funD , THEN rel-funD , OF id-transfer ]vimage2p-abs-repAbs-transfervimage2p-rel-funrel-funI
)+)?)
attribute-setup locale-witness = 〈Scan.succeed Locale.witness-add 〉
2 Monomorphic monads and monad transformers
2.1 Plain monads
record ( ′a, ′m) monad =bind :: ′m ⇒ ( ′a ⇒ ′m) ⇒ ′mreturn :: ′a ⇒ ′m
context begin local-setup 〈Local-Theory .map-background-naming (Name-Space.mandatory-pathmonad)〉
definition lift :: ( ′a, ′m, ′more) monad-ext ⇒ ( ′a ⇒ ′a) ⇒ ′m ⇒ ′mwhere lift m f x = bind m x (return m f )end
locale monad-syntax = fixes m :: ( ′a, ′m, ′more) monad-scheme beginadhoc-overloading Monad-Syntax .bind bind mend
locale monad = fixes m :: ( ′a, ′m, ′more) monad-schemeassumes bind-assoc:
∧(x :: ′m) f g . bind m (bind m x f ) g = bind m x (λy . bind
m (f y) g)and return-bind :
∧x f . bind m (return m x ) f = f x
and bind-return:∧
x . bind m x (return m) = x
lemma inj-Rep-monad-ext [simp]: inj Rep-monad-extby(simp add : inj-on-def Rep-monad-ext-inject)
lemma surj-Rep-monad-ext [simp]: surj Rep-monad-extby(rule surjI [where f =Abs-monad-ext ])(simp add : Abs-monad-ext-inverse)
25
context begin interpretation lifting-syntax .
definition rel-monad-ext:: ( ′a ⇒ ′b ⇒ bool) ⇒ ( ′m1 ⇒ ′m2 ⇒ bool) ⇒ ( ′more1 ⇒ ′more2 ⇒ bool)⇒ ( ′a, ′m1 , ′more1 ) monad-ext ⇒ ( ′b, ′m2 , ′more2 ) monad-ext ⇒ bool
where [record-parametricity ]:rel-monad-ext A M X =BNF-Def .vimage2p Rep-monad-ext Rep-monad-ext (rel-prod (rel-prod (M ===>
(A ===> M ) ===> M ) (A ===> M )) X )
declaremonad-ext-Tuple-Iso-def [record-parametricity ]monad .select-defs [record-parametricity ]monad .update-defs [record-parametricity ]type-definition-monad-ext [record-typedef ]
abbreviation rel-monad :: ( ′a ⇒ ′b ⇒ bool) ⇒ ( ′m1 ⇒ ′m2 ⇒ bool)⇒ ( ′a, ′m1 ) monad ⇒ ( ′b, ′m2 ) monad ⇒ bool
where rel-monad A M == rel-monad-ext A M op =
lemma rel-monad-ext-conversep:rel-monad-ext Aˆ−−1 Mˆ−−1 Xˆ−−1 = (rel-monad-ext A M X )ˆ−−1
unfolding rel-monad-ext-def rel-fun-conversep prod .rel-conversep vimage2p-conversep..
lemma left-unique-rel-monad-ext [transfer-rule]:[[ left-unique X ; left-unique A; left-total A; left-unique M ; left-total M ]]=⇒ left-unique (rel-monad-ext A M X )
unfolding rel-monad-ext-defby(simp add : prod .left-unique-rel left-unique-fun left-total-fun)
lemma right-unique-rel-monad-ext [transfer-rule]:[[ right-unique X ; right-unique A; right-total A; right-unique M ; right-total M ]]=⇒ right-unique (rel-monad-ext A M X )
unfolding rel-monad-ext-defby(simp add : prod .right-unique-rel right-unique-fun right-total-fun)
lemma left-total-rel-monad-ext [transfer-rule]:[[ left-total X ; left-unique A; left-total A; left-unique M ; left-total M ]]=⇒ left-total (rel-monad-ext A M X )
unfolding rel-monad-ext-defby(simp add : prod .left-total-rel left-total-fun left-unique-fun)
lemma right-total-rel-monad-ext [transfer-rule]:[[ right-total X ; right-unique A; right-total A; right-unique M ; right-total M ]]=⇒ right-total (rel-monad-ext A M X )
unfolding rel-monad-ext-def
26
by(simp add : prod .right-total-rel right-total-fun right-unique-fun)
lemma rel-monad-ext-eq [relator-eq ]:rel-monad-ext op = op = op = = op =
unfolding rel-monad-ext-def rel-fun-eq prod .rel-eqby(simp add : eq-OO eq-alt [symmetric])
lemma bind-monad-parametric [transfer-rule]:(rel-monad-ext A M X ===> M ===> (A ===> M ) ===> M ) bind bind
by(record-parametricity)
lemma return-monad-parametric [transfer-rule]:(rel-monad-ext A M X ===> A ===> M ) return return
by(record-parametricity)
lemma more-monad-parametric [transfer-rule]:(rel-monad-ext A M X ===> X ) more more
by(record-parametricity)
lemma lift-monad-parametric [transfer-rule]:(rel-monad-ext A M X ===> (A ===> A) ===> M ===> M ) monad .lift
monad .liftunfolding monad .lift-def [abs-def ] by transfer-prover
lemma bind-update-parametric [transfer-rule]:(((M ===> (A ===> M ) ===> M ) ===> (M ===> (A ===> M ) ===>
M ))===> rel-monad-ext A M X ===> rel-monad-ext A M X ) bind-update bind-update
by record-parametricity
lemma return-update-parametric [transfer-rule]:(((A ===> M ) ===> (A ===> M )) ===> rel-monad-ext A M X ===>
rel-monad-ext A M X )return-update return-update
by record-parametricity
lemma more-update-monad-parametric [transfer-rule]:((X ===> X ′) ===> rel-monad-ext A M X ===> rel-monad-ext A M X ′)more-update more-update
by record-parametricity
lemma monad-ext-parametric [transfer-rule]:((M ===> (A ===> M ) ===> M ) ===> (A ===> M ) ===> X ===>
rel-monad-ext A M X )monad-ext monad-ext
by(record-parametricity unfold : monad-ext-def [abs-def ])
lemma make-monad-parametric [transfer-rule]:((M ===> (A ===> M ) ===> M ) ===> (A ===> M ) ===> rel-monad
27
A M ) make makeunfolding monad .defs[abs-def ] by transfer-prover
lemma extend-monad-parametric [transfer-rule]:(rel-monad A M ===> X ===> rel-monad-ext A M X ) extend extend
unfolding monad .defs[abs-def ] by transfer-prover
lemma fields-monad-parametric [transfer-rule]:((M ===> (A ===> M ) ===> M ) ===> (A ===> M ) ===> rel-monad
A M ) fields fieldsunfolding monad .defs[abs-def ] by transfer-prover
lemma truncate-monad-parametric [transfer-rule]:(rel-monad-ext A M X ===> rel-monad A M ) truncate truncate
unfolding monad .defs[abs-def ] by transfer-prover
end
2.1.1 Identity monad
definition identity-monad-ext :: ′more ⇒ ( ′a, ′a, ′more) monad-extwhere
∧more. identity-monad-ext more = (|bind = λx f . f x , return = λx . x , . . .
= more|)
abbreviation identity-monad :: ( ′a, ′a) monadwhere identity-monad ≡ identity-monad-ext ()
lemma identity-sel [simp]:shows bind-identity :
∧more. bind (identity-monad-ext more) = (λx f . f x )
and return-identity :∧
more. return (identity-monad-ext more) = (λx . x )and more-identity :
∧more. monad .more (identity-monad-ext more) = more
by(simp-all add : identity-monad-ext-def )
lemma monad-identity [simp, intro!, locale-witness]:∧
more. monad (identity-monad-extmore)by unfold-locales simp-all
context begin interpretation lifting-syntax .lemma identity-monad-parametric [transfer-rule]:
(X ===> rel-monad-ext A A X ) identity-monad-ext identity-monad-extunfolding identity-monad-ext-def [abs-def ] by transfer-proverend
2.2 Monads with failure
record ( ′a, ′m) monad-fail = ( ′a, ′m) monad +fail :: ′m
copy-bnf ( ′m, ′mpre) monad-fail-ext
28
declaretype-definition-monad-fail-ext [record-typedef ]rel-monad-fail-ext-def [record-parametricity ]monad-fail-ext-Tuple-Iso-def [record-parametricity ]monad-fail .select-defs [record-parametricity ]monad-fail .update-defs [record-parametricity ]
abbreviation rel-monad-fail-scheme:: ( ′a ⇒ ′b ⇒ bool) ⇒ ( ′m1 ⇒ ′m2 ⇒ bool) ⇒ ( ′more1 ⇒ ′more2 ⇒ bool)⇒ ( ′a, ′m1 , ′more1 ) monad-fail-scheme ⇒ ( ′b, ′m2 , ′more2 ) monad-fail-scheme⇒ boolwhere rel-monad-fail-scheme A M X ≡ rel-monad-ext A M (rel-monad-fail-ext MX )
abbreviation rel-monad-fail:: ( ′a ⇒ ′b ⇒ bool) ⇒ ( ′m1 ⇒ ′m2 ⇒ bool)⇒ ( ′a, ′m1 ) monad-fail ⇒ ( ′b, ′m2 ) monad-fail ⇒ bool
where rel-monad-fail A M ≡ rel-monad-fail-scheme A M op =
context begin interpretation lifting-syntax .lemma fail-monad-parametric [transfer-rule]:
(rel-monad-fail-scheme A M X ===> M ) fail failby record-parametricity
lemma more-monad-fail-parametric [transfer-rule]:(rel-monad-fail-scheme A M X ===> X ) more more
by record-parametricity
lemma fail-update-parametric [transfer-rule]:((M ===> M ) ===> rel-monad-fail-scheme A M X ===> rel-monad-fail-scheme
A M X )fail-update fail-update
by record-parametricity
lemma more-update-monad-fail-parametric [transfer-rule]:((X ===> X ′) ===> rel-monad-fail-scheme A M X ===> rel-monad-fail-scheme
A M X ′) more-update more-updateby record-parametricity
lemma monad-fail-ext-parametric [transfer-rule]:(M ===> X ===> rel-monad-fail-ext M X ) monad-fail-ext monad-fail-ext
by(record-parametricity unfold : monad-fail-ext-def [abs-def ])
lemma make-monad-fail-parametric [transfer-rule]:((M ===> (A ===> M ) ===> M ) ===> (A ===> M ) ===> M ===>
rel-monad-fail A M ) make makeunfolding monad-fail .defs[abs-def ] by transfer-prover
lemma extend-monad-fail-parametric [transfer-rule]:
29
(rel-monad-fail A M ===> X ===> rel-monad-fail-scheme A M X ) extendextendunfolding monad-fail .defs[abs-def ] by transfer-prover
lemma fields-monad-fail-parametric [transfer-rule]:(M ===> rel-monad-fail-ext M op =) fields fields
unfolding monad-fail .defs[abs-def ] by transfer-prover
lemma truncate-monad-fail-parametric [transfer-rule]:(rel-monad-fail-scheme A M X ===> rel-monad-fail A M ) truncate truncate
unfolding monad-fail .defs[abs-def ] by transfer-prover
end
context begin local-setup 〈Local-Theory .map-background-naming (Name-Space.mandatory-pathmonad)〉
definition bind-option :: ( ′a, ′m, ′more) monad-fail-scheme ⇒ ′b option ⇒ ( ′b ⇒′m) ⇒ ′mwhere bind-option m x f = (case x of None ⇒ fail m | Some x ′⇒ f x ′)
simps-of-case bind-option-simps [simp]: bind-option-def
interpretation lifting-syntax .lemma bind-option-parametric [transfer-rule]:(rel-monad-fail-scheme A M X ===> rel-option B ===> (B ===> M ) ===>
M ) bind-option bind-optionunfolding bind-option-def [abs-def ] by transfer-proverend
locale monad-fail-syntax = monad-syntax m for m :: ( ′a, ′m, ′more) monad-fail-schemebeginadhoc-overloading Monad-Syntax .bind monad .bind-option mend
locale monad-fail = monad m for m :: ( ′a, ′m, ′more) monad-fail-scheme +assumes fail-bind :
∧f . bind m (fail m) f = fail m
2.3 The option monad
definition option-monad-ext :: ′more ⇒ ( ′a, ′a option, ′more) monad-fail-schemewhere
∧more. option-monad-ext more = (|bind = Option.bind , return = Some,
fail = None, . . . = more|)
abbreviation option-monad :: ( ′a, ′a option) monad-fail where option-monad ≡option-monad-ext ()
lemma option-monad-sel [simp]:shows bind-option-monad :
∧more. bind (option-monad-ext more) = Option.bind
and return-option-monad :∧
more. return (option-monad-ext more) = Some
30
and fail-option-monad :∧
more. fail (option-monad-ext more) = Noneand more-option-monad :
∧more. monad-fail .more (option-monad-ext more) =
moreby(simp-all add : option-monad-ext-def )
lemma option-monad [simp, intro!, locale-witness]:∧
more. monad (option-monad-extmore)by unfold-locales simp-all
lemma option-monad-fail [simp, intro!, locale-witness]:∧
more. monad-fail (option-monad-extmore)by unfold-locales simp
context begin interpretation lifting-syntax .lemma option-monad-ext-parametric [transfer-rule]:(X ===> rel-monad-fail-scheme A (rel-option A) X ) option-monad-ext option-monad-ext
unfolding option-monad-ext-def [abs-def ] by transfer-proverend
lemma bind-option-option [simp]:∧
more. monad .bind-option (option-monad-extmore) = Option.bindby(simp add : monad .bind-option-def fun-eq-iff split : option.split)
lemma monad-lift-option [simp]:∧
more. monad .lift option-monad = map-optionby(simp add : monad .lift-def map-conv-bind-option fun-eq-iff )
2.4 The set monad
definition set-monad-ext :: ′more ⇒ ( ′a, ′a set , ′more) monad-fail-schemewhere
∧more. set-monad-ext more = (|bind = UNION , return = λx . x, fail =
, . . . = more|)
abbreviation set-monad :: ( ′a, ′a set) monad-fail where set-monad ≡ set-monad-ext()
lemma set-monad-sel [simp]:shows bind-set-monad :
∧more. bind (set-monad-ext more) = UNION
and return-set-monad :∧
more. return (set-monad-ext more) = (λx . x)and fail-set-monad :
∧more. fail (set-monad-ext more) =
and more-set-monad :∧
more. monad-fail .more (set-monad-ext more) = moreby(simp-all add : set-monad-ext-def )
lemma set-monad [simp, intro!, locale-witness]:∧
more. monad (set-monad-extmore)by unfold-locales auto
lemma set-monad-fail [simp, intro!, locale-witness]:∧
more. monad-fail (set-monad-extmore)by unfold-locales simp
31
context begin interpretation lifting-syntax .lemma set-monad-ext-parametric [transfer-rule]:
(X ===> rel-monad-fail-scheme A (rel-set A) X ) set-monad-ext set-monad-extunfolding set-monad-ext-def [abs-def ] by transfer-proverend
lemma bind-option-set [simp]:∧
more. monad .bind-option (set-monad-ext more)= (λx . UNION (set-option x ))by(simp add : monad .bind-option-def fun-eq-iff split : option.split)
lemma monad-lift-set [simp]:∧
more. monad .lift (set-monad-ext more) = imageby(simp add : monad .lift-def image-eq-UN o-def fun-eq-iff )
2.5 Monad homomorphism
locale monad-hom = m1 : monad m1 + m2 : monad m2for m1 :: ( ′a, ′m1 , ′more1 ) monad-schemeand m2 :: ( ′a, ′m2 , ′more2 ) monad-schemeand h :: ′m1 ⇒ ′m2+assumes hom-return:
∧x . h (return m1 x ) = return m2 x
and hom-bind :∧
x f . h (bind m1 x f ) = bind m2 (h x ) (h f )begin
lemma hom-lift : h (monad .lift m1 f x ) = monad .lift m2 f (h x )by(simp add : monad .lift-def hom-bind hom-return o-def )
end
locale monad-fail-hom = m1 : monad-fail m1 + m2 : monad-fail m2 + monad-homm1 m2 h
for m1 :: ( ′a, ′m1 , ′more1 ) monad-fail-schemeand m2 :: ( ′a, ′m2 , ′more2 ) monad-fail-schemeand h :: ′m1 ⇒ ′m2+assumes hom-fail : h (fail m1 ) = fail m2
begin
lemma hom-bind-option: h (monad .bind-option m1 x f ) = monad .bind-option m2x (h f )by(cases x )(simp-all add : hom-fail)
end
32
3 Monad transformers
3.1 The state monad transformer
datatype ( ′s, ′m) ST = ST (run-state: ′s ⇒ ′m)for rel : rel-ST ′
hide-const (open) ST
primrec bind-state :: ( ′a × ′s, ′m, ′more) monad-scheme ⇒ ( ′s, ′m) ST ⇒ ( ′a⇒ ( ′s, ′m) ST ) ⇒ ( ′s, ′m) STwhere bind-state m (ST .ST x ) f = ST .ST (λs. bind m (x s) (λ(a, s ′). run-state(f a) s ′))
lemma run-bind-state [simp]: run-state (bind-state m x f ) s = bind m (run-statex s) (λ(a, s ′). run-state (f a) s ′)by(cases x ) simp
definition return-state :: ( ′a × ′s, ′m, ′more) monad-scheme ⇒ ′a ⇒ ( ′s, ′m) STwhere return-state m x = ST .ST (λs. return m (x , s))
lemma run-return-state [simp]: run-state (return-state m x ) s = return m (x , s)by(simp add : return-state-def )
contextfixes m :: ( ′a × ′s, ′m, ′more) monad-schemeassumes monad m
begininterpretation monad m by fact
lemma bind-state-assoc [simp]: bind-state m (bind-state m x f ) g = bind-state mx (λy . bind-state m (f y) g)by(rule ST .expand ext)+(simp add : bind-assoc split-def )
lemma return-bind-state [simp]: bind-state m (return-state m x ) f = f xby(rule ST .expand ext)+(simp add : return-bind)
lemma bind-return-state [simp]: bind-state m x (return-state m) = xby(rule ST .expand ext)+(simp add : bind-return)
end
context fixes m :: ( ′a × ′s, ′m, ′more) monad-fail-scheme begin
definition fail-state :: ( ′s, ′m) STwhere fail-state = ST .ST (λ-. fail m)
lemma run-fail-state [simp]: run-state fail-state s = fail mby(simp add : fail-state-def )
33
context assumes monad-fail m begininterpretation monad-fail m by fact
lemma fail-bind-state [simp]: bind-state m fail-state f = fail-stateby(rule ST .expand ext)+(simp add : fail-bind)
endend
context begin interpretation lifting-syntax .
inductive rel-ST :: ( ′s1 ⇒ ′s2 ⇒ bool) ⇒ ( ′m1 ⇒ ′m2 ⇒ bool) ⇒ ( ′s1 , ′m1 )ST ⇒ ( ′s2 , ′m2 ) ST ⇒ bool
for S M x ywhere (S ===> M ) (run-state x ) (run-state y) =⇒ rel-ST S M x y
inductive-simps rel-ST-ST1 : rel-ST S M (ST .ST x ) yinductive-simps rel-ST-ST2 : rel-ST S M x (ST .ST y)inductive-simps rel-ST-simps [simp]: rel-ST S M (ST .ST x ) (ST .ST y)
lemma rel-ST-alt-def : rel-ST S M = BNF-Def .vimage2p run-state run-state (S===> M )apply(rule ext)+subgoal for x y
apply(cases x ; cases y)apply(simp add : rel-ST .simps vimage2p-def )done
done
lemma inj-run-state [simp]: inj run-stateby(auto simp add : inj-on-def intro: ST .expand)
lemma surj-run-state [simp]: surj run-stateby(rule surjI [where f =ST .ST ]) simp
lemma rel-ST-eq [relator-eq ]: rel-ST op = op = = op =unfolding rel-ST-alt-def rel-fun-eq by (simp add : eq-OO eq-alt [symmetric])
lemma left-unique-rel-ST [transfer-rule]:[[ left-total S ; left-unique M ]] =⇒ left-unique (rel-ST S M )
unfolding rel-ST-alt-def by(simp add : left-unique-fun)
lemma right-unique-rel-ST [transfer-rule]:[[ right-total S ; right-unique M ]] =⇒ right-unique (rel-ST S M )
unfolding rel-ST-alt-def by(simp add : right-unique-fun)
lemma bi-unique-rel-ST [transfer-rule]:[[ bi-total S ; bi-unique M ]] =⇒ bi-unique (rel-ST S M )
unfolding bi-unique-alt-def bi-total-alt-def by(simp add : left-unique-rel-ST right-unique-rel-ST )
34
lemma right-total-rel-ST [transfer-rule]:[[ right-unique S ; right-total M ]] =⇒ right-total (rel-ST S M )
unfolding rel-ST-alt-def by(simp add : right-total-fun)
lemma left-total-rel-ST [transfer-rule]:[[ left-unique S ; left-total M ]] =⇒ left-total (rel-ST S M )
unfolding rel-ST-alt-def by(simp add : left-total-fun)
lemma bi-total-rel-ST [transfer-rule]:[[ bi-unique S ; bi-total M ]] =⇒ bi-total (rel-ST S M )
unfolding bi-unique-alt-def bi-total-alt-def by(simp add : left-total-rel-ST right-total-rel-ST )
lemma run-state-parametric [transfer-rule]: (rel-ST S M ===> S ===> M )run-state run-stateby(rule rel-funI )(erule rel-ST .cases)
context begin local-setup 〈Local-Theory .map-background-naming (Name-Space.mandatory-pathST )〉
lemma ST-parametric [transfer-rule]: ((S ===> M ) ===> rel-ST S M ) ST .STST .STby(rule rel-funI )(rule rel-ST .intros; simp)end
lemma rec-ST-parametric [transfer-rule]:(((S ===> M ) ===> C ) ===> rel-ST S M ===> C ) rec-ST rec-ST
apply(rule rel-funI )+subgoal for f g x y
apply(cases x )apply(cases y)apply(auto dest : rel-funD)done
done
lemma bind-state-parametric [transfer-rule]:(rel-monad-ext (rel-prod A S ) M X ===> rel-ST S M ===> (A ===> rel-ST
S M ) ===> rel-ST S M ) bind-state bind-stateunfolding bind-state-def [abs-def ] by transfer-prover
lemma return-state-parametric [transfer-rule]:(rel-monad-ext (rel-prod A S ) M X ===> A ===> rel-ST S M ) return-state
return-stateunfolding return-state-def [abs-def ] by transfer-prover
lemma fail-state-parametric [transfer-rule]:(rel-monad-fail-scheme (rel-prod A S ) M X ===> rel-ST S M ) fail-state fail-state
unfolding fail-state-def [abs-def ] by transfer-prover
end
35
definition ST-ext :: (( ′a × ′s, ′m, ′more) monad-scheme ⇒ ′more ′)⇒ ( ′a × ′s, ′m, ′more) monad-scheme ⇒ ( ′a, ( ′s, ′m) ST , ′more ′) monad-scheme
whereST-ext MORE m = (|bind = bind-state m, return = return-state m, . . . = MORE
m|)
abbreviation ST-scheme :: (( ′a × ′s, ′m, ′more) monad-scheme ⇒ ′more ′)⇒ ( ′a × ′s, ′m, ′more) monad-scheme ⇒ ( ′a, ( ′s, ′m) ST , ′more ′) monad-scheme
where ST-scheme ≡ ST-ext
abbreviation ST :: ( ′a × ′s, ′m, ′more) monad-scheme ⇒ ( ′a, ( ′s, ′m) ST , ′more)monad-schemewhere ST ≡ ST-scheme monad .more
lemma ST-sel :shows bind-ST : bind (ST-scheme MORE m) = bind-state mand return-ST : return (ST-scheme MORE m) = return-state mand more-ST [simp]: monad .more (ST-scheme MORE m) = MORE m
by(simp-all add : ST-ext-def )
lemma monad-lift-ST [simp]:∧more. monad .lift (ST-scheme more m) f (ST .ST x ) = ST .ST (monad .lift m
(apfst f ) x )by(simp add : monad .lift-def ST-sel o-def split-def apfst-def map-prod-def )
lemma run-bind-ST [simp]:∧more. run-state (bind (ST-scheme more m) x f ) s =
bind m (run-state x s) (λ(a, s ′). run-state (f a) s ′)by(simp add : bind-ST )
lemma run-return-ST [simp]:∧
more. run-state (return (ST-scheme more m) x )s = return m (x , s)by(simp add : return-ST )
lemma run-lift-ST [simp]:∧more. run-state (monad .lift (ST-scheme more m) f x ) s = monad .lift m (apfst
f ) (run-state x s)by(cases x ) simp
lemma monad-ST [simp, intro!, locale-witness]:∧
more. monad m =⇒ monad(ST-scheme more m)by unfold-locales(simp-all add : ST-sel)
context begin interpretation lifting-syntax .lemma ST-ext-parametric [transfer-rule]:
((rel-monad-ext (rel-prod A S ) M X ===> X ′) ===> rel-monad-ext (rel-prodA S ) M X
===> rel-monad-ext A (rel-ST S M ) X ′)
36
ST-ext ST-extunfolding ST-ext-def [abs-def ] by transfer-proverend
definition ST-fail-ext :: (( ′a × ′s, ′m, ′more) monad-fail-scheme ⇒ ′more ′)⇒ ( ′a × ′s, ′m, ′more) monad-fail-scheme ⇒ (( ′s, ′m) ST , ′more ′) monad-fail-ext
where ST-fail-ext MORE m = (|fail = fail-state m, . . . = MORE m|)
abbreviation ST-fail-scheme :: (( ′a × ′s, ′m, ′more) monad-fail-scheme ⇒ ′more ′)⇒ ( ′a × ′s, ′m, ′more) monad-fail-scheme ⇒ ( ′a, ( ′s, ′m) ST , ′more ′) monad-fail-scheme
where ST-fail-scheme MORE ≡ ST-scheme (ST-fail-ext MORE )
abbreviation ST-fail :: ( ′a × ′s, ′m, ′more) monad-fail-scheme ⇒ ( ′a, ( ′s, ′m)ST , ′more) monad-fail-schemewhere ST-fail ≡ ST-fail-scheme monad-fail .more
lemma ST-fail-sel :shows fail-ST-fail :
∧more. fail (ST-fail-scheme more m) = fail-state m
and more-ST-fail [simp]:∧
more. monad-fail .more (ST-fail-scheme more m) =more mby(simp-all add : ST-fail-ext-def ST-ext-def )
lemma run-fail-ST [simp]:∧
more. run-state (fail (ST-fail-scheme more m)) s =fail mby(simp add : fail-ST-fail)
lemma monad-fail-ST [simp, intro!, locale-witness]:fixes more massumes monad-fail mshows monad-fail (ST-fail-scheme more m)
proof −interpret monad-fail m by factshow ?thesis by unfold-locales(rule ST .expand , simp add : fail-bind fun-eq-iff )
qed
lemma run-bind-option-ST [simp]:∧more. run-state (monad .bind-option (ST-fail-scheme more m) x f ) s =
monad .bind-option m x (λy . run-state (f y) s)by(cases x ) simp-all
3.1.1 Transformation of homomorphisms
primrec hom-state :: ( ′m1 ⇒ ′m2 ) ⇒ ( ′s, ′m1 ) ST ⇒ ( ′s, ′m2 ) STwhere hom-state h (ST .ST x ) = ST .ST (λs. h (x s))
lemma run-hom-state [simp]: run-state (hom-state h x ) s = h (run-state x s)by(cases x )(simp)
context begin interpretation lifting-syntax .
37
lemma hom-state-parametric[transfer-rule]:((M1 ===> M2 ) ===> rel-ST S M1 ===> rel-ST S M2 ) hom-state hom-state
unfolding hom-state-def by transfer-proverend
lemma hom-bind-state:assumes monad-hom m1 m2 hshows hom-state h (bind-state m1 x f ) = bind-state m2 (hom-state h x ) (hom-state
h f )proof −
interpret monad-hom m1 m2 h by factshow ?thesis by(rule ST .expand ext)+(simp add : hom-bind split-def o-def )
qed
lemma hom-return-state:assumes monad-hom m1 m2 hshows hom-state h (return-state m1 x ) = return-state m2 x
proof −interpret monad-hom m1 m2 h by factshow ?thesis by(rule ST .expand ext)+(simp add : hom-return split-def o-def )
qed
lemma monad-hom-state [simp, intro!, locale-witness]:assumes monad-hom m1 m2 hshows monad-hom (ST-scheme more1 m1 ) (ST-scheme more2 m2 ) (hom-state
h)proof −
interpret monad-hom m1 m2 h by factshow ?thesis by unfold-locales(simp-all add : hom-return-state hom-bind-state
ST-sel assms)qed
lemma hom-fail-state:assumes monad-fail-hom m1 m2 hshows hom-state h (fail-state m1 ) = fail-state m2
proof −interpret monad-fail-hom m1 m2 h by factshow ?thesis by(rule ST .expand ext)+(simp add : hom-fail)
qed
lemma monad-fail-hom-state [simp, intro!, locale-witness]:assumes monad-fail-hom m1 m2 hshows monad-fail-hom (ST-fail-scheme more1 m1 ) (ST-fail-scheme more2 m2 )
(hom-state h)proof −
interpret monad-fail-hom m1 m2 h by factshow ?thesis by unfold-locales(simp add : hom-fail-state assms ST-fail-sel)
qed
38
3.2 The reader/environment monad transformer
datatype ( ′r , ′m) envT = EnvT (run-env : ′r ⇒ ′m)for rel : rel-envT ′
primrec bind-env :: ( ′a, ′m, ′more) monad-scheme ⇒ ( ′r , ′m) envT ⇒ ( ′a ⇒ ( ′r ,′m) envT ) ⇒ ( ′r , ′m) envTwhere bind-env m (EnvT x ) f = EnvT (λr . bind m (x r) (λy . run-env (f y) r))
definition return-env :: ( ′a, ′m, ′more) monad-scheme ⇒ ′a ⇒ ( ′r , ′m) envTwhere return-env m x = EnvT (λ-. return m x )
lemma run-bind-env [simp]: run-env (bind-env m x f ) r = bind m (run-env x r)(λy . run-env (f y) r)by(cases x ) simp
lemma run-return-env [simp]: run-env (return-env m x ) r = return m xby(simp add : return-env-def )
contextfixes m :: ( ′a, ′m, ′more) monad-schemeassumes monad m
begininterpretation monad m by fact
lemma bind-env-assoc [simp]: bind-env m (bind-env m x f ) g = bind-env m x (λy .bind-env m (f y) g)by(rule envT .expand ext)+(simp add : bind-assoc)
lemma return-bind-env [simp]: bind-env m (return-env m x ) f = f xby(rule envT .expand ext)+(simp add : return-bind)
lemma bind-return-env [simp]: bind-env m x (return-env m) = xby(rule envT .expand ext)+(simp add : bind-return)end
context fixes m :: ( ′a, ′m, ′more) monad-fail-scheme begin
definition fail-env :: ( ′s, ′m) envTwhere fail-env = EnvT (λ-. fail m)
lemma run-fail-env [simp]: run-env fail-env r = fail mby(simp add : fail-env-def )
context assumes monad-fail m begininterpretation monad-fail m by fact
lemma fail-bind-env [simp]: bind-env m fail-env f = fail-envby(rule envT .expand ext)+(simp add : fail-bind)
39
endend
context begin interpretation lifting-syntax .
inductive rel-envT :: ( ′r1 ⇒ ′r2 ⇒ bool) ⇒ ( ′m1 ⇒ ′m2 ⇒ bool) ⇒ ( ′r1 , ′m1 )envT ⇒ ( ′r2 , ′m2 ) envT ⇒ bool
for R M x ywhere (R ===> M ) (run-env x ) (run-env y) =⇒ rel-envT R M x y
inductive-simps rel-envT-EnvT1 : rel-envT R M (EnvT x ) yinductive-simps rel-envT-EnvT2 : rel-envT R M x (EnvT y)inductive-simps rel-envT-simps [simp]: rel-envT R M (EnvT x ) (EnvT y)
lemma rel-envT-alt-def : rel-envT S M = BNF-Def .vimage2p run-env run-env (S===> M )apply(rule ext)+subgoal for x y
apply(cases x ; cases y)apply(simp add : rel-ST .simps vimage2p-def )done
done
lemma inj-run-env [simp]: inj run-envby(auto simp add : inj-on-def intro: envT .expand)
lemma surj-run-env [simp]: surj run-envby(rule surjI [where f =EnvT ]) simp
lemma rel-envT-eq [relator-eq ]: rel-envT op = op = = op =unfolding rel-envT-alt-def rel-fun-eq by (simp add : eq-OO eq-alt [symmetric])
lemma left-unique-rel-envT [transfer-rule]:[[ left-total R; left-unique M ]] =⇒ left-unique (rel-envT R M )
unfolding rel-envT-alt-def by(simp add : left-unique-fun)
lemma right-unique-rel-envT [transfer-rule]:[[ right-total R; right-unique M ]] =⇒ right-unique (rel-envT R M )
unfolding rel-envT-alt-def by(simp add : right-unique-fun)
lemma bi-unique-rel-envT [transfer-rule]:[[ bi-total R; bi-unique M ]] =⇒ bi-unique (rel-envT R M )
unfolding bi-unique-alt-def bi-total-alt-def by(simp add : left-unique-rel-envT right-unique-rel-envT )
lemma right-total-rel-envT [transfer-rule]:[[ right-unique R; right-total M ]] =⇒ right-total (rel-envT R M )
unfolding rel-envT-alt-def by(simp add : right-total-fun)
lemma left-total-rel-envT [transfer-rule]:
40
[[ left-unique R; left-total M ]] =⇒ left-total (rel-envT R M )unfolding rel-envT-alt-def by(simp add : left-total-fun)
lemma bi-total-rel-envT [transfer-rule]:[[ bi-unique R; bi-total M ]] =⇒ bi-total (rel-envT R M )
unfolding bi-unique-alt-def bi-total-alt-def by(simp add : left-total-rel-envT right-total-rel-envT )
lemma run-env-parametric [transfer-rule]: (rel-envT R M ===> R ===> M )run-env run-envby(rule rel-funI )(erule rel-envT .cases)
lemma envT-parametric [transfer-rule]: ((R ===> M ) ===> rel-envT R M )EnvT EnvTby(rule rel-funI )(rule rel-envT .intros; simp)
lemma rec-envT-parametric [transfer-rule]:(((R ===> M ) ===> C ) ===> rel-envT R M ===> C ) rec-envT rec-envT
apply(rule rel-funI )+subgoal for f g x y
apply(cases x )apply(cases y)apply(auto dest : rel-funD)done
done
lemma bind-env-parametric [transfer-rule]:(rel-monad-ext A M X ===> rel-envT R M ===> (A ===> rel-envT R M )
===> rel-envT R M ) bind-env bind-envunfolding bind-env-def [abs-def ] by transfer-prover
lemma return-env-parametric [transfer-rule]:(rel-monad-ext A M X ===> A ===> rel-envT R M ) return-env return-env
unfolding return-env-def [abs-def ] by transfer-prover
lemma fail-env-parametric [transfer-rule]:(rel-monad-fail-scheme A M X ===> rel-envT R M ) fail-env fail-env
unfolding fail-env-def [abs-def ] by transfer-prover
end
definition envT-ext :: (( ′a, ′m, ′more) monad-scheme ⇒ ′more ′)⇒ ( ′a, ′m, ′more) monad-scheme ⇒ ( ′a, ( ′r , ′m) envT , ′more ′) monad-scheme
whereenvT-ext MORE m = (|bind = bind-env m, return = return-env m, . . . = MORE
m|)
abbreviation envT-scheme :: (( ′a, ′m, ′more) monad-scheme ⇒ ′more ′)⇒ ( ′a, ′m, ′more) monad-scheme ⇒ ( ′a, ( ′r , ′m) envT , ′more ′) monad-scheme
where envT-scheme ≡ envT-ext
41
abbreviation envT :: ( ′a, ′m, ′more) monad-scheme ⇒ ( ′a, ( ′r , ′m) envT , ′more)monad-schemewhere envT ≡ envT-scheme monad .more
lemma envT-sel :shows bind-envT : bind (envT-scheme MORE m) = bind-env mand return-envT : return (envT-scheme MORE m) = return-env mand more-envT [simp]: monad .more (envT-scheme MORE m) = MORE m
by(simp-all add : envT-ext-def )
lemma monad-lift-envT [simp]:∧more. monad .lift (envT-scheme more m) f (EnvT x ) = EnvT (monad .lift m f
x )by(simp add : monad .lift-def envT-sel o-def )
lemma run-bind-envT [simp]:∧more. run-env (bind (envT-scheme more m) x f ) r =
bind m (run-env x r) (λa. run-env (f a) r)by(simp add : bind-envT )
lemma run-return-envT [simp]:∧
more. run-env (return (envT-scheme more m)x ) r = return m xby(simp add : return-envT )
lemma run-lift-envT [simp]:∧more. run-env (monad .lift (envT-scheme more m) f x ) r = monad .lift m f
(run-env x r)by(cases x ) simp
lemma monad-envT [simp, intro!, locale-witness]:∧
more. monad m =⇒ monad(envT-scheme more m)by unfold-locales(simp-all add : envT-sel)
context begin interpretation lifting-syntax .lemma envT-ext-parametric [transfer-rule]:
((rel-monad-ext A M X ===> X ′) ===> rel-monad-ext A M X===> rel-monad-ext A (rel-envT R M ) X ′)
envT-ext envT-extunfolding envT-ext-def [abs-def ] by transfer-proverend
definition envT-fail-ext :: (( ′a, ′m, ′more) monad-fail-scheme ⇒ ′more ′)⇒ ( ′a, ′m, ′more) monad-fail-scheme ⇒ (( ′r , ′m) envT , ′more ′) monad-fail-ext
where envT-fail-ext MORE m = (|fail = fail-env m, . . . = MORE m|)
abbreviation envT-fail-scheme :: (( ′a, ′m, ′more) monad-fail-scheme ⇒ ′more ′)⇒ ( ′a, ′m, ′more) monad-fail-scheme ⇒ ( ′a, ( ′r , ′m) envT , ′more ′) monad-fail-scheme
where envT-fail-scheme MORE ≡ envT-scheme (envT-fail-ext MORE )
42
abbreviation envT-fail :: ( ′a, ′m, ′more) monad-fail-scheme ⇒ ( ′a, ( ′r , ′m) envT ,′more) monad-fail-schemewhere envT-fail ≡ envT-fail-scheme monad-fail .more
lemma envT-fail-sel :shows fail-envT-fail :
∧more. fail (envT-fail-scheme more m) = fail-env m
and more-envT-fail [simp]:∧
more. monad-fail .more (envT-fail-scheme more m)= more mby(simp-all add : envT-fail-ext-def envT-ext-def )
lemma run-fail-envT [simp]:∧
more. run-env (fail (envT-fail-scheme more m)) s= fail mby(simp add : fail-envT-fail)
lemma monad-fail-envT [simp, intro!, locale-witness]:fixes more massumes monad-fail mshows monad-fail (envT-fail-scheme more m)
proof −interpret monad-fail m by factshow ?thesis by unfold-locales(rule envT .expand , simp add : fail-bind fun-eq-iff )
qed
lemma run-bind-option-envT [simp]:∧more. run-env (monad .bind-option (envT-fail-scheme more m) x f ) s =
monad .bind-option m x (λy . run-env (f y) s)by(cases x ) simp-all
3.2.1 Transformation of homomorphisms
primrec hom-env :: ( ′m1 ⇒ ′m2 ) ⇒ ( ′r , ′m1 ) envT ⇒ ( ′r , ′m2 ) envTwhere hom-env h (EnvT x ) = EnvT (λr . h (x r))
lemma run-hom-env [simp]: run-env (hom-env h x ) s = h (run-env x s)by(cases x )(simp)
context begin interpretation lifting-syntax .lemma hom-env-parametric[transfer-rule]:
((M1 ===> M2 ) ===> rel-envT S M1 ===> rel-envT S M2 ) hom-envhom-envunfolding hom-env-def by transfer-proverend
lemma hom-bind-env :assumes monad-hom m1 m2 hshows hom-env h (bind-env m1 x f ) = bind-env m2 (hom-env h x ) (hom-env h f )proof −
43
interpret monad-hom m1 m2 h by factshow ?thesis by(rule envT .expand ext)+(simp add : hom-bind split-def o-def )
qed
lemma hom-return-env :assumes monad-hom m1 m2 hshows hom-env h (return-env m1 x ) = return-env m2 x
proof −interpret monad-hom m1 m2 h by factshow ?thesis by(rule envT .expand ext)+(simp add : hom-return split-def o-def )
qed
lemma monad-hom-env [simp, intro!, locale-witness]:assumes monad-hom m1 m2 hshows monad-hom (envT-scheme more1 m1 ) (envT-scheme more2 m2 ) (hom-env
h)proof −
interpret monad-hom m1 m2 h by factshow ?thesis by unfold-locales(simp-all add : hom-return-env hom-bind-env envT-sel
assms)qed
lemma hom-fail-env :assumes monad-fail-hom m1 m2 hshows hom-env h (fail-env m1 ) = fail-env m2
proof −interpret monad-fail-hom m1 m2 h by factshow ?thesis by(rule envT .expand ext)+(simp add : hom-fail)
qed
lemma monad-fail-hom-env [simp, intro!, locale-witness]:assumes monad-fail-hom m1 m2 hshows monad-fail-hom (envT-fail-scheme more1 m1 ) (envT-fail-scheme more2
m2 ) (hom-env h)proof −
interpret monad-fail-hom m1 m2 h by factshow ?thesis by unfold-locales(simp add : hom-fail-env assms envT-fail-sel)
qed
endtheory SPMF imports
Probability-MoreMiscAFP/Coinductive/Complete-Partial-Order2∼∼/src/HOL/Library/RewriteMonad-Locale
begin
lemma monotone-gfp-eadd1 : monotone op ≥ op ≥ (λx . x + y :: enat)
44
by(auto intro!: monotoneI )
lemma monotone-gfp-eadd2 : monotone op ≥ op ≥ (λy . x + y :: enat)by(auto intro!: monotoneI )
lemma mono2mono-gfp-eadd [THEN gfp.mono2mono2 , cont-intro, simp]:shows monotone-eadd : monotone (rel-prod op ≥ op ≥) op ≥ (λ(x , y). x + y ::
enat)by(simp add : monotone-gfp-eadd1 monotone-gfp-eadd2 )
lemma eadd-gfp-partial-function-mono [partial-function-mono]:[[ monotone (fun-ord op ≥) op ≥ f ; monotone (fun-ord op ≥) op ≥ g ]]=⇒ monotone (fun-ord op ≥) op ≥ (λx . f x + g x :: enat)
by(rule mono2mono-gfp-eadd)
lemma map-option-mono [partial-function-mono]:mono-option B =⇒ mono-option (λf . map-option g (B f ))
unfolding map-conv-bind-option by(rule bind-mono) simp-all
lemma mono2mono-ereal [THEN lfp.mono2mono]:shows monotone-ereal : monotone op ≤ op ≤ ereal
by(rule monotoneI ) simp
lemma compact-flat-lub [cont-intro]: Complete-Partial-Order2 .compact (flat-lub x )(flat-ord x ) yusing flat-interpretation[THEN ccpo]proof(rule ccpo.compactI [OF - ccpo.admissibleI ])
fix Aassume chain: Complete-Partial-Order .chain (flat-ord x ) A
and A: A 6= and ∗: ∀ z∈A. ¬ flat-ord x y z
from A obtain z where z ∈ A by blastwith ∗ have z : ¬ flat-ord x y z ..hence y : x 6= y y 6= z by(auto simp add : flat-ord-def ) assume ¬ A ⊆ x
then obtain z ′ where z ′ ∈ A z ′ 6= x by autothen have (THE z . z ∈ A − x) = z ′
by(intro the-equality)(auto dest : chainD [OF chain] simp add : flat-ord-def )moreover have z ′ 6= y using 〈z ′ ∈ A〉 ∗ by(auto simp add : flat-ord-def )ultimately have y 6= (THE z . z ∈ A − x) by simp
with z show ¬ flat-ord x y (flat-lub x A) by(simp add : flat-ord-def flat-lub-def )qed
lemma bi-unique-rel-set-bij-betw :assumes unique: bi-unique Rand rel : rel-set R A Bshows ∃ f . bij-betw f A B ∧ (∀ x∈A. R x (f x ))
proof −from assms obtain f where f :
∧x . x ∈ A =⇒ R x (f x ) and B :
∧x . x ∈ A
45
=⇒ f x ∈ Bapply(atomize-elim)apply(fold all-conj-distrib)apply(subst choice-iff [symmetric])apply(auto dest : rel-setD1 )done
have inj-on f A by(rule inj-onI )(auto dest !: f dest : bi-uniqueDl [OF unique])moreover have f ‘ A = B using rel
by(auto 4 3 intro: B dest : rel-setD2 f bi-uniqueDr [OF unique])ultimately have bij-betw f A B unfolding bij-betw-def ..thus ?thesis using f by blast
qed
lemma bij-betw-rel-setD : bij-betw f A B =⇒ rel-set (λx y . y = f x ) A Bby(rule rel-setI )(auto dest : bij-betwE bij-betw-imageE [symmetric])
4 Subprobability mass functions
type-synonym ′a spmf = ′a option pmftranslations (type) ′a spmf (type) ′a option pmf
definition measure-spmf :: ′a spmf ⇒ ′a measurewhere measure-spmf p = distr (restrict-space (measure-pmf p) (range Some))(count-space UNIV ) the
abbreviation spmf :: ′a spmf ⇒ ′a ⇒ realwhere spmf p x ≡ pmf p (Some x )
lemma space-measure-spmf : space (measure-spmf p) = UNIVby(simp add : measure-spmf-def )
lemma sets-measure-spmf [simp, measurable-cong ]: sets (measure-spmf p) = sets(count-space UNIV )by(simp add : measure-spmf-def )
lemma measure-spmf-not-bot [simp]: measure-spmf p 6= ⊥proof
assume measure-spmf p = ⊥hence space (measure-spmf p) = space ⊥ by simpthus False by(simp add : space-measure-spmf )
qed
lemma measurable-the-measure-pmf-Some [measurable, simp]:the ∈ measurable (restrict-space (measure-pmf p) (range Some)) (count-space
UNIV )by(auto simp add : measurable-def sets-restrict-space space-restrict-space integral-restrict-space)
lemma measurable-spmf-measure1 [simp]: measurable (measure-spmf M ) N = UNIV→ space N
46
by(auto simp: measurable-def space-measure-spmf )
lemma measurable-spmf-measure2 [simp]: measurable N (measure-spmf M ) = mea-surable N (count-space UNIV )by(intro measurable-cong-sets) simp-all
lemma subprob-space-measure-spmf [simp, intro!]: subprob-space (measure-spmfp)proof
show emeasure (measure-spmf p) (space (measure-spmf p)) ≤ 1by(simp add : measure-spmf-def emeasure-distr emeasure-restrict-space space-restrict-space
measure-pmf .measure-le-1 )qed(simp add : space-measure-spmf )
interpretation measure-spmf : subprob-space measure-spmf p for pby(rule subprob-space-measure-spmf )
lemma finite-measure-spmf [simp]: finite-measure (measure-spmf p)by unfold-locales
lemma spmf-conv-measure-spmf : spmf p x = measure (measure-spmf p) xby(auto simp add : measure-spmf-def measure-distr measure-restrict-space pmf .rep-eqspace-restrict-space intro: arg-cong2 [where f =measure])
lemma emeasure-measure-spmf-conv-measure-pmf :emeasure (measure-spmf p) A = emeasure (measure-pmf p) (Some ‘ A)
by(auto simp add : measure-spmf-def emeasure-distr emeasure-restrict-space space-restrict-spaceintro: arg-cong2 [where f =emeasure])
lemma measure-measure-spmf-conv-measure-pmf :measure (measure-spmf p) A = measure (measure-pmf p) (Some ‘ A)
using emeasure-measure-spmf-conv-measure-pmf [of p A]by(simp add : measure-spmf .emeasure-eq-measure measure-pmf .emeasure-eq-measure)
lemma emeasure-spmf-map-pmf-Some [simp]:emeasure (measure-spmf (map-pmf Some p)) A = emeasure (measure-pmf p) A
by(auto simp add : measure-spmf-def emeasure-distr emeasure-restrict-space space-restrict-spaceintro: arg-cong2 [where f =emeasure])
lemma measure-spmf-map-pmf-Some [simp]:measure (measure-spmf (map-pmf Some p)) A = measure (measure-pmf p) A
using emeasure-spmf-map-pmf-Some[of p A] by(simp add : measure-spmf .emeasure-eq-measuremeasure-pmf .emeasure-eq-measure)
lemma nn-integral-measure-spmf : (∫
+ x . f x ∂measure-spmf p) =∫
+ x . ereal(spmf p x ) ∗ f x ∂count-space UNIV
(is ?lhs = ?rhs)proof −
have ?lhs =∫
+ x . pmf p x ∗ f (the x ) ∂count-space (range Some)
47
by(simp add : measure-spmf-def nn-integral-distr nn-integral-restrict-space nn-integral-measure-pmfnn-integral-count-space-indicator ac-simps times-ereal .simps(1 )[symmetric] del : times-ereal .simps(1 ))
also have . . . =∫
+ x . ereal (spmf p (the x )) ∗ f (the x ) ∂count-space (rangeSome)
by(rule nn-integral-cong) autoalso have . . . =
∫+ x . spmf p (the (Some x )) ∗ f (the (Some x )) ∂count-space
UNIVby(rule nn-integral-bij-count-space[symmetric])(simp add : bij-betw-def )
also have . . . = ?rhs by simpfinally show ?thesis .
qed
lemma integral-measure-spmf :assumes integrable (measure-spmf p) fshows (
∫x . f x ∂measure-spmf p) =
∫x . spmf p x ∗ f x ∂count-space UNIV
proof −have integrable (count-space UNIV ) (λx . spmf p x ∗ f x )using assms by(simp add : integrable-iff-bounded nn-integral-measure-spmf abs-mult
pmf-nonneg)then show ?thesis using assms
by(simp add : real-lebesgue-integral-def nn-integral-measure-spmf )qed
lemma emeasure-spmf-single: emeasure (measure-spmf p) x = spmf p xby(simp add : measure-spmf .emeasure-eq-measure spmf-conv-measure-spmf )
lemma measurable-measure-spmf [measurable]:(λx . measure-spmf (M x )) ∈ measurable (count-space UNIV ) (subprob-algebra
(count-space UNIV ))by (auto simp: space-subprob-algebra)
lemma nn-integral-measure-spmf-conv-measure-pmf :assumes [measurable]: f ∈ borel-measurable (count-space UNIV )shows nn-integral (measure-spmf p) f = nn-integral (restrict-space (measure-pmf
p) (range Some)) (f the)by(simp add : measure-spmf-def nn-integral-distr o-def )
lemma measure-spmf-in-space-subprob-algebra [simp]:measure-spmf p ∈ space (subprob-algebra (count-space UNIV ))
by(simp add : space-subprob-algebra)
lemma nn-integral-spmf-neq-infinity : (∫
+ x . spmf p x ∂count-space UNIV ) 6= ∞using nn-integral-measure-spmf [where f =λ-. 1 , of p, symmetric] by simp
lemma SUP-spmf-neq-infinity : |SUP i . ereal (spmf (Y i) x )| 6= ∞proof −
have 0 ≤ (SUP i . ereal (spmf (Y i) x )) by(rule SUP-upper2 )(simp-all add :pmf-nonneg)
moreover have . . . ≤ 1 by(rule SUP-least)(simp add : pmf-le-1 )
48
ultimately show ?thesis by autoqed
lemma SUP-spmf-neq-infinity ′:assumes Y 6= shows |SUP p:Y . ereal (spmf p x )| 6= ∞
proof −from assms obtain p where p ∈ Y by autothen have 0 ≤ (SUP p:Y . ereal (spmf p x )) by(rule SUP-upper2 )(simp add :
pmf-nonneg)moreover have . . . ≤ 1 by(rule SUP-least)(simp add : pmf-le-1 )ultimately show ?thesis by auto
qed
lemma SUP-emeasure-spmf-neq-infinity :assumes Y 6= shows |SUP p:Y . emeasure (measure-spmf p) A| 6= ∞
proof −from assms obtain p where p ∈ Y by autohence 0 ≤ (SUP p:Y . emeasure (measure-spmf p) A) by(rule SUP-upper2 )(simp-all
add : emeasure-nonneg)moreover have (SUP p:Y . emeasure (measure-spmf p) A) ≤ 1
by(rule SUP-least)(simp add : measure-spmf .subprob-emeasure-le-1 )ultimately show ?thesis by auto
qed
4.1 Support
definition set-spmf :: ′a spmf ⇒ ′a setwhere set-spmf p = set-pmf p >>= set-option
lemma set-spmf-rep-eq : set-spmf p = x . measure (measure-spmf p) x 6= 0proof −
have∧
x :: ′a. the −‘ x ∩ range Some = Some x by autothen show ?thesis
by(auto simp add : set-spmf-def set-pmf .rep-eq measure-spmf-def measure-distrmeasure-restrict-space space-restrict-space intro: rev-image-eqI )qed
lemma in-set-spmf : x ∈ set-spmf p ←→ Some x ∈ set-pmf pby(simp add : set-spmf-def )
lemma AE-measure-spmf-iff [simp]: (AE x in measure-spmf p. P x )←→ (∀ x∈set-spmfp. P x )by(auto 4 3 simp add : measure-spmf-def AE-distr-iff AE-restrict-space-iff AE-measure-pmf-iffset-spmf-def cong del : AE-cong)
lemma spmf-eq-0-set-spmf : spmf p x = 0 ←→ x /∈ set-spmf pby(auto simp add : pmf-eq-0-set-pmf set-spmf-def intro: rev-image-eqI )
49
lemma in-set-spmf-iff-spmf : x ∈ set-spmf p ←→ spmf p x 6= 0by(auto simp add : set-spmf-def set-pmf-iff intro: rev-image-eqI )
lemma set-spmf-return-pmf-None [simp]: set-spmf (return-pmf None) = by(auto simp add : set-spmf-def )
lemma countable-set-spmf [simp]: countable (set-spmf p)by(simp add : set-spmf-def bind-UNION )
lemma spmf-eqI :assumes
∧i . spmf p i = spmf q i
shows p = qproof(rule pmf-eqI )
fix ishow pmf p i = pmf q iproof(cases i)
case (Some i ′)thus ?thesis by(simp add : assms)
nextcase Nonehave ereal (pmf p i) = measure (measure-pmf p) i by(simp add : pmf-def )also have i = space (measure-pmf p) − range Some
by(auto simp add : None intro: ccontr)also have measure (measure-pmf p) . . . = (1 :: ereal) − measure (measure-pmf
p) (range Some)by(simp add : one-ereal-def measure-pmf .prob-compl del : space-measure-pmf )
also have range Some = (⋃
x∈set-spmf p. Some x) ∪ Some ‘ (− set-spmfp)
by autoalso have measure (measure-pmf p) . . . = measure (measure-pmf p) (
⋃x∈set-spmf
p. Some x)by(rule measure-pmf .measure-zero-union)(auto simp add : measure-pmf .prob-eq-0
AE-measure-pmf-iff in-set-spmf-iff-spmf set-pmf-iff )also have ereal . . . =
∫+ x . measure (measure-pmf p) Some x ∂count-space
(set-spmf p)unfolding measure-pmf .emeasure-eq-measure[symmetric]by(simp-all add : emeasure-UN-countable disjoint-family-on-def )also have . . . =
∫+ x . spmf p x ∂count-space (set-spmf p) by(simp add :
pmf-def )also have . . . =
∫+ x . spmf q x ∂count-space (set-spmf p) by(simp add : assms)
also have set-spmf p = set-spmf q by(auto simp add : in-set-spmf-iff-spmfassms)
also have (∫
+ x . spmf q x ∂count-space (set-spmf q)) =∫
+ x . measure(measure-pmf q) Some x ∂count-space (set-spmf q)
by(simp add : pmf-def )also have . . . = measure (measure-pmf q) (
⋃x∈set-spmf q . Some x)
unfolding measure-pmf .emeasure-eq-measure[symmetric]by(simp-all add : emeasure-UN-countable disjoint-family-on-def )
50
also have . . . = measure (measure-pmf q) ((⋃
x∈set-spmf q . Some x) ∪Some ‘ (− set-spmf q))
unfolding ereal .injectby(rule measure-pmf .measure-zero-union[symmetric])(auto simp add : measure-pmf .prob-eq-0
AE-measure-pmf-iff in-set-spmf-iff-spmf set-pmf-iff )also have ((
⋃x∈set-spmf q . Some x) ∪ Some ‘ (− set-spmf q)) = range
Some by autoalso have (1 :: ereal) − measure (measure-pmf q) . . . = measure (measure-pmf
q) (space (measure-pmf q) − range Some)by(simp add : one-ereal-def measure-pmf .prob-compl del : space-measure-pmf )
also have space (measure-pmf q) − range Some = iby(auto simp add : None intro: ccontr)
also have measure (measure-pmf q) . . . = pmf q i by(simp add : pmf-def )finally show ?thesis by simp
qedqed
lemma integral-measure-spmf-restrict :fixes f :: ′a ⇒ ′b :: banach, second-countable-topology shows(∫
x . f x ∂measure-spmf M ) = (∫
x . f x ∂restrict-space (measure-spmf M )(set-spmf M ))by(auto intro!: integral-cong-AE simp add : integral-restrict-space)
lemma nn-integral-measure-spmf ′:(∫
+ x . f x ∂measure-spmf p) =∫
+ x . ereal (spmf p x ) ∗ f x ∂count-space(set-spmf p)by(auto simp add : nn-integral-measure-spmf nn-integral-count-space-indicator pmf-nonnegin-set-spmf-iff-spmf intro!: nn-integral-cong split : split-indicator)
4.2 Functorial structure
abbreviation map-spmf :: ( ′a ⇒ ′b) ⇒ ′a spmf ⇒ ′b spmfwhere map-spmf f ≡ map-pmf (map-option f )
context beginlocal-setup 〈〈 Local-Theory .map-background-naming (Name-Space.mandatory-pathspmf ) 〉〉
lemma map-comp: map-spmf f (map-spmf g p) = map-spmf (f g) pby(simp add : pmf .map-comp o-def option.map-comp)
lemma map-id0 : map-spmf id = idby(simp add : pmf .map-id option.map-id0 )
lemma map-id [simp]: map-spmf id p = pby(simp add : map-id0 )
lemma map-ident [simp]: map-spmf (λx . x ) p = pby(simp add : id-def [symmetric])
51
end
lemma set-map-spmf [simp]: set-spmf (map-spmf f p) = f ‘ set-spmf pby(simp add : set-spmf-def image-bind bind-image o-def Option.option.set-map)
lemma map-spmf-cong :[[ p = q ;
∧x . x ∈ set-spmf q =⇒ f x = g x ]]
=⇒ map-spmf f p = map-spmf g qby(auto intro: pmf .map-cong option.map-cong simp add : in-set-spmf )
lemma map-spmf-cong-simp:[[ p = q ;
∧x . x ∈ set-spmf q =simp=> f x = g x ]]
=⇒ map-spmf f p = map-spmf g qunfolding simp-implies-def by(rule map-spmf-cong)
lemma map-spmf-idI : (∧
x . x ∈ set-spmf p =⇒ f x = x ) =⇒ map-spmf f p = pby(rule map-pmf-idI map-option-idI )+(simp add : in-set-spmf )
lemma emeasure-map-spmf :emeasure (measure-spmf (map-spmf f p)) A = emeasure (measure-spmf p) (f −‘
A)by(auto simp add : measure-spmf-def emeasure-distr measurable-restrict-space1 space-restrict-spaceemeasure-restrict-space intro: arg-cong2 [where f =emeasure])
lemma measure-map-spmf : measure (measure-spmf (map-spmf f p)) A = measure(measure-spmf p) (f −‘ A)using emeasure-map-spmf [of f p A] by(simp add : measure-spmf .emeasure-eq-measure)
lemma measure-map-spmf-conv-distr :measure-spmf (map-spmf f p) = distr (measure-spmf p) (count-space UNIV ) f
by(rule measure-eqI )(simp-all add : emeasure-map-spmf emeasure-distr)
lemma spmf-map-pmf-Some [simp]: spmf (map-pmf Some p) i = pmf p iby(simp add : pmf-map-inj ′)
lemma spmf-map-inj : [[ inj-on f (set-spmf M ); x ∈ set-spmf M ]] =⇒ spmf (map-spmff M ) (f x ) = spmf M xby(subst option.map(2 )[symmetric, where f =f ])(rule pmf-map-inj , auto simp add :in-set-spmf inj-on-def elim!: option.inj-map-strong [rotated ])
lemma spmf-map-inj ′: inj f =⇒ spmf (map-spmf f M ) (f x ) = spmf M xby(subst option.map(2 )[symmetric, where f =f ])(rule pmf-map-inj ′[OF option.inj-map])
lemma spmf-map-outside: x /∈ f ‘ set-spmf M =⇒ spmf (map-spmf f M ) x = 0unfolding spmf-eq-0-set-spmf by simp
lemma ereal-spmf-map: ereal (spmf (map-spmf f p) x ) = emeasure (measure-spmfp) (f −‘ x)
52
by(auto simp add : ereal-pmf-map measure-spmf-def emeasure-distr emeasure-restrict-spacespace-restrict-space intro: arg-cong2 [where f =emeasure])
lemma spmf-map: spmf (map-spmf f p) x = measure (measure-spmf p) (f −‘ x)using ereal-spmf-map[of f p x ] by(simp add : measure-spmf .emeasure-eq-measure)
lemma ereal-spmf-map-conv-nn-integral :ereal (spmf (map-spmf f p) x ) = integralN (measure-spmf p) (indicator (f −‘x))by(auto simp add : ereal-pmf-map measure-spmf-def emeasure-distr space-restrict-spaceemeasure-restrict-space intro: arg-cong2 [where f =emeasure])
4.3 Monad operations
4.3.1 Return
abbreviation return-spmf :: ′a ⇒ ′a spmfwhere return-spmf x ≡ return-pmf (Some x )
lemma pmf-return-spmf : pmf (return-spmf x ) y = indicator y (Some x )by(fact pmf-return)
lemma measure-spmf-return-spmf : measure-spmf (return-spmf x ) = Giry-Monad .return(count-space UNIV ) xby(rule measure-eqI )(simp-all add : measure-spmf-def emeasure-distr space-restrict-spaceemeasure-restrict-space indicator-def )
lemma measure-spmf-return-pmf-None [simp]: measure-spmf (return-pmf None)= null-measure (count-space UNIV )by(rule measure-eqI )(auto simp add : measure-spmf-def emeasure-distr space-restrict-spaceemeasure-restrict-space indicator-eq-0-iff )
lemma set-return-spmf [simp]: set-spmf (return-spmf x ) = xby(auto simp add : set-spmf-def )
4.3.2 Bind
definition bind-spmf :: ′a spmf ⇒ ( ′a ⇒ ′b spmf ) ⇒ ′b spmfwhere bind-spmf x f = bind-pmf x (λa. case a of None ⇒ return-pmf None | Somea ′⇒ f a ′)
adhoc-overloading Monad-Syntax .bind bind-spmf
lemma return-None-bind-spmf [simp]: return-pmf None >>= (f :: ′a ⇒ -) = return-pmfNoneby(simp add : bind-spmf-def bind-return-pmf )
lemma return-bind-spmf [simp]: return-spmf x >>= f = f xby(simp add : bind-spmf-def bind-return-pmf )
53
lemma bind-return-spmf [simp]: x >>= return-spmf = xproof −have
∧a :: ′a option. (case a of None ⇒ return-pmf None | Some a ′⇒ return-spmf
a ′) = return-pmf aby(simp split : option.split)
then show ?thesisby(simp add : bind-spmf-def bind-return-pmf ′)
qed
lemma bind-spmf-assoc [simp]:fixes x :: ′a spmf and f :: ′a ⇒ ′b spmf and g :: ′b ⇒ ′c spmfshows (x >>= f ) >>= g = x >>= (λy . f y >>= g)
by(auto simp add : bind-spmf-def bind-assoc-pmf fun-eq-iff bind-return-pmf split :option.split intro: arg-cong [where f =bind-pmf x ])
lemma pmf-bind-spmf-None: pmf (p >>= f ) None = pmf p None +∫
x . pmf (fx ) None ∂measure-spmf p
(is ?lhs = ?rhs)proof −
let ?f = λx . pmf (case x of None ⇒ return-pmf None | Some x ⇒ f x ) Nonehave ?lhs =
∫x . ?f x ∂measure-pmf p
by(simp add : bind-spmf-def pmf-bind)also have . . . =
∫x . ?f None ∗ indicator None x + ?f x ∗ indicator (range
Some) x ∂measure-pmf pby(rule integral-cong)(auto simp add : indicator-def )
also have . . . = (∫
x . ?f None ∗ indicator None x ∂measure-pmf p) + (∫
x .?f x ∗ indicator (range Some) x ∂measure-pmf p)
by(rule integral-add)(auto 4 3 intro: integrable-real-mult-indicator measure-pmf .integrable-const-bound [whereB=1 ] simp add : AE-measure-pmf-iff pmf-nonneg pmf-le-1 )
also have . . . = pmf p None +∫
x . indicator (range Some) x ∗ pmf (f (thex )) None ∂measure-pmf p
by(auto simp add : measure-measure-pmf-finite indicator-eq-0-iff intro!: integral-cong)also have . . . = ?rhs unfolding measure-spmf-def
by(subst integral-distr)(auto simp add : integral-restrict-space)finally show ?thesis .
qed
lemma spmf-bind : spmf (p >>= f ) y =∫
x . spmf (f x ) y ∂measure-spmf punfolding measure-spmf-defby(subst integral-distr)(auto simp add : bind-spmf-def pmf-bind integral-restrict-spaceindicator-eq-0-iff intro!: integral-cong split : option.split)
lemma ereal-spmf-bind : ereal (spmf (p >>= f ) x ) =∫
+ y . spmf (f y) x ∂measure-spmfpby(auto simp add : bind-spmf-def ereal-pmf-bind nn-integral-measure-spmf-conv-measure-pmfnn-integral-restrict-space intro: nn-integral-cong split : split-indicator option.split)
lemma measure-spmf-bind-pmf : measure-spmf (p >>= f ) = measure-pmf p >>=measure-spmf f
54
(is ?lhs = ?rhs)proof(rule measure-eqI )
show sets ?lhs = sets ?rhsby(simp add : sets-bind [where N =count-space UNIV ] space-measure-spmf )
nextfix A :: ′a sethave emeasure ?lhs A =
∫+ x . emeasure (measure-spmf (f x )) A ∂measure-pmf
pby(simp add : measure-spmf-def emeasure-distr space-restrict-space emeasure-restrict-space
bind-spmf-def )also have . . . = emeasure ?rhs Aby(simp add : emeasure-bind [where N =count-space UNIV ] space-measure-spmf
space-subprob-algebra)finally show emeasure ?lhs A = emeasure ?rhs A .
qed
lemma measure-spmf-bind : measure-spmf (p >>= f ) = measure-spmf p >>= measure-spmf f
(is ?lhs = ?rhs)proof(rule measure-eqI )
show sets ?lhs = sets ?rhsby(simp add : sets-bind [where N =count-space UNIV ] space-measure-spmf )
nextfix A :: ′a setlet ?A = the −‘ A ∩ range Somehave emeasure ?lhs A =
∫+ x . emeasure (measure-pmf (case x of None ⇒
return-pmf None | Some x ⇒ f x )) ?A ∂measure-pmf pby(simp add : measure-spmf-def emeasure-distr space-restrict-space emeasure-restrict-space
bind-spmf-def )also have . . . =
∫+ x . emeasure (measure-pmf (f (the x ))) ?A ∗ indicator
(range Some) x ∂measure-pmf pby(rule nn-integral-cong)(auto split : option.split simp add : indicator-def )
also have . . . =∫
+ x . emeasure (measure-spmf (f x )) A ∂measure-spmf pby(simp add : measure-spmf-def nn-integral-distr nn-integral-restrict-space emeasure-distr
space-restrict-space emeasure-restrict-space)also have . . . = emeasure ?rhs Aby(simp add : emeasure-bind [where N =count-space UNIV ] space-measure-spmf
space-subprob-algebra)finally show emeasure ?lhs A = emeasure ?rhs A .
qed
lemma map-spmf-bind-spmf : map-spmf f (bind-spmf p g) = bind-spmf p (map-spmff g)by(auto simp add : bind-spmf-def map-bind-pmf fun-eq-iff split : option.split intro:arg-cong2 [where f =bind-pmf ])
lemma bind-map-spmf : map-spmf f p >>= g = p >>= g fby(simp add : bind-spmf-def bind-map-pmf o-def cong del : option.case-cong-weak)
55
lemma spmf-bind-leI :assumes
∧y . y ∈ set-spmf p =⇒ spmf (f y) x ≤ r
and 0 ≤ rshows spmf (bind-spmf p f ) x ≤ r
proof −have ereal (spmf (bind-spmf p f ) x ) =
∫+ y . spmf (f y) x ∂measure-spmf p
by(rule ereal-spmf-bind)also have . . . ≤
∫+ y . r ∂measure-spmf p by(rule nn-integral-mono-AE )(simp
add : assms)also have . . . ≤ r using assms measure-spmf .emeasure-space-le-1
by(auto simp add : measure-spmf .emeasure-eq-measure intro: mult-left-le)finally show ?thesis by simp
qed
lemma map-spmf-conv-bind-spmf : map-spmf f p = (p >>= (λx . return-spmf (f x )))by(simp add : map-pmf-def bind-spmf-def )(rule bind-pmf-cong , simp-all split : op-tion.split)
lemma bind-spmf-cong :[[ p = q ;
∧x . x ∈ set-spmf q =⇒ f x = g x ]]
=⇒ bind-spmf p f = bind-spmf q gby(auto simp add : bind-spmf-def in-set-spmf intro: bind-pmf-cong option.case-cong)
lemma bind-spmf-cong-simp:[[ p = q ;
∧x . x ∈ set-spmf q =simp=> f x = g x ]]
=⇒ bind-spmf p f = bind-spmf q gby(simp add : simp-implies-def cong : bind-spmf-cong)
lemma set-bind-spmf : set-spmf (M >>= f ) = set-spmf M >>= (set-spmf f )by(auto simp add : set-spmf-def bind-spmf-def bind-UNION split : option.splits)
lemma set-pmf-bind-spmf : set-pmf (M >>= f ) = set-pmf M >>= map-option-set(set-pmf f )by(auto 4 3 simp add : bind-spmf-def split : option.splits intro: rev-bexI )
lemma case-option-same: case-option x (λ-. x ) = (λ-. x )by(simp add : fun-eq-iff split : option.split)
lemma bind-spmf-const-return-None [simp]: bind-spmf p (λ-. return-pmf None) =return-pmf Noneby(simp add : bind-spmf-def case-option-same)
lemma bind-commute-spmf :bind-spmf p (λx . bind-spmf q (f x )) = bind-spmf q (λy . bind-spmf p (λx . f x y))(is ?lhs = ?rhs)
proof −let ?f = λx y . case x of None ⇒ return-pmf None | Some a ⇒ (case y of None⇒ return-pmf None | Some b ⇒ f a b)
have ?lhs = p >>= (λx . q >>= ?f x )
56
unfolding bind-spmf-def by(rule bind-pmf-cong [OF refl ])(simp split : option.split)also have . . . = q >>= (λy . p >>= (λx . ?f x y)) by(rule bind-commute-pmf )also have . . . = ?rhs unfolding bind-spmf-defby(rule bind-pmf-cong [OF refl ])(auto split : option.split , metis bind-spmf-const-return-None
bind-spmf-def )finally show ?thesis .
qed
4.4 Relator
abbreviation rel-spmf :: ( ′a ⇒ ′b ⇒ bool) ⇒ ′a spmf ⇒ ′b spmf ⇒ boolwhere rel-spmf R ≡ rel-pmf (rel-option R)
lemma rel-pmf-mono:[[rel-pmf A f g ;
∧x y . A x y =⇒ B x y ]] =⇒ rel-pmf B f g
using pmf .rel-mono[of A B ] by(simp add : le-fun-def )
lemma rel-spmf-mono:[[rel-spmf A f g ;
∧x y . A x y =⇒ B x y ]] =⇒ rel-spmf B f g
apply(erule rel-pmf-mono)using option.rel-mono[of A B ] by(simp add : le-fun-def )
lemma rel-spmf-mono-strong :[[ rel-spmf A f g ;
∧x y . [[ A x y ; x ∈ set-spmf f ; y ∈ set-spmf g ]] =⇒ B x y ]] =⇒
rel-spmf B f gapply(erule pmf .rel-mono-strong)apply(erule option.rel-mono-strong)apply(auto simp add : in-set-spmf )done
lemma rel-spmf-reflI : (∧
x . x ∈ set-spmf p =⇒ P x x ) =⇒ rel-spmf P p pby(rule rel-pmf-reflI )(auto simp add : set-spmf-def intro: rel-option-reflI )
lemma rel-spmfI [intro? ]:[[∧
x y . (x , y) ∈ set-spmf pq =⇒ P x y ; map-spmf fst pq = p; map-spmf snd pq= q ]]
=⇒ rel-spmf P p qby(rule rel-pmf .intros[where pq=map-pmf (λx . case x of None ⇒ (None, None)| Some (a, b) ⇒ (Some a, Some b)) pq ])(auto simp add : pmf .map-comp o-def in-set-spmf split : option.splits intro: pmf .map-cong)
lemma rel-spmfE [elim? , consumes 1 , case-names rel-spmf ]:assumes rel-spmf P p qobtains pq where∧
x y . (x , y) ∈ set-spmf pq =⇒ P x yp = map-spmf fst pqq = map-spmf snd pq
using assmsproof(cases rule: rel-pmf .cases[consumes 1 , case-names rel-pmf ])
57
case (rel-pmf pq)let ?pq = map-pmf (λ(a, b). case (a, b) of (Some x , Some y) ⇒ Some (x , y) |
- ⇒ None) pqhave
∧x y . (x , y) ∈ set-spmf ?pq =⇒ P x y
by(auto simp add : in-set-spmf split : option.split-asm dest : rel-pmf (1 ))moreoverhave
∧x . (x , None) ∈ set-pmf pq =⇒ x = None by(auto dest !: rel-pmf (1 ))
then have p = map-spmf fst ?pq using rel-pmf (2 )by(auto simp add : pmf .map-comp split-beta intro!: pmf .map-cong split : op-
tion.split)moreoverhave
∧y . (None, y) ∈ set-pmf pq =⇒ y = None by(auto dest !: rel-pmf (1 ))
then have q = map-spmf snd ?pq using rel-pmf (3 )by(auto simp add : pmf .map-comp split-beta intro!: pmf .map-cong split : op-
tion.split)ultimately show thesis ..
qed
lemma rel-spmf-simps:rel-spmf R p q ←→ (∃ pq . (∀ (x , y)∈set-spmf pq . R x y) ∧ map-spmf fst pq = p∧ map-spmf snd pq = q)by(auto intro: rel-spmfI elim!: rel-spmfE )
lemma spmf-rel-map:shows spmf-rel-map1 :
∧R f x . rel-spmf R (map-spmf f x ) = rel-spmf (λx . R (f
x )) xand spmf-rel-map2 :
∧R x g y . rel-spmf R x (map-spmf g y) = rel-spmf (λx y .
R x (g y)) x yby(simp-all add : fun-eq-iff pmf .rel-map option.rel-map[abs-def ])
lemma spmf-rel-conversep: rel-spmf R−1−1 = (rel-spmf R)−1−1
by(simp add : option.rel-conversep pmf .rel-conversep)
lemma spmf-rel-eq : rel-spmf op = = op =by(simp add : pmf .rel-eq option.rel-eq)
context begin interpretation lifting-syntax .
lemma bind-spmf-parametric [transfer-rule]:(rel-spmf A ===> (A ===> rel-spmf B) ===> rel-spmf B) bind-spmf bind-spmf
unfolding bind-spmf-def [abs-def ] by transfer-prover
end
lemma rel-spmf-bindI :[[ rel-spmf R p q ;
∧x y . R x y =⇒ rel-spmf P (f x ) (g y) ]]
=⇒ rel-spmf P (p >>= f ) (q >>= g)by(fact bind-spmf-parametric[THEN rel-funD , THEN rel-funD , OF - rel-funI ])
58
lemma rel-spmf-bind-reflI :(∧
x . x ∈ set-spmf p =⇒ rel-spmf P (f x ) (g x )) =⇒ rel-spmf P (p >>= f ) (p >>=g)by(rule rel-spmf-bindI [where R=λx y . x = y ∧ x ∈ set-spmf p])(auto intro:rel-spmf-reflI )
lemma rel-pmf-return-pmfI : P x y =⇒ rel-pmf P (return-pmf x ) (return-pmf y)by(rule rel-pmf .intros[where pq=return-pmf (x , y)])(simp-all)
lemma spmf-rel-mono-strong :[[rel-spmf A f g ;
∧x y . [[ x ∈ set-spmf f ; y ∈ set-spmf g ; A x y ]] =⇒ B x y ]] =⇒
rel-spmf B f gapply(erule pmf .rel-mono-strong)apply(erule option.rel-mono-strong)by(clarsimp simp add : in-set-spmf )
context begin interpretation lifting-syntax .
We do not yet have a relator for ′a measure, so we combine Sigma-Algebra.measureand measure-pmf
lemma measure-pmf-parametric:(rel-pmf A ===> rel-pred A ===> op =) (λp. measure (measure-pmf p)) (λq .
measure (measure-pmf q))proof(rule rel-funI )+
fix p q X Yassume rel-pmf A p q and rel-pred A X Yfrom this(1 ) obtain pq where A:
∧x y . (x , y) ∈ set-pmf pq =⇒ A x y
and p: p = map-pmf fst pq and q : q = map-pmf snd pq by cases autoshow measure p X = measure q Y unfolding p q measure-map-pmfby(rule measure-pmf .finite-measure-eq-AE )(auto simp add : AE-measure-pmf-iff
dest !: A rel-predD [OF 〈rel-pred - - -〉])qed
lemma measure-spmf-parametric:(rel-spmf A ===> rel-pred A ===> op =) (λp. measure (measure-spmf p))
(λq . measure (measure-spmf q))unfolding measure-measure-spmf-conv-measure-pmf [abs-def ]apply(rule rel-funI )+apply(erule measure-pmf-parametric[THEN rel-funD , THEN rel-funD ])apply(auto simp add : rel-pred-def rel-fun-def elim: option.rel-cases)doneend
4.5 From ′a pmf to ′a spmf
definition spmf-of-pmf :: ′a pmf ⇒ ′a spmfwhere spmf-of-pmf = map-pmf Some
lemma set-spmf-spmf-of-pmf [simp]: set-spmf (spmf-of-pmf p) = set-pmf p
59
by(auto simp add : spmf-of-pmf-def set-spmf-def bind-image o-def )
lemma spmf-spmf-of-pmf [simp]: spmf (spmf-of-pmf p) x = pmf p xby(simp add : spmf-of-pmf-def )
lemma pmf-spmf-of-pmf-None [simp]: pmf (spmf-of-pmf p) None = 0using ereal-pmf-map[of Some p None] by(simp add : spmf-of-pmf-def )
lemma emeasure-spmf-of-pmf [simp]: emeasure (measure-spmf (spmf-of-pmf p))A = emeasure (measure-pmf p) Aby(simp add : emeasure-measure-spmf-conv-measure-pmf spmf-of-pmf-def inj-vimage-image-eq)
lemma measure-spmf-spmf-of-pmf [simp]: measure-spmf (spmf-of-pmf p) = measure-pmfpby(rule measure-eqI ) simp-all
lemma map-spmf-of-pmf [simp]: map-spmf f (spmf-of-pmf p) = spmf-of-pmf (map-pmff p)by(simp add : spmf-of-pmf-def pmf .map-comp o-def )
lemma rel-spmf-spmf-of-pmf [simp]: rel-spmf R (spmf-of-pmf p) (spmf-of-pmf q)= rel-pmf R p qby(simp add : spmf-of-pmf-def pmf .rel-map)
lemma spmf-of-pmf-return-pmf [simp]: spmf-of-pmf (return-pmf x ) = return-spmfxby(simp add : spmf-of-pmf-def )
lemma bind-spmf-of-pmf [simp]: bind-spmf (spmf-of-pmf p) f = bind-pmf p fby(simp add : spmf-of-pmf-def bind-spmf-def bind-map-pmf )
lemma set-spmf-bind-pmf : set-spmf (bind-pmf p f ) = Set .bind (set-pmf p) (set-spmf f )unfolding bind-spmf-of-pmf [symmetric] by(subst set-bind-spmf ) simp
lemma spmf-of-pmf-bind : spmf-of-pmf (bind-pmf p f ) = bind-pmf p (λx . spmf-of-pmf(f x ))by(simp add : spmf-of-pmf-def map-bind-pmf )
lemma bind-pmf-return-spmf : p >>= (λx . return-spmf (f x )) = spmf-of-pmf (map-pmff p)by(simp add : map-pmf-def spmf-of-pmf-bind)
4.6 Weight of a subprobability
abbreviation weight-spmf :: ′a spmf ⇒ realwhere weight-spmf p ≡ measure (measure-spmf p) (space (measure-spmf p))
lemma weight-spmf-def : weight-spmf p = measure (measure-spmf p) UNIV
60
by(simp add : space-measure-spmf )
lemma weight-spmf-le-1 : weight-spmf p ≤ 1by(simp add : measure-spmf .subprob-measure-le-1 )
lemma weight-return-spmf [simp]: weight-spmf (return-spmf x ) = 1by(simp add : measure-spmf-return-spmf measure-return)
lemma weight-return-pmf-None [simp]: weight-spmf (return-pmf None) = 0by(simp)
lemma weight-map-spmf [simp]: weight-spmf (map-spmf f p) = weight-spmf pby(simp add : weight-spmf-def measure-map-spmf )
lemma weight-spmf-of-pmf [simp]: weight-spmf (spmf-of-pmf p) = 1using measure-pmf .prob-space[of p] by(simp add : spmf-of-pmf-def weight-spmf-def )
lemma weight-spmf-nonneg : weight-spmf p ≥ 0by(fact measure-nonneg)
lemma (in finite-measure) integrable-weight-spmf [simp]:(λx . weight-spmf (f x )) ∈ borel-measurable M =⇒ integrable M (λx . weight-spmf
(f x ))by(rule integrable-const-bound [where B=1 ])(simp-all add : weight-spmf-nonneg weight-spmf-le-1 )
lemma weight-spmf-eq-nn-integral-spmf : weight-spmf p =∫
+ x . spmf p x ∂count-spaceUNIVby(simp add : measure-measure-spmf-conv-measure-pmf space-measure-spmf measure-pmf .emeasure-eq-measure[symmetric]nn-integral-pmf [symmetric] embed-measure-count-space[symmetric] inj-on-def nn-integral-embed-measuremeasurable-embed-measure1 )
lemma weight-spmf-eq-nn-integral-support :weight-spmf p =
∫+ x . spmf p x ∂count-space (set-spmf p)
unfolding weight-spmf-eq-nn-integral-spmfby(auto simp add : nn-integral-count-space-indicator in-set-spmf-iff-spmf intro!: nn-integral-congsplit : split-indicator)
lemma pmf-None-eq-weight-spmf : pmf p None = 1 − weight-spmf pproof −have weight-spmf p =
∫+ x . spmf p x ∂count-space UNIV by(rule weight-spmf-eq-nn-integral-spmf )
also have . . . =∫
+ x . ereal (pmf p x ) ∗ indicator (range Some) x ∂count-spaceUNIV
by(simp add : nn-integral-count-space-indicator [symmetric] embed-measure-count-space[symmetric]nn-integral-embed-measure measurable-embed-measure1 )
also have . . . + pmf p None =∫
+ x . ereal (pmf p x ) ∗ indicator (range Some)x + ereal (pmf p None) ∗ indicator None x ∂count-space UNIV
by(subst nn-integral-add)(simp-all add : pmf-nonneg max-def )also have . . . =
∫+ x . pmf p x ∂count-space UNIV
by(rule nn-integral-cong)(auto split : split-indicator)
61
also have . . . = 1 by (simp add : nn-integral-pmf )finally show ?thesis by simp
qed
lemma weight-spmf-conv-pmf-None: weight-spmf p = 1 − pmf p Noneby(simp add : pmf-None-eq-weight-spmf )
lemma weight-spmf-le-0 : weight-spmf p ≤ 0 ←→ weight-spmf p = 0using weight-spmf-nonneg [of p] by auto
lemma weight-spmf-lt-0 : ¬ weight-spmf p < 0by(simp add : not-less weight-spmf-nonneg)
lemma spmf-le-weight : spmf p x ≤ weight-spmf pproof −
have ereal (spmf p x ) =∫
+ y . ereal (spmf p y) ∗ indicator x y ∂count-spaceUNIV
by(simp add : max-def pmf-nonneg)also have . . . ≤ weight-spmf p unfolding weight-spmf-eq-nn-integral-spmf
by(rule nn-integral-mono)(simp add : indicator-def pmf-nonneg)finally show ?thesis by simp
qed
lemma weight-spmf-eq-0 : weight-spmf p = 0 ←→ p = return-pmf Noneby(auto intro!: pmf-eqI simp add : pmf-None-eq-weight-spmf split : split-indicator)(metisnot-Some-eq pmf-le-0-iff spmf-le-weight)
lemma rel-spmf-weightD : rel-spmf A p q =⇒ weight-spmf p = weight-spmf qby(erule rel-spmfE ) simp
lemma rel-spmf-bij-betw :assumes f : bij-betw f (set-spmf p) (set-spmf q)and eq :
∧x . x ∈ set-spmf p =⇒ spmf p x = spmf q (f x )
shows rel-spmf (λx y . f x = y) p qproof −
let ?f = map-option f
have weq : ereal (weight-spmf p) = ereal (weight-spmf q)unfolding weight-spmf-eq-nn-integral-support
by(subst nn-integral-bij-count-space[OF f , symmetric])(rule nn-integral-cong-AE ,simp add : eq AE-count-space)
then have None ∈ set-pmf p ←→ None ∈ set-pmf qby(simp add : pmf-None-eq-weight-spmf set-pmf-iff )
with f have bij-betw (map-option f ) (set-pmf p) (set-pmf q)apply(auto simp add : bij-betw-def in-set-spmf inj-on-def intro: option.expand)apply(rename-tac [!] x )apply(case-tac [!] x )apply(auto iff : in-set-spmf )done
62
then have rel-pmf (λx y . ?f x = y) p qby(rule rel-pmf-bij-betw)(case-tac x , simp-all add : weq [simplified ] eq in-set-spmf
pmf-None-eq-weight-spmf )thus ?thesis by(rule pmf .rel-mono-strong)(auto intro!: rel-optionI simp add :
Option.is-none-def )qed
4.7 From density to spmfs
context fixes f :: ′a ⇒ real begin
definition embed-spmf :: ′a spmfwhere embed-spmf = embed-pmf (λx . case x of None ⇒ 1 − real-of-ereal (
∫+ x .
ereal (f x ) ∂count-space UNIV ) | Some x ′⇒ max 0 (f x ′))
contextassumes prob: (
∫+ x . ereal (f x ) ∂count-space UNIV ) ≤ 1
begin
lemma nn-integral-embed-spmf-eq-1 :(∫
+ x . ereal (case x of None ⇒ 1 − real-of-ereal (∫
+ x . ereal (f x ) ∂count-spaceUNIV ) | Some x ′⇒ max 0 (f x ′)) ∂count-space UNIV ) = 1
(is ?lhs = - is (∫
+ x . ?f x ∂?M ) = -)proof −
have ?lhs =∫
+ x . ?f x ∗ indicator None x + ?f x ∗ indicator (range Some)x ∂?M
by(rule nn-integral-cong)(auto split : split-indicator)also have . . . = (1 − real-of-ereal (
∫+ x . ereal (f x ) ∂count-space UNIV )) +∫
+ x . ?f x ∗ indicator (range Some) x ∂?M(is - = ?None + ?Some)
by(subst nn-integral-add)(simp-all add : AE-count-space max-def le-diff-eq real-le-ereal-iffone-ereal-def [symmetric] prob split : option.split)
also have ?Some =∫
+ x . ?f x ∂count-space (range Some)by(simp add : nn-integral-count-space-indicator)
also have count-space (range Some) = embed-measure (count-space UNIV ) Someby(simp add : embed-measure-count-space)
also have (∫
+ x . ?f x ∂. . . ) =∫
+ x . max 0 (ereal (f x )) ∂count-space UNIVby(subst nn-integral-embed-measure)(simp-all add : zero-ereal-def measurable-embed-measure1 )also have ?None + . . . = 1 using prob
by(auto simp add : nn-integral-max-0 ereal-minus(1 )[symmetric] one-ereal-defereal-real simp del : ereal-minus(1 )) simp
finally show ?thesis .qed
lemma pmf-embed-spmf-None: pmf embed-spmf None = 1 − real-of-ereal (∫
+ x .ereal (f x ) ∂count-space UNIV )unfolding embed-spmf-defapply(subst pmf-embed-pmf )
using prob
63
apply(simp add : field-simps real-le-ereal-iff one-ereal-def split : option.split)apply(rule nn-integral-embed-spmf-eq-1 )
apply simpdone
lemma spmf-embed-spmf [simp]: spmf embed-spmf x = max 0 (f x )unfolding embed-spmf-defapply(subst pmf-embed-pmf )
using probapply(simp add : field-simps real-le-ereal-iff one-ereal-def split : option.split)
apply(rule nn-integral-embed-spmf-eq-1 )apply simpdone
end
end
lemma embed-spmf-K-0 [simp]: embed-spmf (λ-. 0 ) = return-pmf None (is ?lhs =?rhs)by(rule spmf-eqI )(simp add : zero-ereal-def [symmetric])
4.8 Ordering on spmfs
rel-pmf does not preserve a ccpo structure. Counterexample by Saheb-Djahromi: Take prefix order over bool llist and the set range (λn :: nat .uniform (llist-n n)) where llist-n is the set of all llists of length n anduniform returns a uniform distribution over the given set. The set formsa chain in ord-pmf lprefix, but it has not an upper bound. Any upperbound may contain only infinite lists in its support because otherwise it isnot greater than the n+1 -st element in the chain where n is the length ofthe finite list. Moreover its support must contain all infinite lists, becauseotherwise there is a finite list all of whose finite extensions are not in thesupport - a contradiction to the upper bound property. Hence, the supportis uncountable, but pmf’s only have countable support.
However, if all chains in the ccpo are finite, then it should preserve the ccpostructure.
abbreviation ord-spmf :: ( ′a ⇒ ′a ⇒ bool) ⇒ ′a spmf ⇒ ′a spmf ⇒ boolwhere ord-spmf ord ≡ rel-pmf (ord-option ord)
locale ord-spmf-syntax beginnotation ord-spmf (infix vı 60 )end
lemma ord-spmf-map-spmf1 : ord-spmf R (map-spmf f p) = ord-spmf (λx . R (fx )) pby(simp add : pmf .rel-map[abs-def ] ord-option-map1 [abs-def ])
64
lemma ord-spmf-map-spmf2 : ord-spmf R p (map-spmf f q) = ord-spmf (λx y . Rx (f y)) p qby(simp add : pmf .rel-map ord-option-map2 )
lemma ord-spmf-map-spmf12 : ord-spmf R (map-spmf f p) (map-spmf f q) = ord-spmf(λx y . R (f x ) (f y)) p qby(simp add : pmf .rel-map ord-option-map1 [abs-def ] ord-option-map2 )
lemmas ord-spmf-map-spmf = ord-spmf-map-spmf1 ord-spmf-map-spmf2 ord-spmf-map-spmf12
context fixes ord :: ′a ⇒ ′a ⇒ bool (structure) begininterpretation ord-spmf-syntax .
lemma ord-spmfI :[[∧
x y . (x , y) ∈ set-spmf pq =⇒ ord x y ; map-spmf fst pq = p; map-spmf snd pq= q ]]
=⇒ p v qby(rule rel-pmf .intros[where pq=map-pmf (λx . case x of None ⇒ (None, None)| Some (a, b) ⇒ (Some a, Some b)) pq ])(auto simp add : pmf .map-comp o-def in-set-spmf split : option.splits intro: pmf .map-cong)
lemma ord-spmf-None [simp]: return-pmf None v xby(rule rel-pmf .intros[where pq=map-pmf (Pair None) x ])(auto simp add : pmf .map-compo-def )
lemma ord-spmf-reflI : (∧
x . x ∈ set-spmf p =⇒ ord x x ) =⇒ p v pby(rule rel-pmf-reflI ord-option-reflI )+(auto simp add : in-set-spmf )
lemma rel-spmf-inf :assumes p v qand q v pand refl : reflp ordand trans: transp ordshows rel-spmf (inf ord ord−1−1) p q
proof −from 〈p v q〉 〈q v p〉
have rel-pmf (inf (ord-option ord) (ord-option ord)−1−1) p qby(rule rel-pmf-inf )(blast intro: reflp-ord-option transp-ord-option refl trans)+
also have inf (ord-option ord) (ord-option ord)−1−1 = rel-option (inf ord ord−1−1)by(auto simp add : fun-eq-iff elim: ord-option.cases option.rel-cases)
finally show ?thesis .qed
end
lemma ord-spmf-return-spmf2 : ord-spmf R p (return-spmf y) ←→ (∀ x∈set-spmfp. R x y)by(auto simp add : rel-pmf-return-pmf2 in-set-spmf ord-option.simps intro: ccontr)
65
lemma ord-spmf-mono: [[ ord-spmf A p q ;∧
x y . A x y =⇒ B x y ]] =⇒ ord-spmfB p qby(erule rel-pmf-mono)(erule ord-option-mono)
lemma ord-spmf-compp: ord-spmf (A OO B) = ord-spmf A OO ord-spmf Bby(simp add : ord-option-compp pmf .rel-compp)
lemma ord-spmf-bindI :assumes pq : ord-spmf R p qand fg :
∧x y . R x y =⇒ ord-spmf P (f x ) (g y)
shows ord-spmf P (p >>= f ) (q >>= g)unfolding bind-spmf-def using pqby(rule rel-pmf-bindI )(auto split : option.split intro: fg)
lemma ord-spmf-bind-reflI :(∧
x . x ∈ set-spmf p =⇒ ord-spmf R (f x ) (g x ))=⇒ ord-spmf R (p >>= f ) (p >>= g)
by(rule ord-spmf-bindI [where R=λx y . x = y ∧ x ∈ set-spmf p])(auto intro:ord-spmf-reflI )
lemma ord-pmf-increaseI :assumes le:
∧x . spmf p x ≤ spmf q x
and refl :∧
x . x ∈ set-spmf p =⇒ R x xshows ord-spmf R p q
proof(rule rel-pmf .intros)def pq ≡ embed-pmf
(λ(x , y). case x of Some x ′ ⇒ (case y of Some y ′ ⇒ if x ′ = y ′ then spmf p x ′
else 0 | None ⇒ 0 )| None ⇒ (case y of None ⇒ pmf q None | Some y ′ ⇒ spmf q y ′ − spmf p
y ′))(is embed-pmf ?f )
have nonneg :∧
xy . ?f xy ≥ 0by(clarsimp simp add : pmf-nonneg le field-simps split : option.split)
have integral : (∫
+ xy . ?f xy ∂count-space UNIV ) = 1 (is nn-integral ?M - = -)proof −
have (∫
+ xy . ?f xy ∂count-space UNIV ) =∫+ xy . ereal (?f xy) ∗ indicator (None, None) xy +
ereal (?f xy) ∗ indicator (range (λx . (None, Some x ))) xy +ereal (?f xy) ∗ indicator (range (λx . (Some x , Some x ))) xy ∂?M
by(rule nn-integral-cong)(auto split : split-indicator option.splits split-if-asm)also have . . . = (
∫+ xy . ?f xy ∗ indicator (None, None) xy ∂?M ) +
(∫
+ xy . ereal (?f xy) ∗ indicator (range (λx . (None, Some x ))) xy ∂?M ) +(∫
+ xy . ereal (?f xy) ∗ indicator (range (λx . (Some x , Some x ))) xy ∂?M )(is - = ?None + ?Some2 + ?Some)
by(subst nn-integral-add)(simp-all add : nn-integral-add AE-count-space pmf-nonnegle-diff-eq le split : option.split)
also have ?None = pmf q Noneby(simp add : one-ereal-def [symmetric] max-def pmf-nonneg)
66
also have ?Some2 =∫
+ x . ereal (spmf q x ) − spmf p x ∂count-space UNIVby(simp add : nn-integral-count-space-indicator [symmetric] embed-measure-count-space[symmetric]
inj-on-def nn-integral-embed-measure measurable-embed-measure1 )also have . . . = (
∫+ x . spmf q x ∂count-space UNIV ) − (
∫+ x . spmf p x
∂count-space UNIV )(is - = ?Some2 ′ − ?Some2 ′′)
by(subst nn-integral-diff )(simp-all add : pmf-nonneg le nn-integral-spmf-neq-infinity)also have ?Some =
∫+ x . spmf p x ∂count-space UNIV
by(simp add : nn-integral-count-space-indicator [symmetric] embed-measure-count-space[symmetric]inj-on-def nn-integral-embed-measure measurable-embed-measure1 )
also have pmf q None + (?Some2 ′ − ?Some2 ′′) + . . . = pmf q None +?Some2 ′
by(cases ?Some2 ′ ?Some2 ′′ rule: ereal2-cases)(simp-all add : ereal-minus-eq-PInfty-iffnn-integral-spmf-neq-infinity)
also have . . . =∫
+ x . ereal (pmf q x ) ∗ indicator None x + ereal (pmf qx ) ∗ indicator (range Some) x ∂count-space UNIV
by(subst nn-integral-add)(simp-all add : pmf-nonneg one-ereal-def [symmetric]max-def nn-integral-count-space-indicator [symmetric] embed-measure-count-space[symmetric]inj-on-def nn-integral-embed-measure measurable-embed-measure1 )
also have . . . =∫
+ x . pmf q x ∂count-space UNIVby(rule nn-integral-cong)(auto split : split-indicator)
also have . . . = 1 by(simp add : nn-integral-pmf )finally show ?thesis .
qednote f = nonneg integral
fix x yassume (x , y) ∈ set-pmf pqhence ?f (x , y) 6= 0 unfolding pq-def by(simp add : set-embed-pmf [OF f ])then show ord-option R x y
by(simp add : spmf-eq-0-set-spmf refl split : option.split-asm split-if-asm)
show map-pmf fst pq = pproof(rule pmf-eqI )
fix ihave ereal (pmf (map-pmf fst pq) i) = (
∫+ y . pmf pq (i , y) ∂count-space
UNIV )unfolding pq-def ereal-pmf-map
apply(simp add : embed-pmf .rep-eq [OF f ] o-def emeasure-density nn-integral-count-space-indicator [symmetric])apply(subst pmf-embed-pmf [OF f ])apply(rule nn-integral-bij-count-space[symmetric])apply(auto simp add : bij-betw-def inj-on-def )done
also have . . . = pmf p iproof(cases i)
case (Some x )have (
∫+ y . pmf pq (Some x , y) ∂count-space UNIV ) =
∫+ y . pmf p (Some
x ) ∗ indicator Some x y ∂count-space UNIVby(rule nn-integral-cong)(simp add : pq-def pmf-embed-pmf [OF f ] split :
67
option.split)also have . . . = pmf p (Some x ) by(simp add : pmf-nonneg max-def )finally show ?thesis using Some by simp
nextcase Nonehave (
∫+ y . pmf pq (None, y) ∂count-space UNIV ) =
(∫
+ y . ereal (pmf pq (None, Some (the y))) ∗ indicator (range Some) y+
ereal (pmf pq (None, None)) ∗ indicator None y ∂count-spaceUNIV )
by(rule nn-integral-cong)(auto split : split-indicator)also have . . . = (
∫+ y . ereal (pmf pq (None, Some (the y))) ∂count-space
(range Some)) + pmf pq (None, None)by(subst nn-integral-add)(simp-all add : pmf-nonneg max-def nn-integral-count-space-indicator)also have . . . = (
∫+ y . ereal (spmf q y) − ereal (spmf p y) ∂count-space
UNIV ) + pmf q Noneby(simp add : pq-def pmf-embed-pmf [OF f ] embed-measure-count-space[symmetric]
inj-on-def nn-integral-embed-measure measurable-embed-measure1 )also have (
∫+ y . ereal (spmf q y) − ereal (spmf p y) ∂count-space UNIV ) =
(∫
+ y . spmf q y ∂count-space UNIV ) − (∫
+ y . spmf p y ∂count-spaceUNIV )
by(subst nn-integral-diff )(simp-all add : pmf-nonneg AE-count-space lenn-integral-spmf-neq-infinity split : split-indicator)
also have . . . = pmf p None − pmf q Noneby(simp add : pmf-None-eq-weight-spmf weight-spmf-eq-nn-integral-spmf [symmetric])finally show ?thesis using None by simp
qedfinally show pmf (map-pmf fst pq) i = pmf p i by simp
qed
show map-pmf snd pq = qproof(rule pmf-eqI )
fix ihave ereal (pmf (map-pmf snd pq) i) = (
∫+ x . pmf pq (x , i) ∂count-space
UNIV )unfolding pq-def ereal-pmf-map
apply(simp add : embed-pmf .rep-eq [OF f ] o-def emeasure-density nn-integral-count-space-indicator [symmetric])apply(subst pmf-embed-pmf [OF f ])apply(rule nn-integral-bij-count-space[symmetric])apply(auto simp add : bij-betw-def inj-on-def )done
also have . . . = ereal (pmf q i)proof(cases i)
case Nonehave (
∫+ x . pmf pq (x , None) ∂count-space UNIV ) =
∫+ x . pmf q None ∗
indicator None :: ′a option x ∂count-space UNIVby(rule nn-integral-cong)(simp add : pq-def pmf-embed-pmf [OF f ] split :
option.split)also have . . . = pmf q None by(simp add : max-def pmf-nonneg)
68
finally show ?thesis using None by simpnext
case (Some y)have (
∫+ x . pmf pq (x , Some y) ∂count-space UNIV ) =
(∫
+ x . ereal (pmf pq (x , Some y)) ∗ indicator (range Some) x +ereal (pmf pq (None, Some y)) ∗ indicator None x ∂count-space
UNIV )by(rule nn-integral-cong)(auto split : split-indicator)
also have . . . = (∫
+ x . ereal (pmf pq (x , Some y)) ∗ indicator (range Some)x ∂count-space UNIV ) + pmf pq (None, Some y)
by(subst nn-integral-add)(simp-all add : pmf-nonneg max-def )also have . . . = (
∫+ x . ereal (spmf p y) ∗ indicator Some y x ∂count-space
UNIV ) + (spmf q y − spmf p y)by(auto simp add : pq-def pmf-embed-pmf [OF f ] one-ereal-def [symmetric]
simp del : nn-integral-indicator-singleton intro!: arg-cong2 [where f =op +] nn-integral-congsplit : option.split)
also have . . . = spmf q y by(simp add : max-def pmf-nonneg)finally show ?thesis using Some by simp
qedfinally show pmf (map-pmf snd pq) i = pmf q i by simp
qedqed
lemma ord-spmf-eq-leD :assumes ord-spmf op = p qshows spmf p x ≤ spmf q x
proof(cases x ∈ set-spmf p)case Falsethus ?thesis by(simp add : in-set-spmf-iff-spmf pmf-nonneg)
nextcase Truefrom assms obtain pq
where pq :∧
x y . (x , y) ∈ set-pmf pq =⇒ ord-option op = x yand p: p = map-pmf fst pqand q : q = map-pmf snd pq by cases auto
have ereal (spmf p x ) = integralN pq (indicator (fst −‘ Some x))using p by(simp add : ereal-pmf-map)
also have . . . = integralN pq (indicator (Some x , Some x ))by(rule nn-integral-cong-AE )(auto simp add : AE-measure-pmf-iff split : split-indicator
dest : pq)also have . . . ≤ integralN pq (indicator (snd −‘ Some x))
by(rule nn-integral-mono) simpalso have . . . = ereal (spmf q x ) using q by(simp add : ereal-pmf-map)finally show ?thesis by simp
qed
lemma ord-spmf-eqD-set-spmf : ord-spmf op = p q =⇒ set-spmf p ⊆ set-spmf qby(rule subsetI )(drule-tac x=x in ord-spmf-eq-leD , auto simp add : in-set-spmf-iff-spmf )
69
lemma ord-spmf-eqD-emeasure:ord-spmf op = p q =⇒ emeasure (measure-spmf p) A ≤ emeasure (measure-spmf
q) Aby(auto intro!: nn-integral-mono split : split-indicator dest : ord-spmf-eq-leD simpadd : nn-integral-measure-spmf nn-integral-indicator [symmetric])
lemma ord-spmf-eqD-measure-spmf : ord-spmf op = p q =⇒ measure-spmf p ≤measure-spmf qby(rule less-eq-measure.intros)(simp-all add : ord-spmf-eqD-emeasure)
CCPO structure for the flat ccpo ord-option op =
context fixes Y :: ′a spmf set begin
definition lub-spmf :: ′a spmfwhere lub-spmf = embed-spmf (λx . real-of-ereal (SUP p : Y . ereal (spmf p x )))
— We go through ereal to have a sensible definition even if Y is empty.
lemma lub-spmf-empty [simp]: SPMF .lub-spmf = return-pmf Noneby(simp add : SPMF .lub-spmf-def bot-ereal-def )
context assumes chain: Complete-Partial-Order .chain (ord-spmf op =) Y begin
lemma chain-ord-spmf-eqD : Complete-Partial-Order .chain (op ≤) ((λp x . ereal(spmf p x )) ‘ Y )
(is Complete-Partial-Order .chain - (?f ‘ -))proof(rule chainI )
fix f gassume f ∈ ?f ‘ Y g ∈ ?f ‘ Ythen obtain p q where f : f = ?f p p ∈ Y and g : g = ?f q q ∈ Y by blastfrom chain 〈p ∈ Y 〉 〈q ∈ Y 〉 have ord-spmf op = p q ∨ ord-spmf op = q p
by(rule chainD)thus f ≤ g ∨ g ≤ fproof
assume ord-spmf op = p qhence
∧x . spmf p x ≤ spmf q x by(rule ord-spmf-eq-leD)
hence f ≤ g unfolding f g by(auto intro: le-funI )thus ?thesis ..
nextassume ord-spmf op = q phence
∧x . spmf q x ≤ spmf p x by(rule ord-spmf-eq-leD)
hence g ≤ f unfolding f g by(auto intro: le-funI )thus ?thesis ..
qedqed
lemma ord-spmf-eq-pmf-None-eq :assumes le: ord-spmf op = p qand None: pmf p None = pmf q Noneshows p = q
70
proof(rule spmf-eqI )fix ifrom le have le ′:
∧x . spmf p x ≤ spmf q x by(rule ord-spmf-eq-leD)
have (∫
+ x . ereal (spmf q x ) − spmf p x ∂count-space UNIV ) =(∫
+ x . spmf q x ∂count-space UNIV ) − (∫
+ x . spmf p x ∂count-space UNIV )by(subst nn-integral-diff )(simp-all add : pmf-nonneg AE-count-space le ′ nn-integral-spmf-neq-infinity)
also have . . . = (1 − pmf q None) − (1 − pmf p None) unfolding pmf-None-eq-weight-spmfby(simp add : weight-spmf-eq-nn-integral-spmf [symmetric])
also have . . . = 0 using None by simpfinally have
∧x . spmf q x ≤ spmf p x by(simp add : nn-integral-0-iff-AE AE-count-space)
with le ′ show spmf p i = spmf q i by(rule antisym)qed
lemma ord-spmf-eqD-pmf-None:assumes ord-spmf op = x yshows pmf x None ≥ pmf y None
using assmsapply casesapply clarifyapply(unfold ereal-less-eq(3 )[symmetric] ereal-pmf-map)apply(fastforce simp add : AE-measure-pmf-iff intro!: nn-integral-mono-AE )done
Chains on ′a spmf maintain countable support. Thanks to Johannes Hlzlfor the proof idea.
lemma spmf-chain-countable: countable (⋃
p∈Y . set-spmf p)proof(cases Y = )
case Y : Falseshow ?thesisproof(cases ∃ x∈Y . ∀ y∈Y . ord-spmf op = y x )
case Truethen obtain x where x : x ∈ Y and upper :
∧y . y ∈ Y =⇒ ord-spmf op = y
x by blasthence (
⋃x∈Y . set-spmf x ) ⊆ set-spmf x by(auto dest : ord-spmf-eqD-set-spmf )
thus ?thesis by(rule countable-subset) simpnext
case Falsedef N ≡ λp :: ′a option pmf . pmf p None
have N-less-imp-le-spmf : [[ x ∈ Y ; y ∈ Y ; N y < N x ]] =⇒ ord-spmf op = xy for x y
using chainD [OF chain, of x y ] ord-spmf-eqD-pmf-None[of x y ] ord-spmf-eqD-pmf-None[ofy x ]
by (auto simp: N-def )have N-eq-imp-eq : [[ x ∈ Y ; y ∈ Y ; N y = N x ]] =⇒ x = y for x yusing chainD [OF chain, of x y ] by(auto simp add : N-def dest : ord-spmf-eq-pmf-None-eq)
have NC : N ‘ Y 6= bdd-below (N ‘ Y )using 〈Y 6= 〉 by(auto intro!: bdd-belowI [of - 0 ] simp: N-def pmf-nonneg)
71
have NC-less: Inf (N ‘ Y ) < N x if x ∈ Y for x unfolding cInf-less-iff [OFNC ]
proof(rule ccontr)assume ∗∗: ¬ (∃ y∈N ‘ Y . y < N x ) fix y
assume y ∈ Ywith ∗∗ consider N x < N y | N x = N y by(auto simp add : not-less
le-less)hence ord-spmf op = y x using 〈y ∈ Y 〉 〈x ∈ Y 〉
by cases(auto dest : N-less-imp-le-spmf N-eq-imp-eq intro: ord-spmf-reflI )
with False 〈x ∈ Y 〉 show False by blastqed
from NC have Inf (N ‘ Y ) ∈ closure (N ‘ Y ) by (intro closure-contains-Inf )then obtain X ′ where
∧n. X ′ n ∈ N ‘ Y and X ′: X ′ −−−−→ Inf (N ‘ Y )
unfolding closure-sequential by autothen obtain X where X :
∧n. X n ∈ Y and X ′ = (λn. N (X n)) unfolding
image-iff Bex-def by metis
with X ′ have seq : (λn. N (X n)) −−−−→ Inf (N ‘ Y ) by simphave (
⋃x ∈ Y . set-spmf x ) ⊆ (
⋃n. set-spmf (X n))
proof(rule UN-least)fix xassume x ∈ Yfrom order-tendstoD(2 )[OF seq NC-less[OF 〈x ∈ Y 〉]]obtain i where N (X i) < N x by (auto simp: eventually-sequentially)thus set-spmf x ⊆ (
⋃n. set-spmf (X n)) using X 〈x ∈ Y 〉
by(blast dest : N-less-imp-le-spmf ord-spmf-eqD-set-spmf )qedthus ?thesis by(rule countable-subset) simp
qedqed simp
lemma lub-spmf-subprob: (∫
+ x . (SUP p : Y . ereal (spmf p x )) ∂count-spaceUNIV ) ≤ 1proof(cases Y = )
case Truethus ?thesis by(subst nn-integral-max-0 [symmetric])(simp add : bot-ereal-def max-def )
nextcase Falselet ?B =
⋃p∈Y . set-spmf p
have countable: countable ?B by(rule spmf-chain-countable)
have (∫
+ x . (SUP p:Y . ereal (spmf p x )) ∂count-space UNIV ) =(∫
+ x . (SUP p:Y . ereal (spmf p x ) ∗ indicator ?B x ) ∂count-space UNIV )by(intro nn-integral-cong SUP-cong)(auto split : split-indicator simp add : spmf-eq-0-set-spmf )also have . . . = (
∫+ x . (SUP p:Y . ereal (spmf p x )) ∂count-space ?B)
unfolding ereal-indicator [symmetric] using False
72
by(subst Sup-ereal-mult-right ′[symmetric])(simp-all add : ereal-indicator nn-integral-count-space-indicator)also have . . . = (SUP p:Y .
∫+ x . spmf p x ∂count-space ?B) using False -
countableby(rule nn-integral-monotone-convergence-SUP-countable)(rule chain-ord-spmf-eqD)also have . . . ≤ 1proof(rule SUP-least)
fix passume p ∈ Yhave (
∫+ x . spmf p x ∂count-space ?B) =
∫+ x . ereal (spmf p x ) ∗ indicator
?B x ∂count-space UNIVby(simp add : nn-integral-count-space-indicator)
also have . . . =∫
+ x . spmf p x ∂count-space UNIVby(rule nn-integral-cong)(auto split : split-indicator simp add : spmf-eq-0-set-spmf
〈p ∈ Y 〉)also have . . . ≤ 1
by(simp add : weight-spmf-eq-nn-integral-spmf [symmetric] weight-spmf-le-1 )finally show (
∫+ x . spmf p x ∂count-space ?B) ≤ 1 .
qedfinally show ?thesis .
qed
lemma spmf-lub-spmf :assumes Y 6= shows spmf lub-spmf x = (SUP p : Y . spmf p x )
proof −from assms obtain p where p ∈ Y by autohave spmf lub-spmf x = max 0 (real-of-ereal (SUP p:Y . ereal (spmf p x )))
unfolding lub-spmf-defby(rule spmf-embed-spmf )(simp add : ereal-real assms SUP-spmf-neq-infinity ′
lub-spmf-subprob)also have . . . = real-of-ereal (SUP p:Y . ereal (spmf p x ))
by(rule max-absorb2 )(simp add : real-of-ereal-pos SUP-upper2 [OF 〈p ∈ Y 〉]pmf-nonneg)
also have . . . = (SUP p : Y . spmf p x )by(subst ereal-SUP [symmetric])(simp-all add : assms SUP-spmf-neq-infinity ′)
finally show ?thesis .qed
lemma ereal-spmf-lub-spmf : Y 6= =⇒ ereal (spmf lub-spmf x ) = (SUP p:Y .ereal (spmf p x ))unfolding spmf-lub-spmf by(subst ereal-SUP)(simp-all add : SUP-spmf-neq-infinity ′)
lemma lub-spmf-upper :assumes p: p ∈ Yshows ord-spmf op = p lub-spmf
proof(rule ord-pmf-increaseI )fix xfrom p have [simp]: Y 6= by autofrom p have ereal (spmf p x ) ≤ (SUP p:Y . ereal (spmf p x )) by(rule SUP-upper)
73
also have . . . = ereal (spmf lub-spmf x ) using pby(subst spmf-lub-spmf )(auto simp add : ereal-SUP SUP-spmf-neq-infinity ′)
finally show spmf p x ≤ spmf lub-spmf x by simpqed simp
lemma lub-spmf-least :assumes z :
∧x . x ∈ Y =⇒ ord-spmf op = x z
shows ord-spmf op = lub-spmf zproof(cases Y = )
case nonempty : Falseshow ?thesisproof(rule ord-pmf-increaseI )
fix xfrom nonempty obtain p where p: p ∈ Y by autohave ereal (spmf lub-spmf x ) = (SUP p:Y . ereal (spmf p x ))
by(subst spmf-lub-spmf )(auto simp add : ereal-SUP SUP-spmf-neq-infinity ′
nonempty)also have . . . ≤ ereal (spmf z x ) by(rule SUP-least)(simp add : ord-spmf-eq-leD
z )finally show spmf lub-spmf x ≤ spmf z x by simp
qed simpqed simp
lemma set-lub-spmf : set-spmf lub-spmf = (⋃
p∈Y . set-spmf p) (is ?lhs = ?rhs)proof(cases Y = )
case [simp]: Falseshow ?thesisproof(rule set-eqI )
fix xhave x ∈ ?lhs ←→ ereal (spmf lub-spmf x ) > 0
by(simp-all add : in-set-spmf-iff-spmf pmf-nonneg less-le)also have . . . ←→ (∃ p∈Y . ereal (spmf p x ) > 0 )
by(simp add : ereal-spmf-lub-spmf less-SUP-iff )also have . . . ←→ x ∈ ?rhs
by(auto simp add : in-set-spmf-iff-spmf pmf-nonneg less-le)finally show x ∈ ?lhs ←→ x ∈ ?rhs .
qedqed simp
lemma emeasure-lub-spmf :assumes Y : Y 6= shows emeasure (measure-spmf lub-spmf ) A = (SUP y :Y . emeasure (measure-spmf
y) A)(is ?lhs = ?rhs)
proof −let ?M = count-space (set-spmf lub-spmf )have ?lhs =
∫+ x . ereal (spmf lub-spmf x ) ∗ indicator A x ∂?M
by(auto simp add : nn-integral-indicator [symmetric] nn-integral-measure-spmf ′)also have . . . =
∫+ x . (SUP y :Y . ereal (spmf y x ) ∗ indicator A x ) ∂?M
74
unfolding ereal-indicator [symmetric]by(simp add : spmf-lub-spmf assms ereal-SUP [OF SUP-spmf-neq-infinity ′] Sup-ereal-mult-right ′)also from assms have . . . = (SUP y :Y .
∫+ x . ereal (spmf y x ) ∗ indicator A
x ∂?M )proof(rule nn-integral-monotone-convergence-SUP-countable)
have (λi x . ereal (spmf i x ) ∗ indicator A x ) ‘ Y = (λf x . f x ∗ indicator A x )‘ (λp x . ereal (spmf p x )) ‘ Y
by(simp add : image-image)also have Complete-Partial-Order .chain op ≤ . . . using chain-ord-spmf-eqD
by(rule chain-imageI )(auto simp add : le-fun-def split : split-indicator)finally show Complete-Partial-Order .chain op ≤ ((λi x . ereal (spmf i x ) ∗
indicator A x ) ‘ Y ) .qed simpalso have . . . = (SUP y :Y .
∫+ x . ereal (spmf y x ) ∗ indicator A x ∂count-space
UNIV )by(auto simp add : nn-integral-count-space-indicator set-lub-spmf spmf-eq-0-set-spmf
split : split-indicator intro!: SUP-cong nn-integral-cong)also have . . . = ?rhs
by(auto simp add : nn-integral-indicator [symmetric] nn-integral-measure-spmf )finally show ?thesis .
qed
lemma measure-lub-spmf :assumes Y : Y 6= shows measure (measure-spmf lub-spmf ) A = (SUP y :Y . measure (measure-spmf
y) A)using emeasure-lub-spmf [OF assms] SUP-emeasure-spmf-neq-infinity [OF Y ]unfolding measure-spmf .emeasure-eq-measure by(subst (asm) ereal-SUP [symmetric];simp)
lemma weight-lub-spmf :assumes Y : Y 6= shows weight-spmf lub-spmf = (SUP y :Y . weight-spmf y)
unfolding weight-spmf-def by(rule measure-lub-spmf ) fact
lemma measure-spmf-lub-spmf :assumes Y : Y 6= shows measure-spmf lub-spmf = (SUP p:Y . measure-spmf p) (is ?lhs = ?rhs)
proof(rule measure-eqI )from assms obtain p where p: p ∈ Y by autofrom chain have chain ′: Complete-Partial-Order .chain op ≤ (measure-spmf ‘
Y )by(rule chain-imageI )(rule ord-spmf-eqD-measure-spmf )
show sets ?lhs = sets ?rhs and emeasure ?lhs A = emeasure ?rhs A for Ausing chain ′ Y p by(simp-all add : sets-SUP emeasure-SUP emeasure-lub-spmf )
qed
end
75
end
lemma partial-function-definitions-spmf : partial-function-definitions (ord-spmf op=) lub-spmf
(is partial-function-definitions ?R -)proof
fix x show ?R x x by(simp add : ord-spmf-reflI )next
fix x y zassume ?R x y ?R y zwith transp-ord-option[OF transp-equality ] show ?R x z by(rule transp-rel-pmf [THEN
transpD ])next
fix x yassume ?R x y ?R y xthus x = yby(rule rel-pmf-antisym)(simp-all add : reflp-ord-option transp-ord-option antisymP-ord-option)
nextfix Y xassume Complete-Partial-Order .chain ?R Y x ∈ Ythen show ?R x (lub-spmf Y )
by(rule lub-spmf-upper)next
fix Y zassume Complete-Partial-Order .chain ?R Y
∧x . x ∈ Y =⇒ ?R x z
then show ?R (lub-spmf Y ) zby(cases Y = )(simp-all add : lub-spmf-least)
qed
lemma ccpo-spmf : class.ccpo lub-spmf (ord-spmf op =) (mk-less (ord-spmf op =))by(rule ccpo partial-function-definitions-spmf )+
interpretation spmf : partial-function-definitions ord-spmf op = lub-spmfrewrites lub-spmf ≡ return-pmf None
by(rule partial-function-definitions-spmf ) simp
declaration 〈〈 Partial-Function.init spmf @term spmf .fixp-fun@term spmf .mono-body @thm spmf .fixp-rule-uc @thm spmf .fixp-induct-ucNONE 〉〉
declare spmf .leq-refl [simp]declare admissible-leI [OF ccpo-spmf , cont-intro]
abbreviation mono-spmf ≡ monotone (fun-ord (ord-spmf op =)) (ord-spmf op=)
lemma lub-spmf-const [simp]: lub-spmf p = pby(rule spmf-eqI )(simp add : spmf-lub-spmf [OF ccpo.chain-singleton[OF ccpo-spmf ]])
76
lemma bind-spmf-mono ′:assumes fg : ord-spmf op = f gand hk :
∧x :: ′a. ord-spmf op = (h x ) (k x )
shows ord-spmf op = (f >>= h) (g >>= k)unfolding bind-spmf-def using assms(1 )by(rule rel-pmf-bindI )(auto split : option.split simp add : hk)
lemma bind-spmf-mono [partial-function-mono]:assumes mf : mono-spmf B and mg :
∧y . mono-spmf (λf . C y f )
shows mono-spmf (λf . bind-spmf (B f ) (λy . C y f ))proof (rule monotoneI )
fix f g :: ′a ⇒ ′b spmfassume fg : fun-ord (ord-spmf op =) f gwith mf have ord-spmf op = (B f ) (B g) by (rule monotoneD [of - - - f g ])moreover from mg have
∧y ′. ord-spmf op = (C y ′ f ) (C y ′ g)
by (rule monotoneD) (rule fg)ultimately show ord-spmf op = (bind-spmf (B f ) (λy . C y f )) (bind-spmf (B
g) (λy ′. C y ′ g))by(rule bind-spmf-mono ′)
qed
lemma monotone-bind-spmf1 : monotone (ord-spmf op =) (ord-spmf op =) (λy .bind-spmf y g)by(rule monotoneI )(simp add : bind-spmf-mono ′ ord-spmf-reflI )
lemma monotone-bind-spmf2 :assumes g :
∧x . monotone ord (ord-spmf op =) (λy . g y x )
shows monotone ord (ord-spmf op =) (λy . bind-spmf p (g y))by(rule monotoneI )(auto intro: bind-spmf-mono ′monotoneD [OF g ] ord-spmf-reflI )
lemma bind-lub-spmf :assumes chain: Complete-Partial-Order .chain (ord-spmf op =) Yshows bind-spmf (lub-spmf Y ) f = lub-spmf ((λp. bind-spmf p f ) ‘ Y ) (is ?lhs
= ?rhs)proof(cases Y = )
case Y : Falseshow ?thesisproof(rule spmf-eqI )
fix ihave chain ′: Complete-Partial-Order .chain op ≤ ((λp x . ereal (spmf p x ∗ spmf
(f x ) i)) ‘ Y )using chain by(rule chain-imageI )(auto simp add : le-fun-def pmf-nonneg
dest : ord-spmf-eq-leD intro: mult-right-mono)have chain ′′: Complete-Partial-Order .chain (ord-spmf op =) ((λp. p >>= f ) ‘
Y )using chain by(rule chain-imageI )(auto intro!: monotoneI bind-spmf-mono ′
ord-spmf-reflI )let ?M = count-space (set-spmf (lub-spmf Y ))have ereal (spmf ?lhs i) =
∫+ x . ereal (spmf (lub-spmf Y ) x ) ∗ ereal (spmf
77
(f x ) i) ∂?Mby(auto simp add : ereal-spmf-lub-spmf ereal-spmf-bind nn-integral-measure-spmf ′)also have . . . =
∫+ x . (SUP p:Y . ereal (spmf p x ∗ spmf (f x ) i)) ∂?M
by(subst ereal-spmf-lub-spmf [OF chain Y ])(subst Sup-ereal-mult-right ′, simp-alladd : pmf-nonneg Y )
also have . . . = (SUP p:Y .∫
+ x . ereal (spmf p x ∗ spmf (f x ) i) ∂?M )using Y chain ′ by(rule nn-integral-monotone-convergence-SUP-countable)
simpalso have . . . = (SUP p:Y . ereal (spmf (bind-spmf p f ) i))by(auto simp add : ereal-spmf-bind nn-integral-measure-spmf nn-integral-count-space-indicator
set-lub-spmf [OF chain] in-set-spmf-iff-spmf intro!: SUP-cong nn-integral-cong split :split-indicator)
also have . . . = ereal (spmf ?rhs i) using chain ′′ by(simp add : ereal-spmf-lub-spmfY )
finally show spmf ?lhs i = spmf ?rhs i by simpqed
qed simp
lemma map-lub-spmf :Complete-Partial-Order .chain (ord-spmf op =) Y=⇒ map-spmf f (lub-spmf Y ) = lub-spmf (map-spmf f ‘ Y )
unfolding map-spmf-conv-bind-spmf [abs-def ] by(simp add : bind-lub-spmf o-def )
lemma mcont-bind-spmf1 : mcont lub-spmf (ord-spmf op =) lub-spmf (ord-spmfop =) (λy . bind-spmf y f )using monotone-bind-spmf1 by(rule mcontI )(rule contI , simp add : bind-lub-spmf )
lemma bind-lub-spmf2 :assumes chain: Complete-Partial-Order .chain ord Yand g :
∧y . monotone ord (ord-spmf op =) (g y)
shows bind-spmf x (λy . lub-spmf (g y ‘ Y )) = lub-spmf ((λp. bind-spmf x (λy .g y p)) ‘ Y )
(is ?lhs = ?rhs)proof(cases Y = )
case Y : Falseshow ?thesisproof(rule spmf-eqI )
fix ihave chain ′:
∧y . Complete-Partial-Order .chain (ord-spmf op =) (g y ‘ Y )
using chain g [THEN monotoneD ] by(rule chain-imageI )have chain ′′: Complete-Partial-Order .chain op ≤ ((λp y . ereal (spmf x y ∗
spmf (g y p) i)) ‘ Y )using chain by(rule chain-imageI )(auto simp add : le-fun-def pmf-nonneg
dest : ord-spmf-eq-leD monotoneD [OF g ] intro!: mult-left-mono)have chain ′′′: Complete-Partial-Order .chain (ord-spmf op =) ((λp. bind-spmf
x (λy . g y p)) ‘ Y )using chain by(rule chain-imageI )(rule monotone-bind-spmf2 [OF g , THEN
monotoneD ])
78
have ereal (spmf ?lhs i) =∫
+ y . (SUP p:Y . ereal (spmf x y ∗ spmf (g y p)i)) ∂count-space (set-spmf x )
thm Sup-ereal-mult-right ′
by(simp add : ereal-spmf-bind ereal-spmf-lub-spmf [OF chain ′] Y nn-integral-measure-spmf ′
Sup-ereal-mult-left ′ pmf-nonneg)also have . . . = (SUP p:Y .
∫+ y . ereal (spmf x y ∗ spmf (g y p) i) ∂count-space
(set-spmf x ))unfolding nn-integral-measure-spmf ′ using Y chain ′′
by(rule nn-integral-monotone-convergence-SUP-countable) simpalso have . . . = (SUP p:Y . ereal (spmf (bind-spmf x (λy . g y p)) i))
by(simp add : ereal-spmf-bind nn-integral-measure-spmf ′)also have . . . = ereal (spmf ?rhs i) using chain ′′′
by(auto simp add : ereal-spmf-lub-spmf Y )finally show spmf ?lhs i = spmf ?rhs i by simp
qedqed simp
lemma mcont-bind-spmf [cont-intro]:assumes f : mcont luba orda lub-spmf (ord-spmf op =) fand g :
∧y . mcont luba orda lub-spmf (ord-spmf op =) (g y)
shows mcont luba orda lub-spmf (ord-spmf op =) (λx . bind-spmf (f x ) (λy . g yx ))proof(rule spmf .mcont2mcont ′[OF - - f ])
fix zshow mcont lub-spmf (ord-spmf op =) lub-spmf (ord-spmf op =) (λx . bind-spmf
x (λy . g y z ))by(rule mcont-bind-spmf1 )
nextfix xlet ?f = λz . bind-spmf x (λy . g y z )have monotone orda (ord-spmf op =) ?f using mcont-mono[OF g ] by(rule
monotone-bind-spmf2 )moreover have cont luba orda lub-spmf (ord-spmf op =) ?fproof(rule contI )
fix Yassume chain: Complete-Partial-Order .chain orda Y and Y : Y 6= have bind-spmf x (λy . g y (luba Y )) = bind-spmf x (λy . lub-spmf (g y ‘ Y ))
by(rule bind-spmf-cong)(simp-all add : mcont-contD [OF g chain Y ])also have . . . = lub-spmf ((λp. x >>= (λy . g y p)) ‘ Y ) using chain
by(rule bind-lub-spmf2 )(rule mcont-mono[OF g ])finally show bind-spmf x (λy . g y (luba Y )) = . . . .
qedultimately show mcont luba orda lub-spmf (ord-spmf op =) ?f by(rule mcontI )
qed
lemma bind-pmf-mono [partial-function-mono]:(∧
y . mono-spmf (λf . C y f )) =⇒ mono-spmf (λf . bind-pmf p (λx . C x f ))using bind-spmf-mono[of λ-. spmf-of-pmf p C ] by simp
79
lemma map-spmf-mono [partial-function-mono]: mono-spmf B =⇒ mono-spmf(λg . map-spmf f (B g))unfolding map-spmf-conv-bind-spmf by(rule bind-spmf-mono) simp-all
lemma mcont-map-spmf [cont-intro]:mcont luba orda lub-spmf (ord-spmf op =) g=⇒ mcont luba orda lub-spmf (ord-spmf op =) (λx . map-spmf f (g x ))
unfolding map-spmf-conv-bind-spmf by(rule mcont-bind-spmf ) simp-all
lemma monotone-set-spmf : monotone (ord-spmf op =) op ⊆ set-spmfby(rule monotoneI )(rule ord-spmf-eqD-set-spmf )
lemma cont-set-spmf : cont lub-spmf (ord-spmf op =) Union op ⊆ set-spmfby(rule contI )(subst set-lub-spmf ; simp)
lemma mcont2mcont-set-spmf [THEN mcont2mcont , cont-intro]:shows mcont-set-spmf : mcont lub-spmf (ord-spmf op =) Union op ⊆ set-spmf
by(rule mcontI monotone-set-spmf cont-set-spmf )+
lemma monotone-spmf : monotone (ord-spmf op =) op ≤ (λp. spmf p x )by(rule monotoneI )(simp add : ord-spmf-eq-leD)
lemma cont-spmf : cont lub-spmf (ord-spmf op =) Sup op ≤ (λp. spmf p x )by(rule contI )(simp add : spmf-lub-spmf )
lemma mcont-spmf : mcont lub-spmf (ord-spmf op =) Sup op ≤ (λp. spmf p x )by(rule mcontI monotone-spmf cont-spmf )+
lemma cont-ereal-spmf : cont lub-spmf (ord-spmf op =) Sup op ≤ (λp. ereal (spmfp x ))by(rule contI )(simp add : ereal-spmf-lub-spmf )
lemma mcont2mcont-ereal-spmf [THEN mcont2mcont , cont-intro]:shows mcont-ereal-spmf : mcont lub-spmf (ord-spmf op =) Sup op ≤ (λp. ereal
(spmf p x ))by(rule mcontI mono2mono-ereal monotone-spmf cont-ereal-spmf )+
lemma nn-integral-map-spmf [simp]: nn-integral (measure-spmf (map-spmf f p))g = nn-integral (measure-spmf p) (g f )by(auto 4 3 simp add : measure-spmf-def nn-integral-distr nn-integral-restrict-spaceintro: nn-integral-cong split : split-indicator)
4.9 Restrictions on spmfs
definition restrict-spmf :: ′a spmf ⇒ ′a set ⇒ ′a spmf (infixl 110 )where p A = map-pmf (λx . x >>= (λy . if y ∈ A then Some y else None)) p
lemma set-restrict-spmf [simp]: set-spmf (p A) = set-spmf p ∩ Aby(fastforce simp add : restrict-spmf-def set-spmf-def split : bind-splits split-if-asm)
80
lemma restrict-map-spmf : map-spmf f p A = map-spmf f (p (f −‘ A))by(simp add : restrict-spmf-def pmf .map-comp o-def map-option-bind bind-map-optionif-distrib cong del : if-weak-cong)
lemma restrict-restrict-spmf [simp]: p A B = p (A ∩ B)by(auto simp add : restrict-spmf-def pmf .map-comp o-def intro!: pmf .map-congbind-option-cong)
lemma restrict-spmf-empty [simp]: p = return-pmf Noneby(simp add : restrict-spmf-def )
lemma restrict-spmf-UNIV [simp]: p UNIV = pby(simp add : restrict-spmf-def )
lemma spmf-restrict-spmf-outside [simp]: x /∈ A =⇒ spmf (p A) x = 0by(simp add : spmf-eq-0-set-spmf )
lemma emeasure-restrict-spmf [simp]:emeasure (measure-spmf (p A)) X = emeasure (measure-spmf p) (X ∩ A)
by(auto simp add : restrict-spmf-def measure-spmf-def emeasure-distr measurable-restrict-space1emeasure-restrict-space space-restrict-space intro: arg-cong2 [where f =emeasure]split : bind-splits split-if-asm)
lemma measure-restrict-spmf [simp]:measure (measure-spmf (p A)) X = measure (measure-spmf p) (X ∩ A)
using emeasure-restrict-spmf [of p A X ]by(simp only : measure-spmf .emeasure-eq-measure ereal .inject)
lemma spmf-restrict-spmf : spmf (p A) x = (if x ∈ A then spmf p x else 0 )by(simp add : spmf-conv-measure-spmf )
lemma spmf-restrict-spmf-inside [simp]: x ∈ A =⇒ spmf (p A) x = spmf p xby(simp add : spmf-restrict-spmf )
lemma pmf-restrict-spmf-None: pmf (p A) None = pmf p None + measure(measure-spmf p) (− A)proof −
have [simp]: None /∈ Some ‘ (− A) by autohave (λx . x >>= (λy . if y ∈ A then Some y else None)) −‘ None = None ∪
(Some ‘ (− A))by(auto split : bind-splits split-if-asm)
then show ?thesis unfolding ereal .inject [symmetric]by(simp add : restrict-spmf-def ereal-pmf-map emeasure-pmf-single del : ereal .inject)(simp add : pmf .rep-eq measure-pmf .finite-measure-Union[symmetric] measure-measure-spmf-conv-measure-pmf
measure-pmf .emeasure-eq-measure)qed
lemma restrict-spmf-trivial : (∧
x . x ∈ set-spmf p =⇒ x ∈ A) =⇒ p A = p
81
by(rule spmf-eqI )(auto simp add : spmf-restrict-spmf spmf-eq-0-set-spmf )
lemma restrict-spmf-trivial ′: set-spmf p ⊆ A =⇒ p A = pby(rule restrict-spmf-trivial) blast
lemma restrict-return-spmf : return-spmf x A = (if x ∈ A then return-spmf xelse return-pmf None)by(simp add : restrict-spmf-def )
lemma restrict-return-spmf-inside [simp]: x ∈ A =⇒ return-spmf x A = return-spmfxby(simp add : restrict-return-spmf )
lemma restrict-return-spmf-outside [simp]: x /∈ A =⇒ return-spmf x A = return-pmfNoneby(simp add : restrict-return-spmf )
lemma restrict-spmf-return-pmf-None [simp]: return-pmf None A = return-pmfNoneby(simp add : restrict-spmf-def )
lemma restrict-bind-pmf : bind-pmf p g A = p >>= (λx . g x A)by(simp add : restrict-spmf-def map-bind-pmf o-def )
lemma restrict-bind-spmf : bind-spmf p g A = p >>= (λx . g x A)by(auto simp add : bind-spmf-def restrict-bind-pmf cong del : option.case-cong-weakcong : option.case-cong intro!: bind-pmf-cong split : option.split)
lemma bind-restrict-pmf : bind-pmf (p A) g = p >>= (λx . if x ∈ Some ‘ A theng x else g None)by(auto simp add : restrict-spmf-def bind-map-pmf fun-eq-iff split : bind-split intro:arg-cong2 [where f =bind-pmf ])
lemma bind-restrict-spmf : bind-spmf (p A) g = p >>= (λx . if x ∈ A then g xelse return-pmf None)by(auto simp add : bind-spmf-def bind-restrict-pmf fun-eq-iff intro: arg-cong2 [wheref =bind-pmf ] split : option.split)
lemma spmf-map-restrict : spmf (map-spmf fst (p (snd −‘ y))) x = spmf p(x , y)by(subst spmf-map)(auto intro: arg-cong2 [where f =measure] simp add : spmf-conv-measure-spmf )
lemma measure-eqI-restrict-spmf :assumes rel-spmf R (restrict-spmf p A) (restrict-spmf q B)shows measure (measure-spmf p) A = measure (measure-spmf q) B
proof −from assms have weight-spmf (restrict-spmf p A) = weight-spmf (restrict-spmf
q B) by(rule rel-spmf-weightD)thus ?thesis by(simp add : weight-spmf-def )
82
qed
definition map-filter-spmf :: ( ′a ⇒ ′b option) ⇒ ′a spmf ⇒ ′b spmfwhere map-filter-spmf f p = map-spmf (the f ) (p dom f )
lemma map-spmf-map-filter :map-spmf g (map-filter-spmf f p) = map-filter-spmf (map-option g f ) p
by(fastforce simp add : map-filter-spmf-def pmf .map-comp map-option.comp o-associntro: map-spmf-cong)
lemma map-filter-return-spmf [simp]:map-filter-spmf f (return-spmf x ) = return-pmf (f x )
by(cases x ∈ dom f )(auto simp add : map-filter-spmf-def dest : not-sym)
lemma map-filter-spmf-return-pmf-None [simp]:map-filter-spmf f (return-pmf None) = return-pmf None
by(simp add : map-filter-spmf-def )
lemma emeasure-map-filter-spmf :emeasure (measure-spmf (map-filter-spmf f p)) A = emeasure (measure-spmf p)
(f −‘ Some ‘ A)by(auto simp add : map-filter-spmf-def emeasure-map-spmf intro: arg-cong2 [wheref =emeasure])
lemma measure-map-filter-spmf-conv-distr :measure-spmf (map-filter-spmf f p) =distr (restrict-space (measure-spmf p) (dom f )) (count-space UNIV ) (the f )
by(rule measure-eqI )(simp-all add : map-filter-spmf-def emeasure-map-spmf emeasure-distremeasure-restrict-space space-restrict-space measurable-restrict-space1 )
lemma nn-integral-map-filter-spmf :notes [measurable (raw)] = measurable-restrict-space1shows(∫
+ x . h x ∂measure-spmf (map-filter-spmf f p)) =∫+ x . h (the (f x )) ∗ indicator (dom f ) x ∂measure-spmf p
by(simp add : measure-map-filter-spmf-conv-distr nn-integral-distr nn-integral-restrict-space)
lemma integral-map-filter-spmf :fixes h :: - ⇒ - :: banach, second-countable-topologyshows (
∫x . h x ∂measure-spmf (map-filter-spmf f p)) =∫
x . indicator (dom f ) x ∗R h (the (f x )) ∂measure-spmf punfolding measure-map-filter-spmf-conv-distrby(subst integral-distr)(auto intro: measurable-restrict-space1 simp add : integral-restrict-space)
lemma map-filter-bind-pmf [simp]: map-filter-spmf f (bind-pmf p g) = p >>=map-filter-spmf f gby(simp add : map-filter-spmf-def restrict-bind-pmf map-bind-pmf o-def )
83
lemma map-filter-bind-spmf ′:map-filter-spmf f (bind-spmf p g) = p >>= map-filter-spmf f g
by(simp add : map-filter-spmf-def restrict-bind-spmf map-spmf-bind-spmf o-def )
lemma map-filter-bind-spmf [simp]:map-filter-spmf f (bind-spmf p g) = p >>= (map-filter-spmf f g)
by(simp add : map-filter-bind-spmf ′ o-def )
lemma map-filter-map-spmf [simp]: map-filter-spmf f (map-spmf g p) = map-filter-spmf(f g) pby(auto simp add : map-filter-spmf-def spmf .map-comp restrict-map-spmf o-def in-tro: arg-cong2 [where f =map-spmf ] arg-cong2 [where f =restrict-spmf ])
lemma map-filter-spmf-None [simp]: map-filter-spmf (λ-. None) p = return-pmfNoneby(simp add : map-filter-spmf-def )
lemma bind-map-filter-spmf : bind-spmf (map-filter-spmf f p) g = bind-spmf p (λx .if x ∈ dom f then g (the (f x )) else return-pmf None)by(simp add : map-filter-spmf-def bind-map-spmf bind-restrict-spmf o-def )
lemma map-filter-spmf-alt-def :map-filter-spmf f p = bind-spmf p (return-pmf f )
apply(simp add : map-filter-spmf-def restrict-spmf-def pmf .map-comp o-def bind-spmf-defoption.case-distrib[symmetric] map-pmf-def [symmetric])apply(rule pmf .map-cong)apply(auto split : option.split)done
lemma set-map-filter-spmf : set-spmf (map-filter-spmf f p) = (the f ) ‘ (set-spmfp ∩ dom f )by(simp add : map-filter-spmf-def )
4.10 Integral over spmf
4.10.1 Non-negative integral
definition nn-integral-spmf :: ′a spmf ⇒ ( ′a ⇒ ereal) ⇒ erealwhere nn-integral-spmf p f = nn-integral (measure-spmf p) f
syntax -nn-integral-spmf :: pttrn ⇒ ′a spmf ⇒ ereal ⇒ ereal ((∫
+ (2- ←/ -)./-) [0 , 0 , 52 ] 70 )
translations∫
+ x←p. f == CONST nn-integral-spmf p (λx . f )
lemma nn-integral-spmf-cong :[[ p = q ;
∧x . x ∈ set-spmf q =⇒ f x = g x ]]
=⇒ nn-integral-spmf p f = nn-integral-spmf q gby(auto simp add : nn-integral-spmf-def intro: nn-integral-cong-AE )
84
lemma nn-integral-spmf-cong-simp:[[ p = q ;
∧x . x ∈ set-spmf q =simp=> f x = g x ]]
=⇒ nn-integral-spmf p f = nn-integral-spmf q gunfolding simp-implies-def by(rule nn-integral-spmf-cong)
lemma nn-integral-spmf-return-spmf [simp]: nn-integral-spmf (return-spmf x ) f =max 0 (f x )proof −have nn-integral-spmf (return-spmf x ) f = nn-integral (Giry-Monad .return (count-space
UNIV ) x ) (λx . max 0 (f x ))by(simp add : nn-integral-max-0 nn-integral-spmf-def measure-spmf-return-spmf )also have . . . = max 0 (f x ) by(simp add : nn-integral-return)finally show ?thesis .
qed
lemma nn-integral-spmf-return-pmf-None [simp]: nn-integral-spmf (return-pmf None)f = 0by(simp add : nn-integral-spmf-def )
lemma nn-integral-spmf-bind :nn-integral-spmf (p >>= g) f = nn-integral-spmf p (λx . nn-integral-spmf (g x ) f )
apply(simp add : nn-integral-spmf-def measure-spmf-bind)apply(subst nn-integral-bind [where B=count-space UNIV ])
apply simpapply measurable
done
lemma nn-integral-spmf-const : nn-integral (measure-spmf p) (λ-. c) = max 0 c ∗weight-spmf pby(subst nn-integral-max-0 [symmetric])(simp add : weight-spmf-def measure-spmf .emeasure-eq-measurespace-measure-spmf )
lemma nn-integral-spmf-swap:nn-integral-spmf p (λx . nn-integral-spmf q (λy . f x y)) =nn-integral-spmf q (λy . nn-integral-spmf p (λx . f x y))
(is ?lhs = ?rhs)proof −
interpret sigma-finite-measure restrict-space (measure-spmf r) (set-spmf r) forr
by(rule sigma-finite-measure-restrict-space)(unfold-locales, simp)have ?lhs =
∫+ x .
∫+ y . f x y ∂measure-spmf q ∂measure-spmf p
by(simp add : nn-integral-spmf-def )also have . . . =
∫+ x .
∫+ y . f x y ∂restrict-space (measure-spmf q) (set-spmf
q) ∂restrict-space (measure-spmf p) (set-spmf p)by(subst (1 2 ) nn-integral-restrict-space)(auto intro!: nn-integral-cong-AE simp
add : indicator-def )also have . . . =
∫+ y .
∫+ x . f x y ∂restrict-space (measure-spmf p) (set-spmf
p) ∂restrict-space (measure-spmf q) (set-spmf q)
85
by(rule pair-sigma-finite.Fubini ′)(unfold-locales, measurable, simp add : restrict-count-spacepair-measure-countable)
also have . . . =∫
+ y .∫
+ x . f x y ∂measure-spmf p ∂measure-spmf qby(subst (1 2 ) nn-integral-restrict-space)(auto intro!: nn-integral-cong-AE simp
add : indicator-def )also have . . . = ?rhs by(simp add : nn-integral-spmf-def )finally show ?thesis .
qed
lemma nn-integral-spmf-nonneg : 0 ≤ nn-integral-spmf p fby(simp add : nn-integral-spmf-def nn-integral-nonneg)
lemma max-0-nn-integral-spmf [simp]: max 0 (nn-integral-spmf p f ) = nn-integral-spmfp fby(simp add : max-def nn-integral-spmf-nonneg)
4.10.2 Lebesgue integral
definition integral-spmf :: ′a spmf ⇒ ( ′a ⇒ real) ⇒ realwhere integral-spmf p f = integralL (measure-spmf p) f
syntax -integral-spmf :: pttrn ⇒ ′a spmf ⇒ real ⇒ real ((∫
(2- ←/ -)./ -) [0 , 0 ,60 ] 60 )
translations∫
x←p. f == CONST integral-spmf p (λx . f )
lemma integral-spmf-cong :[[ p = q ;
∧x . x ∈ set-spmf q =⇒ f x = g x ]]
=⇒ integral-spmf p f = integral-spmf q gby(auto simp add : integral-spmf-def intro: integral-cong-AE )
lemma integral-spmf-cong-simp:[[ p = q ;
∧x . x ∈ set-spmf q =simp=> f x = g x ]]
=⇒ integral-spmf p f = integral-spmf q gunfolding simp-implies-def by(rule integral-spmf-cong)
lemma integral-spmf-return-spmf [simp]: integral-spmf (return-spmf x ) f = f xproof −have integral-spmf (return-spmf x ) f = integralL (Giry-Monad .return (count-space
UNIV ) x ) fby(simp add : integral-spmf-def measure-spmf-return-spmf )
also have . . . = f x by(simp add : integral-return)finally show ?thesis .
qed
lemma integral-spmf-return-pmf-None [simp]: integral-spmf (return-pmf None) f= 0by(simp add : integral-spmf-def )
86
lemma integral-spmf-bind :(∧
x . |f x | ≤ B) =⇒ integral-spmf (p >>= g) f = integral-spmf p (λx . integral-spmf(g x ) f )using assmsapply(simp add : integral-spmf-def measure-spmf-bind)apply(subst integral-bind [where K =count-space UNIV and B=B and B ′=1 ])apply(simp-all add : one-ereal-def [symmetric] measure-spmf .emeasure-space-le-1space-subprob-algebra)apply(unfold-locales)done
lemma integral-spmf-const : (∫
- ← p. c) = c ∗ weight-spmf pby(simp add : integral-spmf-def space-measure-spmf weight-spmf-def )
lemma integral-spmf-mono:[[ integrable (measure-spmf p) f ; integrable (measure-spmf p) g ;∧
x . x ∈ set-spmf p =⇒ f x ≤ g x]] =⇒ integral-spmf p f ≤ integral-spmf p g
by(simp add : integral-spmf-def integral-mono-AE )
lemma integral-spmf-indicator-set-spmf :(∫
x ← M . f x ∗ indicator (set-spmf M ) x ) = integral-spmf M fby(simp add : integral-spmf-def integral-cong-AE )
lemma integral-spmf-uminus: (∫
x ← M . − f x ) = − integral-spmf M fby(simp add : integral-spmf-def )
lemma nn-integral-spmf-conv-integral-spmf :[[ integrable (measure-spmf p) f ;
∧x . 0 ≤ f x ]]
=⇒ nn-integral-spmf p f = ereal (integral-spmf p f )unfolding nn-integral-spmf-def integral-spmf-defapply(subst real-lebesgue-integral-def )apply(simp-all add : ereal-minus(1 )[symmetric] ereal-real nn-integral-nonneg nn-integral-0-iff-AE [THENiffD2 ] integrableD)done
lemma integral-spmf-map-spmf : integral-spmf (map-spmf f p) g = integral-spmfp (g f )by(simp add : integral-spmf-def measure-map-spmf-conv-distr integral-distr o-def )
lemma integral-spmf-plus:[[ integrable (measure-spmf p) f ; integrable (measure-spmf p) g ]]=⇒ (
∫x ← p. f x + g x ) = integral-spmf p f + integral-spmf p g
by(simp add : integral-spmf-def )
lemma integral-spmf-indicator-singleton: (∫
x ← p. f x ∗ indicator y x ) = f y∗ spmf p yby(simp add : integral-spmf-def integral-indicator-finite-real spmf-conv-measure-spmf )
87
lemma weight-bind-spmf : weight-spmf (x >>= f ) = integral-spmf x (weight-spmf f )unfolding weight-spmf-defby(simp add : measure-spmf-bind integral-spmf-def o-def measure-spmf .measure-bind [whereN =count-space UNIV ])
4.11 Bounded functions
inductive bounded-on :: ′a set ⇒ ( ′a ⇒ real) ⇒ boolfor A f where (
∧x . x ∈ A =⇒ |f x | ≤ c) =⇒ bounded-on A f
lemma bounded-onE [consumes 1 , case-names bounded-on, cases pred : bounded-on]:assumes bounded-on A (f :: ′a ⇒ real)obtains c where
∧x . x ∈ A =⇒ |f x | ≤ c A 6= =⇒ 0 ≤ c
proof −from assms obtain c where c:
∧x . x ∈ A =⇒ |f x | ≤ c by cases blast
moreover assume A 6= then obtain x where x ∈ A by blastfrom c[OF this] have 0 ≤ c by auto
ultimately show thesis ..qed
lemma bounded-on-empty [simp]: bounded-on (f :: - ⇒ real)by(simp add : bounded-on.simps)
lemma bounded-on-mono: [[ bounded-on B f ; A ⊆ B ]] =⇒ bounded-on A fby(auto simp add : bounded-on.simps)
lemma bounded-on-const [simp]: bounded-on A (λx . c :: real)by(auto simp add : bounded-on.simps)
lemma bounded-on-abs [simp]: bounded-on A (λx . |f x :: real |) ←→ bounded-on Afby(simp add : bounded-on.simps)
lemma bounded-on-split [simp]: bounded-on A (case-prod f ) ←→ bounded-on A(λx . f (fst x ) (snd x ))by(simp add : split-def )
lemma bounded-on-split2 [simp]: bounded-on A (λx . case f x of (y , z ) ⇒ g x y z )←→ bounded-on A (λx . g x (fst (f x )) (snd (f x )))by(simp add : split-def )
lemma bounded-on-splitD-fst :assumes f : bounded-on A (case-prod f )and x : x ∈ fst ‘ Ashows bounded-on (Pair x −‘ A) (f x )
using f
88
proof casescase (bounded-on c)show ?thesisproof
fix yassume y ∈ Pair x −‘ Ahence (x , y) ∈ A by autofrom bounded-on(1 )[OF this] show |f x y | ≤ c by simp
qedqed
lemma (in finite-measure) nn-integral-bounded-fun-finite:assumes bounded-on (space M ) fshows (
∫+ x . ereal (f x ) ∂M ) 6= ∞
using assmsproof(cases)
case (bounded-on c)have (
∫+ x . f x ∂M ) ≤ (
∫+ x . c ∂M )
by(rule nn-integral-mono)(auto dest : bounded-on)also have . . . ≤ max 0 c ∗ emeasure M (space M )
by(simp add : nn-integral-const-If max-def zero-ereal-def [symmetric])also have . . . < ∞ by(simp add : max-def )finally show ?thesis by simp
qed
lemma (in finite-measure) bounded-on-imp-integrable:[[ f ∈ borel-measurable M ; bounded-on (space M ) f ]] =⇒ integrable M f
by(simp add : integrable-iff-bounded nn-integral-bounded-fun-finite)
lemma [simp]:assumes bounded-on A f bounded-on A gshows bounded-on-add : bounded-on A (λx . f x + g x :: real) (is ?add)and bounded-fun-mult : bounded-on A (λx . f x ∗ g x ) (is ?mult)
proof −from 〈bounded-on A f 〉 obtain c1 where c1 :
∧x . x ∈ A =⇒ |f x | ≤ c1 by cases
blastfrom 〈bounded-on A g〉 obtain c2 where c2 :
∧x . x ∈ A =⇒ |g x | ≤ c2 by
cases blast fix x
assume x : x ∈ Ahave |f x + g x | ≤ |f x | + |g x | by(rule abs-triangle-ineq)also have . . . ≤ c1 + c2 using c1 [OF x ] c2 [OF x ] by(rule add-mono)also note calculation
thus ?add by(fastforce intro: bounded-on.intros) fix x
assume x : x ∈ Ahave |f x | ∗ |g x | ≤ c1 ∗ c2 using c1 [OF x ] c2 [OF x ]
by(rule mult-mono ′)simp-all thus ?mult by(fastforce simp add : abs-mult intro: bounded-on.intros)
89
qed
lemma bounded-on-uminus [simp]: bounded-on A (λx . − f x :: real)←→ bounded-onA fby(simp add : bounded-on.simps)
lemma bounded-on-minus [simp]:[[ bounded-on A f ; bounded-on A g ]] =⇒ bounded-on A (λx . f x − g x :: real)
by(simp add : diff-conv-add-uminus del : diff-conv-add-uminus[symmetric])
lemma bounded-on-multc [simp]:bounded-on A (λx . c ∗ f x :: real) ←→ bounded-on A f ∨ c = 0(is ?lhs ←→ ?rhs)
proof(rule iffI )assume ?lhsthen obtain c ′ where c ′:
∧x . x ∈ A =⇒ |c ∗ f x | ≤ c ′ by cases blast
assume c 6= 0then have
∧x . x ∈ A =⇒ |f x | ≤ c ′ / |c| using c ′
by(simp add : field-simps abs-mult)hence bounded-on A f ..
thus ?rhs by blastqed auto
lemma bounded-on-cmult [simp]: bounded-on A (λx . f x ∗ c :: real)←→ bounded-onA f ∨ c = 0by(subst mult .commute) simp
lemma bounded-on-If [simp]:assumes then: bounded-on (A ∩ x . b x) fand else: bounded-on (A ∩ x . ¬ b x) gshows bounded-on A (λx . if b x then f x else g x )
proof −from then obtain c1 where c1 :
∧x . [[ x ∈ A; b x ]] =⇒ |f x | ≤ c1 by cases
autofrom else obtain c2 where c2 :
∧x . [[ x ∈ A; ¬ b x ]] =⇒ |g x | ≤ c2 by cases
autoshow ?thesisproof
fix xassume x ∈ Athen show |if b x then f x else g x | ≤ max c1 c2
by(auto dest : c1 c2 )qed
qed
lemma (in finite-measure) bounded-on-measure [simp]: bounded-on A (λx . mea-sure M x )proof − fix x
90
have emeasure M x ≤ emeasure M (space M )proof(cases x ⊆ space M )
case Falsehence x /∈ sets M using sets.space-closed [of M ] by autothen have emeasure M x = 0 by(rule emeasure-notin-sets)thus ?thesis by(simp add : emeasure-nonneg)
qed(simp add : emeasure-mono) also obtain c where emeasure M (space M ) = ereal c using emeasure-real [of
space M ] by blastfinally have
∧x . |measure M x | ≤ c by(simp add : emeasure-eq-measure measure-nonneg)
thus ?thesis ..qed
lemma bounded-on-measure [simp]:assumes
∧x . x ∈ A =⇒ subprob-space (M x )
shows bounded-on A (λx . measure (M x ) (f x ))proof
fix xassume x ∈ Athen interpret subprob-space M x by(rule assms)have measure (M x ) (f x ) ≤ 1 by(rule subprob-measure-le-1 )thus |measure (M x ) (f x )| ≤ 1 by(simp add : measure-nonneg)
qed
lemma bounded-on-indicator [simp]: bounded-on A (λx . indicator (B x ) (f x ))by(simp add : indicator-def )
lemma bounded-on-mult-indicator [simp]:bounded-on A (λx . f x ∗ indicator B x ) ←→ bounded-on (A ∩ B) (λx . f x )(is ?lhs ←→ ?rhs)
proofassume ?lhsthus ?rhsproof cases
case (bounded-on c)show ?thesisproof
fix xassume x ∈ A ∩ Bwith bounded-on(1 )[of x ]show |f x | ≤ c by auto
qedqed
nextassume ?rhsthus ?lhsproof cases
case (bounded-on c)show ?thesis
91
prooffix xassume x ∈ Awith bounded-on(1 )[of x ]show |f x ∗ indicator B x | ≤ max 0 c
by(auto split : split-indicator)qed
qedqed
lemma bounded-on-integral-spmf [simp]:assumes bounded-on (Sigma A (set-spmf M )) (case-prod f )shows bounded-on A (λx . integral-spmf (M x ) (f x ))
using assmsproof cases
case (bounded-on c)let ?A = Sigma A (set-spmf M )show ?thesisproof
fix xassume x ∈ Ashow |integral-spmf (M x ) (f x )| ≤ max 0 cproof(cases set-spmf (M x ) = )
case Truehence integral-spmf (M x ) (f x ) = integral-spmf (M x ) (λ-. 0 )
by(auto intro: integral-spmf-cong)also have . . . = 0 by(simp add : integral-spmf-const)finally show ?thesis by simp
nextcase Falsethen obtain y where y : y ∈ set-spmf (M x ) by blastwith 〈x ∈ A〉 have x ∈ fst ‘ ?A by(auto 4 3 intro: rev-image-eqI )with assms have bounded-on (set-spmf (M x )) (f x )
by(auto dest : bounded-on-splitD-fst simp add : Pair-vimage-Sigma simp del :bounded-on-split bounded-on-split2 )
then have fx : integrable (measure-spmf (M x )) (λy . f x y ∗ indicator (set-spmf(M x )) y)
by(simp add : measure-spmf .bounded-on-imp-integrable)from 〈x ∈ A〉 y have (x , y) ∈ Sigma A (set-spmf M ) by autowith bounded-on(2 ) have [simp]: 0 ≤ c by(auto simp del : mem-Sigma-iff )
have∫
y ← M x . max 0 (|f x y ∗ indicator (set-spmf (M x )) y |) ≤∫
y← M x . max 0 c
using bounded-on(1 )[of (x , y) for y ] 〈x ∈ A〉
by(intro integral-spmf-mono)(simp-all add : fx , simp add : max-def )also have . . . ≤ max 0 c
by(simp add : integral-spmf-const mult-left-le weight-spmf-le-1 )also note calculation
moreover
92
have integral-spmf (M x ) (f x ) =∫
y ← M x . f x y ∗ indicator (set-spmf(M x )) y
by(simp add : integral-spmf-indicator-set-spmf )also have . . . ≤
∫y ← M x . max 0 (|f x y ∗ indicator (set-spmf (M x ))
y |)by(rule integral-spmf-mono)(simp-all add : fx )
also note calculation moreover
have − integral-spmf (M x ) (f x ) =∫
y ← M x . − f x y ∗ indicator(set-spmf (M x )) y
by(simp add : integral-spmf-indicator-set-spmf integral-spmf-uminus)also have . . . ≤
∫y ← M x . max 0 (|f x y ∗ indicator (set-spmf (M x ))
y |)by(rule integral-spmf-mono)(simp-all add : fx )
also note calculation ultimately show ?thesis by(simp add : abs-real-def )
qedqed
qed
lemma nn-integral-spmf-conv-integral-spmf-bounded :[[ bounded-on UNIV f ;
∧x . 0 ≤ f x ]]
=⇒ nn-integral-spmf p f = ereal (integral-spmf p f )apply(rule nn-integral-spmf-conv-integral-spmf )apply(rule measure-spmf .bounded-on-imp-integrable)apply(simp-all add : space-measure-spmf )done
lemma integral-spmf-bind-bounded [simp]:bounded-on UNIV f =⇒ integral-spmf (p >>= g) f = integral-spmf p (λx . integral-spmf
(g x ) f )by(blast intro: integral-spmf-bind elim!: bounded-on.cases)
lemma integral-spmf-diff :[[ bounded-on UNIV f ; bounded-on UNIV g ]]=⇒ integral-spmf p f − integral-spmf p g = integral-spmf p (λx . f x − g x )
by(simp add : integral-spmf-def measure-spmf .bounded-on-imp-integrable space-measure-spmf )
lemma integral-spmf-swap:bounded-on (set-spmf p × set-spmf q) (λ(x , y). f x y)=⇒
∫x ← p.
∫y ← q . f x y =
∫y ← q .
∫x ← p. f x y
apply(simp add : integral-spmf-def integral-measure-spmf-restrict)apply(rule pair-sigma-finite.Fubini-integral [symmetric])apply(intro pair-sigma-finite.intro sigma-finite-measure-restrict-space)
apply unfold-localesapply simp
apply simpapply(rule finite-measure.bounded-on-imp-integrable)apply(intro finite-measure-pair-measure finite-measure-restrict-space)
93
apply simp-allapply measurableapply simpapply(rule measurable-pair-measure-countable1 )apply simp
apply simpapply(simp add : space-pair-measure space-restrict-space)done
4.12 Subprobability distributions
definition spmf-of-set :: ′a set ⇒ ′a spmfwhere
spmf-of-set A = (if finite A ∧ A 6= then spmf-of-pmf (pmf-of-set A) elsereturn-pmf None)
lemma spmf-of-set : spmf (spmf-of-set A) x = indicator A x / card Aby(auto simp add : spmf-of-set-def )
lemma pmf-spmf-of-set-None [simp]: pmf (spmf-of-set A) None = indicator A.infinite A ∨ A = Aby(simp add : spmf-of-set-def )
lemma set-spmf-of-set : set-spmf (spmf-of-set A) = (if finite A then A else )by(simp add : spmf-of-set-def )
lemma set-spmf-of-set-finite [simp]: finite A =⇒ set-spmf (spmf-of-set A) = Aby(simp add : set-spmf-of-set)
lemma spmf-of-set-singleton: spmf-of-set x = return-spmf xby(simp add : spmf-of-set-def pmf-of-set-singleton)
lemma map-spmf-of-set-inj-on [simp]:inj-on f A =⇒ map-spmf f (spmf-of-set A) = spmf-of-set (f ‘ A)
by(auto simp add : spmf-of-set-def map-pmf-of-set-inj dest : finite-imageD)
lemma spmf-of-pmf-pmf-of-set [simp]:[[ finite A; A 6= ]] =⇒ spmf-of-pmf (pmf-of-set A) = spmf-of-set A
by(simp add : spmf-of-set-def )
lemma weight-spmf-of-set :weight-spmf (spmf-of-set A) = (if finite A ∧ A 6= then 1 else 0 )
by(auto simp only : spmf-of-set-def weight-spmf-of-pmf weight-return-pmf-None split :split-if )
lemma weight-spmf-of-set-finite [simp]: [[ finite A; A 6= ]] =⇒ weight-spmf(spmf-of-set A) = 1by(simp add : weight-spmf-of-set)
94
lemma weight-spmf-of-set-infinite [simp]: infinite A =⇒ weight-spmf (spmf-of-setA) = 0by(simp add : weight-spmf-of-set)
lemma measure-spmf-spmf-of-set :measure-spmf (spmf-of-set A) = (if finite A ∧ A 6= then measure-pmf (pmf-of-set
A) else null-measure (count-space UNIV ))by(simp add : spmf-of-set-def del : spmf-of-pmf-pmf-of-set)
lemma emeasure-spmf-of-set :emeasure (measure-spmf (spmf-of-set S )) A = card (S ∩ A) / card S
by(auto simp add : measure-spmf-spmf-of-set emeasure-pmf-of-set)
lemma measure-spmf-of-set :measure (measure-spmf (spmf-of-set S )) A = card (S ∩ A) / card S
by(auto simp add : measure-spmf-spmf-of-set measure-pmf-of-set)
lemma nn-integral-spmf-of-set : nn-integral (measure-spmf (spmf-of-set A)) f =setsum (max 0 f ) A / card Aby(cases finite A)(auto simp add : spmf-of-set-def nn-integral-pmf-of-set card-gt-0-iffereal-divide-eq-0-iff simp del : spmf-of-pmf-pmf-of-set)
lemma integral-spmf-of-set : integralL (measure-spmf (spmf-of-set A)) f = setsumf A / card Aby(clarsimp simp add : spmf-of-set-def integral-pmf-of-set card-gt-0-iff simp del :spmf-of-pmf-pmf-of-set)
notepad begin — pmf-of-set is not fully parametric.def R == λx :: nat . λy :: nat . x 6= 0 −→ y = 0def A == 0 , 1 :: nat setdef B == 0 , 1 , 2 :: nat sethave rel-set R A B unfolding R-def A-def B-def rel-set-def by autohave ¬ rel-pmf R (pmf-of-set A) (pmf-of-set B)proof
assume rel-pmf R (pmf-of-set A) (pmf-of-set B)then obtain pq where pq :
∧x y . (x , y) ∈ set-pmf pq =⇒ R x y
and 1 : map-pmf fst pq = pmf-of-set Aand 2 : map-pmf snd pq = pmf-of-set Bby cases auto
have pmf (pmf-of-set B) 1 = 1 / 3 by(simp add : B-def )have pmf (pmf-of-set B) 2 = 1 / 3 by(simp add : B-def )
have 2 / 3 = pmf (pmf-of-set B) 1 + pmf (pmf-of-set B) 2 by(simp add :B-def )
also have . . . = measure (measure-pmf (pmf-of-set B)) (1 ∪ 2)by(subst measure-pmf .finite-measure-Union)(simp-all add : measure-pmf-single)also have . . . = emeasure (measure-pmf pq) (snd −‘ 2 , 1)unfolding 2 [symmetric] measure-pmf .emeasure-eq-measure[symmetric] by(simp)also have . . . = emeasure (measure-pmf pq) (0 , 2 ), (0 , 1 )
95
by(rule emeasure-eq-AE )(auto simp add : AE-measure-pmf-iff R-def dest !: pq)also have . . . ≤ emeasure (measure-pmf pq) (fst −‘ 0)
by(rule emeasure-mono) autoalso have . . . = emeasure (measure-pmf (pmf-of-set A)) 0
unfolding 1 [symmetric] by simpalso have . . . = pmf (pmf-of-set A) 0
by(simp add : measure-pmf-single measure-pmf .emeasure-eq-measure)also have pmf (pmf-of-set A) 0 = 1 / 2 by(simp add : A-def )finally show False by simp
qedend
lemma rel-pmf-of-set-bij :assumes f : bij-betw f A Band A: A 6= finite Aand B : B 6= finite Band R:
∧x . x ∈ A =⇒ R x (f x )
shows rel-pmf R (pmf-of-set A) (pmf-of-set B)proof(rule pmf .rel-mono-strong)
def AB ≡ (λx . (x , f x )) ‘ Adef R ′ ≡ λx y . (x , y) ∈ ABhave (x , y) ∈ AB if (x , y) ∈ set-pmf (pmf-of-set AB) for x y
using that by(auto simp add : AB-def A)moreover have map-pmf fst (pmf-of-set AB) = pmf-of-set Aby(simp add : AB-def map-pmf-of-set-inj [symmetric] inj-on-def A pmf .map-comp
o-def )moreoverfrom f have [simp]: inj-on f A by(rule bij-betw-imp-inj-on)from f have [simp]: f ‘ A = B by(rule bij-betw-imageE )have map-pmf snd (pmf-of-set AB) = pmf-of-set Bby(simp add : AB-def map-pmf-of-set-inj [symmetric] inj-on-def A pmf .map-comp
o-def )(simp add : map-pmf-of-set-inj A)
ultimately show rel-pmf (λx y . (x , y) ∈ AB) (pmf-of-set A) (pmf-of-set B) ..qed(auto intro: R)
lemma rel-spmf-of-set-bij :assumes f : bij-betw f A Band R:
∧x . x ∈ A =⇒ R x (f x )
shows rel-spmf R (spmf-of-set A) (spmf-of-set B)proof −
have finite A ←→ finite B using f by(rule bij-betw-finite)moreover have A = ←→ B = using f by(auto dest : bij-betw-empty2
bij-betw-empty1 )ultimately show ?thesis using assmsby(auto simp add : spmf-of-set-def simp del : spmf-of-pmf-pmf-of-set intro: rel-pmf-of-set-bij )
qed
context begin interpretation lifting-syntax .
96
lemma rel-spmf-of-set :assumes bi-unique Rshows (rel-set R ===> rel-spmf R) spmf-of-set spmf-of-set
prooffix A Bassume R: rel-set R A Bwith assms obtain f where bij-betw f A B and f :
∧x . x ∈ A =⇒ R x (f x )
by(auto dest : bi-unique-rel-set-bij-betw)then show rel-spmf R (spmf-of-set A) (spmf-of-set B) by(rule rel-spmf-of-set-bij )
qedend
lemma map-mem-spmf-of-set :assumes finite B B 6= shows map-spmf (λx . x ∈ A) (spmf-of-set B) = spmf-of-pmf (bernoulli-pmf
(card (A ∩ B) / card B))(is ?lhs = ?rhs)
proof(rule spmf-eqI )fix ihave ereal (spmf ?lhs i) = card (B ∩ (λx . x ∈ A) −‘ i) / (card B)by(subst ereal-spmf-map)(simp add : measure-spmf-spmf-of-set assms emeasure-pmf-of-set)also have . . . = (if i then card (B ∩ A) / card B else card (B − A) / card B)
by(auto intro: arg-cong [where f =card ])also have . . . = (if i then card (B ∩ A) / card B else (card B − card (B ∩ A))
/ card B)by(auto simp add : card-Diff-subset-Int assms)
also have . . . = ereal (spmf ?rhs i)by(simp add : assms card-gt-0-iff field-simps card-mono Int-commute of-nat-diff )
finally show spmf ?lhs i = spmf ?rhs i by simpqed
abbreviation coin-spmf :: bool spmfwhere coin-spmf ≡ spmf-of-set UNIV
lemma map-eq-const-coin-spmf : map-spmf (op = c) coin-spmf = coin-spmfproof −
have inj (op ←→ c) range (op ←→ c) = UNIV by(auto intro: inj-onI )then show ?thesis by simp
qed
lemma integral-spmf-coin-spmf-expand : integral-spmf coin-spmf f = 1 / 2 ∗ (fFalse + f True)by(simp add : integral-spmf-def integral-spmf-of-set UNIV-bool field-simps)
lemma bind-coin-spmf-eq-const : coin-spmf >>= (λx :: bool . return-spmf (b = x ))= coin-spmfusing map-eq-const-coin-spmf unfolding map-spmf-conv-bind-spmf by simp
lemma bind-coin-spmf-eq-const ′: coin-spmf >>= (λx :: bool . return-spmf (x = b))
97
= coin-spmfby(rewrite in - = ◊ bind-coin-spmf-eq-const [symmetric, of b])(auto intro: bind-spmf-cong)
4.13 Losslessness
definition lossless-spmf :: ′a spmf ⇒ boolwhere lossless-spmf p ←→ weight-spmf p = 1
lemma lossless-iff-pmf-None: lossless-spmf p ←→ pmf p None = 0by(simp add : lossless-spmf-def pmf-None-eq-weight-spmf )
lemma lossless-return-spmf [iff ]: lossless-spmf (return-spmf x )by(simp add : lossless-iff-pmf-None)
lemma lossless-return-pmf-None [iff ]: ¬ lossless-spmf (return-pmf None)by(simp add : lossless-iff-pmf-None)
lemma lossless-map-spmf [simp]: lossless-spmf (map-spmf f p) ←→ lossless-spmfpby(auto simp add : lossless-iff-pmf-None pmf-eq-0-set-pmf )
lemma lossless-bind-spmf [simp]:lossless-spmf (p >>= f ) ←→ lossless-spmf p ∧ (∀ x∈set-spmf p. lossless-spmf (f
x ))by(simp add : lossless-iff-pmf-None pmf-bind-spmf-None add-nonneg-eq-0-iff pmf-nonnegintegral-nonneg-AE integral-nonneg-eq-0-iff-AE measure-spmf .integrable-const-bound [whereB=1 ] pmf-le-1 )
lemma lossless-weight-spmfD : lossless-spmf p =⇒ weight-spmf p = 1by(simp add : lossless-spmf-def )
lemma lossless-iff-set-pmf-None:lossless-spmf p ←→ None /∈ set-pmf p
by (simp add : lossless-iff-pmf-None pmf-eq-0-set-pmf )
lemma lossless-spmf-of-set [simp]: lossless-spmf (spmf-of-set A) ←→ finite A ∧ A6= by(auto simp add : lossless-spmf-def weight-spmf-of-set)
lemma lossless-spmf-spmf-of-spmf [simp]: lossless-spmf (spmf-of-pmf p)by(simp add : lossless-spmf-def )
lemma lossless-spmf-bind-pmf [simp]:lossless-spmf (bind-pmf p f ) ←→ (∀ x∈set-pmf p. lossless-spmf (f x ))
by(simp add : lossless-iff-pmf-None pmf-bind pmf-nonneg integral-nonneg-AE integral-nonneg-eq-0-iff-AEmeasure-pmf .integrable-const-bound [where B=1 ] AE-measure-pmf-iff pmf-le-1 )
lemma lossless-spmf-conv-spmf-of-pmf : lossless-spmf p ←→ (∃ p ′. p = spmf-of-pmfp ′)
98
proofassume lossless-spmf phence ∗:
∧y . y ∈ set-pmf p =⇒ ∃ x . y = Some x
by(case-tac y)(simp-all add : lossless-iff-set-pmf-None)
let ?p = map-pmf the phave p = spmf-of-pmf ?pproof(rule spmf-eqI )
fix ihave ereal (pmf (map-pmf the p) i) =
∫+ x . indicator (the −‘ i) x ∂p
by(simp add : ereal-pmf-map)also have . . . =
∫+ x . indicator i x ∂measure-spmf p unfolding measure-spmf-def
by(subst nn-integral-distr)(auto simp add : nn-integral-restrict-space AE-measure-pmf-iffsimp del : nn-integral-indicator intro!: nn-integral-cong-AE split : split-indicator dest !:∗ )
also have . . . = spmf p i by(simp add : emeasure-spmf-single)finally show spmf p i = spmf (spmf-of-pmf ?p) i by simp
qedthus ∃ p ′. p = spmf-of-pmf p ′ ..
qed auto
lemma spmf-False-conv-True: lossless-spmf p =⇒ spmf p False = 1 − spmf pTrueby(clarsimp simp add : lossless-spmf-conv-spmf-of-pmf pmf-False-conv-True)
lemma spmf-True-conv-False: lossless-spmf p =⇒ spmf p True = 1 − spmf p Falseby(simp add : spmf-False-conv-True)
lemma bind-eq-return-spmf :bind-spmf p f = return-spmf x ←→ (∀ y∈set-spmf p. f y = return-spmf x ) ∧
lossless-spmf pby(auto simp add : bind-spmf-def bind-eq-return-pmf in-set-spmf lossless-iff-pmf-Nonepmf-eq-0-set-pmf iff del : not-None-eq split : option.split)
lemma rel-spmf-return-spmf2 :rel-spmf R p (return-spmf x ) ←→ lossless-spmf p ∧ (∀ a∈set-spmf p. R a x )
by(auto simp add : lossless-iff-set-pmf-None rel-pmf-return-pmf2 option-rel-Some2in-set-spmf , metis in-set-spmf not-None-eq)
lemma rel-spmf-return-spmf1 :rel-spmf R (return-spmf x ) p ←→ lossless-spmf p ∧ (∀ a∈set-spmf p. R x a)
using rel-spmf-return-spmf2 [of R−1−1] by(simp add : spmf-rel-conversep)
lemma rel-spmf-bindI1 :assumes f :
∧x . x ∈ set-spmf p =⇒ rel-spmf R (f x ) q
and p: lossless-spmf pshows rel-spmf R (bind-spmf p f ) q
proof −fix x :: ′a
99
have rel-spmf R (bind-spmf p f ) (bind-spmf (return-spmf x ) (λ-. q))by(rule rel-spmf-bindI [where R=λx -. x ∈ set-spmf p])(simp-all add : rel-spmf-return-spmf2
p f )then show ?thesis by simp
qed
lemma rel-spmf-bindI2 :[[∧
x . x ∈ set-spmf q =⇒ rel-spmf R p (f x ); lossless-spmf q ]]=⇒ rel-spmf R p (bind-spmf q f )
using rel-spmf-bindI1 [of q conversep R f p] by(simp add : spmf-rel-conversep)
4.14 Scaling
definition scale-spmf :: real ⇒ ′a spmf ⇒ ′a spmfwhere
scale-spmf r p = embed-spmf (λx . min (inverse (weight-spmf p)) (max 0 r) ∗spmf p x )
lemma scale-spmf-le-1 :(∫
+ x . min (inverse (weight-spmf p)) (max 0 r) ∗ spmf p x ∂count-space UNIV )≤ 1 (is ?lhs ≤ -)proof −have ?lhs = min (inverse (weight-spmf p)) (max 0 r) ∗
∫+ x . spmf p x ∂count-space
UNIVby(subst nn-integral-cmult [symmetric])(simp-all add : weight-spmf-nonneg max-def
min-def )also have . . . ≤ 1 unfolding weight-spmf-eq-nn-integral-spmf [symmetric]by(simp add : min-def max-def weight-spmf-nonneg order .strict-iff-order field-simps)finally show ?thesis .
qed
lemma spmf-scale-spmf : spmf (scale-spmf r p) x = max 0 (min (inverse (weight-spmfp)) r) ∗ spmf p x (is ?lhs = ?rhs)unfolding scale-spmf-defapply(subst spmf-embed-spmf [OF scale-spmf-le-1 ])apply(simp add : max-def min-def weight-spmf-le-0 field-simps weight-spmf-nonnegpmf-nonneg not-le order .strict-iff-order)apply(metis antisym-conv order-trans weight-spmf-nonneg zero-le-mult-iff zero-le-one)done
lemma real-inverse-le-1-iff : fixes x :: realshows [[ 0 ≤ x ; x ≤ 1 ]] =⇒ 1 / x ≤ 1 ←→ x = 1 ∨ x = 0
by auto
lemma spmf-scale-spmf ′: r ≤ 1 =⇒ spmf (scale-spmf r p) x = max 0 r ∗ spmf pxusing real-inverse-le-1-iff [OF weight-spmf-nonneg weight-spmf-le-1 , of p]by(auto simp add : spmf-scale-spmf max-def min-def field-simps)(metis pmf-le-0-iffspmf-le-weight)
100
lemma scale-spmf-neg : r ≤ 0 =⇒ scale-spmf r p = return-pmf Noneby(rule spmf-eqI )(simp add : spmf-scale-spmf ′ max-def )
lemma scale-spmf-return-None [simp]: scale-spmf r (return-pmf None) = return-pmfNoneby(rule spmf-eqI )(simp add : spmf-scale-spmf )
lemma scale-spmf-conv-bind-bernoully :assumes r ≤ 1shows scale-spmf r p = bind-pmf (bernoulli-pmf r) (λb. if b then p else return-pmf
None) (is ?lhs = ?rhs)proof(rule spmf-eqI )
fix xhave ereal (spmf ?lhs x ) = ereal (spmf ?rhs x ) using assms
unfolding spmf-scale-spmf ereal-pmf-bind nn-integral-measure-pmf UNIV-boolbernoulli-pmf .rep-eq
apply(auto simp add : nn-integral-count-space-finite zero-ereal-def max-def min-defpmf-nonneg field-simps real-inverse-le-1-iff [OF weight-spmf-nonneg weight-spmf-le-1 ]weight-spmf-lt-0 not-le)
apply (metis pmf-le-0-iff spmf-le-weight)apply (metis pmf-le-0-iff spmf-le-weight)apply (meson leD less-le-trans mult-less-cancel-left1 weight-spmf-le-1 )by (metis le-less-trans less-le zero-less-mult-iff zero-less-one)
thus spmf ?lhs x = spmf ?rhs x by simpqed
lemma nn-integral-spmf : (∫
+ x . spmf p x ∂count-space A) = emeasure (measure-spmfp) Aapply(simp add : measure-spmf-def emeasure-distr emeasure-restrict-space space-restrict-spacenn-integral-pmf [symmetric])apply(rule nn-integral-bij-count-space[where g=Some])apply(auto simp add : bij-betw-def )done
lemma measure-spmf-scale-spmf : measure-spmf (scale-spmf r p) = scale-measure(min (inverse (weight-spmf p)) r) (measure-spmf p)apply(rule measure-eqI )apply simp
apply(simp add : nn-integral-spmf [symmetric] spmf-scale-spmf )apply(subst nn-integral-cmult [symmetric])apply(simp-all add : max-def min-def )done
lemma measure-spmf-scale-spmf ′:r ≤ 1 =⇒ measure-spmf (scale-spmf r p) = scale-measure r (measure-spmf p)
unfolding measure-spmf-scale-spmfapply(cases weight-spmf p > 0 )apply(simp add : min.absorb2 field-simps weight-spmf-le-1 mult-le-one)
101
apply(clarsimp simp add : weight-spmf-le-0 min-def scale-spmf-neg weight-spmf-eq-0not-less)done
lemma scale-spmf-1 [simp]: scale-spmf 1 p = papply(rule spmf-eqI )apply(simp add : spmf-scale-spmf max-def min-def order .strict-iff-order field-simpsweight-spmf-nonneg)apply(metis antisym-conv divide-le-eq-1 less-imp-le pmf-nonneg spmf-le-weight weight-spmf-nonnegweight-spmf-le-1 )done
lemma scale-spmf-0 [simp]: scale-spmf 0 p = return-pmf Noneby(rule spmf-eqI )(simp add : spmf-scale-spmf min-def max-def )
lemma bind-scale-spmf :assumes r : r ≤ 1shows bind-spmf (scale-spmf r p) f = bind-spmf p (λx . scale-spmf r (f x ))(is ?lhs = ?rhs)
proof(rule spmf-eqI )fix xhave ereal (spmf ?lhs x ) = ereal (spmf ?rhs x ) using rby(simp add : ereal-spmf-bind measure-spmf-scale-spmf ′ nn-integral-scale-measure
spmf-scale-spmf ′)(simp add : times-ereal .simps(1 )[symmetric] nn-integral-cmult max-def min-def
del : times-ereal .simps(1 ))thus spmf ?lhs x = spmf ?rhs x by simp
qed
lemma scale-bind-spmf :assumes r ≤ 1shows scale-spmf r (bind-spmf p f ) = bind-spmf p (λx . scale-spmf r (f x ))(is ?lhs = ?rhs)
proof(rule spmf-eqI )fix xhave ereal (spmf ?lhs x ) = ereal (spmf ?rhs x ) using assms
unfolding spmf-scale-spmf ′[OF assms] times-ereal .simps(1 )[symmetric]by(subst (1 2 ) ereal-spmf-bind)(simp add : spmf-scale-spmf ′ times-ereal .simps(1 )[symmetric]
nn-integral-cmult max-def min-def del : times-ereal .simps(1 ))thus spmf ?lhs x = spmf ?rhs x by simp
qed
lemma bind-spmf-const : bind-spmf p (λx . q) = scale-spmf (weight-spmf p) q (is?lhs = ?rhs)proof(rule spmf-eqI )
fix xhave ereal (spmf ?lhs x ) = ereal (spmf ?rhs x )
using measure-spmf .subprob-measure-le-1 [of p space (measure-spmf p)]by(subst ereal-spmf-bind)(simp add : pmf-nonneg spmf-scale-spmf ′weight-spmf-le-1
102
measure-nonneg max-def min-def measure-spmf .emeasure-eq-measure)thus spmf ?lhs x = spmf ?rhs x by simp
qed
lemma map-scale-spmf : map-spmf f (scale-spmf r p) = scale-spmf r (map-spmf fp) (is ?lhs = ?rhs)proof(rule spmf-eqI )
fix ishow spmf ?lhs i = spmf ?rhs i unfolding spmf-scale-spmfby(subst (1 2 ) spmf-map)(simp add : measure-spmf-scale-spmf max-def min-def )
qed
lemma set-scale-spmf : set-spmf (scale-spmf r p) = (if r > 0 then set-spmf p else)apply(auto simp add : in-set-spmf-iff-spmf spmf-scale-spmf )apply(simp add : max-def min-def not-le weight-spmf-lt-0 weight-spmf-eq-0 split :split-if-asm)done
lemma set-scale-spmf ′ [simp]: 0 < r =⇒ set-spmf (scale-spmf r p) = set-spmf pby(simp add : set-scale-spmf )
lemma rel-spmf-scaleI :assumes r > 0 =⇒ rel-spmf A p qshows rel-spmf A (scale-spmf r p) (scale-spmf r q)
proof(cases r > 0 )case Truefrom assms[OF this] show ?thesis
by(rule rel-spmfE )(auto simp add : map-scale-spmf [symmetric] spmf-rel-mapTrue intro: rel-spmf-reflI )qed(simp add : not-less scale-spmf-neg)
lemma weight-scale-spmf : weight-spmf (scale-spmf r p) = min 1 (max 0 r ∗weight-spmf p)proof −have ereal (weight-spmf (scale-spmf r p)) = min 1 (max 0 r ∗ ereal (weight-spmf
p))unfolding weight-spmf-eq-nn-integral-spmf
apply(simp add : spmf-scale-spmf times-ereal .simps(1 )[symmetric] zero-ereal-def [symmetric]nn-integral-cmult)
apply(auto simp add : weight-spmf-eq-nn-integral-spmf [symmetric] field-simpsmin-def max-def not-le weight-spmf-lt-0 )
apply (metis less-le-trans mult-less-cancel-left-neg mult-zero-right not-le zero-less-one)by (meson less-divide-eq not-le weight-spmf-lt-0 )
thus ?thesis by(simp add : one-ereal-def ereal-min[symmetric] del : ereal-minereal-max )qed
lemma weight-scale-spmf ′ [simp]:
103
[[ 0 ≤ r ; r ≤ 1 ]] =⇒ weight-spmf (scale-spmf r p) = r ∗ weight-spmf pby(simp add : weight-scale-spmf max-def min-def )(metis antisym-conv mult-left-leorder-trans weight-spmf-le-1 )
lemma pmf-scale-spmf-None:pmf (scale-spmf k p) None = 1 − min 1 (max 0 k ∗ (1 − pmf p None))
unfolding pmf-None-eq-weight-spmf by(simp add : weight-scale-spmf )
lemma scale-scale-spmf :scale-spmf r (scale-spmf r ′ p) = scale-spmf (r ∗ max 0 (min (inverse (weight-spmf
p)) r ′)) p(is ?lhs = ?rhs)
proof(rule spmf-eqI )fix ihave max 0 (min (1 / weight-spmf p) r ′) ∗
max 0 (min (1 / min 1 (weight-spmf p ∗ max 0 r ′)) r) =max 0 (min (1 / weight-spmf p) (r ∗ max 0 (min (1 / weight-spmf p) r ′)))
proof(cases weight-spmf p > 0 )case Falsethus ?thesis by(simp add : not-less weight-spmf-le-0 )
nextcase True
thus ?thesis by(simp add : field-simps max-def min.absorb-iff2 [symmetric])(autosimp add : min-def field-simps zero-le-mult-iff )
qedthen show spmf ?lhs i = spmf ?rhs i
by(simp add : spmf-scale-spmf field-simps weight-scale-spmf )qed
lemma scale-scale-spmf ′ [simp]:[[ 0 ≤ r ; r ≤ 1 ; 0 ≤ r ′; r ′ ≤ 1 ]]=⇒ scale-spmf r (scale-spmf r ′ p) = scale-spmf (r ∗ r ′) p
apply(cases weight-spmf p > 0 )apply(auto simp add : scale-scale-spmf min-def max-def field-simps not-le weight-spmf-lt-0weight-spmf-eq-0 )apply(metis antisym-conv divide-1 eq-divide-eq-1 less-le mult .right-neutral mult-imp-div-pos-lescale-spmf-1 weight-scale-spmf ′ weight-spmf-le-1 )done
lemma scale-spmf-eq-same: scale-spmf r p = p ←→ weight-spmf p = 0 ∨ r = 1∨ r ≥ 1 ∧ weight-spmf p = 1
(is ?lhs ←→ ?rhs)proof
assume ?lhshence weight-spmf (scale-spmf r p) = weight-spmf p by simphence ∗: min 1 (max 0 r ∗ weight-spmf p) = weight-spmf p by(simp add :
weight-scale-spmf )hence ∗∗: weight-spmf p = 0 ∨ r ≥ 1 by(auto simp add : min-def max-def split :
split-if-asm)
104
show ?rhsproof(cases weight-spmf p = 0 )
case Falsewith ∗∗ have r ≥ 1 by simpwith ∗ False have r = 1 ∨ weight-spmf p = 1 by(simp add : max-def min-def
not-le split : split-if-asm)with 〈r ≥ 1 〉 show ?thesis by simp
qed simpqed(auto intro!: spmf-eqI simp add : spmf-scale-spmf , metis pmf-le-0-iff spmf-le-weight)
lemma map-const-spmf-of-set :[[ finite A; A 6= ]] =⇒ map-spmf (λ-. c) (spmf-of-set A) = return-spmf c
by(simp add : map-spmf-conv-bind-spmf bind-spmf-const)
4.15 Conditional spmfs
lemma set-pmf-Int-Some: set-pmf p ∩ Some ‘ A = ←→ set-spmf p ∩ A = by(auto simp add : in-set-spmf )
lemma measure-spmf-zero-iff : measure (measure-spmf p) A = 0 ←→ set-spmf p∩ A = unfolding measure-measure-spmf-conv-measure-pmf by(simp add : measure-pmf-zero-iffset-pmf-Int-Some)
definition cond-spmf :: ′a spmf ⇒ ′a set ⇒ ′a spmfwhere cond-spmf p A = (if set-spmf p ∩ A = then return-pmf None elsecond-pmf p (Some ‘ A))
lemma set-cond-spmf [simp]: set-spmf (cond-spmf p A) = set-spmf p ∩ Aby(auto 4 4 simp add : cond-spmf-def in-set-spmf iff : set-cond-pmf [THEN set-eq-iff [THENiffD1 ], THEN spec, rotated ])
lemma cond-map-spmf [simp]: cond-spmf (map-spmf f p) A = map-spmf f (cond-spmfp (f −‘ A))proof −
have map-option f −‘ Some ‘ A = Some ‘ f −‘ A by automoreover have set-pmf p ∩ map-option f −‘ Some ‘ A 6= if Some x ∈ set-pmf
p f x ∈ A for xusing that by auto
ultimately show ?thesis by(auto simp add : cond-spmf-def in-set-spmf cond-map-pmf )qed
lemma spmf-cond-spmf [simp]:spmf (cond-spmf p A) x = (if x ∈ A then spmf p x / measure (measure-spmf p)
A else 0 )by(auto simp add : cond-spmf-def pmf-cond set-pmf-Int-Some[symmetric] measure-measure-spmf-conv-measure-pmfmeasure-pmf-zero-iff )
lemma bind-eq-return-pmf-None:
105
bind-spmf p f = return-pmf None ←→ (∀ x∈set-spmf p. f x = return-pmf None)by(auto simp add : bind-spmf-def bind-eq-return-pmf in-set-spmf split : option.splits)
lemma return-pmf-None-eq-bind :return-pmf None = bind-spmf p f ←→ (∀ x∈set-spmf p. f x = return-pmf None)
using bind-eq-return-pmf-None[of p f ] by auto
4.16 Product spmf
definition pair-spmf :: ′a spmf ⇒ ′b spmf ⇒ ( ′a × ′b) spmfwhere pair-spmf p q = bind-pmf (pair-pmf p q) (λxy . case xy of (Some x , Somey) ⇒ return-spmf (x , y) | - ⇒ return-pmf None)
lemma map-fst-pair-spmf [simp]: map-spmf fst (pair-spmf p q) = scale-spmf (weight-spmfq) punfolding bind-spmf-const [symmetric]apply(simp add : pair-spmf-def map-bind-pmf pair-pmf-def bind-assoc-pmf option.case-distrib)apply(subst bind-commute-pmf )apply(auto intro!: bind-pmf-cong [OF refl ] simp add : bind-return-pmf bind-spmf-defbind-return-pmf ′ case-option-collapse option.case-distrib[where h=map-spmf -] op-tion.case-distrib[symmetric] case-option-id split : option.split cong del : option.case-cong)done
lemma map-snd-pair-spmf [simp]: map-spmf snd (pair-spmf p q) = scale-spmf(weight-spmf p) qunfolding bind-spmf-const [symmetric]apply(simp add : pair-spmf-def map-bind-pmf pair-pmf-def bind-assoc-pmf option.case-distribcong del : option.case-cong)apply(auto intro!: bind-pmf-cong [OF refl ] simp add : bind-return-pmf bind-spmf-defbind-return-pmf ′ case-option-collapse option.case-distrib[where h=map-spmf -] op-tion.case-distrib[symmetric] case-option-id split : option.split cong del : option.case-cong)done
lemma set-pair-spmf [simp]: set-spmf (pair-spmf p q) = set-spmf p × set-spmf qby(auto 4 3 simp add : pair-spmf-def set-spmf-bind-pmf bind-UNION in-set-spmfintro: rev-bexI split : option.splits)
lemma spmf-pair [simp]: spmf (pair-spmf p q) (x , y) = spmf p x ∗ spmf q y (is?lhs = ?rhs)proof −
have ereal ?lhs =∫
+ a.∫
+ b. indicator (x , y) (a, b) ∂measure-spmf q∂measure-spmf p
unfolding measure-spmf-def pair-spmf-def ereal-pmf-bind nn-integral-pair-pmf ′
by(auto simp add : zero-ereal-def [symmetric] nn-integral-distr nn-integral-restrict-spacenn-integral-multc[symmetric] intro!: nn-integral-cong split : option.split split-indicator)
also have . . . =∫
+ a. (∫
+ b. indicator y b ∂measure-spmf q) ∗ indicatorx a ∂measure-spmf p
by(subst nn-integral-multc[symmetric])(auto intro!: nn-integral-cong split : split-indicator)also have . . . = ereal ?rhs by(simp add : emeasure-spmf-single max-def pmf-nonneg)
106
finally show ?thesis by simpqed
lemma pair-map-spmf2 : pair-spmf p (map-spmf f q) = map-spmf (apsnd f ) (pair-spmfp q)by(auto simp add : pair-spmf-def pair-map-pmf2 bind-map-pmf map-bind-pmf intro:bind-pmf-cong split : option.split)
lemma pair-map-spmf1 : pair-spmf (map-spmf f p) q = map-spmf (apfst f ) (pair-spmfp q)by(auto simp add : pair-spmf-def pair-map-pmf1 bind-map-pmf map-bind-pmf intro:bind-pmf-cong split : option.split)
lemma pair-map-spmf : pair-spmf (map-spmf f p) (map-spmf g q) = map-spmf(map-prod f g) (pair-spmf p q)unfolding pair-map-spmf2 pair-map-spmf1 spmf .map-comp by(simp add : apfst-defapsnd-def o-def prod .map-comp)
lemma pair-spmf-alt-def : pair-spmf p q = bind-spmf p (λx . bind-spmf q (λy .return-spmf (x , y)))by(auto simp add : pair-spmf-def pair-pmf-def bind-spmf-def bind-assoc-pmf bind-return-pmfsplit : option.split intro: bind-pmf-cong)
lemma weight-pair-spmf [simp]: weight-spmf (pair-spmf p q) = weight-spmf p ∗weight-spmf qunfolding pair-spmf-alt-def by(simp add : weight-bind-spmf integral-spmf-const o-def )
lemma pair-scale-spmf1 :r ≤ 1 =⇒ pair-spmf (scale-spmf r p) q = scale-spmf r (pair-spmf p q)
by(simp add : pair-spmf-alt-def scale-bind-spmf bind-scale-spmf )
lemma pair-scale-spmf2 :r ≤ 1 =⇒ pair-spmf p (scale-spmf r q) = scale-spmf r (pair-spmf p q)
by(simp add : pair-spmf-alt-def scale-bind-spmf bind-scale-spmf )
lemma pair-spmf-return-None1 [simp]: pair-spmf (return-pmf None) p = return-pmfNoneby(rule spmf-eqI )(clarsimp)
lemma pair-spmf-return-None2 [simp]: pair-spmf p (return-pmf None) = return-pmfNoneby(rule spmf-eqI )(clarsimp)
lemma pair-spmf-return-spmf1 : pair-spmf (return-spmf x ) q = map-spmf (Pairx ) qby(rule spmf-eqI )(auto split : split-indicator simp add : spmf-map-inj ′ inj-on-def in-tro: spmf-map-outside)
lemma pair-spmf-return-spmf2 : pair-spmf p (return-spmf y) = map-spmf (λx . (x ,
107
y)) pby(rule spmf-eqI )(auto split : split-indicator simp add : inj-on-def intro!: spmf-map-outsidespmf-map-inj ′[symmetric])
lemma pair-spmf-return-spmf [simp]: pair-spmf (return-spmf x ) (return-spmf y)= return-spmf (x , y)by(simp add : pair-spmf-return-spmf1 )
lemma rel-pair-spmf-prod :rel-spmf (rel-prod A B) (pair-spmf p q) (pair-spmf p ′ q ′) ←→rel-spmf A (scale-spmf (weight-spmf q) p) (scale-spmf (weight-spmf q ′) p ′) ∧rel-spmf B (scale-spmf (weight-spmf p) q) (scale-spmf (weight-spmf p ′) q ′)
(is ?lhs ←→ ?rhs is - ←→ ?A ∧ ?B is - ←→ rel-spmf - ?p ?p ′ ∧ rel-spmf - ?q?q ′)proof(intro iffI conjI )
assume ?rhsthen obtain pq pq ′ where p: map-spmf fst pq = ?p and p ′: map-spmf snd pq
= ?p ′
and q : map-spmf fst pq ′ = ?q and q ′: map-spmf snd pq ′ = ?q ′
and ∗:∧
x x ′. (x , x ′) ∈ set-spmf pq =⇒ A x x ′
and ∗∗:∧
y y ′. (y , y ′) ∈ set-spmf pq ′ =⇒ B y y ′ by(auto elim!: rel-spmfE )let ?f = λ((x , x ′), (y , y ′)). ((x , y), (x ′, y ′))let ?r = 1 / (weight-spmf p ∗ weight-spmf q)let ?pq = scale-spmf ?r (map-spmf ?f (pair-spmf pq pq ′))
fix p :: ′x spmf and q :: ′y spmfassume weight-spmf q 6= 0
and weight-spmf p 6= 0and 1 / (weight-spmf p ∗ weight-spmf q) ≤ weight-spmf p ∗ weight-spmf q
hence 1 ≤ (weight-spmf p ∗ weight-spmf q) ∗ (weight-spmf p ∗ weight-spmf q)by(simp add : pos-divide-le-eq order .strict-iff-order weight-spmf-nonneg)
moreover have (weight-spmf p ∗ weight-spmf q) ∗ (weight-spmf p ∗ weight-spmfq) ≤ (1 ∗ 1 ) ∗ (1 ∗ 1 )
by(intro mult-mono)(simp-all add : weight-spmf-nonneg weight-spmf-le-1 )ultimately have (weight-spmf p ∗ weight-spmf q) ∗ (weight-spmf p ∗ weight-spmf
q) = 1 by simphence ∗: weight-spmf p ∗ weight-spmf q = 1by(metis antisym-conv less-le mult-less-cancel-left1 weight-pair-spmf weight-spmf-le-1
weight-spmf-nonneg)hence weight-spmf p = 1 by(metis antisym-conv mult-left-le weight-spmf-le-1
weight-spmf-nonneg)moreover with ∗ have weight-spmf q = 1 by simpmoreover note calculation
note full = this
show ?lhsproof
have [simp]: fst ?f = map-prod fst fst by(simp add : fun-eq-iff )have map-spmf fst ?pq = scale-spmf ?r (pair-spmf ?p ?q)
108
by(simp add : pair-map-spmf [symmetric] p q map-scale-spmf spmf .map-comp)also have . . . = pair-spmf p q using full [of p q ]by(simp add : pair-scale-spmf1 pair-scale-spmf2 weight-spmf-le-1 weight-spmf-nonneg)(auto simp add : scale-scale-spmf max-def min-def field-simps weight-spmf-nonneg
weight-spmf-eq-0 )finally show map-spmf fst ?pq = . . . .
have [simp]: snd ?f = map-prod snd snd by(simp add : fun-eq-iff )from 〈?rhs〉 have eq : weight-spmf p ∗ weight-spmf q = weight-spmf p ′ ∗
weight-spmf q ′
by(auto dest !: rel-spmf-weightD simp add : weight-spmf-le-1 weight-spmf-nonneg)
have map-spmf snd ?pq = scale-spmf ?r (pair-spmf ?p ′ ?q ′)by(simp add : pair-map-spmf [symmetric] p ′ q ′map-scale-spmf spmf .map-comp)also have . . . = pair-spmf p ′ q ′ using full [of p ′ q ′] eqby(simp add : pair-scale-spmf1 pair-scale-spmf2 weight-spmf-le-1 weight-spmf-nonneg)(auto simp add : scale-scale-spmf max-def min-def field-simps weight-spmf-nonneg
weight-spmf-eq-0 )finally show map-spmf snd ?pq = . . . .
qed(auto simp add : set-scale-spmf split : split-if-asm dest : ∗ ∗∗ )next
assume ?lhsthen obtain pq where pq : map-spmf fst pq = pair-spmf p q
and pq ′: map-spmf snd pq = pair-spmf p ′ q ′
and ∗:∧
x y x ′ y ′. ((x , y), (x ′, y ′)) ∈ set-spmf pq =⇒ A x x ′ ∧ B y y ′
by(auto elim: rel-spmfE )
show ?Aproof
let ?f = (λ((x , y), (x ′, y ′)). (x , x ′))let ?pq = map-spmf ?f pqhave [simp]: fst ?f = fst fst by(simp add : split-def o-def )show map-spmf fst ?pq = scale-spmf (weight-spmf q) p using pq
by(simp add : spmf .map-comp)(simp add : spmf .map-comp[symmetric])
have [simp]: snd ?f = fst snd by(simp add : split-def o-def )show map-spmf snd ?pq = scale-spmf (weight-spmf q ′) p ′ using pq ′
by(simp add : spmf .map-comp)(simp add : spmf .map-comp[symmetric])qed(auto dest : ∗ )
show ?Bproof
let ?f = (λ((x , y), (x ′, y ′)). (y , y ′))let ?pq = map-spmf ?f pqhave [simp]: fst ?f = snd fst by(simp add : split-def o-def )show map-spmf fst ?pq = scale-spmf (weight-spmf p) q using pq
by(simp add : spmf .map-comp)(simp add : spmf .map-comp[symmetric])
have [simp]: snd ?f = snd snd by(simp add : split-def o-def )
109
show map-spmf snd ?pq = scale-spmf (weight-spmf p ′) q ′ using pq ′
by(simp add : spmf .map-comp)(simp add : spmf .map-comp[symmetric])qed(auto dest : ∗ )
qed
lemma pair-pair-spmf :pair-spmf (pair-spmf p q) r = map-spmf (λ(x , (y , z )). ((x , y), z )) (pair-spmf p
(pair-spmf q r))by(simp add : pair-spmf-alt-def map-spmf-conv-bind-spmf )
lemma pair-commute-spmf :pair-spmf p q = map-spmf (λ(y , x ). (x , y)) (pair-spmf q p)
unfolding pair-spmf-alt-def by(subst bind-commute-spmf )(simp add : map-spmf-conv-bind-spmf )
4.17 Assertions
definition assert-spmf :: bool ⇒ unit spmfwhere assert-spmf b = (if b then return-spmf () else return-pmf None)
lemma assert-spmf-simps [simp]:assert-spmf True = return-spmf ()assert-spmf False = return-pmf None
by(simp-all add : assert-spmf-def )
lemma in-set-assert-spmf [simp]: x ∈ set-spmf (assert-spmf p) ←→ pby(cases p) simp-all
lemma set-spmf-assert-spmf-eq-empty [simp]: set-spmf (assert-spmf b) = ←→¬ bby(cases b) simp-all
lemma lossless-assert-spmf [iff ]: lossless-spmf (assert-spmf b) ←→ bby(cases b) simp-all
4.18 Try
definition try-spmf :: ′a spmf ⇒ ′a spmf ⇒ ′a spmf (TRY - ELSE - [0 ,60 ] 59 )where try-spmf p q = bind-pmf p (λx . case x of None ⇒ q | Some y ⇒ return-spmfy)
lemma try-spmf-lossless [simp]:assumes lossless-spmf pshows TRY p ELSE q = p
proof −have TRY p ELSE q = bind-pmf p return-pmf unfolding try-spmf-def using
assmsby(auto simp add : lossless-iff-set-pmf-None split : option.split intro: bind-pmf-cong)thus ?thesis by(simp add : bind-return-pmf ′)
qed
110
lemma try-spmf-return-spmf1 : TRY return-spmf x ELSE q = return-spmf xby(simp add : try-spmf-def bind-return-pmf )
lemma try-spmf-return-None [simp]: TRY return-pmf None ELSE q = qby(simp add : try-spmf-def bind-return-pmf )
lemma try-spmf-return-pmf-None2 [simp]: TRY p ELSE return-pmf None = pby(simp add : try-spmf-def option.case-distrib[symmetric] bind-return-pmf ′ case-option-id)
lemma map-try-spmf :map-spmf f (try-spmf p q) = try-spmf (map-spmf f p) (map-spmf f q)
by(simp add : try-spmf-def map-bind-pmf bind-map-pmf option.case-distrib[whereh=map-spmf f ] o-def cong del : option.case-cong-weak)
lemma try-spmf-bind-pmf : TRY (bind-pmf p f ) ELSE q = bind-pmf p (λx . TRY(f x ) ELSE q)by(simp add : try-spmf-def bind-assoc-pmf )
lemma try-spmf-bind-spmf-lossless:lossless-spmf p =⇒ TRY (bind-spmf p f ) ELSE q = bind-spmf p (λx . TRY (f
x ) ELSE q)by(auto simp add : try-spmf-def bind-spmf-def bind-assoc-pmf bind-return-pmf lossless-iff-set-pmf-Noneintro!: bind-pmf-cong split : option.split)
lemma try-spmf-bind-out :lossless-spmf p =⇒ bind-spmf p (λx . TRY (f x ) ELSE q) = TRY (bind-spmf p
f ) ELSE qby(simp add : try-spmf-bind-spmf-lossless)
lemma lossless-try-spmf [simp]:lossless-spmf (TRY p ELSE q) ←→ lossless-spmf p ∨ lossless-spmf q
by(auto simp add : try-spmf-def in-set-spmf lossless-iff-set-pmf-None split : option.splits)
context begin interpretation lifting-syntax .lemma try-spmf-parametric [transfer-rule]:
(rel-spmf A ===> rel-spmf A ===> rel-spmf A) try-spmf try-spmfunfolding try-spmf-def [abs-def ] by transfer-proverend
lemma try-spmf-cong :[[ p = p ′; ¬ lossless-spmf p ′ =⇒ q = q ′ ]] =⇒ TRY p ELSE q = TRY p ′ ELSE q ′
unfolding try-spmf-defby(rule bind-pmf-cong)(auto split : option.split simp add : lossless-iff-set-pmf-None)
lemma rel-spmf-try-spmf :[[ rel-spmf R p p ′; ¬ lossless-spmf p ′ =⇒ rel-spmf R q q ′ ]]=⇒ rel-spmf R (TRY p ELSE q) (TRY p ′ ELSE q ′)
unfolding try-spmf-defapply(rule rel-pmf-bindI [where R=λx y . rel-option R x y ∧ x ∈ set-pmf p ∧ y ∈
111
set-pmf p ′])apply(erule pmf .rel-mono-strong ; simp)
apply(auto split : option.split simp add : lossless-iff-set-pmf-None)done
lemma spmf-try-spmf :spmf (TRY p ELSE q) x = spmf p x + pmf p None ∗ spmf q x
proof −have ereal (spmf (TRY p ELSE q) x ) =
∫+ y . ereal (spmf q x ) ∗ indicator
None y + indicator Some x y ∂measure-pmf punfolding try-spmf-def ereal-pmf-bind by(rule nn-integral-cong)(simp split :
option.split split-indicator)also have . . . = (
∫+ y . ereal (spmf q x ) ∗ indicator None y ∂measure-pmf p)
+∫
+ y . indicator Some x y ∂measure-pmf pby(simp add : nn-integral-add pmf-nonneg)
also have . . . = ereal (spmf q x ) ∗ pmf p None + spmf p xby(simp add : emeasure-pmf-single max-def not-le pmf-nonneg)
finally show ?thesis by simpqed
lemma try-scale-spmf-same [simp]: lossless-spmf p =⇒ TRY scale-spmf k p ELSEp = pby(rule spmf-eqI )(auto simp add : spmf-try-spmf spmf-scale-spmf pmf-scale-spmf-Nonelossless-iff-pmf-None weight-spmf-conv-pmf-None min-def max-def field-simps)
lemma pmf-try-spmf-None [simp]: pmf (TRY p ELSE q) None = pmf p None ∗pmf q None (is ?lhs = ?rhs)proof −
have ?lhs =∫
x . pmf q None ∗ indicator None x ∂measure-pmf punfolding try-spmf-def pmf-bind by(rule integral-cong)(simp-all split : op-
tion.split)also have . . . = ?rhs by(simp add : measure-pmf-single)finally show ?thesis .
qed
lemma try-bind-spmf-lossless2 :lossless-spmf q =⇒ TRY (bind-spmf p f ) ELSE q = TRY (p >>= (λx . TRY (f
x ) ELSE q)) ELSE qby(rule spmf-eqI )(simp add : spmf-try-spmf pmf-bind-spmf-None spmf-bind field-simpsmeasure-spmf .integrable-const-bound [where B=1 ] pmf-nonneg pmf-le-1 lossless-iff-pmf-None)
lemma try-bind-spmf-lossless2 ′:fixes f :: ′a ⇒ ′b spmf shows[[ NO-MATCH (λx :: ′a. try-spmf (g x :: ′b spmf ) (h x )) f ; lossless-spmf q ]]=⇒ TRY (bind-spmf p f ) ELSE q = TRY (p >>= (λx :: ′a. TRY (f x ) ELSE
q)) ELSE qby(rule try-bind-spmf-lossless2 )
lemma try-bind-assert-spmf :
112
TRY (assert-spmf b >>= f ) ELSE q = (if b then TRY (f ()) ELSE q else q)by simp
4.19 Embedding of ′a option into ′a spmf
definition spmf-monad :: ( ′a, ′a spmf ) monad-failwhere spmf-monad = (|bind = bind-spmf , return = return-spmf , fail = return-pmfNone |)
lemma spmf-monad-sel [simp]:shows bind-spmf : bind spmf-monad = bind-spmfand return-spmf : return spmf-monad = return-spmfand fail-spmf : fail spmf-monad = return-pmf None
by(simp-all add : spmf-monad-def )
lemma bind-option-spmf-monad [simp]: monad .bind-option spmf-monad x = bind-spmf(return-pmf x )by(cases x )(simp-all add : fun-eq-iff )
lemma monad-spmf [simp, intro, locale-witness]: monad spmf-monadby unfold-locales(simp-all)
lemma monad-fail-spmf [simp, intro, locale-witness]: monad-fail spmf-monadby unfold-locales(simp)
context begin interpretation lifting-syntax .
lemma return-spmf-parametric: (A ===> rel-spmf A) return-spmf return-spmfby transfer-prover
lemma map-spmf-parametric: ((A ===> B) ===> rel-spmf A ===> rel-spmfB) map-spmf map-spmfby transfer-prover
lemma rel-spmf-parametric:((A ===> B ===> op =) ===> rel-spmf A ===> rel-spmf B ===> op =)
rel-spmf rel-spmfby transfer-prover
lemma set-spmf-parametric [transfer-rule]:(rel-spmf A ===> rel-set A) set-spmf set-spmf
unfolding set-spmf-def [abs-def ] by transfer-prover
lemma return-spmf-None-parametric:(rel-spmf A) (return-pmf None) (return-pmf None)
by simp
end
113
locale option-to-spmf begin
definition option-of-spmf :: ′a spmf ⇒ ′a optionwhere option-of-spmf p = (THE x . p = return-pmf x )
lemma option-of-spmf-return-pmf [simp]: option-of-spmf (return-pmf x ) = xunfolding option-of-spmf-def by auto
definition cr-option-spmf :: ′a spmf ⇒ ′a option ⇒ boolwhere cr-option-spmf p x ←→ p = return-pmf x
lemma left-unique-cr-option-spmf : left-unique cr-option-spmfby(rule left-uniqueI )(simp add : cr-option-spmf-def )
lemma right-unique-cr-option-spmf : right-unique cr-option-spmfby(rule right-uniqueI )(simp add : cr-option-spmf-def )
lemma bi-unique-cr-option-spmf : bi-unique cr-option-spmfby(simp add : bi-unique-alt-def left-unique-cr-option-spmf right-unique-cr-option-spmf )
lemma right-total-cr-option-spmf : right-total cr-option-spmfby(rule right-totalI )(simp add : cr-option-spmf-def )
interpretation lifting-syntax .
lemma return-option-spmf-transfer [transfer-rule]:(op = ===> cr-option-spmf ) return-spmf Some
by(rule rel-funI )(simp add : cr-option-spmf-def )
lemma map-option-spmf-transfer [transfer-rule]:((op = ===> op =) ===> cr-option-spmf ===> cr-option-spmf ) map-spmf
map-optionunfolding rel-fun-eq by(auto simp add : rel-fun-def cr-option-spmf-def )
lemma fail-option-spmf-transfer [transfer-rule]:cr-option-spmf (return-pmf None) None
by(simp add : cr-option-spmf-def )
lemma bind-option-spmf-transfer [transfer-rule]:(cr-option-spmf ===> (op = ===> cr-option-spmf ) ===> cr-option-spmf )
bind-spmf Option.bindapply(clarsimp simp add : rel-fun-def cr-option-spmf-def )subgoal for x f g by(cases x ; simp)done
lemma set-option-spmf-transfer [transfer-rule]:(cr-option-spmf ===> rel-set op =) set-spmf set-option
apply(clarsimp simp add : rel-fun-def cr-option-spmf-def rel-set-eq)subgoal for x by(cases x ; simp)
114
done
lemma rel-option-spmf-transfer [transfer-rule]:((op = ===> op = ===> op =) ===> cr-option-spmf ===> cr-option-spmf
===> op =) rel-spmf rel-optionunfolding rel-fun-eq by(simp add : rel-fun-def cr-option-spmf-def )
end
locale option-le-spmf begin
Embedding where only successful computations in the option monad arerelated to Dirac spmf.
definition cr-option-le-spmf :: ′a option ⇒ ′a spmf ⇒ boolwhere cr-option-le-spmf x p ←→ ord-spmf op = (return-pmf x ) p
interpretation lifting-syntax .
lemma return-option-le-spmf-transfer [transfer-rule]:(op = ===> cr-option-le-spmf ) (λx . x ) return-pmf
by(rule rel-funI )(simp add : cr-option-le-spmf-def ord-option-reflI )
lemma map-option-le-spmf-transfer [transfer-rule]:((op = ===> op =) ===> cr-option-le-spmf ===> cr-option-le-spmf ) map-option
map-spmfunfolding rel-fun-eqapply(clarsimp simp add : rel-fun-def cr-option-le-spmf-def rel-pmf-return-pmf1 ord-option-map1ord-option-map2 )subgoal for f x p y by(cases x ; simp add : ord-option-reflI )done
lemma bind-option-le-spmf-transfer [transfer-rule]:(cr-option-le-spmf ===> (op = ===> cr-option-le-spmf ) ===> cr-option-le-spmf )
Option.bind bind-spmfapply(clarsimp simp add : rel-fun-def cr-option-le-spmf-def )subgoal for x p f g by(cases x ; auto 4 3 simp add : rel-pmf-return-pmf1 set-pmf-bind-spmf )done
end
context notes [[quick-and-dirty ]] beginlemma rel-pmf-measureI :assumes
∧A. measure (measure-pmf p) A ≤ measure (measure-pmf q) y . ∃ x∈A.
R x yshows rel-pmf R p q
sorry — Not yet formalised, proved by J. Sack and L. Zhang: A General Frameworkfor Probabilistic Characterizing Formulae, VMCAI 2012end
115
lemma rel-spmf-measureI :assumes eq1 :
∧A. measure (measure-spmf p) A ≤ measure (measure-spmf q)
y . ∃ x∈A. R x yassumes eq2 : weight-spmf q ≤ weight-spmf pshows rel-spmf R p q
proof(rule rel-pmf-measureI )fix A :: ′a option setdef A ′ ≡ the ‘ (A ∩ range Some) and A ′′ ≡ A ∩ Nonehave A: A = Some ‘ A ′ ∪ A ′′ Some ‘ A ′ ∩ A ′′ =
unfolding A ′-def A ′′-def by(auto 4 3 intro: rev-image-eqI )have measure (measure-pmf p) A = measure (measure-pmf p) (Some ‘ A ′) +
measure (measure-pmf p) A ′′
by(simp add : A measure-pmf .finite-measure-Union)also have measure (measure-pmf p) (Some ‘ A ′) = measure (measure-spmf p)
A ′
by(simp add : measure-measure-spmf-conv-measure-pmf )also have . . . ≤ measure (measure-spmf q) y . ∃ x∈A ′. R x y by(rule eq1 )also (ord-eq-le-trans[OF - add-right-mono])have . . . = measure (measure-pmf q) y . ∃ x∈A ′. rel-option R (Some x ) y
unfolding measure-measure-spmf-conv-measure-pmfby(rule arg-cong2 [where f =measure])(auto simp add : A ′-def option-rel-Some1 )
also have weight-spmf p ≤ measure (measure-spmf q) y . ∃ x . R x y
using eq1 [of UNIV ] unfolding weight-spmf-def by simpalso have . . . ≤ weight-spmf q unfolding weight-spmf-def
by(rule measure-spmf .finite-measure-mono) simp-allfinally have weight-spmf p = weight-spmf q using eq2 by simp
then have measure (measure-pmf p) A ′′ = measure (measure-pmf q) (if None∈ A then None else )
unfolding A ′′-def by(simp add : pmf-None-eq-weight-spmf measure-pmf-single)also have measure (measure-pmf q) y . ∃ x∈A ′. rel-option R (Some x ) y + . . .
= measure (measure-pmf q) y . ∃ x∈A. rel-option R x yby(subst measure-pmf .finite-measure-Union[symmetric])
(auto 4 3 intro!: arg-cong2 [where f =measure] simp add : option-rel-Some1option-rel-Some2 A ′-def intro: rev-bexI elim: option.rel-cases)
finally show measure (measure-pmf p) A ≤ . . . .qed
lemma rel-spmf-measureD :assumes rel-spmf R p qshows measure (measure-spmf p) A ≤ measure (measure-spmf q) y . ∃ x∈A. R
x y (is ?lhs ≤ ?rhs)proof −have ?lhs = measure (measure-pmf p) (Some ‘ A) by(simp add : measure-measure-spmf-conv-measure-pmf )also have . . . ≤ measure (measure-pmf q) y . ∃ x∈Some ‘ A. rel-option R x y
using assms by(rule rel-pmf-measureD)also have . . . = ?rhs unfolding measure-measure-spmf-conv-measure-pmf
by(rule arg-cong2 [where f =measure])(auto simp add : option-rel-Some1 )finally show ?thesis .
116
qed
lemma admissible-rel-spmf :ccpo.admissible (prod-lub lub-spmf lub-spmf ) (rel-prod (ord-spmf op =) (ord-spmf
op =)) (case-prod (rel-spmf R))(is ccpo.admissible ?lub ?ord ?P)
proof(rule ccpo.admissibleI )fix Yassume chain: Complete-Partial-Order .chain ?ord Y
and Y : Y 6= and R: ∀ (p, q) ∈ Y . rel-spmf R p q
from R have R:∧
p q . (p, q) ∈ Y =⇒ rel-spmf R p q by autohave chain1 : Complete-Partial-Order .chain (ord-spmf op =) (fst ‘ Y )
and chain2 : Complete-Partial-Order .chain (ord-spmf op =) (snd ‘ Y )using chain by(rule chain-imageI ; clarsimp)+
from Y have Y1 : fst ‘ Y 6= and Y2 : snd ‘ Y 6= by auto
have rel-spmf R (lub-spmf (fst ‘ Y )) (lub-spmf (snd ‘ Y ))proof(rule rel-spmf-measureI )
show weight-spmf (lub-spmf (snd ‘ Y )) ≤ weight-spmf (lub-spmf (fst ‘ Y ))by(auto simp add : weight-lub-spmf chain1 chain2 Y rel-spmf-weightD [OF R,
symmetric] intro!: cSUP-least intro: cSUP-upper2 [OF bdd-aboveI2 [OF weight-spmf-le-1 ]])
fix Ahave measure (measure-spmf (lub-spmf (fst ‘ Y ))) A = (SUP y :fst ‘ Y . measure
(measure-spmf y) A)using chain1 Y1 by(rule measure-lub-spmf )
also have . . . ≤ (SUP y :snd ‘ Y . measure (measure-spmf y) y . ∃ x∈A. R xy) using Y1
by(rule cSUP-least)(auto intro!: cSUP-upper2 [OF bdd-aboveI2 [OF measure-spmf .subprob-measure-le-1 ]]rel-spmf-measureD R)
also have . . . = measure (measure-spmf (lub-spmf (snd ‘ Y ))) y . ∃ x∈A. Rx y
using chain2 Y2 by(rule measure-lub-spmf [symmetric])finally show measure (measure-spmf (lub-spmf (fst ‘ Y ))) A ≤ . . . .
qedthen show ?P (?lub Y ) by(simp add : prod-lub-def )
qed
lemma monotone-Pair : — Move to Complete-Partial-Order2[[ monotone ord orda f ; monotone ord ordb g ]]=⇒ monotone ord (rel-prod orda ordb) (λx . (f x , g x ))
by(simp add : monotone-def )
lemma cont-Pair : — Move to Complete-Partial-Order2[[ cont lub ord luba orda f ; cont lub ord lubb ordb g ]]=⇒ cont lub ord (prod-lub luba lubb) (rel-prod orda ordb) (λx . (f x , g x ))
by(rule contI )(auto simp add : prod-lub-def image-image dest !: contD)
117
lemma mcont-Pair : — Move to Complete-Partial-Order2[[ mcont lub ord luba orda f ; mcont lub ord lubb ordb g ]]=⇒ mcont lub ord (prod-lub luba lubb) (rel-prod orda ordb) (λx . (f x , g x ))
by(rule mcontI )(simp-all add : monotone-Pair mcont-mono cont-Pair)
lemma admissible-rel-spmf-mcont [cont-intro]:[[ mcont lub ord lub-spmf (ord-spmf op =) f ; mcont lub ord lub-spmf (ord-spmf
op =) g ]]=⇒ ccpo.admissible lub ord (λx . rel-spmf R (f x ) (g x ))
by(rule admissible-subst [OF admissible-rel-spmf , where f =λx . (f x , g x ), simpli-fied ])(rule mcont-Pair)
context begin interpretation lifting-syntax .lemma fixp-spmf-parametric ′:
assumes f :∧
x . monotone (ord-spmf op =) (ord-spmf op =) Fand g :
∧x . monotone (ord-spmf op =) (ord-spmf op =) G
and param: (rel-spmf A ===> rel-spmf A) F Gshows (rel-spmf A) (ccpo.fixp lub-spmf (ord-spmf op =) F ) (ccpo.fixp lub-spmf
(ord-spmf op =) G)by(rule parallel-fixp-induct [OF ccpo-spmf ccpo-spmf - f g ])(auto intro: param[THENrel-funD ])
lemma fixp-spmf-parametric:assumes f :
∧x . mono-spmf (λf . F f x )
and g :∧
x . mono-spmf (λf . G f x )and param: ((A ===> rel-spmf B) ===> A ===> rel-spmf B) F Gshows (A ===> rel-spmf B) (spmf .fixp-fun F ) (spmf .fixp-fun G)
using f gproof(rule parallel-fixp-induct-1-1 [OF partial-function-definitions-spmf partial-function-definitions-spmf- - reflexive reflexive, where P=(A ===> rel-spmf B)])
show ccpo.admissible (prod-lub (fun-lub lub-spmf ) (fun-lub lub-spmf )) (rel-prod(fun-ord (ord-spmf op =)) (fun-ord (ord-spmf op =))) (λx . (A ===> rel-spmf B)(fst x ) (snd x ))
unfolding rel-fun-defapply(rule admissible-all admissible-imp admissible-rel-spmf-mcont)+apply(rule spmf .mcont2mcont [OF mcont-call ])apply(rule mcont-fst)
apply(rule spmf .mcont2mcont [OF mcont-call ])apply(rule mcont-snd)
doneshow (A ===> rel-spmf B) (λ-. lub-spmf ) (λ-. lub-spmf ) by autoshow (A ===> rel-spmf B) (F f ) (G g) if (A ===> rel-spmf B) f g for f g
using that by(rule rel-funD [OF param])qed
end
lemma if-distrib-bind-spmf1 [if-distribs]:bind-spmf (if b then x else y) f = (if b then bind-spmf x f else bind-spmf y f )
118
by simp
lemma if-distrib-bind-spmf2 [if-distribs]:bind-spmf x (λy . if b then f y else g y) = (if b then bind-spmf x f else bind-spmf
x g)by simp
lemma rel-spmf-if-distrib [if-distribs]:rel-spmf R (if b then x else y) (if b then x ′ else y ′) ←→(b −→ rel-spmf R x x ′) ∧ (¬ b −→ rel-spmf R y y ′)
by(simp)
lemma if-distrib-map-spmf [if-distribs]:map-spmf f (if b then p else q) = (if b then map-spmf f p else map-spmf f q)
by simp
lemma if-distrib-restrict-spmf1 [if-distribs]:restrict-spmf (if b then p else q) A = (if b then restrict-spmf p A else restrict-spmf
q A)by simp
lemma assumes rel-spmf (λx y . bad1 x = bad2 y ∧ (¬ bad2 y −→ A x ←→ By)) p q (is rel-spmf ?A - -)
shows fundamental-lemma-bad : measure (measure-spmf p) x . bad1 x = mea-sure (measure-spmf q) y . bad2 y (is ?bad)and fundamental-lemma: |measure (measure-spmf p) x . A x − measure (measure-spmf
q) y . B y| ≤measure (measure-spmf p) x . bad1 x (is ?fundamental)
proof −have good : rel-fun ?A op = (λx . A x ∧ ¬ bad1 x ) (λy . B y ∧ ¬ bad2 y) by(auto
simp add : rel-fun-def )from assms have 1 : measure (measure-spmf p) x . A x ∧ ¬ bad1 x = measure
(measure-spmf q) y . B y ∧ ¬ bad2 yby(rule measure-spmf-parametric[THEN rel-funD , THEN rel-funD ])(rule Collect-parametric[THEN
rel-funD , OF good ])
have bad : rel-fun ?A op = bad1 bad2 by(simp add : rel-fun-def )show 2 : ?bad using assmsby(rule measure-spmf-parametric[THEN rel-funD , THEN rel-funD ])(rule Collect-parametric[THEN
rel-funD , OF bad ])
let ?µp = measure (measure-spmf p) and ?µq = measure (measure-spmf q)have x . A x ∧ bad1 x ∪ x . A x ∧ ¬ bad1 x = x . A x
and y . B y ∧ bad2 y ∪ y . B y ∧ ¬ bad2 y = y . B y by autothen have |?µp x . A x − ?µq x . B x| = |?µp (x . A x ∧ bad1 x ∪ x . A
x ∧ ¬ bad1 x) − ?µq (y . B y ∧ bad2 y ∪ y . B y ∧ ¬ bad2 y)|by simp
also have . . . = |?µp x . A x ∧ bad1 x + ?µp x . A x ∧ ¬ bad1 x − ?µqy . B y ∧ bad2 y − ?µq y . B y ∧ ¬ bad2 y|
119
by(subst (1 2 ) measure-Union)(auto)also have . . . = |?µp x . A x ∧ bad1 x − ?µq y . B y ∧ bad2 y| using 1 by
simpalso have . . . ≤ max (?µp x . A x ∧ bad1 x) (?µq y . B y ∧ bad2 y)
by(rule abs-leI )(auto simp add : max-def measure-nonneg not-le, simp-all only :add-increasing measure-nonneg mult-2 )
also have . . . ≤ max (?µp x . bad1 x) (?µq y . bad2 y)by(rule max .mono; rule measure-spmf .finite-measure-mono; auto)
also note 2 [symmetric]finally show ?fundamental by simp
qed
end
5 The IO monad
theory IO-Monad imports∼∼/src/HOL/Library/Monad-SyntaxMisc
begin
5.1 The real world
We model the real world as an uninterpreted type real-world and buildthe IO monad like in Haskell. The additional result None denotes a non-terminating computation.
typedecl real-world
typedef ′a IO = UNIV :: (real-world ⇒ ( ′a × real-world) option) set ..
setup-lifting type-definition-IO
context begin interpretation lifting-syntax .
lemma return-IO-raw-parametric: (A ===> op = ===> rel-option (rel-prod Aop =)) (λx state. Some (x , state)) (λx state. Some (x , state))by transfer-prover
lift-definition return-IO :: ′a ⇒ ′a IO is λx state. Some (x , state) parametricreturn-IO-raw-parametric .
lemma bind-IO-parametric-raw :((A ===> rel-option (rel-prod B op =)) ===> (B ===> op = ===>
rel-option (rel-prod D op =)) ===> A ===> rel-option (rel-prod D op =))(λf (g :: ′a ⇒ real-world ⇒ ( ′b × real-world) option) state. f state >>= case-prod
g)(λf (g :: ′c ⇒ real-world ⇒ ( ′d × real-world) option) state. f state >>= case-prod
g)
120
by transfer-prover
lift-definition bind-IO :: ( ′a IO) ⇒ ( ′a ⇒ ′b IO) ⇒ ′b IOis λf (g :: ′a ⇒ real-world ⇒ ( ′b × real-world) option) state. f state >>= case-prodgparametric bind-IO-parametric-raw .
adhoc-overloading bind bind-IO
lemma return-IO-bind [simp]:return-IO x >>= g = g x
by transfer simp
lemma bind-IO-return [simp]:f >>= return-IO = f
by transfer simp
lemma bind-IO-bind [simp]:fixes f :: ′a IO showsf >>= (λx . g x >>= h) = (f >>= g) >>= h
by transfer(simp add : split-def )
lemmas IO-monad = return-IO-bind bind-IO-return bind-IO-bind
lift-definition run-IO :: ′a IO ⇒ real-world ⇒ ′a optionis λf state. map-option fst (f state) .
lemma run-IO-return-IO [simp]: run-IO (return-IO x ) state = Some xby(transfer) simp
lemma run-IO-bind-IO : run-IO (x >>= f ) state = (Rep-IO x state >>= (λ(x ,state ′). run-IO (f x ) state ′))by transfer(simp add : split-def map-option-bind o-def )
lift-definition fail-IO :: ′a IOis λstate. None .
lemma run-IO-fail-IO [simp]: run-IO fail-IO state = Noneby transfer simp
definition fail-IO ′ :: unit ⇒ ′a IOwhere [simp, code del ]: fail-IO ′ - = fail-IO
lemma fail-IO-code [code, code-unfold ]: fail-IO = fail-IO ′ ()by simp
declare [[code abort : fail-IO ′]]
121
5.2 Setup for lifting and transfer
lemma IO-rel-parametric-raw :((A ===> B ===> op =) ===> (op = ===> rel-option (rel-prod A op =))
===> (op = ===> rel-option (rel-prod B op =)) ===> op =)(λA. op = ===> rel-option (rel-prod A op =)) (λB . op = ===> rel-option
(rel-prod B op =))by(clarsimp simp add : rel-fun-def rel-prod-conv split-beta rel-option-unfold)(safe,blast+)
lift-definition IO-rel :: ( ′a ⇒ ′b ⇒ bool) ⇒ ′a IO ⇒ ′b IO ⇒ boolis λA. rel-fun op = (rel-option (rel-prod A op =)) parametric IO-rel-parametric-raw.
declare [[code drop: IO-rel ]]
lemma IO-pred-parametric-raw :((A ===> op =) ===> (op = ===> rel-option (rel-prod A op =)) ===> op
=)(λP . fun-eq-pred (pred-option (pred-prod P (λ-. True))))(λP . fun-eq-pred (pred-option (pred-prod P (λ-. True))))
by transfer-prover
lift-definition IO-pred :: ( ′a ⇒ bool) ⇒ ′a IO ⇒ boolis λP . fun-eq-pred (pred-option (pred-prod P (λ-. True)))parametric IO-pred-parametric-raw .
declare [[code drop: IO-pred ]]
lemma IO-rel-eq [relator-eq ]: IO-rel op = = op =unfolding fun-eq-iff by transfer(simp add : relator-eq)
lemma IO-rel-mono [relator-mono]: A ≤ B =⇒ IO-rel A ≤ IO-rel Bunfolding le-fun-def by transfer(auto simp add : rel-fun-def rel-prod-conv split-betarel-option-unfold)
lemma IO-rel-OO [relator-distr ]: IO-rel A OO IO-rel B = IO-rel (A OO B)unfolding fun-eq-iff by transfer(simp add : fun-rel-eq-OO prod .rel-compp[symmetric]eq-OO option.rel-compp[symmetric])
lemma Domainp-IO [relator-domain]:Domainp A = P =⇒ Domainp (IO-rel A) = IO-pred P
by transfer(simp add : Domainp-fun-rel-eq prod .Domainp-rel Domainp-eq option.Domainp-rel)
lemma reflp-fun1 : [[ is-equality A; reflp B ]] =⇒ reflp (A ===> B)by(simp add : reflp-def rel-fun-def is-equality-def )
lemma left-total-IO-rel [transfer-rule]:
122
left-total A =⇒ left-total (IO-rel A)by(transfer)(intro left-total-eq left-total-fun left-unique-eq prod .left-total-rel option.left-total-rel)+
lemma left-unique-IO-rel [transfer-rule]:left-unique A =⇒ left-unique (IO-rel A)
by transfer(intro left-unique-fun left-total-eq prod .left-unique-rel left-unique-eq op-tion.left-unique-rel)
lemma right-total-IO-rel [transfer-rule]:right-total A =⇒ right-total (IO-rel A)
by transfer(intro right-total-fun right-unique-eq prod .right-total-rel right-total-eqoption.right-total-rel)
lemma right-unique-IO-rel [transfer-rule]:right-unique A =⇒ right-unique (IO-rel A)
by transfer (intro right-unique-fun right-total-eq prod .right-unique-rel right-unique-eqoption.right-unique-rel)
lemma bi-total-IO-rel [transfer-rule]:bi-total A =⇒ bi-total (IO-rel A)
unfolding bi-total-alt-def by(simp add : left-total-IO-rel right-total-IO-rel)
lemma bi-unique-IO-rel [transfer-rule]:bi-unique A =⇒ bi-unique (IO-rel A)
unfolding bi-unique-alt-def by(simp add : left-unique-IO-rel right-unique-IO-rel)
lemma IO-invariant-commute [relator-eq-onp]:IO-rel (eq-onp P) = eq-onp (IO-pred P)
by transfer(simp add : fun-eq-invariant [symmetric] prod .rel-eq-onp[symmetric] op-tion.rel-eq-onp[symmetric] invariant-True)
lemma IO-map-parametric-raw :((A ===> B) ===> (op = ===> rel-option (rel-prod A op =)) ===> (op
= ===> rel-option (rel-prod B op =)))(λf . op (map-option (apfst f )))(λf . op (map-option (apfst f )))
by transfer-prover
lift-definition IO-map :: ( ′a ⇒ ′b) ⇒ ′a IO ⇒ ′b IOis λf . op (map-option (apfst f )) parametric IO-map-parametric-raw .
lemma IO-map-code [code]:IO-map f x = x >>= return-IO f
apply transferapply(clarsimp simp add : fun-eq-iff apfst-def split-beta map-prod-def )apply(case-tac x xa)apply(simp-all add : split-beta)done
123
lemma Quotient-prod [quot-map]:assumes Quotient R Abs Rep Tshows Quotient (IO-rel R) (IO-map Abs) (IO-map Rep) (IO-rel T )
using fun-quotient [OF identity-quotient [where ? ′a=real-world ] option.Quotient [OFprod .Quotient [OF assms identity-quotient [where ? ′a=real-world ]]]]unfolding Quotient-alt-defby transfer(simp add : apfst-def map-fun-def )
lemma return-IO-parametric [transfer-rule]:(A ===> IO-rel A) return-IO return-IO
prooffix x yassume [transfer-rule]: A x yshow IO-rel A (return-IO x ) (return-IO y)
by transfer transfer-proverqed
lemma bind-IO-parametric [transfer-rule]:(IO-rel A ===> (A ===> IO-rel B) ===> IO-rel B) bind-IO bind-IO
proof(rule rel-funI )+fix x y f ghave [transfer-rule]:
(op = ===> (pcr-IO op = ===> pcr-IO op = ===> op =) ===> (op ====> pcr-IO op =) ===> (op = ===> pcr-IO op =) ===> op =) op ===>op ===>
by(auto simp add : rel-fun-def IO .pcr-cr-eq cr-IO-def )
assume IO-rel A x y (A ===> IO-rel B) f gthus IO-rel B (x >>= f ) (y >>= g)
by(transfer fixing : A B)(rule bind-IO-parametric-raw [THEN rel-funD , THENrel-funD ])qed
lemma IO-map-parametric [transfer-rule]:((A ===> B) ===> IO-rel A ===> IO-rel B) IO-map IO-map
by(rule rel-funI )+(transfer , rule IO-map-parametric-raw [THEN rel-funD , THENrel-funD ])
lemma IO-pred-parametric [transfer-rule]:((A ===> op =) ===> IO-rel A ===> op =) IO-pred IO-pred
by(rule rel-funI )+(transfer , rule IO-pred-parametric-raw [THEN rel-funD , THENrel-funD ])
lemma IO-rel-parametric [transfer-rule]:((A ===> B ===> op =) ===> IO-rel A ===> IO-rel B ===> op =)
IO-rel IO-relby(rule rel-funI )+(transfer , rule IO-rel-parametric-raw [THEN rel-funD , THENrel-funD , THEN rel-funD ])
124
lifting-update IO .liftinglifting-forget IO .lifting
end
5.3 Code generator setup
lemma [code, code del ]: return-IO = return-IO ..
lemma [code, code del ]: bind-IO = bind-IO ..
declare [[code abort : bind-IO return-IO ]]
code-printing code-module Reactive-Concurrency (Scala)〈〈object Reactive-Concurrency
def bind [A, B ](x : A, g : A => B) : B = g(x ) 〉〉code-reserved Scala Reactive-Concurrency
code-printing type-constructor IO (SML) - and(OCaml) - and(Haskell) Prelude.IO - and(Scala) -| constant return-IO
(SML) - and(OCaml) - and(Haskell) return and(Scala) -| constant bind-IO
(SML) !(fn f ′- => f ′- -) and(OCaml) !(fun f ′- −> f ′- -) and(Scala) Reactive ′-Concurrency .bind
code-monad bind-IO Haskell
lemmas [transfer-rule] =identity-quotientfun-quotientQuotient-integer [folded integer .pcr-cr-eq ]Quotient-IO [folded IO .pcr-cr-eq ]
lemma undefined-transfer :assumes Quotient R Abs Rep Tshows T (Rep undefined) undefined
using assms unfolding Quotient-alt-def by blast
bundle undefined-transfer = undefined-transfer [transfer-rule]
end
125
5.4 Semantics of the IO monad
theory IO-Execution importsIO-MonadAFP/Coinductive/TLList
begin
hide-const (open) cont
lemma lnth-ltl-ldropn-conv-ldropn:enat n < llength xs =⇒ LCons (lnth xs n) (ltl (ldropn n xs)) = ldropn n xs
by(simp add : ltl-ldropn ldrop-eSuc-ltl [symmetric] ldropn-Suc-conv-ldropn)
lemma lprefix-lappend2-iff :llength xs = llength us=⇒ lprefix (lappend xs ys) (lappend us vs) ←→ xs = us ∧ (lfinite us −→ lprefix
ys vs)by(metis lappend-eq-lappend-conv lappend-lprefixE lprefix-lappend-same)
lemma tlength-eq-0-iff :tlength xs = 0 ←→ is-TNil xs
by(cases xs) simp-all
lemma tdropn-Suc ′: tdropn (Suc n) xs = tdropn n (ttl xs)by(simp add : tdropn-Suc split : tllist .split)
contextincludes tllist .lifting
begin
interpretation lifting-syntax .
lemma tllist-set-rel-transfer [transfer-rule]:(rel-set (pcr-tllist op = op =) ===> rel-set (pcr-tllist op = op =) ===> op =)(rel-set (λ(xs, a) (ys, b). xs = ys ∧ (lfinite ys −→ a = b))) op =
unfolding tllist .pcr-cr-eqby(rule Quotient-set-rel-eq)(rule Quotient-tllist)
lemma epred-tlength: epred (tlength xs) = tlength (ttl xs)by(transfer)(simp add : epred-llength)
lift-definition tcast :: ( ′a, ′b) tllist ⇒ ( ′a, ′c) tllistis λ(xs, a). (xs, undefined) by clarsimp
lemma tcast-TNil : tcast (TNil x ) = TNil undefinedby transfer simp
lemma tcast-TCons [simp]: tcast (TCons x xs) = TCons x (tcast xs)by transfer clarsimp
126
lemma terminal-tcast : terminal (tcast xs) = undefinedby transfer clarsimp
lemma is-TNil-tcast [simp]: is-TNil (tcast xs) ←→ is-TNil xsby transfer clarsimp
lemma thd-tcast [simp]: thd (tcast xs) = thd xsby transfer clarsimp
lemma ttl-tcast [simp]: ttl (tcast xs) = tcast (ttl xs)by transfer clarsimp
lemma tset-tcast [simp]: tset (tcast xs) = tset xsby transfer clarsimp
lemma tcast-lappendt [simp]: tcast (lappendt xs ys) = lappendt xs (tcast ys)by transfer auto
lemma tcast-tappend [simp]: tcast (tappend xs f ) = tappend xs (tcast f )by transfer(auto simp add : split-beta)
lemma llist-of-tllist-tcast [simp]: llist-of-tllist (tcast xs) = llist-of-tllist xsby transfer clarsimp
lemma tllist-all2-tcast-iff :tllist-all2 A B (tcast xs) (tcast ys) ←→llist-all2 A (llist-of-tllist xs) (llist-of-tllist ys) ∧ (tfinite xs −→ tfinite ys −→ B
undefined undefined)by transfer(auto dest : llist-all2-lfiniteD)
lemma tllist-all2-tcastI :[[ llist-all2 A (llist-of-tllist xs) (llist-of-tllist ys);
[[ tfinite xs; tfinite ys ]] =⇒ B undefined undefined ]]=⇒ tllist-all2 A B (tcast xs) (tcast ys)
by(simp add : tllist-all2-tcast-iff )
lift-definition timage :: ( ′a ⇒ ( ′b, ′c) tllist set) ⇒ ( ′b, ′a) tllist ⇒ ( ′b, ′c) tllistsetis λf (xs, a). if lfinite xs then apfst (lappend xs) ‘ f a else (xs, undefined)
by(fastforce intro!: rel-setI dest : rel-setD1 rel-setD2 intro: rev-bexI )
lemma timage-TCons [simp]:timage f (TCons x xs) = TCons x ‘ timage f xs
by transfer(fastforce intro: rel-setI rev-bexI )
lemma timage-TNil [simp]: timage f (TNil x ) = f xby transfer(fastforce intro: rel-setI rev-bexI )
127
lemma timage-is-TNil : is-TNil xs =⇒ timage f xs = f (terminal xs)by(cases xs) simp-all
lemma timage-tinfite [simp]:¬ tfinite xs =⇒ timage f xs = tcast xs
by transfer(auto intro: rel-setI )
lemma timage-tfinite:tfinite xs =⇒ timage f xs = lappendt (llist-of-tllist xs) ‘ f (terminal xs)
by transfer(auto intro: rel-setI elim!: rev-bexI )
lemma timage-cases:assumes ys ∈ timage f xsobtains (tfinite) zs where tfinite xs ys = lappendt (llist-of-tllist xs) zs zs ∈ f
(terminal xs)| (tinfinite) ¬ tfinite xs ys = tcast xs
using assms by(cases tfinite xs)(auto simp add : timage-tfinite)
lemma timage-tfiniteE :assumes ys ∈ timage f xsand tfinite xsobtains zs where ys = lappendt (llist-of-tllist xs) zs zs ∈ f (terminal xs)
using assms by(auto simp add : timage-tfinite)
lemma timage-tfiniteI :[[ tfinite xs; zs ∈ f (terminal xs) ]] =⇒ lappendt (llist-of-tllist xs) zs ∈ timage f xs
by(simp add : timage-tfinite)
lemma timage-tinfiniteI :¬ tfinite xs =⇒ tcast xs ∈ timage f xs
by simp
lemma timage-lappendt [simp]:lfinite xs =⇒ timage f (lappendt xs ys) = lappendt xs ‘ timage f ys
by transfer(fastforce intro: rel-setI elim!: rev-bexI simp add : lappend-assoc)
lemma tllist-all2-lappendtI :[[ llist-all2 A xs xs ′; [[ lfinite xs; lfinite xs ′ ]] =⇒ tllist-all2 A B ys ys ′ ]]=⇒ tllist-all2 A B (lappendt xs ys) (lappendt xs ′ ys ′)
by transfer(auto 4 3 dest : llist-all2-lfiniteD intro: llist-all2-lappendI )
lemma timage-parametric [transfer-rule]:((A ===> rel-set (tllist-all2 B C )) ===> tllist-all2 B A ===> rel-set (tllist-all2
B C )) timage timageby(rule rel-funI )+(blast intro!: rel-setI dest : tllist-all2-tfiniteD tllist-all2-tfinite1-terminalDtllist-all2-tfinite2-terminalD rel-funD rel-setD1 rel-setD2 intro: rev-bexI timage-tfiniteItllist-all2-lappendtI llist-all2-tllist-of-llistI tllist-all2-tcastI tllist-all2D-llist-all2-llist-of-tllisttimage-tinfiniteI elim!: timage-cases)
128
lifting-update tllist .liftinglifting-forget tllist .lifting
end
datatype ( ′a, ′b) event = Event (event-out : ′a) (event-in: ′b)
datatype-compat event
type-synonym ( ′a, ′out , ′in) trace = (( ′out , ′in) event , ′a option) tllist
locale IO-execution-base =fixes wf-response :: ′out ⇒ ′in setand interp :: ′out ⇒ ′in IO
definition unit-wf-response :: unit ⇒ unit setwhere unit-wf-response - = ()
definition unit-interp :: unit ⇒ unit IOwhere unit-interp = return-IO
end
6 The resumption monad
theory Resumptionimports
IO-ExecutionPF-SetMisc
begin
context fixes dflt :: ′b begin
definition terminal-default :: ( ′a, ′b) tllist ⇒ ′bwhere terminal-default xs = (if tfinite xs then terminal xs else dflt)
lemma terminal-default-TNil [simp, code]: terminal-default (TNil b) = bby(simp add : terminal-default-def )
lemma terminal-default-TCons [simp, code]: terminal-default (TCons x xs) =terminal-default xsby(simp add : terminal-default-def )
lemma terminal-default-ttl [simp]: terminal-default (ttl xs) = terminal-default xsby(auto simp add : terminal-default-def ltl-llist-of-tllist [symmetric] simp del : ltl-llist-of-tllist)
129
end
codatatype (results: ′a, outputs: ′out , ′in) resumption= Done (result : ′a option)| Pause (output : ′out) (resume: ′in ⇒ ( ′a, ′out , ′in) resumption)
whereresume (Done a) = (λinp. Done None)
code-datatype Done Pause
primcorec bind-resumption ::( ′a, ′out , ′in) resumption⇒ ( ′a ⇒ ( ′b, ′out , ′in) resumption) ⇒ ( ′b, ′out , ′in) resumption
where[[ is-Done x ; result x 6= None −→ is-Done (f (the (result x ))) ]] =⇒ is-Done
(bind-resumption x f )| result (bind-resumption x f ) = result x >>= result f| output (bind-resumption x f ) = (if is-Done x then output (f (the (result x ))) elseoutput x )| resume (bind-resumption x f ) = (λinp. if is-Done x then resume (f (the (resultx ))) inp else bind-resumption (resume x inp) f )
declare bind-resumption.sel [simp del ]
adhoc-overloading bind bind-resumption
lemma is-Done-bind-resumption [simp]:is-Done (x >>= f ) ←→ is-Done x ∧ (result x 6= None −→ is-Done (f (the (result
x ))))by(simp add : bind-resumption-def )
lemma result-bind-resumption [simp]:is-Done (x >>= f ) =⇒ result (x >>= f ) = result x >>= result f
by(simp add : bind-resumption-def )
lemma output-bind-resumption [simp]:¬ is-Done (x >>= f ) =⇒ output (x >>= f ) = (if is-Done x then output (f (the
(result x ))) else output x )by(simp add : bind-resumption-def )
lemma resume-bind-resumption [simp]:¬ is-Done (x >>= f ) =⇒resume (x >>= f ) =(if is-Done x then resume (f (the (result x )))else (λinp. resume x inp >>= f ))
by(auto simp add : bind-resumption-def )
definition DONE :: ′a ⇒ ( ′a, ′out , ′in) resumptionwhere DONE = Done Some
130
definition ABORT :: ( ′a, ′out , ′in) resumptionwhere ABORT = Done None
lemma [simp]:shows is-Done-DONE : is-Done (DONE a)and is-Done-ABORT : is-Done ABORTand result-DONE : result (DONE a) = Some aand result-ABORT : result ABORT = Noneand DONE-inject : DONE a = DONE b ←→ a = band DONE-neq-ABORT : DONE a 6= ABORTand ABORT-neq-DONE : ABORT 6= DONE aand ABORT-eq-Done:
∧a. ABORT = Done a ←→ a = None
and Done-eq-ABORT :∧
a. Done a = ABORT ←→ a = Noneand DONE-eq-Done:
∧b. DONE a = Done b ←→ b = Some a
and Done-eq-DONE :∧
b. Done b = DONE a ←→ b = Some aand DONE-neq-Pause: DONE a 6= Pause out cand Pause-neq-DONE : Pause out c 6= DONE aand ABORT-neq-Pause: ABORT 6= Pause out cand Pause-neq-ABORT : Pause out c 6= ABORT
by(auto simp add : DONE-def ABORT-def )
lemma resume-ABORT [simp]:resume (Done r) = (λinp. ABORT )
by(simp add : ABORT-def )
declare resumption.sel(3 )[simp del ]
lemma results-DONE [simp]: results (DONE x ) = xby(simp add : DONE-def )
lemma Done-bind [code]:Done a >>= f = (case a of None ⇒ Done None | Some a ⇒ f a)
by(rule resumption.expand)(auto split : option.split)
lemma DONE-bind [simp]:DONE a >>= f = f a
by(simp add : DONE-def Done-bind)
lemma bind-resumption-Pause [simp, code]: fixes cont showsPause out cont >>= f= Pause out (λinp. cont inp >>= f )
by(rule resumption.expand)(simp-all)
lemma bind-DONE [simp]:x >>= DONE = x
by(coinduction arbitrary : x )(auto simp add : split-beta o-def )
lemma bind-bind-resumption:
131
fixes r :: ( ′a, ′in, ′out) resumptionshows (r >>= f ) >>= g = do x ← r ; f x >>= g
apply(coinduction arbitrary : r rule: resumption.coinduct-strong)apply(auto simp add : split-beta bind-eq-Some-conv)apply(case-tac [!] result r)apply simp-alldone
lemmas resumption-monad = DONE-bind bind-DONE bind-bind-resumption
lemma ABORT-bind [simp]: ABORT >>= f = ABORTby(simp add : ABORT-def Done-bind)
lemma bind-resumption-is-Done: is-Done f =⇒ f >>= g = (if result f = Nonethen ABORT else g (the (result f )))by(rule resumption.expand) auto
lemma bind-resumption-eq-Done-iff [simp]:f >>= g = Done x ←→ (∃ y . f = DONE y ∧ g y = Done x ) ∨ f = ABORT ∧ x
= Noneby(cases f )(auto simp add : Done-bind split : option.split)
lemma bind-resumption-cong :assumes x = yand
∧z . z ∈ results y =⇒ f z = g z
shows x >>= f = y >>= gusing assms(2 ) unfolding 〈x = y〉
proof(coinduction arbitrary : y rule: resumption.coinduct-strong)case Eq-resumption thus ?case
by(auto intro: resumption.set-sel simp add : is-Done-def rel-fun-def )(fastforce intro!: exI intro: resumption.set-sel(2 ) simp add : is-Done-def )
qed
primrec ensure :: bool ⇒ (unit , ′out , ′in) resumptionwhere
ensure True = DONE ()| ensure False = ABORT
lemma is-Done-map-resumption [simp]:is-Done (map-resumption f1 f2 r) ←→ is-Done r
by(cases r) simp-all
lemma result-map-resumption [simp]:is-Done r =⇒ result (map-resumption f1 f2 r) = map-option f1 (result r)
by(clarsimp simp add : is-Done-def )
lemma output-map-resumption [simp]:¬ is-Done r =⇒ output (map-resumption f1 f2 r) = f2 (output r)
by(cases r) simp-all
132
lemma resume-map-resumption [simp]:¬ is-Done r=⇒ resume (map-resumption f1 f2 r) = map-resumption f1 f2 resume r
by(cases r) simp-all
lemma rel-resumption-is-DoneD : rel-resumption A B r1 r2 =⇒ is-Done r1 ←→is-Done r2by(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ]) simp-all
lemma rel-resumption-resultD1 :[[ rel-resumption A B r1 r2 ; is-Done r1 ]] =⇒ rel-option A (result r1 ) (result r2 )
by(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ]) simp-all
lemma rel-resumption-resultD2 :[[ rel-resumption A B r1 r2 ; is-Done r2 ]] =⇒ rel-option A (result r1 ) (result r2 )
by(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ]) simp-all
lemma rel-resumption-outputD1 :[[ rel-resumption A B r1 r2 ; ¬ is-Done r1 ]] =⇒ B (output r1 ) (output r2 )
by(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ]) simp-all
lemma rel-resumption-outputD2 :[[ rel-resumption A B r1 r2 ; ¬ is-Done r2 ]] =⇒ B (output r1 ) (output r2 )
by(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ]) simp-all
lemma rel-resumption-resumeD1 :[[ rel-resumption A B r1 r2 ; ¬ is-Done r1 ]]=⇒ rel-resumption A B (resume r1 inp) (resume r2 inp)
by(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ])(auto dest :rel-funD)
lemma rel-resumption-resumeD2 :[[ rel-resumption A B r1 r2 ; ¬ is-Done r2 ]]=⇒ rel-resumption A B (resume r1 inp) (resume r2 inp)
by(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ])(auto dest :rel-funD)
lemma rel-resumption-coinduct[consumes 1 , case-names Done Pause,case-conclusion Done is-Done result ,case-conclusion Pause output resume,coinduct pred : rel-resumption]:
assumes X : X r1 r2and Done:
∧r1 r2 . X r1 r2 =⇒ (is-Done r1 ←→ is-Done r2 ) ∧ (is-Done r1
−→ is-Done r2 −→ rel-option A (result r1 ) (result r2 ))
133
and Pause:∧
r1 r2 . [[ X r1 r2 ; ¬ is-Done r1 ; ¬ is-Done r2 ]] =⇒ B (output r1 )(output r2 ) ∧ (∀ inp. X (resume r1 inp) (resume r2 inp))
shows rel-resumption A B r1 r2using Xapply(rule resumption.rel-coinduct)apply(unfold rel-fun-def )apply(rule conjI )apply(erule Done[THEN conjunct1 ])
apply(rule conjI )apply(erule Done[THEN conjunct2 ])
apply(rule impI )+apply(drule (2 ) Pause)apply blastdone
6.1 setup for partial-function
context begin interpretation lifting-syntax .
coinductive resumption-ord :: ( ′a, ′out , ′in) resumption ⇒ ( ′a, ′out , ′in) resump-tion ⇒ boolwhere
Done-Done: flat-ord None a a ′ =⇒ resumption-ord (Done a) (Done a ′)| Done-Pause: resumption-ord ABORT (Pause out c)| Pause-Pause: (op = ===> resumption-ord) c c ′ =⇒ resumption-ord (Pause outc) (Pause out c ′)
inductive-simps resumption-ord-simps [simp]:resumption-ord (Pause out c) rresumption-ord r (Done a)
lemma resumption-ord-is-DoneD :[[ resumption-ord r r ′; is-Done r ′ ]] =⇒ is-Done r
by(cases r ′)(auto simp add : fun-ord-def )
lemma resumption-ord-resultD :[[ resumption-ord r r ′; is-Done r ′ ]] =⇒ flat-ord None (result r) (result r ′)
by(cases r ′)(auto simp add : flat-ord-def )
lemma resumption-ord-outputD :[[ resumption-ord r r ′; ¬ is-Done r ]] =⇒ output r = output r ′
by(cases r) auto
lemma resumption-ord-resumeD :[[ resumption-ord r r ′; ¬ is-Done r ]] =⇒ (op = ===> resumption-ord) (resume
r) (resume r ′)by(cases r) auto
lemma resumption-ord-abort :
134
[[ resumption-ord r r ′; is-Done r ; ¬ is-Done r ′ ]] =⇒ result r = Noneby(auto elim: resumption-ord .cases)
lemma resumption-ord-coinduct [consumes 1 , case-names Done Abort Pause, case-conclusionPause output resume, coinduct pred : resumption-ord ]:
assumes X r r ′
and Done:∧
r r ′. [[ X r r ′; is-Done r ′ ]] =⇒ is-Done r ∧ flat-ord None (resultr) (result r ′)
and Abort :∧
r r ′. [[ X r r ′; ¬ is-Done r ′; is-Done r ]] =⇒ result r = Noneand Pause:
∧r r ′. [[ X r r ′; ¬ is-Done r ; ¬ is-Done r ′ ]]
=⇒ output r = output r ′ ∧ (op = ===> (λr r ′. X r r ′ ∨ resumption-ord r r ′))(resume r) (resume r ′)
shows resumption-ord r r ′
using 〈X r r ′〉
proof coinductcase (resumption-ord r r ′)thus ?case
by(cases r r ′ rule: resumption.exhaust [case-product resumption.exhaust ])(autodest : Done Pause Abort)qed
end
lemma resumption-ort-ABORT [intro!, simp]: resumption-ord ABORT rby(cases r)(simp-all add : flat-ord-def resumption-ord .Done-Pause)
lemma resumption-ord-refl : resumption-ord r rby(coinduction arbitrary : r)(auto simp add : flat-ord-def )
lemma resumption-ord-antisym:[[ resumption-ord r r ′; resumption-ord r ′ r ]]=⇒ r = r ′
proof(coinduction arbitrary : r r ′ rule: resumption.coinduct-strong)case (Eq-resumption r r ′)thus ?case
by cases(auto simp add : flat-ord-def rel-fun-def )qed
lemma resumption-ord-trans:[[ resumption-ord r r ′; resumption-ord r ′ r ′′ ]]=⇒ resumption-ord r r ′′
proof(coinduction arbitrary : r r ′ r ′′)case (Done r r ′ r ′′)thus ?case by(auto 4 4 elim: resumption-ord .cases simp add : flat-ord-def )
nextcase (Abort r r ′ r ′′)thus ?case by(auto 4 4 elim: resumption-ord .cases simp add : flat-ord-def )
nextcase (Pause r r ′ r ′′)
135
hence resumption-ord r r ′ resumption-ord r ′ r ′′ by simp-allthus ?case using 〈¬ is-Done r 〉 〈¬ is-Done r ′′〉
by(cases)(auto simp add : rel-fun-def )qed
primcorec resumption-lub :: ( ′a, ′out , ′in) resumption set ⇒ ( ′a, ′out , ′in) resumptionwhere∀ r ∈ R. is-Done r =⇒ is-Done (resumption-lub R)| result (resumption-lub R) = flat-lub None (result ‘ R)| output (resumption-lub R) = (THE out . out ∈ output ‘ (R ∩ r . ¬ is-Done r))| resume (resumption-lub R) = (λinp. resumption-lub ((λc. c inp) ‘ resume ‘ (R ∩r . ¬ is-Done r)))
lemma is-Done-resumption-lub [simp]:is-Done (resumption-lub R) ←→ (∀ r ∈ R. is-Done r)
by(simp add : resumption-lub-def )
lemma result-resumption-lub [simp]:∀ r ∈ R. is-Done r =⇒ result (resumption-lub R) = flat-lub None (result ‘ R)
by(simp add : resumption-lub-def )
lemma output-resumption-lub [simp]:∃ r∈R. ¬ is-Done r =⇒ output (resumption-lub R) = (THE out . out ∈ output ‘
(R ∩ r . ¬ is-Done r))by(simp add : resumption-lub-def )
lemma resume-resumption-lub [simp]:∃ r∈R. ¬ is-Done r=⇒ resume (resumption-lub R) inp =
resumption-lub ((λc. c inp) ‘ resume ‘ (R ∩ r . ¬ is-Done r))by(simp add : resumption-lub-def )
contextfixes R state inp R ′
defines R ′-def : R ′ ≡ (λc. c inp) ‘ resume ‘ (R ∩ r . ¬ is-Done r)assumes chain: Complete-Partial-Order .chain resumption-ord R
begin
lemma resumption-ord-chain-resume: Complete-Partial-Order .chain resumption-ordR ′
proof(rule chainI )fix r ′ r ′′
assume r ′ ∈ R ′
and r ′′ ∈ R ′
then obtain r ′ r ′′
where r ′: r ′ = resume r ′ inp r ′ ∈ R ¬ is-Done r ′
and r ′′: r ′′ = resume r ′′ inp r ′′ ∈ R ¬ is-Done r ′′
by(auto simp add : R ′-def )from chain 〈r ′ ∈ R〉 〈r ′′ ∈ R〉
136
have resumption-ord r ′ r ′′ ∨ resumption-ord r ′′ r ′
by(auto elim: chainE )with r ′ r ′′
have resumption-ord (resume r ′ inp) (resume r ′′ inp) ∨resumption-ord (resume r ′′ inp) (resume r ′ inp)
by(auto elim: resumption-ord .cases simp add : rel-fun-def )with r ′ r ′′
show resumption-ord r ′ r ′′ ∨ resumption-ord r ′′ r ′ by autoqed
end
lemma resumption-partial-function-definition:partial-function-definitions resumption-ord resumption-lub
prooffix rshow resumption-ord r r by(rule resumption-ord-refl)
nextfix r r ′ r ′′
assume resumption-ord r r ′ resumption-ord r ′ r ′′
thus resumption-ord r r ′′ by(rule resumption-ord-trans)next
fix r r ′
assume resumption-ord r r ′ resumption-ord r ′ rthus r = r ′ by(rule resumption-ord-antisym)
nextfix R and r :: ( ′a, ′b, ′c) resumptionassume Complete-Partial-Order .chain resumption-ord R r ∈ Rthus resumption-ord r (resumption-lub R)proof(coinduction arbitrary : r R)
case (Done r R)note chain = 〈Complete-Partial-Order .chain resumption-ord R〉
and r = 〈r ∈ R〉
from 〈is-Done (resumption-lub R)〉 have A: ∀ r ∈ R. is-Done r by simpwith r obtain a ′ where r = Done a ′ by(cases r) auto fix r ′
assume a ′ 6= Nonehence (THE x . x ∈ result ‘ R ∧ x 6= None) = a ′
using r A 〈r = Done a ′〉
by(auto 4 3 intro!: the-equality intro: rev-image-eqI elim: chainE [OF chain]simp add : flat-ord-def is-Done-def )
with A r 〈r = Done a ′〉 show ?case
by(cases a ′)(auto simp add : flat-ord-def flat-lub-def )next
case (Abort r R)hence chain: Complete-Partial-Order .chain resumption-ord R and r ∈ R by
simp-allfrom 〈r ∈ R〉 〈¬ is-Done (resumption-lub R)〉 〈is-Done r 〉
137
show ?case by(auto elim: chainE [OF chain] dest : resumption-ord-abort resumption-ord-is-DoneD)next
case (Pause r R)hence chain: Complete-Partial-Order .chain resumption-ord R
and r : r ∈ R by simp-allhave ?resume
using r 〈¬ is-Done r 〉 resumption-ord-chain-resume[OF chain]by(auto simp add : rel-fun-def bexI )
moreoverfrom r 〈¬ is-Done r 〉 have output (resumption-lub R) = output r
by(auto 4 4 simp add : bexI intro!: the-equality elim: chainE [OF chain] dest :resumption-ord-outputD)
ultimately show ?case by simpqed
nextfix R and r :: ( ′a, ′b, ′c) resumptionassume Complete-Partial-Order .chain resumption-ord R
∧r ′. r ′∈ R =⇒ resumption-ord
r ′ rthus resumption-ord (resumption-lub R) rproof(coinduction arbitrary : R r)
case (Done R r)hence chain: Complete-Partial-Order .chain resumption-ord R
and ub: ∀ r ′∈R. resumption-ord r ′ r by simp-allfrom 〈is-Done r 〉 ub have is-Done: ∀ r ′ ∈ R. is-Done r ′
and ub ′:∧
r ′. r ′ ∈ result ‘ R =⇒ flat-ord None r ′ (result r)by(auto dest : resumption-ord-is-DoneD resumption-ord-resultD)from is-Done have chain ′: Complete-Partial-Order .chain (flat-ord None)
(result ‘ R)by(auto 5 2 intro!: chainI elim: chainE [OF chain] dest : resumption-ord-resultD)hence flat-ord None (flat-lub None (result ‘ R)) (result r)
by(rule partial-function-definitions.lub-least [OF flat-interpretation])(rule ub ′)thus ?case using is-Done by simp
nextcase (Abort R r)hence chain: Complete-Partial-Order .chain resumption-ord R
and ub: ∀ r ′∈R. resumption-ord r ′ r by simp-allfrom 〈¬ is-Done r 〉 〈is-Done (resumption-lub R)〉 ubshow ?case by(auto simp add : flat-lub-def dest : resumption-ord-abort)
nextcase (Pause R r)hence chain: Complete-Partial-Order .chain resumption-ord R
and ub:∧
r ′. r ′∈R =⇒ resumption-ord r ′ r by simp-allfrom 〈¬ is-Done (resumption-lub R)〉 have exR: ∃ r ∈ R. ¬ is-Done r by simpthen obtain r ′ where r ′: r ′ ∈ R ¬ is-Done r ′ by auto
with ub[of r ′] have output r = output r ′ by(auto dest : resumption-ord-outputD)also have [symmetric]: output (resumption-lub R) = output r ′ using exR r ′
by(auto 4 4 elim: chainE [OF chain] dest : resumption-ord-outputD)finally have ?output ..moreover
138
fix inp r ′′
assume r ′′ ∈ R ¬ is-Done r ′′
with ub[of r ′′]have resumption-ord (resume r ′′ inp) (resume r inp)
by(auto dest !: resumption-ord-resumeD simp add : rel-fun-def ) with exR resumption-ord-chain-resume[OF chain] r ′
have ?resume by(auto simp add : rel-fun-def )ultimately show ?case ..
qedqed
interpretation resumption:partial-function-definitions resumption-ord resumption-lub
by (rule resumption-partial-function-definition)
declaration 〈〈 Partial-Function.init resumption @term resumption.fixp-fun@term resumption.mono-body @thm resumption.fixp-rule-uc @thm resump-
tion.fixp-induct-uc NONE 〉〉
abbreviation mono-resumption ≡ monotone (fun-ord resumption-ord) resumption-ord
lemma mono-resumption-resume:assumes mono-resumption Bshows mono-resumption (λf . resume (B f ) inp)
prooffix f g :: ′a ⇒ ( ′b, ′c, ′d) resumptionassume fg : fun-ord resumption-ord f ghence resumption-ord (B f ) (B g) by(rule monotoneD [OF assms])with resumption-ord-resumeD [OF this]show resumption-ord (resume (B f ) inp) (resume (B g) inp)
by(cases is-Done (B f ))(auto simp add : rel-fun-def is-Done-def )qed
lemma bind-resumption-mono [partial-function-mono]:assumes mf : mono-resumption Band mg :
∧y . mono-resumption (C y)
shows mono-resumption (λf . do y ← B f ; C y f )proof(rule monotoneI )
fix f g :: ′a ⇒ ( ′b, ′c, ′d) resumptionassume ∗: fun-ord resumption-ord f gdef f ′ ≡ B f and g ′ ≡ B g
and h ≡ λx . C x f and k ≡ λx . C x gwith mf [THEN monotoneD , OF ∗] mg [THEN monotoneD , OF ∗]have resumption-ord f ′ g ′
∧x . resumption-ord (h x ) (k x ) by auto
thus resumption-ord (f ′ >>= h) (g ′ >>= k)proof(coinduction arbitrary : f ′ g ′ h k)
case (Done f ′ g ′ h k)hence le: resumption-ord f ′ g ′
and mg :∧
y . resumption-ord (h y) (k y) by simp-all
139
from 〈is-Done (g ′ >>= k)〉
have done-Bg : is-Done g ′
and result g ′ 6= None =⇒ is-Done (k (the (result g ′))) by simp-allmoreoverhave is-Done f ′ using le done-Bg by(rule resumption-ord-is-DoneD)moreoverfrom le done-Bg have flat-ord None (result f ′) (result g ′)
by(rule resumption-ord-resultD)hence result f ′ 6= None =⇒ result g ′ = result f ′
by(auto simp add : flat-ord-def )moreoverhave resumption-ord (h (the (result f ′))) (k (the (result f ′))) by(rule mg)ultimately show ?case
by(subst (1 2 ) result-bind-resumption)(auto dest : resumption-ord-is-DoneDresumption-ord-resultD simp add : flat-ord-def bind-eq-None-conv)
nextcase (Abort f ′ g ′ h k)hence resumption-ord (h (the (result f ′))) (k (the (result f ′))) by simpthus ?case using Abort
by(cases is-Done g ′)(auto 4 4 simp add : bind-eq-None-conv flat-ord-def dest :resumption-ord-abort resumption-ord-resultD resumption-ord-is-DoneD)
nextcase (Pause f ′ g ′ h k)hence ?outputby(auto 4 4 dest : resumption-ord-outputD resumption-ord-is-DoneD resumption-ord-resultD
resumption-ord-abort simp add : flat-ord-def )moreover have ?resumeproof(cases is-Done f ′)
case Falsewith Pause show ?thesisby(auto simp add : rel-fun-def dest : resumption-ord-is-DoneD intro: resumption-ord-resumeD [THEN
rel-funD ] intro!: exI )next
case Truehence is-Done g ′ using Pause by(auto dest : resumption-ord-abort)thus ?thesis using True Pause resumption-ord-resultD [OF 〈resumption-ord
f ′ g ′〉]by(auto intro!: rel-funI simp add : bind-resumption-is-Done flat-ord-def intro:
resumption-ord-resumeD [THEN rel-funD ] exI [where x=f ′] exI [where x=g ′])qedultimately show ?case ..
qedqed
6.2 Execution resumption
context IO-execution-base begin
partial-function (coset) resumption-traces :: ( ′a, ′out , ′in) resumption ⇒ (( ′a,
140
′out , ′in) trace) setwhere
resumption-traces r =(if is-Done r then TNil (result r)else do
input ← wf-response (output r);t ← resumption-traces (resume r input);TCons (Event (output r) input) t)
lemma resumption-traces-unfold :resumption-traces r =(case r of Done x ⇒ TNil x| Pause out c ⇒ do
input ← wf-response out ;t ← resumption-traces (c input);TCons (Event out input) t)
by(subst resumption-traces.simps)(simp split : resumption.split option.split)
lemma resumption-traces-cases [consumes 1 , case-names Done Pause, cases set :resumption-traces]:
assumes t ∈ resumption-traces robtains (Done)
is-Done ris-TNil tterminal t = result r| (Pause)¬ is-Done r¬ is-TNil toutput r = event-out (thd t)event-in (thd t) ∈ wf-response (event-out (thd t))ttl t ∈ resumption-traces (resume r (event-in (thd t)))
using assms by(subst (asm) resumption-traces-unfold)(auto split : resumption.split-asmoption.split-asm)
lemma resumption-traces-coinduct[consumes 1 , case-names Done Pause,case-conclusion Done is-TNil terminal ,case-conclusion Pause is-TNil output wf-response ttl ,coinduct set : resumption-traces]:
assumes X r tand Done:∧
r t . [[ X r t ; is-Done r ]]=⇒ is-TNil t ∧ terminal t = result r
and Pause:∧r t .
[[ X r t ; ¬ is-Done r ]]=⇒ ¬ is-TNil t ∧
141
output r = event-out (thd t) ∧event-in (thd t) ∈ wf-response (event-out (thd t)) ∧(X (resume r (event-in (thd t))) (ttl t) ∨ttl t ∈ resumption-traces (resume r (event-in (thd t))))
shows t ∈ resumption-traces rusing 〈X r t 〉
apply(rule contrapos-pp)apply(erule resumption-traces.raw-induct [rotated ])apply(simp)apply(intro conjI strip)
apply(fastforce dest : Done intro: tllist .expand)apply(drule (1 ) Pause, auto 4 4 intro: tllist .expand)done
lemma resumption-traces-Done [simp]:resumption-traces (Done x ) = TNil x
by(simp add : resumption-traces-unfold)
lemma resumption-traces-Pause [simp]:resumption-traces (Pause out c) =(do input ← wf-response out ; TCons (Event out input) ‘ resumption-traces (c
input))by(subst resumption-traces-unfold)(simp add : bind-singleton-conv-image)
lemma resumption-traces-DONE [simp]:resumption-traces (DONE x ) = TNil (Some x )
by(simp add : DONE-def )
lemma resumption-traces-ABORT [simp]:resumption-traces ABORT = TNil None
by(simp add : ABORT-def )
lemma TNil-in-resumption-traces-iff [simp]:TNil x ∈ resumption-traces r ←→ is-Done r ∧ x = result r
by(subst resumption-traces-unfold)(simp split : resumption.split option.split)
lemma TCons-in-resumption-traces-iff [simp]:TCons e t ∈ resumption-traces r←→ ¬ is-Done r ∧ output r = event-out e∧ event-in e ∈ wf-response (event-out e)∧ t ∈ resumption-traces (resume r (event-in e))
by(subst resumption-traces-unfold)(auto split : resumption.split option.split intro:rev-bexI )
lemma resumption-traces-bind :resumption-traces (r >>= g) =resumption-traces r >>= timage (case-option TNil None (resumption-traces
g))(is - = - >>= timage ?g)
142
proof(rule set-eqI iffI )+fix tassume t ∈ resumption-traces r >>= timage ?gthen obtain t ′ where t ′ ∈ resumption-traces r t ∈ timage ?g t ′
unfolding bind-UNION by autothen show t ∈ resumption-traces (r >>= g)proof(coinduction arbitrary : t t ′ r)
case (Done t t ′ r)thus ?caseby(simp add : resumption-traces-unfold split : resumption.split-asm option.split-asm)
nextcase (Pause t t ′ r)thus ?case
apply(subst (asm) resumption-traces-unfold)apply(simp-all split : option.split-asm resumption.split-asm)
apply(auto 4 4 split : option.split-asm resumption.split-asm elim: resumption-traces-cases)done
qednext
fix tassume t : t ∈ resumption-traces (r >>= g)
construct corresponding trace in resumption-traces f
def t ′ ≡ λ(t :: ( ′a, ′out , ′in) trace) (r :: ( ′b, ′out , ′in) resumption). unfold-tllist(λ(t , r). is-Done r)(λ(t , r). result r)(λ(t , r). thd t)(λ(t , r). (ttl t , resume r (event-in (thd t))))(t , r)
hence [simp]:∧t r . is-TNil (t ′ t r) ←→ is-Done r∧t r . is-Done r =⇒ terminal (t ′ t r) = result r∧t r . ¬ is-Done r =⇒ thd (t ′ t r) = thd t∧t r . ¬ is-Done r =⇒ ttl (t ′ t r) = t ′ (ttl t) (resume r (event-in (thd t)))
by(simp-all)
have t ′ t r ∈ resumption-traces r using tproof(coinduction arbitrary : t r)
case (Done t r)thus ?case by simp
nextcase (Pause t r)thus ?caseby(subst (asm) resumption-traces.simps)(auto simp add : Option.is-none-def )
qedmoreoverhave t ∈ timage ?g (t ′ t r)proof(cases tfinite (t ′ t r))
case True
143
let ?n = the-enat (tlength (t ′ t r))
have eq : t = lappendt (ltake (enat ?n) (llist-of-tllist t)) (tdropn ?n t)by(simp add : lappendt-ltake-tdropn)
from True thave ltake (enat ?n) (llist-of-tllist t) = llist-of-tllist (t ′ t r)and tdropn ?n t ∈ case-option TNil None (resumption-traces g) (terminal
(t ′ t r))proof(induct ys≡llist-of-tllist (t ′ t r) arbitrary : t r rule: lfinite-induct)
case (LNil t r)hence [simp]: tlength (t ′ t r) = 0 by(simp add : tlength-eq-0-iff )
case 1show ?case using LNil
by(auto simp add : zero-enat-def [symmetric] llist-of-tllist-eq-LNil intro:sym)
nextcase 2thus ?case using LNilby(subst (asm) resumption-traces.simps)(auto simp add : Option.is-none-def
bind-eq-Some-conv split : split-if-asm option.split)
nextcase (LCons t r)assume t : t ∈ resumption-traces (r >>= g)let ?r = resume r (event-in (thd t))
from 〈¬ lnull (llist-of-tllist (t ′ t r))〉
have [simp]: ¬ is-Done r by simpfrom t have [simp]: ¬ is-TNil t by(auto simp add : resumption-traces.simps)from 〈tfinite (t ′ t r)〉
have [simp]: enat (the-enat (tlength (t ′ t r))) = tlength (t ′ t r)unfolding lfinite-eq-range-llist-ofby clarsimp(simp add : llength-llist-of-tllist [symmetric])
from 〈tfinite (t ′ t r)〉 have tfinite (ttl (t ′ t r))by(simp only : lfinite-ltl ltl-llist-of-tllist [symmetric])
hence [simp]: enat (the-enat (tlength (t ′ (ttl t) ?r))) = tlength (t ′ (ttl t) ?r)unfolding lfinite-eq-range-llist-ofby clarsimp(simp add : llength-llist-of-tllist [symmetric])
have t ′: ttl t ∈ resumption-traces (?r >>= g) using tby(subst (asm) resumption-traces.simps) clarsimp
case 1from - t ′
have ltake (enat (the-enat (tlength (t ′ (ttl t) ?r)))) (llist-of-tllist (ttl t)) =llist-of-tllist (t ′ (ttl t) ?r)by(rule LCons) simp
thus ?case
144
by −(rule llist .expand , simp-all add : tlength-eq-0-iff ltl-ltake epred-tlength)next
case 2have tlength (t ′ t r) = eSuc (tlength (t ′ (ttl t) ?r))
by(rule co.enat .expand)(simp-all add : tlength-eq-0-iff epred-tlength)also have the-enat . . . = Suc (the-enat (tlength (t ′ (ttl t) ?r)))
using 〈tfinite (ttl (t ′ t r))〉 unfolding lfinite-eq-range-llist-ofby clarsimp(simp add : llength-llist-of-tllist [symmetric] eSuc-enat)
finally show ?case using t ′ LCons(4 )[of ttl t ?r ]by(subst terminal-ttl [symmetric])(auto simp add : tdropn-Suc ′ split : op-
tion.split)
qedthus ?thesis using True
by(subst eq)(simp add : timage-tfiniteI split : option.split-asm)next
case Falsewith t have t = tcast (t ′ t r)proof(coinduction arbitrary : t r)
case Eq-tllistthus ?case
by(subst (asm) resumption-traces.simps)(auto split : split-if-asm simp add :bind-eq-Some-conv intro: lfinite-ltl [THEN iffD1 ])
qedthus ?thesis using False by(simp)
qedultimately show t ∈ resumption-traces r >>= timage ?g unfolding bind-UNION
..qed
contextfixes interp-raw :: ′out ⇒ real-world ⇒ ( ′in × real-world) optiondefines interp-raw-def : interp-raw ≡ map-fun id Rep-IO interp
begin
partial-function (option) interp-resumption-raw :: ( ′a, ′out , ′in) resumption ⇒real-world ⇒ ( ′a × real-world) optionwhere
interp-resumption-raw r state =(if is-Done r then case result r of None ⇒ None | Some x ⇒ Some (x , state)
else interp-raw (output r) state >>= (λ(input , state). interp-resumption-raw(resume r input) state))
context includes IO .lifting begininterpretation lifting-syntax .
lift-definition interp-resumption :: ( ′a, ′out , ′in) resumption ⇒ ′a IO is interp-resumption-raw.
145
lemma interp-resumption-Done [simp]:interp-resumption (Done x ) = (case x of None ⇒ fail-IO | Some x ′⇒ return-IO
x ′)including undefined-transferby transfer (simp add : interp-resumption-raw .simps fun-eq-iff split : option.split)
lemma interp-resumption-DONE [simp]:interp-resumption (DONE x ) = return-IO x
by(simp add : DONE-def )
lemma interp-resumption-ABORT :interp-resumption ABORT = fail-IO
by(simp add : ABORT-def )
lemma interp-resumption-Pause [simp]:interp-resumption (Pause out c) = interp out >>= interp-resumption c
proof −have [transfer-rule]: (op = ===> pcr-IO op =) interp-raw interp
unfolding interp-raw-def IO .pcr-cr-eq by(auto simp add : cr-IO-def )show ?thesisby transfer(simp add : interp-resumption-raw .simps fun-eq-iff o-def cong : prod .case-cong)
qed
end
end
end
lemmas [code] =IO-execution-base.resumption-traces-DoneIO-execution-base.resumption-traces-PauseIO-execution-base.interp-resumption-DoneIO-execution-base.interp-resumption-Pause
lemma resumption-traces-refinement :assumes
∧out . wf-response1 out ⊆ wf-response2 out
shows IO-execution-base.resumption-traces wf-response1 f ⊆ IO-execution-base.resumption-traceswf-response2 fproof
interpret rb1 : IO-execution-base wf-response1 .interpret rb2 : IO-execution-base wf-response2 .
fix tassume t ∈ rb1 .resumption-traces fthus t ∈ rb2 .resumption-traces fproof coinduct
case (Done f t)thus ?case by cases auto
146
nextcase (Pause f t)thus ?case using assms by cases auto
qedqed
6.3 Code generator setup
Implement resumption concurrency as IO monad in Haskell and as sideeffects in SML/OCaml/Scala.
— use type variable ′inp instead of the usual ′in because the code generator forgetsto rename type variables for code-abort constants and OCaml does not like the typevariable ′inpdefinition resumption-ABORT :: unit ⇒ ( ′a, ′out , ′inp) resumption
where [simp, code del ]: resumption-ABORT - = ABORTlemma ABORT-code [code, code-unfold ]: ABORT = resumption-ABORT () bysimpdeclare [[code abort : resumption-ABORT ]]
6.4 Setup for lifting and transfer
declare resumption.rel-eq [id-simps, relator-eq ]declare resumption.rel-mono [relator-mono]
lemma rel-resumption-OO [relator-distr ]:rel-resumption A B OO rel-resumption C D = rel-resumption (A OO C ) (B OO
D)(is ?lhs = ?rhs)
proof(intro ext iffI )fix r1 r2assume ?lhs r1 r2thus ?rhs r1 r2by(coinduct r1 r2 rule: rel-resumption-coinduct)(auto dest : rel-resumption-is-DoneD
rel-resumption-resultD1 rel-resumption-outputD1 rel-resumption-outputD2 rel-resumption-resumeD1rel-resumption-resumeD2 simp add : option.rel-compp)next
def r12 ≡corec-resumption (λ(r1 , r2 ). is-Done r1 )
(λ(r1 , r2 ). do a1 ← result r1 ; a2 ← result r2 ; Some (SOME ac. A a1 ac∧ C ac a2 ) )
(λ(r1 , r2 ). SOME bd . B (output r1 ) bd ∧ D bd (output r2 ))(λ(r1 , r2 ). λinp. Inr (resume r1 inp, resume r2 inp))
:: ( ′a, ′b, ′c) resumption × ( ′d , ′e, ′c) resumption ⇒ ( ′f , ′g , ′c) resumption
fix r1 r2assume ?rhs r1 r2hence rel-resumption A B r1 (r12 (r1 , r2 ))proof(coinduction arbitrary : r1 r2 rule: rel-resumption-coinduct)
case (Done r1 r2 )
147
have ?is-Done by(simp add : r12-def )moreover have ?result using Doneby(cases result r1 )(fastforce simp add : r12-def option.rel-compp option-rel-Some1
dest !: rel-resumption-resultD1 intro: someI2 )+ultimately show ?case ..
nextcase (Pause r1 r2 )hence ?output by(auto dest !: rel-resumption-outputD1 simp add : r12-def intro:
someI2 )moreover have ?resume (is All ?C )proof
fix inpfrom rel-resumption-resumeD1 [OF 〈rel-resumption (A OO C ) (B OO D) r1
r2 〉, of inp] 〈¬ is-Done r1 〉
show ?C inp by(auto simp add : r12-def rel-fun-def )qedultimately show ?case ..
qedmoreoverfrom 〈?rhs r1 r2 〉
have rel-resumption C D (r12 (r1 , r2 )) r2proof(coinduction arbitrary : r1 r2 rule: rel-resumption-coinduct)
case (Done r1 r2 )hence ?is-Done by(auto simp add : r12-def dest : rel-resumption-is-DoneD)moreover have ?result using Doneby(cases result r2 )(fastforce simp add : r12-def option.rel-compp option-rel-Some2
dest !: rel-resumption-resultD2 intro: someI2 )+ultimately show ?case ..
nextcase (Pause r1 r2 )hence ?output by(fastforce dest !: rel-resumption-outputD2 simp add : r12-def
intro: someI2 )moreover have ?resume (is All ?C )proof
fix inpfrom Pause have ¬ is-Done r1 by(simp add : r12-def )with rel-resumption-resumeD1 [OF 〈rel-resumption (A OO C ) (B OO D) r1
r2 〉, of inp]show ?C inp by(auto simp add : r12-def rel-fun-def )
qedultimately show ?case ..
qedultimately show ?lhs r1 r2 ..
qed
lemma left-total-rel-resumption [transfer-rule]:[[ left-total R1 ; left-total R2 ]] =⇒ left-total (rel-resumption R1 R2 )unfolding left-total-def
proof
148
fix r :: ( ′a, ′c, ′e) resumptionassume R1 : ∀ x . ∃ y . R1 x y and R2 : ∀ x . ∃ y . R2 x yhave rel-resumption R1 R2 r (map-resumption (λx . SOME y . R1 x y) (λx .
SOME y . R2 x y) r)proof(coinduction arbitrary : r rule: rel-resumption-coinduct)
case (Done r)have ?is-Done by simpmoreover have ?result using R1
by(cases result r)(auto intro: someI )ultimately show ?case ..
nextcase (Pause r)thus ?case using R2 by(auto intro: someI )
qedthus ∃ r ′. rel-resumption R1 R2 r r ′ ..
qed
lemma left-unique-rel-resumption [transfer-rule]:assumes R1 : left-unique R1and R2 : left-unique R2shows left-unique (rel-resumption R1 R2 )unfolding left-unique-def
proof(intro strip)fix r1 r2 r3assume rel-resumption R1 R2 r1 r3 rel-resumption R1 R2 r2 r3thus r1 = r2proof(coinduction arbitrary : r1 r2 r3 )
case (Eq-resumption r1 r2 r3 )hence ?is-Done by(auto dest : rel-resumption-is-DoneD)moreover have ?Done using Eq-resumption
option.left-unique-rel [OF R1 , unfolded left-unique-def ]by(auto dest !: rel-resumption-resultD1 )
moreover have ?Pause using Eq-resumption R2 [unfolded left-unique-def ]by(auto 4 3 dest : rel-resumption-outputD1 rel-resumption-resumeD1 simp add :
rel-fun-def )ultimately show ?case by simp
qedqed
lemma right-total-rel-resumption [transfer-rule]:[[ right-total R1 ; right-total R2 ]] =⇒ right-total (rel-resumption R1 R2 )unfolding right-total-def
prooffix r :: ( ′b, ′d , ′e) resumptionassume R1 : ∀ y . ∃ x . R1 x y and R2 : ∀ y . ∃ x . R2 x yhave rel-resumption R1 R2 (map-resumption (λy . SOME x . R1 x y) (λy . SOME
x . R2 x y) r) rproof(coinduction arbitrary : r rule: rel-resumption-coinduct)
case (Done r)
149
have ?is-Done by simpmoreover have ?result using R1
by(cases result r)(auto intro: someI )ultimately show ?case ..
nextcase (Pause r)thus ?case using R2
by(auto intro: someI )qedthus ∃ r ′. rel-resumption R1 R2 r ′ r ..
qed
lemma right-unique-rel-resumption [transfer-rule]:assumes R1 : right-unique R1and R2 : right-unique R2shows right-unique (rel-resumption R1 R2 )unfolding right-unique-def
proof(intro strip)fix r1 r2 r3assume rel-resumption R1 R2 r1 r2 rel-resumption R1 R2 r1 r3thus r2 = r3proof(coinduction arbitrary : r1 r2 r3 )
case (Eq-resumption r1 r2 r3 )hence ?is-Done by(auto dest : rel-resumption-is-DoneD)moreover have ?Done using Eq-resumption option.right-unique-rel [OF R1 ,
unfolded right-unique-def ]by(auto dest !: rel-resumption-resultD2 )
moreover have ?Pause using Eq-resumption R2 [unfolded right-unique-def ]by(auto 4 3 dest : rel-resumption-outputD2 rel-resumption-resumeD2 simp add :
rel-fun-def )ultimately show ?case by simp
qedqed
lemma bi-total-rel-resumption [transfer-rule]:[[ bi-total A; bi-total B ]] =⇒ bi-total (rel-resumption A B)
unfolding bi-total-alt-defby(blast intro: left-total-rel-resumption right-total-rel-resumption)
lemma bi-unique-rel-resumption [transfer-rule]:[[ bi-unique A; bi-unique B ]] =⇒ bi-unique (rel-resumption A B)
unfolding bi-unique-alt-defby(blast intro: left-unique-rel-resumption right-unique-rel-resumption)
lemma Quotient-resumption [quot-map]:assumes Q1 : Quotient R1 Abs1 Rep1 T1and Q2 : Quotient R2 Abs2 Rep2 T2shows Quotient (rel-resumption R1 R2 ) (map-resumption Abs1 Abs2 ) (map-resumption
Rep1 Rep2 ) (rel-resumption T1 T2 )
150
unfolding Quotient-alt-defproof(intro conjI allI impI )
have 1 :∧
x y . rel-option T1 x y =⇒ map-option Abs1 x = yusing option.Quotient [OF Q1 ] by(simp add : Quotient-alt-def )
have 2 :∧
x y . T2 x y =⇒ Abs2 x = yusing Q2 by(simp add : Quotient-alt-def )
fix r1 r2assume rel-resumption T1 T2 r1 r2thus map-resumption Abs1 Abs2 r1 = r2by(coinduction arbitrary : r1 r2 )(auto 4 3 dest : rel-resumption-is-DoneD rel-resumption-resultD1
1 rel-resumption-outputD1 2 rel-resumption-resumeD1 )next
from option.Quotient [OF Q1 ] have 1 :∧
y . rel-option T1 (map-option Rep1 y)y
by(simp add : Quotient-alt-def )from Q2 have 2 :
∧x . T2 (Rep2 x ) x by(simp add : Quotient-alt-def )
fix rshow rel-resumption T1 T2 (map-resumption Rep1 Rep2 r) r
by(coinduction arbitrary : r rule: rel-resumption-coinduct)(auto simp add : 1 2 )next
have 1 :∧
x y . rel-option R1 x y ←→ rel-option T1 x (map-option Abs1 x ) ∧rel-option T1 y (map-option Abs1 y) ∧ map-option Abs1 x = map-option Abs1 y
using option.Quotient [OF Q1 ] by(simp add : Quotient-alt-def )have 2 :
∧x y . R2 x y ←→ T2 x (Abs2 x ) ∧ T2 y (Abs2 y) ∧ Abs2 x = Abs2 y
using Q2 by(simp add : Quotient-alt-def )
fix r1 r2show rel-resumption R1 R2 r1 r2 ←→
rel-resumption T1 T2 r1 (map-resumption Abs1 Abs2 r1 ) ∧rel-resumption T1 T2 r2 (map-resumption Abs1 Abs2 r2 ) ∧
map-resumption Abs1 Abs2 r1 = map-resumption Abs1 Abs2 r2 (is ?lhs ←→?rhs)
proofassume ?rhsthus ?lhsproof(coinduction arbitrary : r1 r2 rule: rel-resumption-coinduct)
case (Done r1 r2 )hence ?is-Done by(metis rel-resumption-is-DoneD)moreover have ?result using Done
by(metis rel-resumption-resultD1 result-map-resumption 1 )ultimately show ?case ..
nextcase (Pause r1 r2 )hence ?output by(metis rel-resumption-outputD1 output-map-resumption 2 )moreoverfrom 〈¬ is-Done r1 〉 obtain out1 c1 where r1 : r1 = Pause out1 c1 by(cases
r1 ) auto
151
from 〈¬ is-Done r2 〉 obtain out2 c2 where r2 : r2 = Pause out2 c2 by(casesr2 ) auto
have ?resume (is All ?C )proof
fix inpfrom Pause r1 r2have c1 : rel-resumption T1 T2 (c1 inp) (map-resumption Abs1 Abs2 (c1
inp))and c2 : rel-resumption T1 T2 (c2 inp) (map-resumption Abs1 Abs2 (c2
inp))and eq : map-resumption Abs1 Abs2 c1 = map-resumption Abs1 Abs2
c2by(simp-all add : rel-fun-def )
thus ?C inp by(simp add : fun-eq-iff r1 r2 )qedultimately show ?case ..
qednext
assume ?lhshence rel-resumption T1 T2 r1 (map-resumption Abs1 Abs2 r1 )proof(coinduction arbitrary : r1 r2 rule: rel-resumption-coinduct)
case Donethus ?case by(auto dest !: rel-resumption-resultD1 simp add : 1 )
nextcase (Pause r1 r2 )hence ?output by(auto 4 3 dest : rel-resumption-outputD1 simp add : 2 )moreover have ?resume using Pauseby(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ])(auto
4 3 simp add : rel-fun-def )ultimately show ?case ..
qedmoreover from 〈?lhs〉 have rel-resumption T1 T2 r2 (map-resumption Abs1
Abs2 r2 )proof(coinduction arbitrary : r1 r2 rule: rel-resumption-coinduct)
case Donethus ?case by(auto dest !: rel-resumption-resultD2 simp add : 1 )
nextcase (Pause r1 r2 )hence ?output by(auto dest : rel-resumption-outputD2 simp add : 2 )moreover have ?resume using Pauseby(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ])(auto
4 3 simp add : rel-fun-def )ultimately show ?case ..
qedmoreover from 〈?lhs〉 have map-resumption Abs1 Abs2 r1 = map-resumption
Abs1 Abs2 r2proof(coinduction arbitrary : r1 r2 )
case (Eq-resumption r1 r2 )hence ?is-Done ?Done by(auto dest : rel-resumption-is-DoneD rel-resumption-resultD1
152
simp add : 1 )moreoverhave ?Pause using Eq-resumptionby(cases r1 r2 rule: resumption.exhaust [case-product resumption.exhaust ])(auto
dest : rel-resumption-outputD1 simp add : 2 rel-fun-def )ultimately show ?case by simp
qedultimately show ?rhs by blast
qedqed
endtheory Generat imports
MainMisc∼∼/src/HOL/Library/Countable-Set
begin
6.4.1 Single-step generative
datatype (generat-pures: ′a, generat-outs: ′b, generat-conts: ′c) generat= Pure (result : ′a)| IO (output : ′b) (continuation: ′c)
datatype-compat generat
lemma IO-code-cong : out = out ′ =⇒ IO out c = IO out ′ c by simpsetup 〈〈 Code-Simp.map-ss (Simplifier .add-cong @thm IO-code-cong) 〉〉
lemma is-Pure-map-generat [simp]: is-Pure (map-generat f g h x ) = is-Pure xby(cases x ) simp-all
lemma result-map-generat [simp]: is-Pure x =⇒ result (map-generat f g h x ) = f(result x )by(cases x ) simp-all
lemma output-map-generat [simp]: ¬ is-Pure x =⇒ output (map-generat f g h x )= g (output x )by(cases x ) simp-all
lemma continuation-map-generat [simp]: ¬ is-Pure x =⇒ continuation (map-generatf g h x ) = h (continuation x )by(cases x ) simp-all
lemma rel-generatI :[[ is-Pure x ←→ is-Pure y ;
[[ is-Pure x ; is-Pure y ]] =⇒ A (result x ) (result y);[[ ¬ is-Pure x ; ¬ is-Pure y ]] =⇒ Out (output x ) (output y) ∧ R (continuation
x ) (continuation y) ]]
153
=⇒ rel-generat A Out R x yby(cases x y rule: generat .exhaust [case-product generat .exhaust ]) simp-all
lemma rel-generatD ′:rel-generat A Out R x y=⇒ (is-Pure x ←→ is-Pure y) ∧
(is-Pure x −→ is-Pure y −→ A (result x ) (result y)) ∧(¬ is-Pure x −→ ¬ is-Pure y −→ Out (output x ) (output y) ∧ R (continuation
x ) (continuation y))by(cases x y rule: generat .exhaust [case-product generat .exhaust ]) simp-all
lemma rel-generatD :assumes rel-generat A Out R x yshows rel-generat-is-PureD : is-Pure x ←→ is-Pure yand rel-generat-resultD : is-Pure x ∨ is-Pure y =⇒ A (result x ) (result y)and rel-generat-outputD : ¬ is-Pure x ∨ ¬ is-Pure y =⇒ Out (output x ) (output
y)and rel-generat-continuationD : ¬ is-Pure x ∨ ¬ is-Pure y =⇒ R (continuation
x ) (continuation y)using rel-generatD ′[OF assms] by simp-all
lemma rel-generat-mono:[[ rel-generat A B C x y ;
∧x y . A x y =⇒ A ′ x y ;
∧x y . B x y =⇒ B ′ x y ;
∧x y .
C x y =⇒ C ′ x y ]]=⇒ rel-generat A ′ B ′ C ′ x y
using generat .rel-mono[of A A ′ B B ′ C C ′] by(auto simp add : le-fun-def )
lemma rel-generat-mono ′ [mono]:[[∧
x y . A x y −→ A ′ x y ;∧
x y . B x y −→ B ′ x y ;∧
x y . C x y −→ C ′ x y ]]=⇒ rel-generat A B C x y −→ rel-generat A ′ B ′ C ′ x y
by(blast intro: rel-generat-mono)
lemma rel-generat-same:rel-generat A B C r r ←→(∀ x ∈ generat-pures r . A x x ) ∧(∀ out ∈ generat-outs r . B out out) ∧(∀ c ∈generat-conts r . C c c)
by(cases r)(auto simp add : rel-fun-def )
lemma rel-generat-reflI :[[∧
y . y ∈ generat-pures x =⇒ A y y ;∧out . out ∈ generat-outs x =⇒ B out out ;∧cont . cont ∈ generat-conts x =⇒ C cont cont ]]
=⇒ rel-generat A B C x xusing assmsby(cases x ) auto
lemma reflp-rel-generat [simp]: reflp (rel-generat A B C ) ←→ reflp A ∧ reflp B∧ reflp C
154
by(auto 4 3 intro!: reflpI rel-generatI dest : reflpD reflpD [where x=Pure -] re-flpD [where x=IO - -])
lemma transp-rel-generatI :assumes transp A transp B transp Cshows transp (rel-generat A B C )
by(rule transpI )(auto 6 5 dest : rel-generatD ′ intro!: rel-generatI intro: assms[THENtranspD ] simp add : rel-fun-def )
lemma rel-generat-inf :inf (rel-generat A B C ) (rel-generat A ′ B ′ C ′) = rel-generat (inf A A ′) (inf B
B ′) (inf C C ′)(is ?lhs = ?rhs)
proof(rule antisym)show ?lhs ≤ ?rhs
by(auto elim!: generat .rel-cases simp add : rel-fun-def )qed(auto elim: rel-generat-mono)
lemma rel-generat-Pure1 : rel-generat A B C (Pure x ) = (λr . ∃ y . r = Pure y ∧A x y)by(rule ext)(case-tac r , simp-all)
lemma rel-generat-IO1 : rel-generat A B C (IO out c) = (λr . ∃ out ′ c ′. r = IOout ′ c ′ ∧ B out out ′ ∧ C c c ′)by(rule ext)(case-tac r , simp-all)
lemma not-is-Pure-conv : ¬ is-Pure r ←→ (∃ out c. r = IO out c)by(cases r) auto
lemma finite-generat-outs [simp]: finite (generat-outs generat)by(cases generat) auto
lemma countable-generat-outs [simp]: countable (generat-outs generat)by(simp add : countable-finite)
lemma case-map-generat :case-generat pure io (map-generat a b d r) =case-generat (pure a) (λout . io (b out) d) r
by(cases r) simp-all
lemma continuation-in-generat-conts:¬ is-Pure r =⇒ continuation r ∈ generat-conts r
by(cases r) auto
fun dest-IO :: ( ′a, ′out , ′c) generat ⇒ ( ′out × ′c) optionwhere
dest-IO (Pure -) = None| dest-IO (IO out c) = Some (out , c)
155
lemma dest-IO-eq-Some-iff [simp]: dest-IO generat = Some (out , c) ←→ generat= IO out cby(cases generat) simp-all
lemma dest-IO-eq-None-iff [simp]: dest-IO generat = None ←→ is-Pure generatby(cases generat) simp-all
lemma dest-IO-comp-Pure [simp]: dest-IO Pure = (λ-. None)by(simp add : fun-eq-iff )
lemma dom-dest-IO : dom dest-IO = x . ¬ is-Pure xby(auto simp add : not-is-Pure-conv)
definition generat-lub :: ( ′a set ⇒ ′b)⇒ ( ′out set ⇒ ′out ′)⇒ ( ′cont set ⇒ ′cont ′)
⇒ ( ′a, ′out , ′cont) generat set ⇒ ( ′b, ′out ′, ′cont ′) generatwhere
generat-lub lub1 lub2 lub3 A =(if ∃ x∈A. is-Pure x then Pure (lub1 (result ‘ (A ∩ f . is-Pure f )))else IO (lub2 (output ‘ (A ∩ f . ¬ is-Pure f ))) (lub3 (continuation ‘ (A ∩ f .
¬ is-Pure f ))))
lemma is-Pure-generat-lub [simp]:is-Pure (generat-lub lub1 lub2 lub3 A) ←→ (∃ x∈A. is-Pure x )
by(simp add : generat-lub-def )
lemma result-generat-lub [simp]:∃ x∈A. is-Pure x =⇒ result (generat-lub lub1 lub2 lub3 A) = lub1 (result ‘ (A ∩f . is-Pure f ))by(simp add : generat-lub-def )
lemma output-generat-lub:∀ x∈A. ¬ is-Pure x =⇒ output (generat-lub lub1 lub2 lub3 A) = lub2 (output ‘
(A ∩ f . ¬ is-Pure f ))by(simp add : generat-lub-def )
lemma continuation-generat-lub:∀ x∈A. ¬ is-Pure x =⇒ continuation (generat-lub lub1 lub2 lub3 A) = lub3
(continuation ‘ (A ∩ f . ¬ is-Pure f ))by(simp add : generat-lub-def )
lemma generat-lub-map [simp]:generat-lub lub1 lub2 lub3 (map-generat f g h ‘ A) = generat-lub (lub1 op ‘ f )
(lub2 op ‘ g) (lub3 op ‘ h) Aby(auto 4 3 simp add : generat-lub-def intro: arg-cong [where f =lub1 ] arg-cong [wheref =lub2 ] arg-cong [where f =lub3 ] rev-image-eqI intro!: ext)
156
lemma map-generat-lub [simp]:map-generat f g h (generat-lub lub1 lub2 lub3 A) = generat-lub (f lub1 ) (g
lub2 ) (h lub3 ) Aby(simp add : generat-lub-def o-def )
abbreviation generat-lub ′ :: ( ′cont set ⇒ ′cont ′) ⇒ ( ′a, ′out , ′cont) generat set⇒ ( ′a, ′out , ′cont ′) generatwhere generat-lub ′ ≡ generat-lub (λA. THE x . x ∈ A) (λA. THE x . x ∈ A)
end
7 Generative probabilistic values
theory Generative-Probabilistic-Value importsSPMFPF-SetResumptionGenerat
begin
context begin interpretation lifting-syntax .lemma rel-fun-curry :(A ===> B ===> C ) f g ←→ (rel-prod A B ===> C ) (case-prod f ) (case-prod
g)by(auto simp add : rel-fun-def )end
lemma tlength-eq-infinity-iff : tlength xs = ∞ ←→ ¬ tfinite xsincluding tllist .lifting by transfer(simp add : llength-eq-infty-conv-lfinite)
lemma transp-rel-fun: [[ is-equality Q ; transp R ]] =⇒ transp (rel-fun Q R)by(rule transpI )(auto dest : transpD rel-funD simp add : is-equality-def )
lemma rel-fun-inf : inf (rel-fun Q R) (rel-fun Q R ′) = rel-fun Q (inf R R ′)by(rule antisym)(auto elim: rel-fun-mono dest : rel-funD)
lemma eSuc-SUP : A 6= =⇒ eSuc (SUPREMUM A f ) = (SUP x :A. eSuc (fx ))unfolding SUP-def by(subst eSuc-Sup)(simp-all)
lemma (in ccpo) Sup-image-mono:assumes ccpo: class.ccpo luba orda lessaand mono: monotone orda op ≤ fand chain: Complete-Partial-Order .chain orda Aand A 6= shows Sup (f ‘ A) ≤ (f (luba A))
proof(rule ccpo-Sup-least)from chain show Complete-Partial-Order .chain op ≤ (f ‘ A)
157
by(rule chain-imageI )(rule monotoneD [OF mono])fix xassume x ∈ f ‘ Athen obtain y where x = f y y ∈ A by blastfrom 〈y ∈ A〉 have orda y (luba A) by(rule ccpo.ccpo-Sup-upper [OF ccpo chain])hence f y ≤ f (luba A) by(rule monotoneD [OF mono])thus x ≤ f (luba A) using 〈x = f y〉 by simp
qed
lemma (in ccpo) admissible-le-mono:assumes monotone op ≤ op ≤ fshows ccpo.admissible Sup op ≤ (λx . x ≤ f x )
proof(rule ccpo.admissibleI )fix Yassume chain: Complete-Partial-Order .chain op ≤ Y
and Y : Y 6= and le [rule-format ]: ∀ x∈Y . x ≤ f x
have⊔
Y ≤⊔
(f ‘ Y ) using chainby(rule ccpo-Sup-least)(rule order-trans[OF le]; blast intro!: ccpo-Sup-upper
chain-imageI [OF chain] intro: monotoneD [OF assms])also have . . . ≤ f (
⊔Y )
by(rule Sup-image-mono[OF - assms chain Y , where lessa=op <]) unfold-localesfinally show
⊔Y ≤ . . . .
qed
lemma (in ccpo) fixp-induct-strong2 :assumes adm: ccpo.admissible Sup op ≤ Pand mono: monotone op ≤ op ≤ fand bot : P (
⊔)
and step:∧
x . [[ x ≤ ccpo-class.fixp f ; x ≤ f x ; P x ]] =⇒ P (f x )shows P (ccpo-class.fixp f )
proof(rule fixp-strong-induct [where P=λx . x ≤ f x ∧ P x , THEN conjunct2 ])show ccpo.admissible Sup op ≤ (λx . x ≤ f x ∧ P x )
using admissible-le-mono adm by(rule admissible-conj )(rule mono)next
show⊔ ≤ f (
⊔) ∧ P (
⊔)
by(auto simp add : bot chain-empty intro: ccpo-Sup-least)next
fix xassume x ≤ ccpo-class.fixp f x ≤ f x ∧ P xthus f x ≤ f (f x ) ∧ P (f x )
by(auto dest : monotoneD [OF mono] intro: step)qed(rule mono)
context partial-function-definitions begin
lemma fixp-induct-strong2-uc:fixes F :: ′c ⇒ ′c
and U :: ′c ⇒ ′b ⇒ ′a
158
and C :: ( ′b ⇒ ′a) ⇒ ′cand P :: ( ′b ⇒ ′a) ⇒ bool
assumes mono:∧
x . mono-body (λf . U (F (C f )) x )and eq : f ≡ C (fixp-fun (λf . U (F (C f ))))and inverse:
∧f . U (C f ) = f
and adm: ccpo.admissible lub-fun le-fun Pand bot : P (λ-. lub )and step:
∧f ′. [[ le-fun (U f ′) (U f ); le-fun (U f ′) (U (F f ′)); P (U f ′) ]] =⇒
P (U (F f ′))shows P (U f )
unfolding eq inverseapply (rule ccpo.fixp-induct-strong2 [OF ccpo adm])apply (insert mono, auto simp: monotone-def fun-ord-def bot fun-lub-def )[2 ]apply (rule-tac f ′5 =C x in step)apply (simp-all add : inverse eq)done
end
hide-const (open) Done
7.1 Type definition
codatatype (results ′-gpv : ′a, outs ′-gpv : ′out , ′in) gpv= GPV (the-gpv : ( ′a, ′out , ′in ⇒ ( ′a, ′out , ′in) gpv) generat spmf )
declare gpv .rel-eq [relator-eq ]
Reactive values are like generative, except that they take an input first.
type-synonym ( ′a, ′out , ′in) rpv = ′in ⇒ ( ′a, ′out , ′in) gpvprint-translation — pretty printing for ( ′a, ′out , ′in) rpv 〈
letfun tr ′ [in1 , Const (@type-syntax gpv, -) $ a $ out $ in2 ] =
if in1 = in2 then Syntax .const @type-syntax rpv $ a $ out $ in1else raise Match;
in [(@type-syntax fun, K tr ′)]end
〉
typ ( ′a, ′out , ′in) rpv
Effectively, ( ′a, ′out , ′in) gpv and ( ′a, ′out , ′in) rpv are mutually recursive.
lemma eq-GPV-iff : f = GPV g ←→ the-gpv f = gby(cases f ) auto
declare gpv .set [simp del ]
lemma rel-gpv-def ′:rel-gpv A B gpv gpv ′←→
159
(∃ gpv ′′. (∀ (x , y) ∈ results ′-gpv gpv ′′. A x y) ∧ (∀ (x , y) ∈ outs ′-gpv gpv ′′. B xy) ∧
map-gpv fst fst gpv ′′ = gpv ∧ map-gpv snd snd gpv ′′ = gpv ′)unfolding rel-gpv-def by(auto simp add : BNF-Def .Grp-def )
definition results ′-rpv :: ( ′a, ′out , ′in) rpv ⇒ ′a setwhere results ′-rpv rpv = range rpv >>= results ′-gpv
definition outs ′-rpv :: ( ′a, ′out , ′in) rpv ⇒ ′out setwhere outs ′-rpv rpv = range rpv >>= outs ′-gpv
abbreviation rel-rpv:: ( ′a ⇒ ′b ⇒ bool) ⇒ ( ′out ⇒ ′out ′⇒ bool)⇒ ( ′in ⇒ ( ′a, ′out , ′in) gpv) ⇒ ( ′in ⇒ ( ′b, ′out ′, ′in) gpv) ⇒ bool
where rel-rpv A B ≡ rel-fun op = (rel-gpv A B)
lemma in-results ′-rpv [iff ]: x ∈ results ′-rpv rpv ←→ (∃ input . x ∈ results ′-gpv(rpv input))by(simp add : results ′-rpv-def )
lemma in-outs-rpv [iff ]: out ∈ outs ′-rpv rpv ←→ (∃ input . out ∈ outs ′-gpv (rpvinput))by(simp add : outs ′-rpv-def )
lemma results ′-GPV [simp]:results ′-gpv (GPV r) =(set-spmf r >>= generat-pures) ∪((set-spmf r >>= generat-conts) >>= results ′-rpv)
by(auto simp add : gpv .set bind-UNION set-spmf-def )
lemma outs ′-GPV [simp]:outs ′-gpv (GPV r) =(set-spmf r >>= generat-outs) ∪((set-spmf r >>= generat-conts) >>= outs ′-rpv)
by(auto simp add : gpv .set bind-UNION set-spmf-def )
lemma outs ′-gpv-unfold :outs ′-gpv r =(set-spmf (the-gpv r) >>= generat-outs) ∪((set-spmf (the-gpv r) >>= generat-conts) >>= outs ′-rpv)
by(cases r) simp
lemma outs ′-gpv-induct [consumes 1 , case-names Out Cont , induct set : outs ′-gpv ]:assumes x : x ∈ outs ′-gpv gpvand Out :
∧generat gpv . [[ generat ∈ set-spmf (the-gpv gpv); x ∈ generat-outs
generat ]] =⇒ P gpvand Cont :
∧generat gpv c input .
[[ generat ∈ set-spmf (the-gpv gpv); c ∈ generat-conts generat ; x ∈ outs ′-gpv (cinput); P (c input) ]] =⇒ P gpv
160
shows P gpvusing xapply(induction y≡x gpv)apply(rule Out , simp add : in-set-spmf , simp)
apply(erule imageE , rule Cont , simp add : in-set-spmf , simp, simp, simp).
lemma outs ′-gpv-cases [consumes 1 , case-names Out Cont , cases set : outs ′-gpv ]:assumes x ∈ outs ′-gpv gpvobtains (Out) generat where generat ∈ set-spmf (the-gpv gpv) x ∈ generat-outs
generat| (Cont) generat c input where generat ∈ set-spmf (the-gpv gpv) c ∈ generat-conts
generat x ∈ outs ′-gpv (c input)using assms by cases(auto simp add : in-set-spmf )
lemma outs ′-gpvI [intro? ]:shows outs ′-gpv-Out : [[ generat ∈ set-spmf (the-gpv gpv); x ∈ generat-outs gen-
erat ]] =⇒ x ∈ outs ′-gpv gpvand outs ′-gpv-Cont : [[ generat ∈ set-spmf (the-gpv gpv); c ∈ generat-conts gen-
erat ; x ∈ outs ′-gpv (c input) ]] =⇒ x ∈ outs ′-gpv gpvby(auto intro: gpv .set-sel simp add : in-set-spmf )
lemma results ′-gpv-induct [consumes 1 , case-names Pure Cont , induct set : re-sults ′-gpv ]:
assumes x : x ∈ results ′-gpv gpvand Pure:
∧generat gpv . [[ generat ∈ set-spmf (the-gpv gpv); x ∈ generat-pures
generat ]] =⇒ P gpvand Cont :
∧generat gpv c input .
[[ generat ∈ set-spmf (the-gpv gpv); c ∈ generat-conts generat ; x ∈ results ′-gpv(c input); P (c input) ]] =⇒ P gpv
shows P gpvusing xapply(induction y≡x gpv)apply(rule Pure; simp add : in-set-spmf )
apply(erule imageE , rule Cont , simp add : in-set-spmf , simp, simp, simp).
lemma results ′-gpv-cases [consumes 1 , case-names Pure Cont , cases set : results ′-gpv ]:assumes x ∈ results ′-gpv gpvobtains (Pure) generat where generat ∈ set-spmf (the-gpv gpv) x ∈ generat-pures
generat| (Cont) generat c input where generat ∈ set-spmf (the-gpv gpv) c ∈ generat-conts
generat x ∈ results ′-gpv (c input)using assms by cases(auto simp add : in-set-spmf )
lemma results ′-gpvI [intro? ]:shows results ′-gpv-Pure: [[ generat ∈ set-spmf (the-gpv gpv); x ∈ generat-pures
generat ]] =⇒ x ∈ results ′-gpv gpvand results ′-gpv-Cont : [[ generat ∈ set-spmf (the-gpv gpv); c ∈ generat-conts
161
generat ; x ∈ results ′-gpv (c input) ]] =⇒ x ∈ results ′-gpv gpvby(auto intro: gpv .set-sel simp add : in-set-spmf )
lemma left-unique-rel-gpv [transfer-rule]:[[ left-unique A; left-unique B ]] =⇒ left-unique (rel-gpv A B)
unfolding left-unique-alt-def gpv .rel-conversep[symmetric] gpv .rel-compp[symmetric]by(subst gpv .rel-eq [symmetric])(rule gpv .rel-mono)
lemma right-unique-rel-gpv [transfer-rule]:[[ right-unique A; right-unique B ]] =⇒ right-unique (rel-gpv A B)
unfolding right-unique-alt-def gpv .rel-conversep[symmetric] gpv .rel-compp[symmetric]by(subst gpv .rel-eq [symmetric])(rule gpv .rel-mono)
lemma bi-unique-rel-gpv [transfer-rule]:[[ bi-unique A; bi-unique B ]] =⇒ bi-unique (rel-gpv A B)
unfolding bi-unique-alt-def by(simp add : left-unique-rel-gpv right-unique-rel-gpv)
lemma left-total-rel-gpv [transfer-rule]:[[ left-total A; left-total B ]] =⇒ left-total (rel-gpv A B)
unfolding left-total-alt-def gpv .rel-conversep[symmetric] gpv .rel-compp[symmetric]by(subst gpv .rel-eq [symmetric])(rule gpv .rel-mono)
lemma right-total-rel-gpv [transfer-rule]:[[ right-total A; right-total B ]] =⇒ right-total (rel-gpv A B)
unfolding right-total-alt-def gpv .rel-conversep[symmetric] gpv .rel-compp[symmetric]by(subst gpv .rel-eq [symmetric])(rule gpv .rel-mono)
lemma bi-total-rel-gpv [transfer-rule]: [[ bi-total A; bi-total B ]] =⇒ bi-total (rel-gpvA B)unfolding bi-total-alt-def by(simp add : left-total-rel-gpv right-total-rel-gpv)
declare gpv .map-transfer [transfer-rule]
lemma if-distrib-map-gpv [if-distribs]:map-gpv f g (if b then gpv else gpv ′) = (if b then map-gpv f g gpv else map-gpv f
g gpv ′)by simp
7.2 Simple, derived operations
primcorec Done :: ′a ⇒ ( ′a, ′out , ′in) gpvwhere the-gpv (Done a) = return-spmf (Pure a)
primcorec Pause :: ′out ⇒ ( ′in ⇒ ( ′a, ′out , ′in) gpv) ⇒ ( ′a, ′out , ′in) gpvwhere the-gpv (Pause out c) = return-spmf (IO out c)
primcorec lift-spmf :: ′a spmf ⇒ ( ′a, ′out , ′in) gpvwhere the-gpv (lift-spmf p) = map-spmf Pure p
162
definition Fail :: ( ′a, ′out , ′in) gpvwhere Fail = GPV (return-pmf None)
definition React :: ( ′in ⇒ ′out × ( ′a, ′out , ′in) rpv) ⇒ ( ′a, ′out , ′in) rpvwhere React f input = case-prod Pause (f input)
definition rFail :: ( ′a, ′out , ′in) rpvwhere rFail = (λ-. Fail)
lemma Done-inject [simp]: Done x = Done y ←→ x = yby(simp add : Done.ctr)
lemma Pause-inject [simp]: Pause out c = Pause out ′ c ′ ←→ out = out ′ ∧ c =c ′
by(simp add : Pause.ctr)
lemma [simp]:shows Done-neq-Pause: Done x 6= Pause out cand Pause-neq-Done: Pause out c 6= Done x
by(simp-all add : Done.ctr Pause.ctr)
lemma outs ′-gpv-Done [simp]: outs ′-gpv (Done x ) = by(auto elim: outs ′-gpv-cases)
lemma results ′-gpv-Done [simp]: results ′-gpv (Done x ) = xby(auto intro: results ′-gpvI elim: results ′-gpv-cases)
lemma outs ′-gpv-Pause [simp]: outs ′-gpv (Pause out c) = insert out (⋃
input .outs ′-gpv (c input))by(auto 4 4 intro: outs ′-gpvI elim: outs ′-gpv-cases)
lemma results ′-gpv-Pause [simp]: results ′-gpv (Pause out rpv) = results ′-rpv rpvby(auto 4 4 intro: results ′-gpvI elim: results ′-gpv-cases)
lemma lift-spmf-return [simp]: lift-spmf (return-spmf x ) = Done xby(simp add : lift-spmf .ctr Done.ctr)
lemma lift-spmf-None [simp]: lift-spmf (return-pmf None) = Failby(rule gpv .expand)(simp add : Fail-def )
lemma the-gpv-lift-spmf [simp]: the-gpv (lift-spmf r) = map-spmf Pure rby(simp)
lemma outs ′-gpv-lift-spmf [simp]: outs ′-gpv (lift-spmf p) = by(auto 4 3 elim: outs ′-gpv-cases)
lemma results ′-gpv-lift-spmf [simp]: results ′-gpv (lift-spmf p) = set-spmf pby(auto 4 3 elim: results ′-gpv-cases intro: results ′-gpvI )
163
lemma lift-spmf-inject [simp]: lift-spmf p = lift-spmf q ←→ p = qby(auto simp add : lift-spmf .code dest !: pmf .inj-map-strong [rotated ] option.inj-map-strong [rotated ])
lemma map-lift-spmf : map-gpv f g (lift-spmf p) = lift-spmf (map-spmf f p)by(rule gpv .expand)(simp add : gpv .map-sel spmf .map-comp o-def )
lemma [simp]:shows Fail-neq-Pause: Fail 6= Pause out cand Pause-neq-Fail : Pause out c 6= Failand Fail-neq-Done: Fail 6= Done xand Done-neq-Fail : Done x 6= Fail
by(simp-all add : Fail-def Pause.ctr Done.ctr)
Add unit closure to circumvent SML value restriction
definition Fail ′ :: unit ⇒ ( ′a, ′out , ′in) gpvwhere [code del ]: Fail ′ - = Fail
lemma Fail-code [code-unfold ]: Fail = Fail ′ ()by(simp add : Fail ′-def )
lemma Fail ′-code [code]:Fail ′ x = GPV (return-pmf None)
by(simp add : Fail ′-def Fail-def )
lemma Fail-sel [simp]:the-gpv Fail = return-pmf None
by(simp add : Fail-def )
lemma Fail-eq-GPV-iff [simp]: Fail = GPV f ←→ f = return-pmf Noneby(auto simp add : Fail-def )
lemma outs ′-gpv-Fail [simp]: outs ′-gpv Fail = by(auto elim: outs ′-gpv-cases)
lemma results ′-gpv-Fail [simp]: results ′-gpv Fail = by(auto elim: results ′-gpv-cases)
lemma React-inject [iff ]: React f = React f ′←→ f = f ′
by(auto simp add : React-def fun-eq-iff split-def intro: prod .expand)
lemma React-apply [simp]: f input = (out , c) =⇒ React f input = Pause out cby(simp add : React-def )
lemma rFail-apply [simp]: rFail input = Failby(simp add : rFail-def )
lemma [simp]:shows rFail-neq-React : rFail 6= React fand React-neq-rFail : React f 6= rFail
164
by(simp-all add : React-def fun-eq-iff split-beta)
lemma rel-gpv-FailI [simp]: rel-gpv A C Fail Failby(subst gpv .rel-sel) simp
lemma rel-gpv-Done [iff ]: rel-gpv A C (Done x ) (Done y) ←→ A x yby(subst gpv .rel-sel) simp
lemma rel-gpv-Pause [iff ]: rel-gpv A C (Pause out c) (Pause out ′ c ′) ←→ C outout ′ ∧ (∀ x . rel-gpv A C (c x ) (c ′ x ))by(subst gpv .rel-sel)(simp add : rel-fun-def )
lemma rel-gpv-lift-spmf [iff ]: rel-gpv A C (lift-spmf p) (lift-spmf q) ←→ rel-spmfA p qby(subst gpv .rel-sel)(simp add : spmf-rel-map)
context begin interpretation lifting-syntax .lemma Fail-parametric [transfer-rule]: rel-gpv A C Fail Failby(fact rel-gpv-FailI )
lemma Done-parametric [transfer-rule]: (A ===> rel-gpv A C ) Done Doneby(rule rel-funI ) simp
lemma Pause-parametric [transfer-rule]:(C ===> (op = ===> rel-gpv A C ) ===> rel-gpv A C ) Pause Pause
by(simp add : rel-fun-def )
lemma lift-spmf-parametric [transfer-rule]:(rel-spmf A ===> rel-gpv A C ) lift-spmf lift-spmf
by(simp add : rel-fun-def )end
lemma map-gpv-Done [simp]: map-gpv f g (Done x ) = Done (f x )by(simp add : Done.code)
lemma map-gpv-Pause [simp]: map-gpv f g (Pause x c) = Pause (g x ) (map-gpvf g c)by(simp add : Pause.code)
lemma map-gpv-Fail [simp]: map-gpv f g Fail = Failby(simp add : Fail-def )
7.3 Monad structure
primcorec bind-gpv :: ( ′a, ′out , ′in) gpv ⇒ ( ′a ⇒ ( ′b, ′out , ′in) gpv) ⇒ ( ′b, ′out ,′in) gpvwhere
the-gpv (bind-gpv r f ) =
165
map-spmf (map-generat id id (op (case-sum id (λr . bind-gpv r f ))))(the-gpv r >>=(case-generat
(λx . map-spmf (map-generat id id (op Inl)) (the-gpv (f x )))(λout c. return-spmf (IO out (λinput . Inr (c input))))))
declare bind-gpv .sel [simp del ]
adhoc-overloading Monad-Syntax .bind bind-gpv
lemma bind-gpv-unfold [code]:r >>= f = GPV (do
generat ← the-gpv r ;case generat of Pure x ⇒ the-gpv (f x )| IO out c ⇒ return-spmf (IO out (λinput . c input >>= f ))
)unfolding bind-gpv-defapply(rule gpv .expand)apply(simp add : map-spmf-bind-spmf )apply(rule arg-cong [where f =bind-spmf (the-gpv r)])apply(auto split : generat .split simp add : map-spmf-bind-spmf fun-eq-iff spmf .map-compo-def generat .map-comp id-def [symmetric] generat .map-id pmf .map-id option.map-id)done
lemma bind-gpv-code-cong : f = f ′ =⇒ bind-gpv f g = bind-gpv f ′ g by simpsetup 〈〈 Code-Simp.map-ss (Simplifier .add-cong @thm bind-gpv-code-cong) 〉〉
lemma bind-gpv-sel :the-gpv (r >>= f ) =do
generat ← the-gpv r ;case generat of Pure x ⇒ the-gpv (f x )| IO out c ⇒ return-spmf (IO out (λinput . bind-gpv (c input) f ))
by(subst bind-gpv-unfold) simp
lemma bind-gpv-sel ′ [simp]:the-gpv (r >>= f ) =do
generat ← the-gpv r ;if is-Pure generat then the-gpv (f (result generat))else return-spmf (IO (output generat) (λinput . bind-gpv (continuation generat
input) f ))
unfolding bind-gpv-selby(rule arg-cong [where f =bind-spmf (the-gpv r)])(simp add : fun-eq-iff split : gen-erat .split)
166
lemma Done-bind-gpv [simp]: Done a >>= f = f aby(rule gpv .expand)(simp)
lemma bind-gpv-Done [simp]: f >>= Done = fproof(coinduction arbitrary : f rule: gpv .coinduct)
case (Eq-gpv f )have ∗: the-gpv f >>= (case-generat (λx . return-spmf (Pure x )) (λout c. return-spmf
(IO out (λinput . Inr (c input))))) =map-spmf (map-generat id id (op Inr)) (bind-spmf (the-gpv f )
return-spmf )unfolding map-spmf-bind-spmfby(rule arg-cong2 [where f =bind-spmf ])(auto simp add : fun-eq-iff split : gen-
erat .split)show ?case
by(auto simp add : ∗ bind-gpv .simps pmf .rel-map option.rel-map[abs-def ] gen-erat .rel-map[abs-def ] simp del : bind-gpv-sel ′ intro!: rel-generatI rel-spmf-reflI )qed
lemma if-distrib-bind-gpv2 [if-distribs]:bind-gpv gpv (λy . if b then f y else g y) = (if b then bind-gpv gpv f else bind-gpv
gpv g)by simp
lemma lift-spmf-bind : lift-spmf r >>= f = GPV (r >>= the-gpv f )by(coinduction arbitrary : r f rule: gpv .coinduct-strong)(auto simp add : bind-map-spmfo-def intro: rel-pmf-reflI rel-optionI rel-generatI )
lemma the-gpv-bind-gpv-lift-spmf [simp]:the-gpv (bind-gpv (lift-spmf p) f ) = bind-spmf p (the-gpv f )
by(simp add : bind-map-spmf o-def )
lemma lift-spmf-bind-spmf : lift-spmf (p >>= f ) = lift-spmf p >>= (λx . lift-spmf (fx ))by(rule gpv .expand)(simp add : lift-spmf-bind o-def map-spmf-bind-spmf )
lemma GPV-bind :GPV f >>= g =GPV (f >>= (λgenerat . case generat of Pure x ⇒ the-gpv (g x ) | IO out c ⇒
return-spmf (IO out (λinput . c input >>= g))))by(subst bind-gpv-unfold) simp
lemma GPV-bind ′:GPV f >>= g = GPV (f >>= (λgenerat . if is-Pure generat then the-gpv (g (result
generat)) else return-spmf (IO (output generat) (λinput . continuation generat in-put >>= g))))unfolding GPV-bind gpv .injectby(rule arg-cong [where f =bind-spmf f ])(simp add : fun-eq-iff split : generat .split)
lemma bind-gpv-assoc:
167
fixes f :: ( ′a, ′out , ′in) gpvshows (f >>= g) >>= h = f >>= (λx . g x >>= h)
proof(coinduction arbitrary : f g h rule: gpv .coinduct-strong)case (Eq-gpv f g h)show ?case
apply(simp cong del : if-weak-cong)apply(rule rel-spmf-bindI [where R=op =])apply(simp add : option.rel-eq pmf .rel-eq)
apply(fastforce intro: rel-pmf-return-pmfI rel-generatI rel-spmf-reflI )done
qed
lemma map-gpv-bind-gpv : map-gpv f g (bind-gpv gpv h) = bind-gpv (map-gpv id ggpv) (λx . map-gpv f g (h x ))apply(coinduction arbitrary : gpv rule: gpv .coinduct-strong)apply(simp add : bind-gpv .sel gpv .map-sel spmf-rel-map generat .rel-map o-def bind-map-spmfdel : bind-gpv-sel ′)apply(rule rel-spmf-bind-reflI )apply(auto simp add : spmf-rel-map generat .rel-map split : generat .split intro!: rel-spmf-reflIgenerat .rel-refl rel-funI )done
lemma map-gpv-id-bind-gpv : map-gpv f id (bind-gpv gpv g) = bind-gpv gpv (map-gpvf id g)by(simp add : map-gpv-bind-gpv gpv .map-id o-def )
lemma map-gpv-conv-bind :map-gpv f (λx . x ) x = bind-gpv x (λx . Done (f x ))
using map-gpv-bind-gpv [of f λx . x x Done] by(simp add : id-def [symmetric] gpv .map-id)
lemma bind-map-gpv : bind-gpv (map-gpv f id gpv) g = bind-gpv gpv (g f )by(simp add : map-gpv-conv-bind id-def bind-gpv-assoc o-def )
lemma outs-bind-gpv :outs ′-gpv (bind-gpv x f ) = outs ′-gpv x ∪ (
⋃x ∈ results ′-gpv x . outs ′-gpv (f x ))
(is ?lhs = ?rhs)proof(rule Set .set-eqI iffI )+
fix outassume out ∈ ?lhsthen show out ∈ ?rhsproof(induction g≡x >>= f arbitrary : x )
case (Out generat)then obtain generat ′ where ∗: generat ′ ∈ set-spmf (the-gpv x )
and ∗∗: generat ∈ set-spmf (if is-Pure generat ′ then the-gpv (f (result gen-erat ′))
else return-spmf (IO (output generat ′) (λinput . continuationgenerat ′ input >>= f )))
by(auto simp add : set-bind-spmf )show ?case
168
proof(cases is-Pure generat ′)case Truethen have out ∈ outs ′-gpv (f (result generat ′)) using Out(2 ) ∗∗ by(auto
intro: outs ′-gpvI )moreover have result generat ′ ∈ results ′-gpv x using ∗ True
by(auto intro: results ′-gpvI generat .set-sel)ultimately show ?thesis by blast
nextcase Falsehence out ∈ outs ′-gpv x using ∗ ∗∗ Out(2 ) by(auto intro: outs ′-gpvI gen-
erat .set-sel)thus ?thesis by blast
qednext
case (Cont generat c input)then obtain generat ′ where ∗: generat ′ ∈ set-spmf (the-gpv x )and ∗∗: generat ∈ set-spmf (if is-Pure generat ′ then the-gpv (f (generat .result
generat ′))else return-spmf (IO (generat .output generat ′) (λinput .
continuation generat ′ input >>= f )))by(auto simp add : set-bind-spmf )
show ?caseproof(cases is-Pure generat ′)
case Truethen have out ∈ outs ′-gpv (f (result generat ′)) using Cont(2−3 ) ∗∗ by(auto
intro: outs ′-gpvI )moreover have result generat ′ ∈ results ′-gpv x using ∗ True
by(auto intro: results ′-gpvI generat .set-sel)ultimately show ?thesis by blast
nextcase Falsethen have generat : generat = IO (output generat ′) (λinput . continuation
generat ′ input >>= f )using ∗∗ by simp
with Cont(2 ) have c input = continuation generat ′ input >>= f by autohence out ∈ outs ′-gpv (continuation generat ′ input) ∪ (
⋃x∈results ′-gpv
(continuation generat ′ input). outs ′-gpv (f x ))by(rule Cont)
thus ?thesisproof
assume out ∈ outs ′-gpv (continuation generat ′ input)with ∗ ∗∗ False have out ∈ outs ′-gpv x by(auto intro: outs ′-gpvI gen-
erat .set-sel)thus ?thesis ..
nextassume out ∈ (
⋃x∈results ′-gpv (continuation generat ′ input). outs ′-gpv (f
x ))then obtain y where y ∈ results ′-gpv (continuation generat ′ input) out ∈
outs ′-gpv (f y) ..
169
from 〈y ∈ -〉 ∗ ∗∗ False have y ∈ results ′-gpv xby(auto intro: results ′-gpvI generat .set-sel)
with 〈out ∈ outs ′-gpv (f y)〉 show ?thesis by blastqed
qedqed
nextfix outassume out ∈ ?rhsthen show out ∈ ?lhsproof
assume out ∈ outs ′-gpv xthus ?thesisproof(induction)
case (Out generat gpv)then show ?caseby(cases generat)(fastforce intro: outs ′-gpvI rev-bexI simp add : set-bind-spmf )+
nextcase (Cont generat gpv gpv ′)then show ?case
by(cases generat)(auto 4 4 intro: outs ′-gpvI rev-bexI simp add : in-set-spmfset-pmf-bind-spmf )
qednext
assume out ∈ (⋃
x∈results ′-gpv x . outs ′-gpv (f x ))then obtain y where y ∈ results ′-gpv x out ∈ outs ′-gpv (f y) ..from 〈y ∈ -〉 show ?thesisproof(induction)
case (Pure generat gpv)thus ?case using 〈out ∈ outs ′-gpv -〉
by(cases generat)(auto 4 5 intro: outs ′-gpvI rev-bexI simp add : set-bind-spmfelim: outs ′-gpv-cases)
nextcase (Cont generat gpv gpv ′)thus ?caseby(cases generat)(auto 4 4 simp add : in-set-spmf simp add : set-pmf-bind-spmf
intro: outs ′-gpvI rev-bexI )qed
qedqed
lemma bind-gpv-Fail [simp]: Fail >>= f = Failby(subst bind-gpv-unfold)(simp add : Fail-def )
context begin interpretation lifting-syntax .
lemma bind-gpv-parametric [transfer-rule]:(rel-gpv A C ===> (A ===> rel-gpv B C ) ===> rel-gpv B C ) bind-gpv
bind-gpv
170
unfolding bind-gpv-def by transfer-prover
end
lemma rel-gpv-bindI :[[ rel-gpv A C gpv gpv ′;
∧x y . A x y =⇒ rel-gpv B C (f x ) (g y) ]]
=⇒ rel-gpv B C (bind-gpv gpv f ) (bind-gpv gpv ′ g)by(fact bind-gpv-parametric[THEN rel-funD , THEN rel-funD , OF - rel-funI ])
lemma bind-gpv-cong :[[ gpv = gpv ′;
∧x . x ∈ results ′-gpv gpv ′ =⇒ f x = g x ]] =⇒ bind-gpv gpv f =
bind-gpv gpv ′ gapply(subst gpv .rel-eq [symmetric])apply(rule rel-gpv-bindI [where A=eq-onp (λx . x ∈ results ′-gpv gpv ′)])apply(subst (asm) gpv .rel-eq [symmetric])apply(erule gpv .rel-mono-strong)apply(simp add : eq-onp-def )
apply simpapply(clarsimp simp add : gpv .rel-eq eq-onp-def )done
definition bind-rpv :: ( ′a, ′in, ′out) rpv ⇒ ( ′a ⇒ ( ′b, ′in, ′out) gpv) ⇒ ( ′b, ′in,′out) rpvwhere bind-rpv rpv f = (λinput . bind-gpv (rpv input) f )
lemma bind-rpv-apply [simp]: bind-rpv rpv f input = bind-gpv (rpv input) fby(simp add : bind-rpv-def fun-eq-iff )
adhoc-overloading Monad-Syntax .bind bind-rpv
lemma bind-rpv-code-cong : rpv = rpv ′ =⇒ bind-rpv rpv f = bind-rpv rpv ′ f bysimpsetup 〈〈 Code-Simp.map-ss (Simplifier .add-cong @thm bind-rpv-code-cong) 〉〉
lemma bind-rpv-rDone [simp]: bind-rpv rpv Done = rpvby(simp add : bind-rpv-def )
lemma bind-gpv-Pause [simp]: bind-gpv (Pause out rpv) f = Pause out (bind-rpvrpv f )by(rule gpv .expand)(simp add : fun-eq-iff )
lemma bind-rpv-React [simp]: bind-rpv (React f ) g = React (apsnd (λrpv . bind-rpvrpv g) f )by(simp add : React-def split-beta fun-eq-iff )
lemma bind-rpv-assoc: bind-rpv (bind-rpv rpv f ) g = bind-rpv rpv ((λgpv . bind-gpvgpv g) f )by(simp add : fun-eq-iff bind-gpv-assoc o-def )
171
lemma bind-rpv-Done [simp]: bind-rpv Done f = fby(simp add : bind-rpv-def )
7.4 Embedding ′a spmf as a monad
context begin interpretation lifting-syntax .lemma neg-fun-distr3 :assumes 1 : left-unique R right-total Rassumes 2 : right-unique S left-total Sshows (R OO R ′ ===> S OO S ′) ≤ ((R ===> S ) OO (R ′ ===> S ′))
using functional-relation[OF 2 ] functional-converse-relation[OF 1 ]unfolding rel-fun-def OO-defapply clarifyapply (subst all-comm)apply (subst all-conj-distrib[symmetric])apply (intro choice)by metis
end
locale spmf-to-gpv begin
The lifting package cannot handle free term variables in the merging oftransfer rules, so for the embedding we define a specialised relator rel-gpv ′
which acts only on the returned values.
definition rel-gpv ′ :: ( ′a ⇒ ′b ⇒ bool) ⇒ ( ′a, ′out , ′in) gpv ⇒ ( ′b, ′out , ′in) gpv⇒ boolwhere rel-gpv ′ A = rel-gpv A op =
lemma rel-gpv ′-eq [relator-eq ]: rel-gpv ′ op = = op =unfolding rel-gpv ′-def gpv .rel-eq ..
lemma rel-gpv ′-mono [relator-mono]: A ≤ B =⇒ rel-gpv ′ A ≤ rel-gpv ′ Bunfolding rel-gpv ′-def by(rule gpv .rel-mono; simp)
lemma rel-gpv ′-distr [relator-distr ]: rel-gpv ′ A OO rel-gpv ′ B = rel-gpv ′ (A OOB)unfolding rel-gpv ′-def by (metis OO-eq gpv .rel-compp)
lemma left-unique-rel-gpv ′ [transfer-rule]: left-unique A =⇒ left-unique (rel-gpv ′
A)unfolding rel-gpv ′-def by(simp add : left-unique-rel-gpv left-unique-eq)
lemma right-unique-rel-gpv ′ [transfer-rule]: right-unique A =⇒ right-unique (rel-gpv ′
A)unfolding rel-gpv ′-def by(simp add : right-unique-rel-gpv right-unique-eq)
lemma bi-unique-rel-gpv ′ [transfer-rule]: bi-unique A =⇒ bi-unique (rel-gpv ′ A)unfolding rel-gpv ′-def by(simp add : bi-unique-rel-gpv bi-unique-eq)
172
lemma left-total-rel-gpv ′ [transfer-rule]: left-total A =⇒ left-total (rel-gpv ′ A)unfolding rel-gpv ′-def by(simp add : left-total-rel-gpv left-total-eq)
lemma right-total-rel-gpv ′ [transfer-rule]: right-total A =⇒ right-total (rel-gpv ′ A)unfolding rel-gpv ′-def by(simp add : right-total-rel-gpv right-total-eq)
lemma bi-total-rel-gpv ′ [transfer-rule]: bi-total A =⇒ bi-total (rel-gpv ′ A)unfolding rel-gpv ′-def by(simp add : bi-total-rel-gpv bi-total-eq)
We cannot use setup-lifting because ( ′a, ′out , ′in) gpv contains type variableswhich do not appear in ′a spmf.
definition cr-spmf-gpv :: ′a spmf ⇒ ( ′a, ′out , ′in) gpv ⇒ boolwhere cr-spmf-gpv p gpv ←→ gpv = lift-spmf p
definition spmf-of-gpv :: ( ′a, ′out , ′in) gpv ⇒ ′a spmfwhere spmf-of-gpv gpv = (THE p. gpv = lift-spmf p)
lemma spmf-of-gpv-lift-spmf [simp]: spmf-of-gpv (lift-spmf p) = punfolding spmf-of-gpv-def by auto
lemma rel-spmf-setD2 :[[ rel-spmf A p q ; y ∈ set-spmf q ]] =⇒ ∃ x∈set-spmf p. A x y
by(erule rel-spmfE ) force
lemma rel-gpv-lift-spmf1 : rel-gpv A B (lift-spmf p) gpv ←→ (∃ q . gpv = lift-spmfq ∧ rel-spmf A p q)apply(subst gpv .rel-sel)apply(simp add : spmf-rel-map rel-generat-Pure1 )apply safeapply(rule exI [where x=map-spmf result (the-gpv gpv)])apply(clarsimp simp add : spmf-rel-map)apply(rule conjI )apply(rule gpv .expand)apply(simp add : spmf .map-comp)apply(subst map-spmf-cong [OF refl , where g=id ])apply(drule (1 ) rel-spmf-setD2 )apply clarsimp
apply simpapply(erule rel-spmf-mono)apply clarsimp
apply(clarsimp simp add : spmf-rel-map)done
lemma rel-gpv-lift-spmf2 : rel-gpv A B gpv (lift-spmf q) ←→ (∃ p. gpv = lift-spmfp ∧ rel-spmf A p q)by(subst gpv .rel-flip[symmetric])(simp add : rel-gpv-lift-spmf1 pmf .rel-flip option.rel-conversep)
definition pcr-spmf-gpv :: ( ′a ⇒ ′b ⇒ bool) ⇒ ′a spmf ⇒ ( ′b, ′out , ′in) gpv ⇒bool
173
where pcr-spmf-gpv A = cr-spmf-gpv OO rel-gpv A op =
lemma pcr-cr-eq-spmf-gpv : pcr-spmf-gpv op = = cr-spmf-gpvby(simp add : pcr-spmf-gpv-def gpv .rel-eq OO-eq)
lemma left-unique-cr-spmf-gpv : left-unique cr-spmf-gpvby(rule left-uniqueI )(simp add : cr-spmf-gpv-def )
lemma left-unique-pcr-spmf-gpv [transfer-rule]:left-unique A =⇒ left-unique (pcr-spmf-gpv A)
unfolding pcr-spmf-gpv-def by(intro left-unique-OO left-unique-cr-spmf-gpv left-unique-rel-gpvleft-unique-eq)
lemma right-unique-cr-spmf-gpv : right-unique cr-spmf-gpvby(rule right-uniqueI )(simp add : cr-spmf-gpv-def )
lemma right-unique-pcr-spmf-gpv [transfer-rule]:right-unique A =⇒ right-unique (pcr-spmf-gpv A)
unfolding pcr-spmf-gpv-def by(intro right-unique-OO right-unique-cr-spmf-gpv right-unique-rel-gpvright-unique-eq)
lemma bi-unique-cr-spmf-gpv : bi-unique cr-spmf-gpvby(simp add : bi-unique-alt-def left-unique-cr-spmf-gpv right-unique-cr-spmf-gpv)
lemma bi-unique-pcr-spmf-gpv [transfer-rule]: bi-unique A =⇒ bi-unique (pcr-spmf-gpvA)by(simp add : bi-unique-alt-def left-unique-pcr-spmf-gpv right-unique-pcr-spmf-gpv)
lemma left-total-cr-spmf-gpv : left-total cr-spmf-gpvby(rule left-totalI )(simp add : cr-spmf-gpv-def )
lemma left-total-pcr-spmf-gpv [transfer-rule]: left-total A ==> left-total (pcr-spmf-gpvA)unfolding pcr-spmf-gpv-def by(intro left-total-OO left-total-cr-spmf-gpv left-total-rel-gpvleft-total-eq)
interpretation lifting-syntax .
lemma return-spmf-gpv-transfer ′:(op = ===> cr-spmf-gpv) return-spmf Done
by(rule rel-funI )(simp add : cr-spmf-gpv-def )
lemma return-spmf-gpv-transfer [transfer-rule]:(A ===> pcr-spmf-gpv A) return-spmf Done
unfolding pcr-spmf-gpv-defapply(rewrite in (◊ ===> -) - - eq-OO [symmetric])apply(rule pos-fun-distr [THEN le-funD , THEN le-funD , THEN le-boolD , THENmp])apply(rule relcomppI )
174
apply(rule return-spmf-gpv-transfer ′)apply transfer-proverdone
lemma bind-spmf-gpv-transfer ′:(cr-spmf-gpv ===> (op = ===> cr-spmf-gpv) ===> cr-spmf-gpv) bind-spmf
bind-gpvapply(clarsimp simp add : rel-fun-def cr-spmf-gpv-def )apply(rule gpv .expand)apply(simp add : bind-map-spmf map-spmf-bind-spmf o-def )done
lemma bind-spmf-gpv-transfer [transfer-rule]:(pcr-spmf-gpv A ===> (A ===> pcr-spmf-gpv B) ===> pcr-spmf-gpv B)
bind-spmf bind-gpvunfolding pcr-spmf-gpv-defapply(rewrite in (- ===> (◊ ===> -) ===> -) - - eq-OO [symmetric])apply(rule fun-mono[THEN le-funD , THEN le-funD , THEN le-boolD , THEN mp])
apply(rule order .refl)apply(rule fun-mono)apply(rule neg-fun-distr3 [OF left-unique-eq right-total-eq right-unique-cr-spmf-gpv
left-total-cr-spmf-gpv ])apply(rule order .refl)
apply(rule fun-mono[THEN le-funD , THEN le-funD , THEN le-boolD , THEN mp])apply(rule order .refl)
apply(rule pos-fun-distr)apply(rule pos-fun-distr [THEN le-funD , THEN le-funD , THEN le-boolD , THENmp])apply(rule relcomppI )apply(rule bind-spmf-gpv-transfer ′)
apply transfer-proverdone
lemma lift-spmf-gpv-transfer ′:(op = ===> cr-spmf-gpv) (λx . x ) lift-spmf
by(simp add : rel-fun-def cr-spmf-gpv-def )
lemma lift-spmf-gpv-transfer [transfer-rule]:(rel-spmf A ===> pcr-spmf-gpv A) (λx . x ) lift-spmf
unfolding pcr-spmf-gpv-defapply(rewrite in (◊ ===> -) - - eq-OO [symmetric])apply(rule pos-fun-distr [THEN le-funD , THEN le-funD , THEN le-boolD , THENmp])apply(rule relcomppI )apply(rule lift-spmf-gpv-transfer ′)
apply transfer-proverdone
lemma fail-spmf-gpv-transfer ′: cr-spmf-gpv (return-pmf None) Fail
175
by(simp add : cr-spmf-gpv-def )
lemma fail-spmf-gpv-transfer [transfer-rule]: pcr-spmf-gpv A (return-pmf None)Failunfolding pcr-spmf-gpv-defapply(rule relcomppI )apply(rule fail-spmf-gpv-transfer ′)
apply transfer-proverdone
lemma map-spmf-gpv-transfer ′:(op = ===> R ===> cr-spmf-gpv ===> cr-spmf-gpv) (λf g . map-spmf f )
map-gpvby(simp add : rel-fun-def cr-spmf-gpv-def map-lift-spmf )
lemma map-spmf-gpv-transfer [transfer-rule]:((A ===> B) ===> R ===> pcr-spmf-gpv A ===> pcr-spmf-gpv B) (λf g .
map-spmf f ) map-gpvunfolding pcr-spmf-gpv-defapply(rewrite in ((◊ ===> -) ===> -) - - eq-OO [symmetric])apply(rewrite in ((- ===> ◊) ===> -) - - eq-OO [symmetric])apply(rewrite in (- ===> ◊ ===> -) - - OO-eq [symmetric])apply(rule fun-mono[THEN le-funD , THEN le-funD , THEN le-boolD , THEN mp])apply(rule neg-fun-distr3 [OF left-unique-eq right-total-eq right-unique-eq left-total-eq ])apply(rule fun-mono[OF order .refl ])apply(rule pos-fun-distr)
apply(rule fun-mono[THEN le-funD , THEN le-funD , THEN le-boolD , THEN mp])apply(rule order .refl)
apply(rule pos-fun-distr)apply(rule pos-fun-distr [THEN le-funD , THEN le-funD , THEN le-boolD , THENmp])apply(rule relcomppI )apply(unfold rel-fun-eq)apply(rule map-spmf-gpv-transfer ′)
apply(unfold rel-fun-eq [symmetric])apply transfer-proverdone
end
7.5 Embedding ′a option as a monad
locale option-to-gpv begin
interpretation option-to-spmf .interpretation spmf-to-gpv .
definition cr-option-gpv :: ′a option ⇒ ( ′a, ′out , ′in) gpv ⇒ boolwhere cr-option-gpv x gpv ←→ gpv = (lift-spmf return-pmf ) x
176
lemma cr-option-gpv-conv-OO :cr-option-gpv = cr-option-spmf −1−1 OO cr-spmf-gpv
by(simp add : fun-eq-iff relcompp.simps cr-option-gpv-def cr-spmf-gpv-def cr-option-spmf-def )
interpretation lifting-syntax .
These transfer rules should follow from merging the transfer rules, but thishas not yet been implemented.
lemma return-option-gpv-transfer [transfer-rule]:(op = ===> cr-option-gpv) Some Done
by(simp add : cr-option-gpv-def rel-fun-def )
lemma bind-option-gpv-transfer [transfer-rule]:(cr-option-gpv ===> (op = ===> cr-option-gpv) ===> cr-option-gpv) Op-
tion.bind bind-gpvapply(clarsimp simp add : cr-option-gpv-def rel-fun-def )subgoal for x f g by(cases x ; simp)done
lemma fail-option-gpv-transfer [transfer-rule]: cr-option-gpv None Failby(simp add : cr-option-gpv-def )
lemma map-option-gpv-transfer [transfer-rule]:(op = ===> R ===> cr-option-gpv ===> cr-option-gpv) (λf g . map-option
f ) map-gpvunfolding rel-fun-eq by(simp add : rel-fun-def cr-option-gpv-def map-lift-spmf )
end
locale option-le-gpv begin
interpretation option-le-spmf .interpretation spmf-to-gpv .
definition cr-option-le-gpv :: ′a option ⇒ ( ′a, ′out , ′in) gpv ⇒ boolwhere cr-option-le-gpv x gpv ←→ gpv = (lift-spmf return-pmf ) x ∨ x = None
interpretation lifting-syntax .
lemma return-option-le-gpv-transfer [transfer-rule]:(op = ===> cr-option-le-gpv) Some Done
by(simp add : cr-option-le-gpv-def rel-fun-def )
lemma bind-option-gpv-transfer [transfer-rule]:(cr-option-le-gpv ===> (op = ===> cr-option-le-gpv) ===> cr-option-le-gpv)
Option.bind bind-gpvapply(clarsimp simp add : cr-option-le-gpv-def rel-fun-def bind-eq-Some-conv)
177
subgoal for f g x y by(erule allE [where x=y ]) autodone
lemma fail-option-gpv-transfer [transfer-rule]:cr-option-le-gpv None Fail
by(simp add : cr-option-le-gpv-def )
lemma map-option-gpv-transfer [transfer-rule]:((op = ===> op =) ===> cr-option-le-gpv ===> cr-option-le-gpv) map-option
(λf . map-gpv f id)unfolding rel-fun-eq by(simp add : rel-fun-def cr-option-le-gpv-def map-lift-spmf )
end
7.6 Embedding resumptions
primcorec lift-resumption :: ( ′a, ′out , ′in) resumption ⇒ ( ′a, ′out , ′in) gpvwhere
the-gpv (lift-resumption r) =(case r of resumption.Done None ⇒ return-pmf None| resumption.Done (Some x ′) => return-spmf (Pure x ′)| resumption.Pause out c => map-spmf (map-generat id id (op lift-resumption))
(return-spmf (IO out c)))
lemma the-gpv-lift-resumption:the-gpv (lift-resumption r) =(if is-Done r then if Option.is-none (resumption.result r) then return-pmf None
else return-spmf (Pure (the (resumption.result r)))else return-spmf (IO (resumption.output r) (lift-resumption resume r)))
by(simp split : option.split resumption.split)
declare lift-resumption.simps [simp del ]
lemma lift-resumption-Done [code]:lift-resumption (resumption.Done x ) = (case x of None ⇒ Fail | Some x ′ ⇒
Done x ′)by(rule gpv .expand)(simp add : the-gpv-lift-resumption split : option.split)
lemma lift-resumption-DONE [simp]:lift-resumption (DONE x ) = Done x
by(simp add : DONE-def lift-resumption-Done)
lemma lift-resumption-ABORT [simp]:lift-resumption ABORT = Fail
by(simp add : ABORT-def lift-resumption-Done)
lemma lift-resumption-Pause [simp, code]:lift-resumption (resumption.Pause out c) = Pause out (lift-resumption c)
by(rule gpv .expand)(simp add : the-gpv-lift-resumption)
178
7.7 Assertions
definition assert-gpv :: bool ⇒ (unit , ′out , ′in) gpvwhere assert-gpv b = (if b then Done () else Fail)
lemma assert-gpv-simps [simp]:assert-gpv True = Done ()assert-gpv False = Fail
by(simp-all add : assert-gpv-def )
lemma [simp]:shows assert-gpv-eq-Done: assert-gpv b = Done x ←→ band Done-eq-assert-gpv : Done x = assert-gpv b ←→ band Pause-neq-assert-gpv : Pause out rpv 6= assert-gpv band assert-gpv-neq-Pause: assert-gpv b 6= Pause out rpvand assert-gpv-eq-Fail : assert-gpv b = Fail ←→ ¬ band Fail-eq-assert-gpv : Fail = assert-gpv b ←→ ¬ b
by(simp-all add : assert-gpv-def )
lemma assert-gpv-inject [simp]: assert-gpv b = assert-gpv b ′←→ b = b ′
by(simp add : assert-gpv-def )
lemma assert-gpv-sel [simp]:the-gpv (assert-gpv b) = map-spmf Pure (assert-spmf b)
by(simp add : assert-gpv-def )
lemma the-gpv-bind-assert [simp]:the-gpv (bind-gpv (assert-gpv b) f ) =bind-spmf (assert-spmf b) (the-gpv f )
by(cases b) simp-all
primcorec try-gpv :: ( ′a, ′call , ′ret) gpv ⇒ ( ′a, ′call , ′ret) gpv ⇒ ( ′a, ′call , ′ret)gpv (TRY - ELSE - [0 ,60 ] 59 )where
the-gpv (TRY gpv ELSE gpv ′) =map-spmf (map-generat id id (λc input . case c input of Inl gpv ⇒ try-gpv gpv
gpv ′ | Inr gpv ′⇒ gpv ′))(try-spmf (map-spmf (map-generat id id (map-fun id Inl)) (the-gpv gpv))
(map-spmf (map-generat id id (map-fun id Inr)) (the-gpv gpv ′)))
lemma try-gpv-sel :the-gpv (TRY gpv ELSE gpv ′) =TRY map-spmf (map-generat id id (λc input . TRY c input ELSE gpv ′)) (the-gpv
gpv) ELSE the-gpv gpv ′
by(simp add : try-gpv-def map-try-spmf spmf .map-comp o-def generat .map-compgenerat .map-ident id-def )
lemma try-gpv-Done [simp]: TRY Done x ELSE gpv ′ = Done xby(rule gpv .expand)(simp)
179
lemma try-gpv-Fail [simp]: TRY Fail ELSE gpv ′ = gpv ′
by(rule gpv .expand)(simp add : spmf .map-comp o-def generat .map-comp generat .map-ident)
lemma try-gpv-Pause [simp]: TRY Pause out c ELSE gpv ′ = Pause out (λinput .TRY c input ELSE gpv ′)by(rule gpv .expand) simp
lemma try-gpv-Fail2 [simp]: TRY gpv ELSE Fail = gpvby(coinduction arbitrary : gpv rule: gpv .coinduct-strong)(auto simp add : spmf-rel-map generat .rel-map intro!: rel-spmf-reflI generat .rel-refl)
lemma lift-try-spmf : lift-spmf (TRY p ELSE q) = TRY lift-spmf p ELSE lift-spmfqby(rule gpv .expand)(simp add : map-try-spmf spmf .map-comp o-def )
lemma try-assert-gpv : TRY assert-gpv b ELSE gpv ′= (if b then Done () else gpv ′)by(simp)
context begin interpretation lifting-syntax .lemma try-gpv-parametric [transfer-rule]:
(rel-gpv A C ===> rel-gpv A C ===> rel-gpv A C ) try-gpv try-gpvunfolding try-gpv-def by transfer-proverend
lemma map-try-gpv : map-gpv f g (TRY gpv ELSE gpv ′) = TRY map-gpv f g gpvELSE map-gpv f g gpv ′
by(simp add : gpv .rel-map try-gpv-parametric[THEN rel-funD , THEN rel-funD ]gpv .rel-refl gpv .rel-eq [symmetric])
lemma try-bind-assert-gpv :TRY (assert-gpv b >>= f ) ELSE gpv = (if b then TRY (f ()) ELSE gpv else gpv)
by(simp)
7.8 Executing gpv: possibilistic trace semantics
type-synonym ( ′a, ′out , ′in) raw-trace = (( ′out , ′in) event , ′a option) tllist
context IO-execution-base begin
— Work around the limitation that inductive set does not support instantiatedparameterscoinductive tracesp-gpv :: ( ′a, ′out , ′in) gpv ⇒ ( ′a, ′out , ′in) raw-trace ⇒ boolwhere
Fail : None ∈ set-pmf (the-gpv r) =⇒ tracesp-gpv r (TNil None)| Pure: Pure x ∈ set-spmf (the-gpv r) =⇒ tracesp-gpv r (TNil (Some x ))| IO :
[[ IO out c ∈ set-spmf (the-gpv r); input ∈ wf-response out ; tracesp-gpv (c input)tr ]]
=⇒ tracesp-gpv r (TCons (Event out input) tr)
180
definition traces-gpv :: ( ′a, ′out , ′in) gpv ⇒ ( ′a, ′out , ′in) raw-trace setwhere traces-gpv r ≡ tr . tracesp-gpv r trlemma tracesp-gpv-traces-gpv-eq [pred-set-conv ]: tracesp-gpv r = (λtr . tr ∈ traces-gpvr) by(simp add : traces-gpv-def )context beginlocal-setup 〈〈 Local-Theory .map-background-naming (Name-Space.mandatory-pathtraces-gpv) 〉〉
lemmas intros [intro? ] = tracesp-gpv .intros[to-set ]and coinduct [consumes 1 , case-names Fail Pure IO , coinduct set : traces-gpv ] =
tracesp-gpv .coinduct [to-set ]and cases [consumes 1 , case-names Fail Pure IO , cases set : traces-gpv ] = tracesp-gpv .cases[to-set ]and simps = tracesp-gpv .simps[to-set ]
endlemmas traces-gpv-intros [intro? ] = tracesp-gpv .intros[to-set ]and traces-gpv-cases [consumes 1 , case-names Fail Pure IO , cases set : traces-gpv ]
= tracesp-gpv .cases[to-set ]and traces-gpv-simps = tracesp-gpv .simps[to-set ]
inductive-simps TNil-None-in-traces-gpv [to-set , simp]: tracesp-gpv r (TNil None)inductive-simps TNil-Some-in-traces-gpv [to-set , simp]: tracesp-gpv r (TNil (Somex ))inductive-simps TCons-in-traces-gpv [to-set , simp]: tracesp-gpv r (TCons (Eventout input) tr)
lemma traces-gpv-coinduct [consumes 1 , case-names Fail Pure IO , case-conclusionIO wf-response ttl , coinduct set : traces-gpv ]:
assumes X r trand Fail :
∧r tr . [[ X r tr ; tr = TNil None ]] =⇒ None ∈ set-pmf (the-gpv r)
and Pure:∧
r tr x . [[ X r tr ; tr = TNil (Some x ) ]] =⇒ Pure x ∈ set-spmf(the-gpv r)
and IO :∧
r out input tr tr ′. [[ X r tr ; tr = TCons (Event out input) tr ′ ]]=⇒ input ∈ wf-response out ∧ (∃ c. IO out c ∈ set-spmf (the-gpv r) ∧ (X (c
input) tr ′ ∨ tr ′ ∈ traces-gpv (c input)))shows tr ∈ traces-gpv r
using 〈X r tr 〉
proof(coinduct rule: tracesp-gpv .coinduct [to-set ])case (tracesp-gpv r tr)show ?caseproof(cases tr)
case (TNil xo)show ?thesisproof(cases xo)
case Nonehence ?Fail using TNil tracesp-gpv by(simp add : Fail)thus ?thesis ..
nextcase (Some x )
181
hence ?Pure using TNil tracesp-gpv by(simp add : Pure)thus ?thesis by simp
qednext
case (TCons event tr ′)obtain out input where event = Event out input by(cases event)with IO [OF 〈X r tr 〉] TCons tracesp-gpv have ?IO by autothus ?thesis by simp
qedqed
lemma traces-gpv-coinduct ′ [consumes 1 , case-names Fail Pure IO , case-conclusionIO wf-response ttl ]:
assumes X r trand Fail :
∧r tr . [[ X r tr ; is-TNil tr ; Option.is-none (terminal tr) ]] =⇒ None
∈ set-pmf (the-gpv r)and Pure:
∧r tr . [[ X r tr ; is-TNil tr ; ¬ Option.is-none (terminal tr) ]] =⇒ Pure
(the (terminal tr)) ∈ set-spmf (the-gpv r)and IO :
∧r tr . [[ X r tr ; ¬ is-TNil tr ]]
=⇒ event-in (thd tr) ∈ wf-response (event-out (thd tr)) ∧ (∃ c. IO (event-out(thd tr)) c ∈ set-spmf (the-gpv r) ∧ (X (c (event-in (thd tr))) (ttl tr) ∨ ttl tr ∈traces-gpv (c (event-in (thd tr)))))
shows tr ∈ traces-gpv rusing 〈X r tr 〉
apply(coinduct)apply(drule Fail , simp, simp, simp)
apply(drule Pure, simp, simp, simp)apply(drule IO , simp, simp)done
lemma traces-gpv-cases ′:assumes tr ∈ traces-gpv robtains (Fail) is-TNil tr Option.is-none (terminal tr) None ∈ set-pmf (the-gpv
r)| (Pure) is-TNil tr ¬ Option.is-none (terminal tr) Pure (the (terminal tr)) ∈
set-spmf (the-gpv r)| (IO) out c where ¬ is-TNil tr out = event-out (thd tr) IO out c ∈ set-spmf
(the-gpv r)event-in (thd tr) ∈ wf-response out ttl tr ∈ traces-gpv (c (event-in (thd tr)))
using assms by cases auto
lemma traces-gpv-unfold :traces-gpv r =(if None ∈ set-pmf (the-gpv r) then TNil None else ) ∪(⋃
x . if Pure x ∈ set-spmf (the-gpv r) then TNil (Some x ) else ) ∪(⋃
out c. if IO out c ∈ set-spmf (the-gpv r) then (⋃
input ∈ wf-response out .TCons (Event out input) ‘ traces-gpv (c input)) else )by(rule set-eqI )(subst tracesp-gpv .simps[to-set ], force)
182
lemma traces-gpv-Done [simp]: traces-gpv (Done x ) = TNil (Some x )by(auto simp add : traces-gpv-unfold split : split-if-asm)
lemma traces-gpv-Pause [simp]:traces-gpv (Pause out c) = (do input ← wf-response out ; TCons (Event out
input) ‘ traces-gpv (c input))by(subst traces-gpv-unfold)(auto simp add : bind-singleton-conv-image split : split-if-asm)
lemma traces-gpv-Fail [simp]: traces-gpv Fail = TNil Noneby(simp add : traces-gpv-unfold)
lemma traces-gpv-lift-spmf [simp]: traces-gpv (lift-spmf p) = TNil ‘ set-pmf papply(subst traces-gpv-unfold)apply(auto 0 0 simp add : in-set-spmf split : split-if-asm)apply(fastforce simp add : in-set-spmf )
apply(case-tac xa)apply(auto simp add : in-set-spmf )done
lemma traces-gpv-bind-gpv :traces-gpv (r >>= f ) =
traces-gpv r >>= timage (λx . case x of None ⇒ TNil None | Some a ⇒traces-gpv (f a))
(is - = - >>= timage ?g)proof(rule set-eqI iffI )+
fix trassume tr ∈ traces-gpv r >>= timage ?gthen obtain tr ′ where tr ′ ∈ traces-gpv r tr ∈ timage ?g tr ′
unfolding bind-UNION by autothen show tr ∈ traces-gpv (r >>= f )proof(coinduction arbitrary : tr tr ′ r rule: traces-gpv-coinduct)
case (Fail tr tr ′ r)then show ?case
by cases(auto simp add : set-pmf-bind-spmf in-set-spmf intro: rev-bexI )next
case (Pure x tr tr ′ r)thus ?case by cases(auto simp add : set-bind-spmf intro: rev-bexI )
nextcase (IO out input tr ′′ tr tr ′ r)thus ?case by cases(auto 4 3 simp add : set-bind-spmf intro: rev-bexI )
qednext
fix trassume tr : tr ∈ traces-gpv (r >>= f )
construct corresponding trace in traces-gpv r
def t ′ ≡ λ(tr :: ( ′a, ′out , ′in) raw-trace) (r :: ( ′b, ′out , ′in) gpv). unfold-tllist(λ(tr , r). (∃ x∈set-spmf (the-gpv r). is-Pure x ∧ tr ∈ traces-gpv (f (result
x ))) ∨ is-TNil tr)
183
(λ(tr , r). if ∃ x∈set-spmf (the-gpv r). is-Pure x ∧ tr ∈ traces-gpv (f (resultx )) then
Some (result (SOME x . x ∈ set-spmf (the-gpv r) ∧ is-Pure x ∧ tr∈ traces-gpv (f (result x )))) else None)
(λ(tr , r). thd tr)(λ(tr , r). (ttl tr , (SOME c. IO (event-out (thd tr)) c ∈ set-spmf (the-gpv r)
∧ttl tr ∈ traces-gpv (c (event-in (thd tr)) >>= f ))
(event-in (thd tr))))(tr , r)
hence [simp]:∧tr r . is-TNil (t ′ tr r) ←→ (∃ x∈set-spmf (the-gpv r). is-Pure x ∧ tr ∈
traces-gpv (f (result x ))) ∨ is-TNil tr∧tr r . is-TNil (t ′ tr r)
=⇒ terminal (t ′ tr r) = (if ∃ x∈set-spmf (the-gpv r). is-Pure x ∧ tr ∈ traces-gpv(f (result x )) then
Some (result (SOME x . x ∈ set-spmf (the-gpv r) ∧ is-Pure x ∧tr ∈ traces-gpv (f (result x )))) else None)∧
tr r . [[ is-TNil tr ; ∀ x . Pure x ∈ set-spmf (the-gpv r) −→ tr /∈ traces-gpv (fx ) ]]
=⇒ terminal (t ′ tr r) = None∧tr r . ¬ is-TNil (t ′ tr r) =⇒ thd (t ′ tr r) = thd tr∧tr r . ¬ is-TNil (t ′ tr r)
=⇒ ttl (t ′ tr r) = t ′ (ttl tr) ((SOME c. IO (event-out (thd tr)) c ∈ set-spmf(the-gpv r) ∧
ttl tr ∈ traces-gpv (c (event-in (thd tr)) >>=f )) (event-in (thd tr)))
by(simp-all)have t ′-TCons:
∧out input tr ′ r .
t ′ (TCons (Event out input) tr ′) r =(if ∃ x∈set-spmf (the-gpv r). is-Pure x ∧ TCons (Event out input) tr ′ ∈
traces-gpv (f (result x ))then TNil (Some (result (SOME x . x ∈ set-spmf (the-gpv r) ∧ is-Pure x ∧
TCons (Event out input) tr ′ ∈ traces-gpv (f (result x )))))else TCons (Event out input) (t ′ tr ′ ((SOME c. IO out c ∈ set-spmf (the-gpv
r) ∧ tr ′ ∈ traces-gpv (c input >>= f )) input)))by(rule tllist .expand)(auto split : split-if-asm)
have t ′ tr r ∈ traces-gpv r using trproof(coinduction arbitrary : tr r rule: traces-gpv-coinduct ′)
case (Fail tr r)thus ?case using Fail
apply(cases tr rule: tllist .exhaust)apply(clarsimp split : split-if-asm)apply(erule traces-gpv-cases ′)
apply(auto simp add : set-pmf-bind-spmf set-bind-spmf None-in-map-option-setOption.is-none-def in-set-spmf [symmetric] split : split-if-asm)[3 ]
apply(simp split : split-if-asm)done
184
nextcase (Pure tr r)let ?P = λx . x ∈ set-spmf (the-gpv r) ∧ is-Pure x ∧ tr ∈ traces-gpv (f
(generat .result x ))from Pure obtain x where ?P x by(clarsimp split : split-if-asm)hence ?P (Eps ?P) by(rule someI )thus ?case using Pure by(clarsimp split : split-if-asm)
nextcase (IO tr r)then obtain input out tr ′ c
where tr : tr = TCons (Event out input) tr ′
and input : input ∈ wf-response outand c: IO out c ∈ set-spmf (the-gpv r) tr ′ ∈ traces-gpv (c input >>= f )
by cases(auto simp add : bind-gpv-sel set-bind-spmf split : simp del : bind-gpv-sel ′,simp split : generat .split-asm)
let ?P = λc. IO out c ∈ set-spmf (the-gpv r) ∧ tr ′ ∈ traces-gpv (c input >>=f )
from c have ?P c ..hence ?P (Eps ?P) by(rule someI [where P=?P ])thus ?case using IO tr input by auto
qedmoreoverhave tr ∈ timage ?g (t ′ tr r)proof(cases tfinite (t ′ tr r))
case Truelet ?n = tlength (t ′ tr r)
have eq : tr = lappendt (ltake (enat (the-enat ?n)) (llist-of-tllist tr)) (tdropn(the-enat ?n) tr)
by(simp add : lappendt-ltake-tdropn)
have enat (the-enat ?n) = ?nusing True by(simp-all del : not-infinity-eq add : tlength-eq-infinity-iff enat-the-enat)moreover from True trhave ltake ?n (llist-of-tllist tr) = llist-of-tllist (t ′ tr r)
and tdropn (the-enat ?n) tr ∈ ?g (terminal (t ′ tr r))proof(induct ys≡llist-of-tllist (t ′ tr r) arbitrary : tr r rule: lfinite-induct)
case (LNil tr r)hence [simp]: tlength (t ′ tr r) = 0 by(simp add : tlength-eq-0-iff )
case 1show ?case using LNilby(auto 4 3 simp add : zero-enat-def [symmetric] llist-of-tllist-eq-LNil intro:
sym)next
case 2thus ?caseproof cases
case (Fail r ′)
185
thus ?thesis using LNilby(fastforce simp add : set-pmf-bind-spmf None-in-map-option-set intro:
someI2 split : split-if-asm)next
case (Pure x r ′)thus ?thesis using LNil
by(auto simp add : set-bind-spmf split : split-if-asm)(fastforce intro:someI2 )
nextcase (IO out c r ′ input tr ′)thus ?thesis using LNil
apply(clarsimp simp add : lnull-def llist-of-tllist-eq-LNil [unfolded is-TNil-def ]set-bind-spmf split : split-if-asm option.split)
apply(clarsimp simp add : t ′-TCons split : split-if-asm)apply(rule someI2 )apply fastforce+done
qed
nextcase (LCons tr r)assume t : tr ∈ traces-gpv (r >>= f )with LCons(2 )
have not-Pure:∧
x . [[ x ∈ set-spmf (the-gpv r); is-Pure x ]] =⇒ tr /∈ traces-gpv(f (generat .result x ))
and ¬ is-TNil tr by simp-allthen obtain out input tr ′ where tr ′: tr = TCons (Event out input) tr ′
by(cases thd tr)(auto simp add : tllist .disc-eq-case split : tllist .split-asm)let ?P = λc. IO out c ∈ set-spmf (the-gpv r) ∧ tr ′ ∈ traces-gpv (c input >>=
f )let ?c = Eps ?Pfrom t tr ′ not-Pure obtain c where ?P c input ∈ wf-response out
by cases(auto simp add : set-bind-spmf bind-gpv-sel simp del : bind-gpv-sel ′,simp split : generat .split-asm)
from 〈?P c〉 have c: ?P ?c by(rule someI [where P=?P ])
from LCons(1 ) tr ′ not-Pure have fin: tfinite (t ′ tr ′ (?c input))by(auto simp add : t ′-TCons split : split-if-asm)
case 1show ?case using tr ′ not-Pure c
by(simp add : t ′-TCons)(simp add : LCons(3 ))next
case 2show ?case using tr ′ not-Pure c finby(simp add : t ′-TCons)(auto simp del : not-infinity-eq simp add : tlength-eq-infinity-iff
the-enat-eSuc LCons(4 ))
qed
186
ultimately show ?thesis using Trueby(subst eq)(simp add : timage-tfiniteI )
nextcase Falsewith tr have tr = tcast (t ′ tr r)proof(coinduction arbitrary : tr r)
case Eq-tllistthus ?case
apply casesapply(auto simp add : set-bind-spmf bind-gpv-sel t ′-TCons simp del : bind-gpv-sel ′
split : split-if-asm)apply(auto simp add : split : generat .split-asm intro: someI2 [where P=λc.
IO out c ∈ set-spmf (the-gpv r) ∧ tr ∈ traces-gpv (c input >>= f ) for out inputtr ])
doneqedthus ?thesis using False by(simp)
qedultimately show tr ∈ traces-gpv r >>= timage ?g unfolding bind-UNION ..
qed
lemma traces-gpv-lift-resumption [simp]:traces-gpv (lift-resumption r) = resumption-traces r(is ?lhs = ?rhs)
proof(rule set-eqI iffI )+fix tassume t : t ∈ ?lhsthus t ∈ resumption-traces rproof(coinduction arbitrary : t r)
case Done thus ?caseby cases(auto simp add : Option.is-none-def the-gpv-lift-resumption split :
split-if-asm)next
case (Pause t r)thus ?case by(cases r) auto
qednext
fix tassume t ∈ ?rhsthus t ∈ ?lhsproof(coinduction arbitrary : t r)
case Fail thus ?caseby cases(auto simp add : the-gpv-lift-resumption)
nextcase (Pure t r)thus ?case by(cases)(auto simp add : the-gpv-lift-resumption Option.is-none-def
intro: sym)next
case (IO t r)
187
thus ?case by(cases)(auto simp add : the-gpv-lift-resumption)qed
qed
end
lemma traces-gpv-refinement :assumes
∧out . wf-response1 out ⊆ wf-response2 out
shows IO-execution-base.traces-gpv wf-response1 r ⊆ IO-execution-base.traces-gpvwf-response2 rproof
interpret rb1 : IO-execution-base wf-response1 .interpret rb2 : IO-execution-base wf-response2 .
fix tassume t ∈ rb1 .traces-gpv rthus t ∈ rb2 .traces-gpv r
by coinduct(insert assms, auto)qed
7.9 Order for ( ′a, ′out , ′in) gpv
coinductive ord-gpv :: ( ′a, ′out , ′in) gpv ⇒ ( ′a, ′out , ′in) gpv ⇒ boolwhere
ord-spmf (rel-generat op = op = (rel-fun op = ord-gpv)) f g =⇒ ord-gpv (GPVf ) (GPV g)
inductive-simps ord-gpv-simps [simp]:ord-gpv (GPV f ) (GPV g)
lemma ord-gpv-coinduct [consumes 1 , case-names ord-gpv , coinduct pred : ord-gpv ]:assumes X f gand step:
∧f g . X f g =⇒ ord-spmf (rel-generat op = op = (rel-fun op = X ))
(the-gpv f ) (the-gpv g)shows ord-gpv f g
using 〈X f g〉
by(coinduct)(auto dest : step simp add : eq-GPV-iff intro: ord-spmf-mono rel-generat-monorel-fun-mono)
lemma ord-gpv-the-gpvD :ord-gpv f g =⇒ ord-spmf (rel-generat op = op = (rel-fun op = ord-gpv)) (the-gpv
f ) (the-gpv g)by(erule ord-gpv .cases) simp
lemma reflp-equality : reflp op =by(simp add : reflp-def )
lemma ord-gpv-reflI [simp]: ord-gpv f fby(coinduction arbitrary : f )(auto intro: ord-spmf-reflI simp add : rel-generat-same
188
rel-fun-def )
lemma reflp-ord-gpv : reflp ord-gpvby(rule reflpI )(rule ord-gpv-reflI )
lemma ord-gpv-trans:assumes ord-gpv f g ord-gpv g hshows ord-gpv f h
using assmsproof(coinduction arbitrary : f g h)
case (ord-gpv f g h)have ∗: ord-spmf (rel-generat op = op = (rel-fun op = (λf h. ∃ g . ord-gpv f g ∧
ord-gpv g h))) (the-gpv f ) (the-gpv h) =ord-spmf (rel-generat (op = OO op =) (op = OO op =) (rel-fun op = (ord-gpv
OO ord-gpv))) (the-gpv f ) (the-gpv h)by(simp add : relcompp.simps[abs-def ])
then show ?case using ord-gpvby(auto elim!: ord-gpv .cases simp add : generat .rel-compp ord-spmf-compp fun.rel-compp)
qed
lemma ord-gpv-compp: (ord-gpv OO ord-gpv) = ord-gpvby(auto simp add : fun-eq-iff intro: ord-gpv-trans)
lemma transp-ord-gpv [simp]: transp ord-gpvby(blast intro: transpI ord-gpv-trans)
lemma ord-gpv-antisym:[[ ord-gpv f g ; ord-gpv g f ]] =⇒ f = g
proof(coinduction arbitrary : f g)case (Eq-gpv f g)let ?R = rel-generat op = op = (rel-fun op = ord-gpv)from 〈ord-gpv f g〉 have ord-spmf ?R (the-gpv f ) (the-gpv g) by cases simpmoreoverfrom 〈ord-gpv g f 〉 have ord-spmf ?R (the-gpv g) (the-gpv f ) by cases simpultimately have rel-spmf (inf ?R ?R−1−1) (the-gpv f ) (the-gpv g)by(rule rel-spmf-inf )(auto 4 3 intro: transp-rel-generatI transp-ord-gpv reflp-ord-gpv
reflp-equality reflp-fun1 is-equality-eq transp-rel-fun)also have inf ?R ?R−1−1 = rel-generat (inf op = op =) (inf op = op =) (rel-fun
op = (inf ord-gpv ord-gpv−1−1))unfolding rel-generat-inf [symmetric] rel-fun-inf [symmetric]by(simp add : generat .rel-conversep[symmetric] fun.rel-conversep)
finally show ?case by(simp add : inf-fun-def )qed
lemma RFail-least [simp]: ord-gpv Fail fby(coinduction arbitrary : f )(simp add : eq-GPV-iff )
189
7.10 Bounds on interaction
context notes monotone-SUP [partial-function-mono] begindeclaration 〈〈 Partial-Function.init lfp-strong @term lfp.fixp-fun @term lfp.mono-body
@thm lfp.fixp-rule-uc @thm lfp.fixp-strong-induct-uc NONE 〉〉
partial-function (lfp-strong) interaction-bound :: ( ′a, ′out , ′in) gpv ⇒ enatwhere
interaction-bound gpv =(SUP generat :set-spmf (the-gpv gpv). case generat of Pure - ⇒ 0 | IO out c ⇒
eSuc (SUP input . interaction-bound (c input)))end
lemma interaction-bound-fixp-induct [case-names adm bottom step]:[[ ccpo.admissible (fun-lub Sup) (fun-ord op ≤) P ;
P (λ-. 0 );∧interaction-bound ′. [[ P interaction-bound ′;
∧gpv . interaction-bound ′ gpv ≤
interaction-bound gpv ]]=⇒ P (λgpv .
⊔generat∈set-spmf (the-gpv gpv). case generat of Pure x ⇒ 0
| IO out c ⇒ eSuc (⊔
input . interaction-bound ′ (c input))) ]]=⇒ P interaction-bound
by(erule interaction-bound .fixp-induct)(simp-all add : bot-enat-def fun-ord-def )
lemma interaction-bound-coinduct [consumes 1 , case-names interaction-bound ]:assumes X : X gpv nand ∗:
∧gpv n out c input . [[ X gpv n; IO out c ∈ set-spmf (the-gpv gpv) ]]
=⇒ ∃n ′. (X (c input) n ′ ∨ interaction-bound (c input) ≤ n ′) ∧ eSuc n ′ ≤ nshows interaction-bound gpv ≤ n
using Xproof(induction arbitrary : gpv n rule: interaction-bound-fixp-induct)
case adm show ?case by(intro cont-intro)case bottom show ?case by simp
nextcase (step interaction-bound ′) fix out c
assume IO : IO out c ∈ set-spmf (the-gpv gpv)from ∗[OF step.prems IO ] obtain n ′ where n: n = eSuc n ′
by(cases n rule: co.enat .exhaust) automoreover fix input
have ∃n ′′. (X (c input) n ′′ ∨ interaction-bound (c input) ≤ n ′′) ∧ eSuc n ′′
≤ nusing step.prems IO 〈n = eSuc n ′〉 by(auto 4 3 dest : ∗)
then have interaction-bound ′ (c input) ≤ n ′ using nby(auto dest : step.IH intro: step.hyps[THEN order-trans] elim!: order-trans
simp add : neq-zero-conv-eSuc) ultimately have eSuc (
⊔input . interaction-bound ′ (c input)) ≤ n
by(auto intro: SUP-least) then show ?case by(auto intro!: SUP-least split : generat .split)
qed
190
lemma interaction-bound-IO :IO out c ∈ set-spmf (the-gpv gpv)=⇒ eSuc (interaction-bound (c input)) ≤ interaction-bound gpv
by(rewrite in - ≤ ◊ interaction-bound .simps)(auto intro!: SUP-upper2 )
lemma interaction-bound-Done [simp]: interaction-bound (Done x ) = 0by(simp add : interaction-bound .simps)
lemma interaction-bound-Fail [simp]: interaction-bound Fail = 0by(simp add : interaction-bound .simps bot-enat-def )
lemma interaction-bound-Pause [simp]: interaction-bound (Pause out c) = eSuc(SUP input . interaction-bound (c input))by(simp add : interaction-bound .simps)
lemma interaction-bound-lift-spmf [simp]: interaction-bound (lift-spmf p) = 0by(simp add : interaction-bound .simps SUP-constant bot-enat-def )
lemma interaction-bound-assert-gpv [simp]: interaction-bound (assert-gpv b) = 0by(cases b) simp-all
lemma interaction-bound-bind :defines ib1 ≡ interaction-bound and ib2 ≡ interaction-boundshows interaction-bound (p >>= f ) ≤ ib1 p + (SUP x :results ′-gpv p. ib2 (f x ))
proof(induction arbitrary : p rule: interaction-bound-fixp-induct)case adm show ?case by simpcase bottom show ?case by simpcase (step interaction-bound ′) show ?case unfolding ib1-def ib2-defproof(rule SUP-least)
fix generat ′
assume generat ′ ∈ set-spmf (the-gpv (p >>= f ))then obtain generat where generat : generat ∈ set-spmf (the-gpv p)
and ∗: case generat of Pure x ⇒ generat ′ ∈ set-spmf (the-gpv (f x ))| IO out c ⇒ generat ′ = IO out (λinput . c input >>= f )
by(clarsimp simp add : set-bind-spmf bind-gpv .sel simp del : bind-gpv-sel ′)(clarsimp split : generat .split-asm simp add : generat .map-comp o-def gen-
erat .map-id [unfolded id-def ])show (case generat ′ of Pure x ⇒ 0 | IO out c ⇒ eSuc (
⊔input . interaction-bound ′
(c input)))≤ interaction-bound p + (
⊔x∈results ′-gpv p. interaction-bound (f x ))
(is ?lhs ≤ ?p + ?f )proof(cases generat)
case (Pure x )have ?lhs ≤ (case generat ′ of Pure x ⇒ 0 | IO out c ⇒ eSuc (
⊔input .
interaction-bound (c input)))by(cases generat ′)(auto intro: step.hyps SUP-mono)also have . . . ≤ (SUP generat ′:set-spmf (the-gpv (f x )). (case generat ′ of
Pure x ⇒ 0 | IO out c ⇒ eSuc (⊔
input . interaction-bound (c input))))
191
using ∗ Pure by(auto intro: SUP-upper)also have . . . ≤ 0 + ?f using generat Pure
by(rewrite in - ≤ ◊ interaction-bound .simps)(auto 4 3 intro: SUP-upperresults ′-gpv-Pure)
also have . . . ≤ ?p + ?f by simpfinally show ?thesis .
nextcase (IO out c)with ∗ have ?lhs = eSuc (SUP input . interaction-bound ′ (c input >>= f )) by
simpalso have . . . ≤ eSuc (SUP input . interaction-bound (c input) + (SUP
x :results ′-gpv (c input). interaction-bound (f x )))by(auto intro: SUP-mono step.IH [unfolded ib1-def ib2-def ])
also have . . . ≤ (case IO out c of Pure (x :: ′a) ⇒ 0 | IO out c ⇒ eSuc (SUPinput . interaction-bound (c input))) + (SUP input . SUP x :results ′-gpv (c input).interaction-bound (f x ))
by(simp add : iadd-Suc)(metis (mono-tags, lifting) SUP-le-iff add-mono-thms-linordered-semiring(1 )dual-order .refl)
also have . . . ≤ ?p + ?fapply(rewrite in - ≤ ◊ interaction-bound .simps)apply(rule add-mono SUP-least SUP-upper generat [unfolded IO ])+apply(auto intro: results ′-gpv-Cont [OF generat ]simp add : IO)done
finally show ?thesis .qed
qedqed
lemma interaction-bound-bind-lift-spmf [simp]:interaction-bound (lift-spmf p >>= f ) = (SUP x :set-spmf p. interaction-bound (f
x ))by(subst (1 2 ) interaction-bound .simps)(simp add : set-bind-spmf bind-UNION SUP-UNION )
There is no nice interaction-bound equation for op >>=, as it computes anexact bound, but we only need an upper bound. As enat is hard to workwith (and ∞ does not constrain a gpv in any way), we work with nat.
inductive interaction-bounded-by :: ( ′a, ′out , ′in) gpv ⇒ nat ⇒ boolfor gpv n whereinteraction-bounded-by : [[ interaction-bound gpv ≤ enat n ]] =⇒ interaction-bounded-by
gpv n
lemmas interaction-bounded-byI = interaction-bounded-byhide-fact (open) interaction-bounded-by
lemma interaction-bounded-by-mono:[[ interaction-bounded-by gpv n; n ≤ m ]] =⇒ interaction-bounded-by gpv m
unfolding interaction-bounded-by .simps by(erule order-trans) simp
lemma interaction-bounded-by-contD :
192
[[ interaction-bounded-by gpv n; IO out c ∈ set-spmf (the-gpv gpv) ]]=⇒ n > 0 ∧ interaction-bounded-by (c input) (n − 1 )
unfolding interaction-bounded-by .simpsby(subst (asm) interaction-bound .simps)(auto simp add : SUP-le-iff eSuc-le-iff enat-eSuc-iffdest !: bspec)
lemma interaction-bounded-byI-epred :assumes
∧out c. IO out c ∈ set-spmf (the-gpv gpv) =⇒ n 6= 0 ∧ (∀ input .
interaction-bounded-by (c input) (n − 1 ))shows interaction-bounded-by gpv n
unfolding interaction-bounded-by .simpsby(subst interaction-bound .simps)(auto intro!: SUP-least split : generat .split dest !:assms simp add : eSuc-le-iff enat-eSuc-iff gr0-conv-Suc neq-zero-conv-eSuc interaction-bounded-by .simps)
lemma interaction-bounded-by-IO :[[ IO out c ∈ set-spmf (the-gpv gpv); interaction-bounded-by gpv n ]]=⇒ n 6= 0 ∧ interaction-bounded-by (c input) (n − 1 )
by(drule interaction-bound-IO [where input=input ])(auto simp add : interaction-bounded-by .simpsepred-conv-minus eSuc-le-iff enat-eSuc-iff )
named-theorems interaction-bound
lemma interaction-bounded-by-start :[[ TERM gpv ; interaction-bounded-by gpv m; interaction-bounded-by gpv m =⇒
thesis ]] =⇒ thesisby simp
lemma interaction-bounded-by-Done [iff ]: interaction-bounded-by (Done x ) nby(simp add : interaction-bounded-by .simps)
lemma interaction-bounded-by-DoneI [interaction-bound ]: interaction-bounded-by(Done x ) 0by simp
lemma interaction-bounded-by-Fail [iff ]: interaction-bounded-by Fail nby(simp add : interaction-bounded-by .simps)
lemma interaction-bounded-by-FailI [interaction-bound ]: interaction-bounded-by Fail0by simp
lemma interaction-bounded-by-lift-spmf [iff ]: interaction-bounded-by (lift-spmf p)nby(simp add : interaction-bounded-by .simps)
lemma interaction-bounded-by-lift-spmfI [interaction-bound ]: interaction-bounded-by(lift-spmf p) 0by simp
193
lemma interaction-bounded-by-assert-gpv [simp]: interaction-bounded-by (assert-gpvb) nby(cases b) simp-all
lemma interaction-bounded-by-assert-gpvI [interaction-bound ]: interaction-bounded-by(assert-gpv b) 0by simp
lemma interaction-bounded-by-Pause [simp]:interaction-bounded-by (Pause out c) n ←→ 0 < n ∧ (∀ input . interaction-bounded-by
(c input) (n − 1 ))by(auto 4 3 simp add : interaction-bounded-by .simps eSuc-le-iff enat-eSuc-iff gr0-conv-Sucintro: SUP-least dest : order-trans[OF SUP-upper , rotated ])
lemma interaction-bounded-by-bind-PauseI [interaction-bound ]:(∧
input . interaction-bounded-by (c input >>= f ) n)=⇒ interaction-bounded-by (Pause out c >>= f ) (n + 1 )
by(simp add : plus-1-eSuc)
lemma interaction-bounded-by-bindI [interaction-bound ]:[[ interaction-bounded-by gpv n;
∧x . x ∈ results ′-gpv gpv =⇒ interaction-bounded-by
(f x ) m ]]=⇒ interaction-bounded-by (gpv >>= f ) (n + m)
unfolding interaction-bounded-by .simps plus-enat-simps(1 )[symmetric]by(rule order-trans[OF interaction-bound-bind ])(erule add-mono, simp add : SUP-least)
lemma interaction-bounded-by-bind-lift-spmf [iff ]:interaction-bounded-by (lift-spmf p >>= f ) n ←→ (∀ x∈set-spmf p. interaction-bounded-by
(f x ) n)by(simp add : interaction-bounded-by .simps SUP-le-iff )
lemma interaction-bounded-by-bind-lift-spmfI [interaction-bound ]:(∧
x . x ∈ set-spmf p =⇒ interaction-bounded-by (f x ) n)=⇒ interaction-bounded-by (lift-spmf p >>= f ) n
by(simp)
lemma interaction-bounded-by-bind-DoneI [interaction-bound ]:interaction-bounded-by (f x ) n =⇒ interaction-bounded-by (Done x >>= f ) n
by(simp)
lemma interaction-bounded-by-if [interaction-bound ]:[[ b =⇒ interaction-bounded-by gpv1 n; ¬ b =⇒ interaction-bounded-by gpv2 m ]]=⇒ interaction-bounded-by (if b then gpv1 else gpv2 ) (max n m)
by(auto 4 3 simp add : max-def not-le elim: interaction-bounded-by-mono)
7.11 Typing
7.11.1 Interface between gpvs and rpvs
type-synonym ( ′call , ′ret) I = ′call set × ( ′call ⇒ ′ret set)
194
fun outs-I :: ( ′call , ′ret) I ⇒ ′call setwhere outs-I (outs, c) = outs
lemma outs-I-conv : outs-I = fstby(simp add : fun-eq-iff )
fun responses-I :: ( ′call , ′ret) I ⇒ ′call ⇒ ′ret setwhere responses-I (outs, c) = c
lemma responses-I-conv : responses-I = sndby(simp add : fun-eq-iff )
abbreviation I-top :: ( ′call , ′ret) Iwhere I-top ≡ (UNIV , λ-. UNIV )
context beginqualified inductive resultsp-gpv :: ( ′out , ′in) I ⇒ ′a ⇒ ( ′a, ′out , ′in) gpv ⇒bool
for Γ xwhere
Pure: Pure x ∈ set-spmf (the-gpv gpv) =⇒ resultsp-gpv Γ x gpv| IO :
[[ IO out c ∈ set-spmf (the-gpv gpv); input ∈ responses-I Γ out ; resultsp-gpv Γ x(c input) ]]
=⇒ resultsp-gpv Γ x gpv
definition results-gpv :: ( ′out , ′in) I ⇒ ( ′a, ′out , ′in) gpv ⇒ ′a setwhere results-gpv Γ gpv ≡ x . resultsp-gpv Γ x gpv
lemma resultsp-gpv-results-gpv-eq [pred-set-conv ]: resultsp-gpv Γ x gpv ←→ x ∈results-gpv Γ gpvby(simp add : results-gpv-def )
context beginlocal-setup 〈〈 Local-Theory .map-background-naming (Name-Space.mandatory-pathresults-gpv) 〉〉
lemmas intros [intro? ] = resultsp-gpv .intros[to-set ]and Pure = Pure[to-set ]and IO = IO [to-set ]and induct [consumes 1 , case-names Pure IO , induct set : results-gpv ] = resultsp-gpv .induct [to-set ]and cases [consumes 1 , case-names Pure IO , cases set : results-gpv ] = resultsp-gpv .cases[to-set ]and simps = resultsp-gpv .simps[to-set ]
end
inductive-simps results-gpv-GPV [to-set , simp]: resultsp-gpv Γ x (GPV gpv)
195
end
lemma results-gpv-Done [iff ]: results-gpv Γ (Done x ) = xby(auto simp add : Done.ctr)
lemma results-gpv-Fail [iff ]: results-gpv Γ Fail = by(auto simp add : Fail-def )
lemma results-gpv-Pause [simp]:results-gpv Γ (Pause out c) = (
⋃input∈responses-I Γ out . results-gpv Γ (c input))
by(auto simp add : Pause.ctr)
lemma results-gpv-lift-spmf [iff ]: results-gpv Γ (lift-spmf p) = set-spmf pby(auto simp add : lift-spmf .ctr)
lemma results-gpv-assert-gpv [simp]: results-gpv Γ (assert-gpv b) = (if b then ()else )by auto
lemma results-gpv-bind-gpv [simp]:results-gpv Γ (gpv >>= f ) = (
⋃x∈results-gpv Γ gpv . results-gpv Γ (f x ))
(is ?lhs = ?rhs)proof(intro set-eqI iffI )
fix xassume x ∈ ?lhsthen show x ∈ ?rhsproof(induction gpv ′≡gpv >>= f arbitrary : gpv)
case Pure thus ?caseby(auto 4 3 simp add : set-bind-spmf split : split-if-asm intro: results-gpv .intros
rev-bexI )next
case (IO out c input)from 〈IO out c ∈ -〉
obtain generat where generat : generat ∈ set-spmf (the-gpv gpv)and ∗: IO out c ∈ set-spmf (if is-Pure generat then the-gpv (f (result generat))
else return-spmf (IO (output generat) (λinput .continuation generat input >>= f )))
by(auto simp add : set-bind-spmf )thus ?caseproof(cases generat)
case (Pure y)with generat have y ∈ results-gpv Γ gpv by(auto intro: results-gpv .intros)thus ?thesis using ∗ Pure 〈input ∈ responses-I Γ out 〉 〈x ∈ results-gpv Γ (c
input)〉
by(auto intro: results-gpv .IO)next
case (IO out ′ c ′)hence [simp]: out ′ = out
and c:∧
input . c input = bind-gpv (c ′ input) f using ∗ by simp-all
196
from IO .hyps(4 )[OF c] obtain y where y : y ∈ results-gpv Γ (c ′ input)and x ∈ results-gpv Γ (f y) by blast
from y IO generat have y ∈ results-gpv Γ gpv using 〈input ∈ responses-I Γout 〉
by(auto intro: results-gpv .IO)with 〈x ∈ results-gpv Γ (f y)〉 show ?thesis by blast
qedqed
nextfix xassume x ∈ ?rhsthen obtain y where y : y ∈ results-gpv Γ gpv
and x : x ∈ results-gpv Γ (f y) by blastfrom y show x ∈ ?lhsproof(induction)
case (Pure gpv)with x show ?case
by cases(auto 4 4 intro: results-gpv .intros rev-bexI simp add : set-bind-spmf )qed(auto 4 4 simp add : set-bind-spmf intro: rev-bexI results-gpv .IO)
qed
lemma results-gpv-I-top: results-gpv I-top = results ′-gpvproof(intro ext set-eqI iffI )
fix x gpvassume x ∈ results-gpv I-top gpvthen show x ∈ results ′-gpv gpv
by induction(auto intro: results ′-gpvI )next
fix x gpvassume x ∈ results ′-gpv gpvthen show x ∈ results-gpv I-top gpv
by induction(auto intro: results-gpv .intros elim!: generat .set-cases)qed
lemma results ′-bind-gpv [simp]:results ′-gpv (bind-gpv gpv f ) = (
⋃x∈results ′-gpv gpv . results ′-gpv (f x ))
unfolding results-gpv-I-top[symmetric] by simp
definition gpv-monad :: ( ′a, ( ′a, ′out , ′in) gpv) monad-failwhere gpv-monad = (|bind = bind-gpv , return = Done, fail = Fail |)
lemma gpv-monad-sel [simp]:shows bind-gpv : bind gpv-monad = bind-gpvand return-gpv : return gpv-monad = Doneand fail-gpv : fail gpv-monad = Fail
by(simp-all add : gpv-monad-def )
lemma results ′-gpv-bind-option [simp]:results ′-gpv (monad .bind-option gpv-monad x f ) = (
⋃y∈set-option x . results ′-gpv
197
(f y))by(cases x ) simp-all
lemma monad-gpv [simp, intro!, locale-witness]: monad gpv-monadby unfold-locales(simp-all add : bind-gpv-assoc)
lemma monad-fail-gpv [simp, intro!, locale-witness]: monad-fail gpv-monadby unfold-locales simp
7.11.2 Type judgements
coinductive WT-gpv :: ( ′out , ′in) I ⇒ ( ′a, ′out , ′in) gpv ⇒ bool (((-)/ `g (-)√
)[100 , 0 ] 99 )
for Γwhere
(∧
out c. IO out c ∈ set-spmf gpv =⇒ out ∈ outs-I Γ ∧ (∀ input∈responses-I Γout . Γ `g c input
√))
=⇒ Γ `g GPV gpv√
lemma WT-gpv-coinduct [consumes 1 , case-names WT-gpv , case-conclusion WT-gpvout cont , coinduct pred : WT-gpv ]:
assumes ∗: X gpvand step:
∧gpv out c.
[[ X gpv ; IO out c ∈ set-spmf (the-gpv gpv) ]]=⇒ out ∈ outs-I Γ ∧ (∀ input ∈ responses-I Γ out . X (c input) ∨ Γ `g c input√
)shows Γ `g gpv
√
using ∗ by(coinduct)(auto dest : step simp add : eq-GPV-iff )
lemma WT-gpv-simps:Γ `g GPV gpv
√←→
(∀ out c. IO out c ∈ set-spmf gpv −→ out ∈ outs-I Γ ∧ (∀ input∈responses-I Γout . Γ `g c input
√))
by(subst WT-gpv .simps) simp
lemma WT-gpvI :(∧
out c. IO out c ∈ set-spmf (the-gpv gpv) =⇒ out ∈ outs-I Γ ∧ (∀ input∈responses-IΓ out . Γ `g c input
√))
=⇒ Γ `g gpv√
by(cases gpv)(simp add : WT-gpv-simps)
lemma WT-gpvD :assumes Γ `g gpv
√
shows WT-gpv-OutD : IO out c ∈ set-spmf (the-gpv gpv) =⇒ out ∈ outs-I Γand WT-gpv-ContD : [[ IO out c ∈ set-spmf (the-gpv gpv); input ∈ responses-I
Γ out ]] =⇒ Γ `g c input√
using assms by(cases, fastforce)+
lemma WT-gpv-Done [iff ]: Γ `g Done x√
198
by(rule WT-gpvI ) simp-all
lemma WT-gpv-Fail [iff ]: Γ `g Fail√
by(rule WT-gpvI ) simp-all
lemma WT-gpv-PauseI :[[ out ∈ outs-I Γ;
∧input . input ∈ responses-I Γ out =⇒ Γ `g c input
√]]
=⇒ Γ `g Pause out c√
by(rule WT-gpvI ) simp-all
lemma WT-gpv-Pause [iff ]:Γ `g Pause out c
√←→ out ∈ outs-I Γ ∧ (∀ input ∈ responses-I Γ out . Γ `g c
input√
)by(auto intro: WT-gpv-PauseI dest : WT-gpvD)
lemma WT-gpv-bindI :[[ Γ `g gpv
√;∧
x . x ∈ results-gpv Γ gpv =⇒ Γ `g f x√
]]=⇒ Γ `g gpv >>= f
√
proof(coinduction arbitrary : gpv)case [rule-format ]: (WT-gpv out c gpv)from 〈IO out c ∈ -〉
obtain generat where generat : generat ∈ set-spmf (the-gpv gpv)and ∗: IO out c ∈ set-spmf (if is-Pure generat then the-gpv (f (result generat))
else return-spmf (IO (output generat) (λinput . continuationgenerat input >>= f )))
by(auto simp add : set-bind-spmf )show ?caseproof(cases generat)
case (Pure y)with generat have y ∈ results-gpv Γ gpv by(auto intro: results-gpv .Pure)hence Γ `g f y
√by(rule WT-gpv)
with ∗ Pure show ?thesis by(auto dest : WT-gpvD)next
case (IO out ′ c ′)hence [simp]: out ′ = out
and c:∧
input . c input = bind-gpv (c ′ input) f using ∗ by simp-allfrom generat IO have ∗∗: IO out c ′ ∈ set-spmf (the-gpv gpv) by simpwith 〈Γ `g gpv
√〉 have ?out by(auto dest : WT-gpvD)
moreover fix inputassume input : input ∈ responses-I Γ outwith 〈Γ `g gpv
√〉 ∗∗ have Γ `g c ′ input
√by(rule WT-gpvD)
moreover fix yassume y ∈ results-gpv Γ (c ′ input)with ∗∗ input have y ∈ results-gpv Γ gpv by(rule results-gpv .IO)hence Γ `g f y
√by(rule WT-gpv)
moreover note calculation hence ?cont using c by blast
199
ultimately show ?thesis ..qed
qed
lemma WT-gpv-bindD2 :assumes WT : Γ `g gpv >>= f
√
and x : x ∈ results-gpv Γ gpvshows Γ `g f x
√
using x WTproof induction
case (Pure gpv)show ?caseproof(rule WT-gpvI )
fix out cassume IO out c ∈ set-spmf (the-gpv (f x ))with Pure have IO out c ∈ set-spmf (the-gpv (gpv >>= f ))
by(auto simp add : set-bind-spmf intro: rev-bexI )with 〈Γ `g gpv >>= f
√〉 show out ∈ outs-I Γ ∧ (∀ input∈responses-I Γ out .
Γ `g c input√
)by(auto dest : WT-gpvD)
qednext
case (IO out c gpv input)from 〈IO out c ∈ -〉
have IO out (λinput . bind-gpv (c input) f ) ∈ set-spmf (the-gpv (gpv >>= f ))by(auto simp add : set-bind-spmf intro: rev-bexI )
with IO .prems have Γ `g c input >>= f√
using 〈input ∈ -〉 by(rule WT-gpv-ContD)thus ?case by(rule IO .IH )
qed
lemma WT-gpv-bindD1 : Γ `g gpv >>= f√
=⇒ Γ `g gpv√
proof(coinduction arbitrary : gpv)case (WT-gpv out c gpv)from 〈IO out c ∈ -〉
have IO out (λinput . bind-gpv (c input) f ) ∈ set-spmf (the-gpv (gpv >>= f ))by(auto simp add : set-bind-spmf intro: rev-bexI )
with 〈Γ `g gpv >>= f√
〉 show ?caseby(auto simp del : bind-gpv-sel ′ dest : WT-gpvD)
qed
lemma WT-gpv-bind [simp]: Γ `g gpv >>= f√←→ Γ `g gpv
√∧ (∀ x∈results-gpv
Γ gpv . Γ `g f x√
)by(blast intro: WT-gpv-bindI dest : WT-gpv-bindD1 WT-gpv-bindD2 )
lemma WT-gpv-top [simp, intro!]: I-top `g gpv√
by(coinduction arbitrary : gpv)(auto)
lemma WT-gpv-lift-spmf [simp, intro!]: I `g lift-spmf p√
by(rule WT-gpvI ) auto
200
lemma WT-gpv-coinduct-bind [consumes 1 , case-names WT-gpv , case-conclusionWT-gpv out cont ]:
assumes ∗: X gpvand step:
∧gpv out c. [[ X gpv ; IO out c ∈ set-spmf (the-gpv gpv) ]]
=⇒ out ∈ outs-I I ∧ (∀ input∈responses-I I out .X (c input) ∨I `g c input
√∨
(∃ (gpv ′ :: ( ′b, ′call , ′ret) gpv) f . c input = gpv ′ >>= f ∧ I `g gpv ′√∧
(∀ x∈results-gpv I gpv ′. X (f x ))))shows I `g gpv
√
proof −fix xdef gpv ′ ≡ Done x :: ( ′b, ′call , ′ret) gpv
and f ≡ (λ-. gpv) :: ′b ⇒ ( ′a, ′call , ′ret) gpvwith ∗ have I `g gpv ′
√and
∧x . x ∈ results-gpv I gpv ′ =⇒ X (f x ) by
simp-allthen have I `g gpv ′ >>= f
√
proof(coinduction arbitrary : gpv ′ f rule: WT-gpv-coinduct)case [rule-format ]: (WT-gpv out c gpv ′)from 〈IO out c ∈ -〉
obtain generat where generat : generat ∈ set-spmf (the-gpv gpv ′)and ∗: IO out c ∈ set-spmf (if is-Pure generat
then the-gpv (f (result generat))else return-spmf (IO (output generat) (λinput . continuation generat input
>>= f )))by(clarsimp simp add : set-bind-spmf )
show ?caseproof(cases generat)
case (Pure x )from Pure ∗ have IO : IO out c ∈ set-spmf (the-gpv (f x )) by simp
from generat Pure have x ∈ results-gpv I gpv ′ by (simp add : results-gpv .Pure)then have X (f x ) by(rule WT-gpv)from step[OF this IO ] show ?thesis by(auto 4 4 intro: exI [where x=Done
-])next
case (IO out ′ c ′)with ∗ have [simp]: out ′ = out
and c: c = (λinput . c ′ input >>= f ) by simp-allfrom IO generat have IO : IO out c ′ ∈ set-spmf (the-gpv gpv ′) by simpthen have
∧input . input ∈ responses-I I out =⇒ results-gpv I (c ′ input)
⊆ results-gpv I gpv ′
by(auto intro: results-gpv .IO)with WT-gpvD [OF 〈I `g gpv ′
√〉 IO ] show ?thesis unfolding c using
WT-gpv(2 ) by blastqed
qedthen show ?thesis unfolding gpv ′-def f-def by simp
qed
201
7.12 Sub-gpvs
context beginqualified inductive sub-gpvsp :: ( ′out , ′in) I ⇒ ( ′a, ′out , ′in) gpv ⇒ ( ′a, ′out ,′in) gpv ⇒ bool
for I xwhere
base:[[ IO out c ∈ set-spmf (the-gpv gpv); input ∈ responses-I I out ; x = c input ]]=⇒ sub-gpvsp I x gpv| cont :
[[ IO out c ∈ set-spmf (the-gpv gpv); input ∈ responses-I I out ; sub-gpvsp I x(c input) ]]
=⇒ sub-gpvsp I x gpv
qualified lemma sub-gpvsp-base:[[ IO out c ∈ set-spmf (the-gpv gpv); input ∈ responses-I I out ]]=⇒ sub-gpvsp I (c input) gpv
by(rule base) simp-all
definition sub-gpvs :: ( ′out , ′in) I ⇒ ( ′a, ′out , ′in) gpv ⇒ ( ′a, ′out , ′in) gpv setwhere sub-gpvs I gpv ≡ x . sub-gpvsp I x gpv
lemma sub-gpvsp-sub-gpvs-eq [pred-set-conv ]: sub-gpvsp I x gpv ←→ x ∈ sub-gpvsI gpvby(simp add : sub-gpvs-def )
context beginlocal-setup 〈〈 Local-Theory .map-background-naming (Name-Space.mandatory-pathsub-gpvs) 〉〉
lemmas intros [intro? ] = sub-gpvsp.intros[to-set ]and base = sub-gpvsp-base[to-set ]and cont = cont [to-set ]and induct [consumes 1 , case-names Pure IO , induct set : sub-gpvs] = sub-gpvsp.induct [to-set ]and cases [consumes 1 , case-names Pure IO , cases set : sub-gpvs] = sub-gpvsp.cases[to-set ]and simps = sub-gpvsp.simps[to-set ]
endend
lemma WT-sub-gpvsD :assumes I `g gpv
√and gpv ′ ∈ sub-gpvs I gpv
shows I `g gpv ′√
using assms(2 ,1 ) by(induction)(auto dest : WT-gpvD)
lemma WT-sub-gpvsI :[[∧
out c. IO out c ∈ set-spmf (the-gpv gpv) =⇒ out ∈ outs-I Γ;∧gpv ′. gpv ′ ∈ sub-gpvs Γ gpv =⇒ Γ `g gpv ′
√]]
=⇒ Γ `g gpv√
by(rule WT-gpvI )(auto intro: sub-gpvs.base)
202
7.13 Losslessness
A gpv is lossless iff we are guaranteed to get a result after a finite numberof interactions that respect the interface
inductive lossless-gpv :: ( ′out , ′in) I ⇒ ( ′a, ′out , ′in) gpv ⇒ boolfor I
wherelossless-gpv :[[ lossless-spmf p;∧
out c input . [[ IO out c ∈ set-spmf p; input ∈ responses-I I out ]]=⇒ lossless-gpv I (c input) ]]
=⇒ lossless-gpv I (GPV p)
hide-fact lossless-gpv
lemma lossless-gpvI [intro? ]:[[ lossless-spmf (the-gpv gpv);∧
out c input . [[ IO out c ∈ set-spmf (the-gpv gpv); input ∈ responses-I I out]]
=⇒ lossless-gpv I (c input) ]]=⇒ lossless-gpv I gpv
by(cases gpv)(auto intro: lossless-gpv .intros)
lemma lossless-gpvD :assumes lossless-gpv I gpvshows lossless-gpv-lossless-spmfD : lossless-spmf (the-gpv gpv)and lossless-gpv-continuationD :[[ IO out c ∈ set-spmf (the-gpv gpv); input ∈ responses-I I out ]] =⇒ lossless-gpvI (c input)using assms by(auto elim: lossless-gpv .cases)
lemma lossless-gpv-Done [iff ]: lossless-gpv I (Done x )by(rule lossless-gpvI ) auto
lemma lossless-gpv-Fail [iff ]: ¬ lossless-gpv I Failby(auto dest : lossless-gpvD)
lemma lossless-gpv-Pause [simp]:lossless-gpv I (Pause out c) ←→ (∀ input ∈ responses-I I out . lossless-gpv I (c
input))by(auto dest : lossless-gpvD intro: lossless-gpvI )
lemma lossless-gpv-assert-gpv [iff ]: lossless-gpv I (assert-gpv b) ←→ bby(cases b) simp-all
lemma lossless-gpv-lift-spmf [iff ]: lossless-gpv I (lift-spmf p) ←→ lossless-spmf pby(auto dest : lossless-gpvD intro: lossless-gpvI )
lemma lossless-bind-gpvI :
203
[[ lossless-gpv I gpv ;∧
x . x ∈ results-gpv I gpv =⇒ lossless-gpv I (f x ) ]]=⇒ lossless-gpv I (gpv >>= f )
proof(induction rule: lossless-gpv .induct)case (lossless-gpv p) fix x
assume Pure x ∈ set-spmf phence x ∈ results-gpv I (GPV p) by simphence lossless-gpv I (f x ) by(rule lossless-gpv .prems)
with 〈lossless-spmf p〉 show ?case unfolding GPV-bindapply(intro lossless-gpv .intros)apply(fastforce dest : lossless-gpvD split : generat .split)
apply(clarsimp simp add : set-bind-spmf ; split generat .split-asm)apply(auto dest : lossless-gpvD intro!: lossless-gpv)done
qed
lemma lossless-bind-gpvD1 : lossless-gpv I (gpv >>= f ) =⇒ lossless-gpv I gpvproof(induction gpv ′≡gpv >>= f arbitrary : gpv rule: lossless-gpv .induct)
case (lossless-gpv p)obtain p ′ where gpv : gpv = GPV p ′ by(cases gpv)from lossless-gpv .hyps gpv have lossless-spmf p ′ by(simp add : GPV-bind)then show ?case unfolding gpvproof(rule lossless-gpv .intros)
fix out c inputassume IO out c ∈ set-spmf p ′ input ∈ responses-I I outhence IO out (λinput . c input >>= f ) ∈ set-spmf p using lossless-gpv .hyps gpv
by(auto simp add : GPV-bind set-bind-spmf intro: rev-bexI )thus lossless-gpv I (c input) using 〈input ∈ -〉 by(rule lossless-gpv .hyps) simp
qedqed
lemma lossless-bind-gpvD2 :assumes lossless-gpv Γ (gpv >>= f )and x ∈ results-gpv Γ gpvshows lossless-gpv Γ (f x )
using assms(2 ,1 )proof(induction)
case (Pure gpv)thus ?case
by −(rule lossless-gpvI , auto 4 4 dest : lossless-gpvD simp add : set-bind-spmfintro: rev-bexI )qed(auto 4 4 dest : lossless-gpvD simp add : set-bind-spmf intro: rev-bexI )
lemma lossless-bind-gpv [simp]:lossless-gpv Γ (gpv >>= f ) ←→ lossless-gpv Γ gpv ∧ (∀ x∈results-gpv Γ gpv .
lossless-gpv Γ (f x ))by(blast intro: lossless-bind-gpvI dest : lossless-bind-gpvD1 lossless-bind-gpvD2 )
lemma lossless-WT-gpv-induct [consumes 2 , case-names lossless-gpv ]:
204
assumes lossless: lossless-gpv I gpvand WT : I `g gpv
√
and step:∧
p. [[lossless-spmf p;∧
out c. IO out c ∈ set-spmf p =⇒ out ∈ outs-I I;∧out c input . [[IO out c ∈ set-spmf p; out ∈ outs-I I =⇒ input ∈ responses-I
I out ]] =⇒ lossless-gpv I (c input);∧out c input . [[IO out c ∈ set-spmf p; out ∈ outs-I I =⇒ input ∈ responses-I
I out ]] =⇒ I `g c input√
;∧out c input . [[IO out c ∈ set-spmf p; out ∈ outs-I I =⇒ input ∈ responses-I
I out ]] =⇒ P (c input)]]=⇒ P (GPV p)
shows P gpvusing lossless WTapply(induction)apply(erule step)apply(auto elim: WT-gpvD simp add : WT-gpv-simps)done
lemma lossless-gpv-induct-strong [consumes 1 , case-names lossless-gpv ]:assumes gpv : lossless-gpv I gpvand step:∧
p. [[ lossless-spmf p;∧gpv . gpv ∈ sub-gpvs I (GPV p) =⇒ lossless-gpv I gpv ;∧gpv . gpv ∈ sub-gpvs I (GPV p) =⇒ P gpv ]]
=⇒ P (GPV p)shows P gpv
proof −def gpv ′ ≡ gpvthen have gpv ′ ∈ insert gpv (sub-gpvs I gpv) by simpwith gpv have lossless-gpv I gpv ′ ∧ P gpv ′
proof(induction arbitrary : gpv ′)case (lossless-gpv p)from 〈gpv ′ ∈ insert (GPV p) -〉 show ?caseproof(rule insertE )
assume gpv ′ = GPV pmoreover have lossless-gpv I (GPV p)
by(auto 4 3 intro: lossless-gpvI lossless-gpv .hyps)moreover have P (GPV p) using lossless-gpv .hyps(1 )by(rule step)(fastforce elim: sub-gpvs.cases lossless-gpv .IH [THEN conjunct1 ]
lossless-gpv .IH [THEN conjunct2 ])+ultimately show ?case by simp
qed(fastforce elim: sub-gpvs.cases lossless-gpv .IH [THEN conjunct1 ] lossless-gpv .IH [THENconjunct2 ])
qedthus ?thesis by(simp add : gpv ′-def )
qed
lemma lossless-sub-gpvsI :
205
assumes spmf : lossless-spmf (the-gpv gpv)and sub:
∧gpv ′. gpv ′ ∈ sub-gpvs I gpv =⇒ lossless-gpv I gpv ′
shows lossless-gpv I gpvusing spmf by(rule lossless-gpvI )(rule sub[OF sub-gpvs.base])
lemma lossless-sub-gpvsD :assumes lossless-gpv I gpv gpv ′ ∈ sub-gpvs I gpvshows lossless-gpv I gpv ′
using assms(2 ,1 ) by(induction)(auto dest : lossless-gpvD)
lemma lossless-WT-gpv-induct-strong [consumes 2 , case-names lossless-gpv ]:assumes lossless: lossless-gpv I gpvand WT : I `g gpv
√
and step:∧
p. [[ lossless-spmf p;∧out c. IO out c ∈ set-spmf p =⇒ out ∈ outs-I I;∧gpv . gpv ∈ sub-gpvs I (GPV p) =⇒ lossless-gpv I gpv ;∧gpv . gpv ∈ sub-gpvs I (GPV p) =⇒ I `g gpv
√;∧
gpv . gpv ∈ sub-gpvs I (GPV p) =⇒ P gpv ]]=⇒ P (GPV p)
shows P gpvusing lossless WTapply(induction rule: lossless-gpv-induct-strong)apply(erule step)apply(auto elim: WT-gpvD dest : WT-sub-gpvsD)done
lemma try-gpv-lossless [simp]:fixes gpv :: ( ′a, ′call , ′ret) gpvassumes lossless-gpv I-top gpv — TODO: generalise to arbitrary typings ?shows TRY gpv ELSE gpv ′ = gpv
using assmsapply inductionapply(rule gpv .expand)apply(simp add : spmf .map-comp generat .map-comp o-def )apply(rule map-spmf-idI )subgoal for p generat by(cases generat) simp-alldone
lemma try-gpv-bind-lossless:assumes lossless-gpv I-top gpv — TODO: generalise to arbitrary typings?shows TRY bind-gpv gpv f ELSE gpv ′ = bind-gpv gpv (λx . TRY f x ELSE gpv ′)
using assmsapply inductionapply(rule gpv .expand)apply(simp add : map-try-spmf spmf .map-comp o-def generat .map-comp map-spmf-bind-spmfbind-gpv .sel try-gpv-sel del : bind-gpv-sel ′ try-gpv .sel)apply(subst try-spmf-bind-spmf-lossless, simp)apply(rule bind-spmf-cong , simp)apply(clarsimp simp add : spmf .map-comp o-def map-try-spmf generat .map-comp
206
generat .map-ident [abs-def ] split : generat .split)done
7.14 Inlining
lemma gpv-coinduct-bind [consumes 1 , case-names Eq-gpv ]:fixes gpv gpv ′ :: ( ′a, ′call , ′ret) gpvassumes ∗: R gpv gpv ′
and step:∧
gpv gpv ′. R gpv gpv ′
=⇒ rel-spmf (rel-generat op = op = (rel-fun op = (λgpv gpv ′. R gpv gpv ′ ∨gpv = gpv ′ ∨
(∃ gpv2 :: ( ′b, ′call , ′ret) gpv . ∃ gpv2 ′ :: ( ′c, ′call , ′ret) gpv . ∃ f f ′. gpv =bind-gpv gpv2 f ∧ gpv ′ = bind-gpv gpv2 ′ f ′ ∧
rel-gpv (λx y . R (f x ) (f ′ y)) op = gpv2 gpv2 ′))))(the-gpv gpv) (the-gpv gpv ′)
shows gpv = gpv ′
proof −fix x ydef gpv1 ≡ Done x :: ( ′b, ′call , ′ret) gpv
and f ≡ (λ-. gpv) :: ′b ⇒ ( ′a, ′call , ′ret) gpvand gpv1 ′ ≡ Done y :: ( ′c, ′call , ′ret) gpvand f ′ ≡ (λ-. gpv ′) :: ′c ⇒ ( ′a, ′call , ′ret) gpv
from ∗ have rel-gpv (λx y . R (f x ) (f ′ y)) op = gpv1 gpv1 ′
by(simp add : gpv1-def gpv1 ′-def f-def f ′-def )then have gpv1 >>= f = gpv1 ′ >>= f ′
proof(coinduction arbitrary : gpv1 gpv1 ′ f f ′ rule: gpv .coinduct-strong)case (Eq-gpv gpv1 gpv1 ′ f f ′)
from Eq-gpv [unfolded gpv .rel-sel ] show ?case unfolding bind-gpv .sel spmf-rel-mapapply(rule rel-spmf-bindI )subgoal for generat generat ′
apply(cases generat generat ′ rule: generat .exhaust [case-product generat .exhaust ];clarsimp simp add : o-def spmf-rel-map generat .rel-map)
subgoal premises Pure for x yusing step[OF 〈R (f x ) (f ′ y)〉] apply −
apply(assumption | rule rel-spmf-mono rel-generat-mono rel-fun-monorefl)+
apply(fastforce intro: exI [where x=Done -])+done
subgoal by(fastforce simp add : rel-fun-def )done
doneqedthus ?thesis by(simp add : gpv1-def gpv1 ′-def f-def f ′-def )
qed
Inlining one gpv into another. This may throw out arbitrarily many inter-actions between the two gpvs if the inlined one does not call its callee. Sowe define it as the coiteration of a least-fixpoint search operator.
context
207
fixes callee :: ′s ⇒ ′call ⇒ ( ′ret × ′s, ′call ′, ′ret ′) gpvnotes [[function-internals]]
begin
partial-function (spmf ) inline1:: ( ′a, ′call , ′ret) gpv ⇒ ′s⇒ ( ′a × ′s + ′call ′ × ( ′ret × ′s, ′call ′, ′ret ′) rpv × ( ′a, ′call , ′ret) rpv) spmf
whereinline1 gpv s =the-gpv gpv >>=case-generat (λx . return-spmf (Inl (x , s)))
(λout rpv . the-gpv (callee s out) >>=case-generat (λ(x , y). inline1 (rpv x ) y)(λout rpv ′. return-spmf (Inr (out , rpv ′, rpv))))
lemma inline1-unfold :inline1 gpv s =the-gpv gpv >>=case-generat (λx . return-spmf (Inl (x , s)))
(λout rpv . the-gpv (callee s out) >>=case-generat (λ(x , y). inline1 (rpv x ) y)(λout rpv ′. return-spmf (Inr (out , rpv ′, rpv))))
by(fact inline1 .simps)
lemma inline1-fixp-induct [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λinline1 ′.
P (λgpv s. inline1 ′ (gpv , s)))and P (λ- -. return-pmf None)and
∧inline1 ′. P inline1 ′ =⇒ P (λgpv s. the-gpv gpv >>= case-generat (λx .
return-spmf (Inl (x , s))) (λout rpv . the-gpv (callee s out) >>= case-generat (λ(x ,y). inline1 ′ (rpv x ) y) (λout rpv ′. return-spmf (Inr (out , rpv ′, rpv)))))
shows P inline1using assms by(rule inline1 .fixp-induct [unfolded curry-conv [abs-def ]])
lemma inline1-fixp-induct-strong [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λinline1 ′.
P (λgpv s. inline1 ′ (gpv , s)))and P (λ- -. return-pmf None)and
∧inline1 ′. [[
∧gpv s. ord-spmf op = (inline1 ′ gpv s) (inline1 gpv s); P
inline1 ′ ]]=⇒ P (λgpv s. the-gpv gpv >>= case-generat (λx . return-spmf (Inl (x , s))) (λout
rpv . the-gpv (callee s out) >>= case-generat (λ(x , y). inline1 ′ (rpv x ) y) (λout rpv ′.return-spmf (Inr (out , rpv ′, rpv)))))
shows P inline1using assms by(rule spmf .fixp-strong-induct-uc[where P=λf . P (curry f ) andU =case-prod and C =curry , OF inline1 .mono inline1-def , unfolded curry-case-prod ,unfolded curry-conv [abs-def ] fun-ord-def split-paired-All prod .case case-prod-eta,OF refl ]) blast+
208
lemma inline1-fixp-induct-strong2 [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λinline1 ′.
P (λgpv s. inline1 ′ (gpv , s)))and P (λ- -. return-pmf None)and
∧inline1 ′.
[[∧
gpv s. ord-spmf op = (inline1 ′ gpv s) (inline1 gpv s);∧gpv s. ord-spmf op = (inline1 ′ gpv s) (the-gpv gpv >>= case-generat (λx .
return-spmf (Inl (x , s))) (λout rpv . the-gpv (callee s out) >>= case-generat (λ(x ,y). inline1 ′ (rpv x ) y) (λout rpv ′. return-spmf (Inr (out , rpv ′, rpv)))));
P inline1 ′ ]]=⇒ P (λgpv s. the-gpv gpv >>= case-generat (λx . return-spmf (Inl (x , s))) (λout
rpv . the-gpv (callee s out) >>= case-generat (λ(x , y). inline1 ′ (rpv x ) y) (λout rpv ′.return-spmf (Inr (out , rpv ′, rpv)))))
shows P inline1using assmsby(rule spmf .fixp-induct-strong2-uc[where P=λf . P (curry f ) and U =case-prodand C =curry , OF inline1 .mono inline1-def , unfolded curry-case-prod , unfoldedcurry-conv [abs-def ] fun-ord-def split-paired-All prod .case case-prod-eta, OF refl ])blast+
Iterate local .inline1 over all interactions. We’d like to use op >>= beforethe recursive call, but primcorec does not support this. So we emulate op>>= by effectively defining two mutually recursive functions (sum type in theargument) where the second is exactly op >>= specialised to call inline inthe bind.
primcorec inline-aux:: ( ′a, ′call , ′ret) gpv × ′s + ( ′ret ⇒ ( ′a, ′call , ′ret) gpv) × ( ′ret × ′s, ′call ′,
′ret ′) gpv⇒ ( ′a × ′s, ′call ′, ′ret ′) gpv
where∧state. the-gpv (inline-aux state) =
(case state of Inl (c, s) ⇒ map-spmf (λresult .case result of Inl (x , s) ⇒ Pure (x , s)| Inr (out , oracle, rpv)⇒ IO out (λinput . inline-aux (Inr (rpv , oracle input))))
(inline1 c s)| Inr (rpv , c) ⇒
map-spmf (λresult .case result of Inl (Inl (x , s)) ⇒ Pure (x , s)| Inl (Inr (out , oracle, rpv)) ⇒ IO out (λinput . inline-aux (Inr (rpv , oracle
input)))| Inr (out , c) ⇒ IO out (λinput . inline-aux (Inr (rpv , c input))))
(bind-spmf (the-gpv c) (λgenerat . case generat of Pure (x , s ′) ⇒ (map-spmf Inl(inline1 (rpv x ) s ′))| IO out c ⇒ return-spmf (Inr (out , c)))))
declare inline-aux .simps[simp del ]
definition inline :: ( ′a, ′call , ′ret) gpv ⇒ ′s ⇒ ( ′a × ′s, ′call ′, ′ret ′) gpv
209
where inline c s = inline-aux (Inl (c, s))
lemma inline-aux-Inr :inline-aux (Inr (rpv , oracl)) = bind-gpv oracl (λ(x , s). inline (rpv x ) s)
unfolding inline-defapply(coinduction arbitrary : oracl rule: gpv .coinduct-strong)apply(simp add : inline-aux .sel bind-gpv .sel spmf-rel-map del : bind-gpv-sel ′)apply(rule rel-spmf-bindI [where R=op =])apply(auto simp add : spmf-rel-map inline-aux .sel rel-spmf-reflI generat .rel-mapgenerat .rel-refl rel-fun-def split : generat .split)done
lemma inline-sel :the-gpv (inline c s) =map-spmf (λresult . case result of Inl xs ⇒ Pure xs
| Inr (out , oracle, rpv) ⇒ IO out (λinput . bind-gpv (oracleinput) (λ(x , s ′). inline (rpv x ) s ′))) (inline1 c s)by(simp add : inline-def inline-aux .sel inline-aux-Inr cong del : sum.case-cong)
lemma inline1-Fail [simp]: inline1 Fail s = return-pmf Noneby(rewrite inline1 .simps) simp
lemma inline-Fail [simp]: inline Fail s = Failby(rule gpv .expand)(simp add : inline-sel)
lemma inline1-Done [simp]: inline1 (Done x ) s = return-spmf (Inl (x , s))by(rewrite inline1 .simps) simp
lemma inline-Done [simp]: inline (Done x ) s = Done (x , s)by(rule gpv .expand)(simp add : inline-sel)
lemma inline1-lift-spmf [simp]: inline1 (lift-spmf p) s = map-spmf (λx . Inl (x ,s)) pby(rewrite inline1 .simps)(simp add : bind-map-spmf o-def map-spmf-conv-bind-spmf )
lemma inline-lift-spmf [simp]: inline (lift-spmf p) s = lift-spmf (map-spmf (λx .(x , s)) p)by(rule gpv .expand)(simp add : inline-sel spmf .map-comp o-def )
lemma inline1-Pause:inline1 (Pause out c) s =the-gpv (callee s out) >>= (λreact . case react of Pure (x , s ′) ⇒ inline1 (c x ) s ′ |
IO out ′ c ′⇒ return-spmf (Inr (out ′, c ′, c)))by(rewrite inline1 .simps) simp
lemma inline-Pause [simp]:inline (Pause out c) s = callee s out >>= (λ(x , s ′). inline (c x ) s ′)
by(rule gpv .expand)(auto simp add : inline-sel inline1-Pause map-spmf-bind-spmfbind-gpv .sel o-def [abs-def ] spmf .map-comp generat .map-comp id-def generat .map-id [unfolded
210
id-def ] simp del : bind-gpv-sel ′ intro!: bind-spmf-cong [OF refl ] split : generat .split)
lemma inline1-bind-gpv :fixes gpv f sdefines [simp]: inline11 ≡ inline1 and [simp]: inline12 ≡ inline1 and [simp]:
inline13 ≡ inline1shows inline11 (bind-gpv gpv f ) s = bind-spmf (inline12 gpv s)
(λres. case res of Inl (x , s ′) ⇒ inline13 (f x ) s ′ | Inr (out , rpv ′, rpv) ⇒return-spmf (Inr (out , rpv ′, bind-rpv rpv f )))
(is ?lhs = ?rhs)proof(rule spmf .leq-antisym)
note [intro!] = ord-spmf-bind-reflI and [split ] = generat .splitshow ord-spmf op = ?lhs ?rhs unfolding inline11-defproof(induction arbitrary : gpv s f rule: inline1-fixp-induct)
case adm show ?case by simpcase bottom show ?case by simpcase (step inline1 ′)show ?case unfolding inline12-def
apply(rewrite inline1 .simps; clarsimp simp add : bind-rpv-def )apply(rule conjI ; clarsimp)subgoal premises Pure for x
apply(rewrite inline1 .simps; clarsimp)subgoal for out c ret s ′ using step.IH [of Done x λ-. c ret s ′] by simpdonesubgoal for out c ret s ′ using step.IH [of c ret f s ′] by(simp cong del :
sum.case-cong-weak)done
qedshow ord-spmf op = ?rhs ?lhs unfolding inline12-defproof(induction arbitrary : gpv s rule: inline1-fixp-induct)
case adm show ?case by simpcase bottom show ?case by simpcase (step inline1 ′)show ?case unfolding inline11-def
apply(rewrite inline1 .simps; clarsimp simp add : bind-rpv-def )apply(rule conjI ; clarsimp)subgoal by(rewrite inline1 .simps; simp)
subgoal for out c ret s ′ using step.IH [of c ret s ′] by(simp cong del :sum.case-cong-weak)
doneqed
qed
lemma inline-bind-gpv [simp]:inline (bind-gpv gpv f ) s = bind-gpv (inline gpv s) (λ(x , s ′). inline (f x ) s ′)
apply(coinduction arbitrary : gpv s rule: gpv-coinduct-bind)apply(clarsimp simp add : map-spmf-bind-spmf o-def [abs-def ] bind-gpv .sel inline-selbind-map-spmf inline1-bind-gpv simp del : bind-gpv-sel ′ intro!: rel-spmf-bind-reflIsplit : generat .split)
211
apply(rule conjI )subgoal by(auto split : sum.split-asm simp add : spmf-rel-map spmf .map-comp
o-def generat .map-comp generat .map-id [unfolded id-def ] spmf .map-id [unfolded id-def ]inline-sel intro!: rel-spmf-reflI generat .rel-refl fun.rel-refl)by(auto split : sum.split-asm simp add : bind-gpv-assoc split-def intro!: gpv .rel-reflexI disjI2 rel-funI )
end
lemma set-inline1-lift-spmf1 : set-spmf (inline1 (λs x . lift-spmf (p s x )) gpv s) ⊆range Inlapply(induction arbitrary : gpv s rule: inline1-fixp-induct)subgoal by(rule cont-intro ccpo-class.admissible-leI )+apply(auto simp add : set-bind-spmf o-def bind-UNION split : generat .split-asm)+done
lemma in-set-inline1-lift-spmf1 : y ∈ set-spmf (inline1 (λs x . lift-spmf (p s x ))gpv s) =⇒ ∃ r s ′. y = Inl (r , s ′)by(drule set-inline1-lift-spmf1 [THEN subsetD ]) auto
lemma inline-lift-spmf1 :fixes p defines callee ≡ λs c. lift-spmf (p s c)shows inline callee gpv s = lift-spmf (map-spmf projl (inline1 callee gpv s))
by(rule gpv .expand)(auto simp add : inline-sel spmf .map-comp callee-def intro!:map-spmf-cong [OF refl ] dest : in-set-inline1-lift-spmf1 )
context begin interpretation lifting-syntax .lemma inline1-parametric [transfer-rule]:
((S ===> C ===> rel-gpv (rel-prod op = S ) C ′) ===> rel-gpv A C ===>S
===> rel-spmf (rel-sum (rel-prod A S ) (rel-prod C ′ (rel-prod (rel-rpv (rel-prodop = S ) C ′) (rel-rpv A C )))))
inline1 inline1(is (- ===> ?R) - -)
proof(rule rel-funI )show ?R (inline1 callee) (inline1 callee ′)
if [transfer-rule]: (S ===> C ===> rel-gpv (rel-prod op = S ) C ′) calleecallee ′
for callee callee ′
unfolding inline1-defby(unfold rel-fun-curry case-prod-curry)(rule fixp-spmf-parametric[OF inline1 .mono
inline1 .mono]; transfer-prover)qed
lemma inline-parametric [transfer-rule]:((S ===> C ===> rel-gpv (rel-prod op = S ) C ′) ===> rel-gpv A C ===>
S ===> rel-gpv (rel-prod A S ) C ′)inline inline
unfolding inline-def [abs-def ] inline-aux-def
212
apply(rule rel-funI )+subgoal premises [transfer-rule] by transfer-proverdoneend
Associativity rule for inline
contextfixes callee1 :: ′s1 ⇒ ′c1 ⇒ ( ′r1 × ′s1 , ′c, ′r) gpvand callee2 :: ′s2 ⇒ ′c2 ⇒ ( ′r2 × ′s2 , ′c1 , ′r1 ) gpv
begin
partial-function (spmf ) inline2 :: ( ′a, ′c2 , ′r2 ) gpv ⇒ ′s2 ⇒ ′s1⇒ ( ′a × ( ′s2 × ′s1 ) + ′c × ( ′r1 × ′s1 , ′c, ′r) rpv × ( ′r2 × ′s2 , ′c1 , ′r1 ) rpv× ( ′a, ′c2 , ′r2 ) rpv) spmfwhere
inline2 gpv s2 s1 =bind-spmf (the-gpv gpv)(case-generat (λx . return-spmf (Inl (x , s2 , s1 )))
(λout rpv . bind-spmf (inline1 callee1 (callee2 s2 out) s1 )(case-sum (λ((r2 , s2 ), s1 ). inline2 (rpv r2 ) s2 s1 )
(λ(x , rpv ′′, rpv ′). return-spmf (Inr (x , rpv ′′, rpv ′, rpv))))))
lemma inline2-fixp-induct [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λinline2 .
P (λgpv s2 s1 . inline2 ((gpv , s2 ), s1 )))and P (λ- - -. return-pmf None)and
∧inline2 ′. P inline2 ′ =⇒
P (λgpv s2 s1 . bind-spmf (the-gpv gpv) (λgenerat . case generat ofPure x ⇒ return-spmf (Inl (x , s2 , s1 ))| IO out rpv ⇒ bind-spmf (inline1 callee1 (callee2 s2 out) s1 ) (λlr . case lr
ofInl ((r2 , s2 ), c) ⇒ inline2 ′ (rpv r2 ) s2 c
| Inr (x , rpv ′′, rpv ′) ⇒ return-spmf (Inr (x , rpv ′′, rpv ′, rpv)))))shows P inline2
using assms unfolding split-def by(rule inline2 .fixp-induct [unfolded curry-conv [abs-def ]split-def ])
lemma inline1-inline-conv-inline2 :fixes gpv ′ :: ( ′r2 × ′s2 , ′c1 , ′r1 ) gpvshows inline1 callee1 (inline callee2 gpv s2 ) s1 =map-spmf (map-sum (λ(x , (s2 , s1 )). ((x , s2 ), s1 ))(λ(x , rpv ′′, rpv ′, rpv). (x , rpv ′′, λr1 . rpv ′ r1 >>= (λ(r2 , s2 ). inline callee2 (rpv
r2 ) s2 ))))(inline2 gpv s2 s1 )(is ?lhs = ?rhs)
proof(rule spmf .leq-antisym)def inline1-1 ≡ inline1 :: ( ′s1 ⇒ ′c1 ⇒ ( ′r1 × ′s1 , ′c, ′r) gpv) ⇒ ( ′r2 × ′s2 ,′c1 , ′r1 ) gpv ⇒ ′s1 ⇒ -
213
have ord-spmf op = ?lhs ?rhs— We need in the inductive step that the approximation behaves well with op
>>= because of inline-aux-Inr. So we have to thread it through the induction and doone half of the proof from inline1-bind-gpv again. We cannot inline inline1-bind-gpvin this proof here because the types are too specific.
and ord-spmf op = (inline1 callee1 (gpv ′ >>= f ) s1 ′)(do res ← inline1-1 callee1 gpv ′ s1 ′;case res of Inl (x , s ′) ⇒ inline1 callee1 (f x ) s ′
| Inr (out , rpv ′, rpv) ⇒ return-spmf (Inr (out , rpv ′, rpv >>= f ))) for gpv ′ and f :: - ⇒ ( ′a × ′s2 , ′c1 , ′r1 ) gpv and s1 ′
proof(induction arbitrary : gpv s2 s1 gpv ′ f s1 ′ rule: inline1-fixp-induct-strong2 )case adm thus ?case
apply(rule cont-intro)+subgoal for a b c d by(cases d ; clarsimp)done
case (step inline1 ′)note step-IH = step.IH [unfolded inline1-1-def ] and step-hyps = step.hyps[unfolded
inline1-1-def ] case 1
have inline1 : ord-spmf op =(inline1 callee2 gpv s2 >>= (λlr . case lr of Inl as2 ⇒ return-spmf (Inl (as2 ,
s1 ))| Inr (out1 , rpv ′, rpv) ⇒ the-gpv (callee1 s1 out1 ) >>= (λgenerat . case
generat ofPure (r1 , s1 ) ⇒ inline1 ′ (bind-gpv (rpv ′ r1 ) (λ(r2 , s2 ). inline callee2
(rpv r2 ) s2 )) s1| IO out rpv ′′⇒ return-spmf (Inr (out , rpv ′′, λr1 . bind-gpv (rpv ′ r1 )
(λ(r2 , s2 ). inline callee2 (rpv r2 ) s2 )) ))))(the-gpv gpv >>= (λgenerat . case generat of Pure x ⇒ return-spmf (Inl ((x ,
s2 ), s1 ))| IO out2 rpv ⇒ inline1-1 callee1 (callee2 s2 out2 ) s1 >>= (λlr . case lr of
Inl ((r2 , s2 ), s1 ) ⇒map-spmf (map-sum (λ(x , s2 , s1 ). ((x , s2 ), s1 )) (λ(x , rpv ′′, rpv ′,
rpv). (x , rpv ′′, λr1 . bind-gpv (rpv ′ r1 ) (λ(r2 , s2 ). inline callee2 (rpv r2 ) s2 ))))(inline2 (rpv r2 ) s2 s1 )
| Inr (out , rpv ′′, rpv ′) ⇒return-spmf (Inr (out , rpv ′′, λr1 . bind-gpv (rpv ′ r1 ) (λ(r2 , s2 ).
inline callee2 (rpv r2 ) s2 ))))))proof(induction arbitrary : gpv s2 s1 rule: inline1-fixp-induct)
case step2 : (step inline1 ′′)note step2-IH = step2 .IH [unfolded inline1-1-def ]
show ?case unfolding inline1-1-defapply(rewrite in ord-spmf - - ◊ inline1 .simps)apply(clarsimp intro!: ord-spmf-bind-reflI split : generat .split)apply(rule conjI )subgoal by(rewrite in ord-spmf - - ◊ inline2 .simps)(clarsimp simp add :
214
map-spmf-bind-spmf o-def split : generat .split sum.split intro!: ord-spmf-bind-reflIspmf .leq-trans[OF step2-IH ])
subgoal by(clarsimp intro!: ord-spmf-bind-reflI step-IH [THEN spmf .leq-trans]split : generat .split sum.split simp add : bind-rpv-def )
doneqed simp-allshow ?case
apply(rewrite in ord-spmf - ◊ - inline-sel)apply(rewrite in ord-spmf - - ◊ inline2 .simps)apply(clarsimp simp add : map-spmf-bind-spmf bind-map-spmf o-def intro!:
ord-spmf-bind-reflI split : generat .split)apply(rule spmf .leq-trans[OF spmf .leq-trans, OF - inline1 ])
apply(auto intro!: ord-spmf-bind-reflI split : sum.split generat .split simp add :inline1-1-def map-spmf-bind-spmf )
done case 2
show ?case unfolding inline1-1-defby(rewrite inline1 .simps)(auto simp del : bind-gpv-sel ′ simp add : bind-gpv .sel
map-spmf-bind-spmf bind-map-spmf o-def bind-rpv-def intro!: ord-spmf-bind-reflIstep-IH (2 )[THEN spmf .leq-trans] step-hyps(2 ) split : generat .split sum.split)
qed simp-allthus ord-spmf op = ?lhs ?rhs by −
show ord-spmf op = ?rhs ?lhsproof(induction arbitrary : gpv s2 s1 rule: inline2-fixp-induct)
case adm show ?case by simpcase bottom show ?case by simpcase (step inline2 ′)show ?case
apply(rewrite in ord-spmf - - ◊ inline1 .simps)apply(rewrite inline-sel)apply(rewrite in ord-spmf - ◊ - inline1 .simps)apply(rewrite in ord-spmf - - ◊ inline1 .simps)
apply(clarsimp simp add : map-spmf-bind-spmf bind-map-spmf intro!: ord-spmf-bind-reflIsplit : generat .split)
apply(rule conjI )subgoal
apply clarsimpapply(rule step.IH [THEN spmf .leq-trans])apply(rewrite in ord-spmf - ◊ - inline1 .simps)apply(rewrite inline-sel)apply(simp add : bind-map-spmf )done
subgoal by(clarsimp intro!: ord-spmf-bind-reflI split : generat .split sum.splitsimp add : o-def inline1-bind-gpv bind-rpv-def step.IH )
doneqed
qed
215
lemma inline1-inline-conv-inline2 ′:inline1 (λ(s2 , s1 ) c2 . map-gpv (λ((r , s2 ), s1 ). (r , s2 , s1 )) id (inline callee1
(callee2 s2 c2 ) s1 )) gpv (s2 , s1 ) =map-spmf (map-sum id (λ(x , rpv ′′, rpv ′, rpv). (x , λr . bind-gpv (rpv ′′ r)
(λ(r1 , s1 ). map-gpv (λ((r2 , s2 ), s1 ). (r2 , s2 , s1 )) id (inline callee1 (rpv ′
r1 ) s1 )), rpv)))(inline2 gpv s2 s1 )
(is ?lhs = ?rhs)proof(rule spmf .leq-antisym)
show ord-spmf op = ?lhs ?rhsproof(induction arbitrary : gpv s2 s1 rule: inline1-fixp-induct)
case (step inline1 ′) show ?caseby(rewrite inline2 .simps)(auto simp add : map-spmf-bind-spmf o-def inline-sel
gpv .map-sel bind-map-spmf id-def [symmetric] gpv .map-id map-gpv-bind-gpv split-defintro!: ord-spmf-bind-reflI step.IH [THEN spmf .leq-trans] split : generat .split sum.split)
qed simp-allshow ord-spmf op = ?rhs ?lhsproof(induction arbitrary : gpv s2 s1 rule: inline2-fixp-induct)case (step inline2 ′)show ?case
apply(rewrite in ord-spmf - - ◊ inline1 .simps)apply(clarsimp simp add : map-spmf-bind-spmf bind-rpv-def o-def gpv .map-sel
bind-map-spmf inline-sel map-gpv-bind-gpv id-def [symmetric] gpv .map-id split-defsplit : generat .split sum.split intro!: ord-spmf-bind-reflI )
apply(rule spmf .leq-trans[OF spmf .leq-trans, OF - step.IH ])apply(auto simp add : split-def id-def [symmetric] intro!: ord-spmf-reflI )done
qed simp-allqed
lemma inline-assoc:inline callee1 (inline callee2 gpv s2 ) s1 =map-gpv (λ(r , s2 , s1 ). ((r , s2 ), s1 )) id (inline (λ(s2 , s1 ) c2 . map-gpv (λ((r ,
s2 ), s1 ). (r , s2 , s1 )) id (inline callee1 (callee2 s2 c2 ) s1 )) gpv (s2 , s1 ))proof(coinduction arbitrary : s2 s1 gpv rule: gpv-coinduct-bind [where ? ′b = ( ′r2× ′s2 ) × ′s1 and ? ′c = ( ′r2 × ′s2 ) × ′s1 ])
case (Eq-gpv s2 s1 gpv)have ∃ gpv2 gpv2 ′ (f :: ( ′r2 × ′s2 ) × ′s1 ⇒ -) (f ′ :: ( ′r2 × ′s2 ) × ′s1 ⇒ -).
bind-gpv (bind-gpv (rpv ′′ r) (λ(r1 , s1 ). inline callee1 (rpv ′ r1 ) s1 )) (λ((r2 ,s2 ), s1 ). inline callee1 (inline callee2 (rpv r2 ) s2 ) s1 ) = gpv2 >>= f ∧
bind-gpv (bind-gpv (rpv ′′ r) (λ(r1 , s1 ). inline callee1 (rpv ′ r1 ) s1 ))(λ((r2 , s2 ), s1 ). map-gpv (λ(r , s2 , y). ((r , s2 ), y)) id (inline (λ(s2 , s1 ) c2 .map-gpv (λ((r , s2 ), s1 ). (r , s2 , s1 )) id (inline callee1 (callee2 s2 c2 ) s1 )) (rpvr2 ) (s2 , s1 ))) = gpv2 ′ >>= f ′ ∧
rel-gpv (λx y . ∃ s2 s1 gpv . f x = inline callee1 (inline callee2 gpv s2 ) s1 ∧f ′ y = map-gpv (λ(r , s2 , y). ((r , s2 ), y)) id (inline (λ(s2 , s1 ) c2 .
map-gpv (λ((r , s2 ), s1 ). (r , s2 , s1 )) id (inline callee1 (callee2 s2 c2 ) s1 )) gpv(s2 , s1 )))
op = gpv2 gpv2 ′
216
for rpv ′′ :: ( ′r1 × ′s1 , ′c, ′r) rpv and rpv ′ :: ( ′r2 × ′s2 , ′c1 , ′r1 ) rpv and rpv:: ( ′a, ′c2 , ′r2 ) rpv and r :: ′r
by(auto intro!: exI gpv .rel-refl)then show ?case
apply(subst inline-sel)apply(subst gpv .map-sel)apply(subst inline-sel)apply(subst inline1-inline-conv-inline2 )apply(subst inline1-inline-conv-inline2 ′)
apply(unfold spmf .map-comp o-def case-sum-map-sum spmf-rel-map generat .rel-map)apply(rule rel-spmf-reflI )subgoal for lr by(cases lr)(auto del : disjCI intro!: rel-funI disjI2 simp add :
split-def map-gpv-conv-bind [folded id-def ] bind-gpv-assoc)done
qed
end
lemma set-inline2-lift-spmf1 : set-spmf (inline2 (λs x . lift-spmf (p s x )) callee gpvs s ′) ⊆ range Inlapply(induction arbitrary : gpv s s ′ rule: inline2-fixp-induct)subgoal by(rule cont-intro ccpo-class.admissible-leI )+apply(auto simp add : set-bind-spmf o-def bind-UNION split : generat .split-asmsum.split-asm dest !: in-set-inline1-lift-spmf1 )apply blastdone
lemma in-set-inline2-lift-spmf1 : y ∈ set-spmf (inline2 (λs x . lift-spmf (p s x ))callee gpv s s ′) =⇒ ∃ r s s ′. y = Inl (r , s, s ′)by(drule set-inline2-lift-spmf1 [THEN subsetD ]) auto
lemma interaction-bound-inline1 ′:assumes (
∧s x . interaction-bound (callee s x ) ≤ q)
shows interaction-bound gpv ≤ p=⇒ set-spmf (inline1 callee gpv s) ⊆ Inr (out , c ′, rpv) | out c ′ rpv .
(∀ input . eSuc (interaction-bound (c ′ input)) ≤ q) ∧(∀ x . eSuc (interaction-bound (rpv x )) ≤ p)∪ range Inl
proof(induction arbitrary : gpv s rule: inline1-fixp-induct) case adm show ?case by(rule cont-intro ccpo-class.admissible-leI )+ case bottom show ?case by simp case (step inline1 ′)have ∗:
∧out c input . IO out c ∈ set-spmf (the-gpv gpv) =⇒ eSuc (interaction-bound
(c input)) ≤ pby(erule interaction-bound-IO [THEN order-trans])(rule step.prems)
have ∗∗:∧
out c s x input . IO out c ∈ set-spmf (the-gpv (callee s x )) =⇒ eSuc(interaction-bound (c input)) ≤ q
using interaction-bound-IO assms by(rule order-trans)show ?case
217
by(auto 6 4 simp add : set-bind-spmf bind-UNION del : subsetI intro!: UN-leaststep.IH assms ∗ ∗∗ order-trans[OF ile-eSuc ∗] split : generat .split)qed
lemma interaction-bound-inline1 :[[ Inr (out , c ′, rpv) ∈ set-spmf (inline1 callee gpv s);
interaction-bound gpv ≤ p;∧
s x . interaction-bound (callee s x ) ≤ q ]]=⇒ eSuc (interaction-bound (c ′ input)) ≤ q ∧ eSuc (interaction-bound (rpv x ))≤ pusing interaction-bound-inline1 ′[where callee=callee and q=q and gpv=gpv andp=p and s=s] by auto
lemma interaction-bounded-by-inline1 :[[ Inr (out , c ′, rpv) ∈ set-spmf (inline1 callee gpv s);
interaction-bounded-by gpv p;∧
s x . interaction-bounded-by (callee s x ) q ]]=⇒ q 6= 0 ∧ interaction-bounded-by (c ′ input) (q − 1 ) ∧ p 6= 0 ∧ interaction-bounded-by
(rpv x ) (p − 1 )unfolding interaction-bounded-by .simpsapply(drule (1 ) interaction-bound-inline1 [where input=input and x=x ], assump-tion)apply(cases p q rule: nat .exhaust [case-product nat .exhaust ])apply(simp-all add : zero-enat-def [symmetric] eSuc-enat [symmetric])done
lemma interaction-bounded-by-inline [interaction-bound ]:fixes callee :: ′s ⇒ ′call ⇒ ( ′ret × ′s, ′call ′, ′ret ′) gpvand gpv :: ( ′a, ′call , ′ret) gpvassumes p: interaction-bounded-by gpv pand q :
∧s x . interaction-bounded-by (callee s x ) q
shows interaction-bounded-by (inline callee gpv s) (p ∗ q)proof −
fix xdef gpv ′ ≡ Done (x , s) :: ( ′ret × ′s, ′call ′, ′ret ′) gpv
and r ≡ 0 :: nat and rpv ≡ (λ-. gpv) :: ( ′a, ′call , ′ret) rpvwith p have interaction-bounded-by gpv ′ r
∧y . interaction-bounded-by (rpv y) p
by simp-allhence interaction-bound (bind-gpv gpv ′ (λ(y , s). inline callee (rpv y) s)) ≤ enat
(r + p ∗ q)proof(coinduction arbitrary : gpv ′ rpv p r rule: interaction-bound-coinduct)
case [rule-format ]: (interaction-bound out c input gpv ′ rpv p r)from 〈IO out c ∈ set-spmf (the-gpv (gpv ′ >>= (λ(y , s). inline callee (rpv y)
s)))〉
obtain generat where generat : generat ∈ set-spmf (the-gpv gpv ′)and ∗: IO out c ∈ set-spmf (if is-Pure generat then the-gpv (case result generat
of (y , s) ⇒ inline callee (rpv y) s)else return-spmf (IO (output generat) (λinput . continuation generat
input >>= (λ(y , s). inline callee (rpv y) s))))by(clarsimp simp add : set-bind-spmf )
show ?case
218
proof(cases generat)case (Pure ys)obtain y s where ys [simp]: ys = (y , s) by(cases ys)from Pure ∗ have IO out c ∈ set-spmf (the-gpv (inline callee (rpv y) s)) by
simpthen obtain c ′ rpv ′ where c ′rpv : Inr (out , c ′, rpv ′) ∈ set-spmf (inline1
callee (rpv y) s)and c: c = (λinput . c ′ input >>= (λ(x , s). inline callee (rpv ′ x ) s))by(clarsimp simp add : inline-sel split : sum.split-asm)
from interaction-bounded-by-inline1 [OF c ′rpv interaction-bound(2 ) q ]have q 6= 0 and c ′: interaction-bounded-by (c ′ input) (q − 1 )and p 6= 0 and rpv ′:
∧x . interaction-bounded-by (rpv ′ x ) (p − 1 ) by blast+
let ?n = (q − 1 ) + (p − 1 ) ∗ qhave eSuc ?n ≤ r + p ∗ q using 〈q 6= 0 〉 〈p 6= 0 〉
by(clarsimp simp add : eSuc-enat gr0-conv-Suc)then show ?thesis unfolding c using c ′ rpv ′ q by blast
nextcase (IO out ′ c ′)with ∗ have c: c = (λinput . c ′ input >>= (λ(y , s). inline callee (rpv y) s))
and [simp]: out ′ = out by simp-allfrom 〈interaction-bounded-by gpv ′ r 〉 generat IOhave r > 0 and c ′: interaction-bounded-by (c ′ input) (r − 1 )
by(auto dest : interaction-bounded-by-IO)let ?n = (r − 1 ) + p ∗ qhave eSuc ?n ≤ r + p ∗ q using 〈r > 0 〉 by(clarsimp simp add : gr0-conv-Suc
eSuc-enat)then show ?thesis unfolding c using c ′ interaction-bound(2 ) by blast
qedqedthen show ?thesis unfolding gpv ′-def rpv-def r-def interaction-bounded-by .simps
by simpqed
contextfixes I :: ( ′call , ′ret) Iand I ′ :: ( ′call ′, ′ret ′) Iand callee :: ′s ⇒ ′call ⇒ ( ′ret × ′s, ′call ′, ′ret ′) gpvassumes results:
∧s x . x ∈ outs-I I =⇒ results-gpv I ′ (callee s x ) ⊆ responses-I
I x × UNIVbegin
lemma inline1-in-sub-gpvs-callee:assumes Inr (out , callee ′, rpv ′) ∈ set-spmf (inline1 callee gpv s)and WT : I `g gpv
√
shows ∃ call∈outs-I I. ∃ s. ∀ x ∈ responses-I I ′ out . callee ′ x ∈ sub-gpvs I ′(callee s call)proof −
from WThave set-spmf (inline1 callee gpv s) ⊆ Inr (out , callee ′, rpv ′) | out callee ′ rpv ′.
219
∃ call∈outs-I I. ∃ s. ∀ x ∈ responses-I I ′ out . callee ′ x ∈ sub-gpvs I ′ (callee scall) ∪ range Inl
(is ?concl (inline1 callee) gpv s)proof(induction arbitrary : gpv s rule: inline1-fixp-induct)
case adm show ?case by(intro cont-intro ccpo-class.admissible-leI )case bottom show ?case by simpcase (step inline1 ′) fix out c
assume IO : IO out c ∈ set-spmf (the-gpv gpv)from step.prems IO have out : out ∈ outs-I I by(rule WT-gpvD) fix x s ′
assume Pure: Pure (x , s ′) ∈ set-spmf (the-gpv (callee s out))then have (x , s ′) ∈ results-gpv I ′ (callee s out) by(rule results-gpv .Pure)with out have x ∈ responses-I I out by(auto dest : results)with step.prems IO have I `g c x
√by(rule WT-gpvD)
hence ?concl inline1 ′ (c x ) s ′ by(rule step.IH ) moreover
fix out ′ c ′
assume IO out ′ c ′ ∈ set-spmf (the-gpv (callee s out))hence ∀ x∈responses-I I ′ out ′. c ′ x ∈ sub-gpvs I ′ (callee s out)
by(auto intro: sub-gpvs.base)then have ∃ call∈outs-I I. ∃ s. ∀ x∈responses-I I ′ out ′. c ′ x ∈ sub-gpvs I ′
(callee s call)using out by blast
moreover note calculation then show ?case using step.prems
by(auto del : subsetI simp add : set-bind-spmf bind-UNION intro!: UN-leastsplit : generat .split)
qedthus ?thesis using assms by fastforce
qed
lemma inline1-in-sub-gpvs:assumes Inr (out , callee ′, rpv ′) ∈ set-spmf (inline1 callee gpv s)and (x , s ′) ∈ results-gpv I ′ (callee ′ input)and input ∈ responses-I I ′ outand I `g gpv
√
shows rpv ′ x ∈ sub-gpvs I gpvproof −
from 〈I `g gpv√
〉
have set-spmf (inline1 callee gpv s) ⊆ Inr (out , callee ′, rpv ′) | out callee ′ rpv ′.∀ input ∈ responses-I I ′ out . ∀ (x , s ′)∈results-gpv I ′ (callee ′ input). rpv ′ x ∈
sub-gpvs I gpv∪ range Inl (is ?concl (inline1 callee) gpv s is - ⊆ ?rhs gpv s)
proof(induction arbitrary : gpv s rule: inline1-fixp-induct)case adm show ?case by(intro cont-intro ccpo-class.admissible-leI )case bottom show ?case by simp
nextcase (step inline1 ′)
220
fix out cassume IO : IO out c ∈ set-spmf (the-gpv gpv)from step.prems IO have out : out ∈ outs-I I by(rule WT-gpvD) fix x s ′
assume Pure: Pure (x , s ′) ∈ set-spmf (the-gpv (callee s out))then have (x , s ′) ∈ results-gpv I ′ (callee s out) by(rule results-gpv .Pure)with out have x ∈ responses-I I out by(auto dest : results)with step.prems IO have I `g c x
√by(rule WT-gpvD)
hence ?concl inline1 ′ (c x ) s ′ by(rule step.IH )also have . . . ⊆ ?rhs gpv s ′ using IO Pure
by(fastforce intro: sub-gpvs.cont dest : WT-gpv-OutD [OF step.prems]results[THEN subsetD , OF - results-gpv .Pure])
finally have set-spmf (inline1 ′ (c x ) s ′) ⊆ . . . . moreover
fix out ′ c ′ input x s ′
assume IO out ′ c ′ ∈ set-spmf (the-gpv (callee s out))and input ∈ responses-I I ′ out ′ and (x , s ′) ∈ results-gpv I ′ (c ′ input)
then have c x ∈ sub-gpvs I gpv using IOby(auto intro!: sub-gpvs.base dest : WT-gpv-OutD [OF step.prems] re-
sults[THEN subsetD , OF - results-gpv .IO ]) moreover note calculation
then show ?caseby(auto simp add : set-bind-spmf bind-UNION intro!: UN-least split : gen-
erat .split del : subsetI )qedwith assms show ?thesis by fastforce
qed
contextassumes WT :
∧x s. x ∈ outs-I I =⇒ I ′ `g callee s x
√
begin
lemma WT-gpv-inline1 :assumes Inr (out , rpv , rpv ′) ∈ set-spmf (inline1 callee gpv s)and I `g gpv
√
shows out ∈ outs-I I ′ (is ?thesis1 )and input ∈ responses-I I ′ out =⇒ I ′ `g rpv input
√(is PROP ?thesis2 )
and [[ input ∈ responses-I I ′ out ; (x , s ′) ∈ results-gpv I ′ (rpv input) ]] =⇒ I `grpv ′ x
√(is PROP ?thesis3 )
proof −from 〈I `g gpv
√〉
have set-spmf (inline1 callee gpv s) ⊆ Inr (out , rpv , rpv ′) | out rpv rpv ′. out∈ outs-I I ′ ∪ range Inl
proof(induction arbitrary : gpv s rule: inline1-fixp-induct) case adm show ?case by(intro cont-intro ccpo-class.admissible-leI ) case bottom show ?case by simp case (step inline1 ′) fix out c
assume IO : IO out c ∈ set-spmf (the-gpv gpv)
221
from step.prems IO have out : out ∈ outs-I I by(rule WT-gpvD) fix x s ′
assume Pure: Pure (x , s ′) ∈ set-spmf (the-gpv (callee s out))then have (x , s ′) ∈ results-gpv I ′ (callee s out) by(rule results-gpv .Pure)with out have x ∈ responses-I I out by(auto dest : results)with step.prems IO have I `g c x
√by(rule WT-gpvD)
moreover fix out ′ c ′
from out have I ′ `g callee s out√
by(rule WT )moreover assume IO out ′ c ′ ∈ set-spmf (the-gpv (callee s out))ultimately have out ′ ∈ outs-I I ′ by(rule WT-gpvD)
moreover note calculation then show ?case
by(auto del : subsetI simp add : set-bind-spmf bind-UNION intro!: UN-leastsplit : generat .split intro!: step.IH [THEN order-trans])
qedthen show ?thesis1 using assms by auto
assume input ∈ responses-I I ′ outwith inline1-in-sub-gpvs-callee[OF 〈Inr - ∈ -〉] 〈I `g gpv
√〉
obtain out ′ s where out ′ ∈ outs-I Iand ∗: rpv input ∈ sub-gpvs I ′ (callee s out ′) by auto
from 〈out ′ ∈ -〉 have I ′ `g callee s out ′√
by(rule WT )then show I ′ `g rpv input
√using ∗ by(rule WT-sub-gpvsD)
assume (x , s ′) ∈ results-gpv I ′ (rpv input)with 〈Inr - ∈ -〉 have rpv ′ x ∈ sub-gpvs I gpv
using 〈input ∈ -〉 〈I `g gpv√
〉 by(rule inline1-in-sub-gpvs)with 〈I `g gpv
√〉 show I `g rpv ′ x
√by(rule WT-sub-gpvsD)
qed
lemma WT-gpv-inline:assumes I `g gpv
√
shows I ′ `g inline callee gpv s√
using assmsproof(coinduction arbitrary : gpv s rule: WT-gpv-coinduct-bind)
case (WT-gpv out c gpv)from 〈IO out c ∈ -〉 obtain callee ′ rpv ′
where Inr : Inr (out , callee ′, rpv ′) ∈ set-spmf (inline1 callee gpv s)and c: c = (λinput . callee ′ input >>= (λ(x , s). inline callee (rpv ′ x ) s))by(clarsimp simp add : inline-sel split : sum.split-asm)
from Inr 〈I `g gpv√
〉 have ?out by(rule WT-gpv-inline1 )moreover have ?cont TYPE ( ′ret × ′s) (is ∀ input∈-. - ∨ - ∨ ?case ′ input)proof(rule ballI disjI2 )+
fix inputassume input ∈ responses-I I ′ outwith Inr 〈I `g gpv
√〉have I ′ `g callee ′ input
√
and∧
x s ′. (x , s ′) ∈ results-gpv I ′ (callee ′ input) =⇒ I `g rpv ′ x√
by(blast intro: WT-gpv-inline1 )+
222
then show ?case ′ input by(subst c)(auto 4 4 )qedultimately show ?case TYPE ( ′ret × ′s) ..
qed
end
contextfixes gpv :: ( ′a, ′call , ′ret) gpvassumes gpv : lossless-gpv I gpv I `g gpv
√
begin
lemma lossless-spmf-inline1 :assumes lossless:
∧s x . x ∈ outs-I I =⇒ lossless-spmf (the-gpv (callee s x ))
shows lossless-spmf (inline1 callee gpv s)using gpvproof(induction arbitrary : s rule: lossless-WT-gpv-induct)
case (lossless-gpv p)show ?case using 〈lossless-spmf p〉
apply(subst inline1-unfold)apply(auto split : generat .split intro: lossless lossless-gpv .hyps dest : results[THEN
subsetD , rotated , OF results-gpv .Pure] intro: lossless-gpv .IH )done
qed
lemma lossless-gpv-inline1 :assumes ∗: Inr (out , rpv , rpv ′) ∈ set-spmf (inline1 callee gpv s)and ∗∗: input ∈ responses-I I ′ outand lossless:
∧s x . x ∈ outs-I I =⇒ lossless-gpv I ′ (callee s x )
shows lossless-gpv I ′ (rpv input)proof −
from inline1-in-sub-gpvs-callee[OF ∗ gpv(2 )] ∗∗obtain out ′ s where out ′ ∈ outs-I I and ∗∗∗: rpv input ∈ sub-gpvs I ′ (callee
s out ′) by blastfrom 〈out ′ ∈ -〉 have lossless-gpv I ′ (callee s out ′) by(rule lossless)thus ?thesis using ∗∗∗ by(rule lossless-sub-gpvsD)
qed
lemma lossless-results-inline1 :assumes Inr (out , rpv , rpv ′) ∈ set-spmf (inline1 callee gpv s)and (x , s ′) ∈ results-gpv I ′ (rpv input)and input ∈ responses-I I ′ outshows lossless-gpv I (rpv ′ x )
proof −from assms gpv(2 ) have rpv ′ x ∈ sub-gpvs I gpv by(rule inline1-in-sub-gpvs)with gpv(1 ) show lossless-gpv I (rpv ′ x ) by(rule lossless-sub-gpvsD)
qed
end
223
lemmas lossless-inline1 [rotated 2 ] = lossless-spmf-inline1 lossless-gpv-inline1 lossless-results-inline1
lemma lossless-inline[rotated ]:fixes gpv :: ( ′a, ′call , ′ret) gpvassumes gpv : lossless-gpv I gpv I `g gpv
√
and lossless:∧
s x . x ∈ outs-I I =⇒ lossless-gpv I ′ (callee s x )shows lossless-gpv I ′ (inline callee gpv s)
using gpvproof(induction arbitrary : s rule: lossless-WT-gpv-induct-strong)
case (lossless-gpv p)have lp: lossless-gpv I (GPV p) by(rule lossless-sub-gpvsI )(auto intro: lossless-gpv .hyps)moreover have wp: I `g GPV p
√by(rule WT-sub-gpvsI )(auto intro: lossless-gpv .hyps)
ultimately have lossless-spmf (the-gpv (inline callee (GPV p) s))by(auto simp add : inline-sel intro: lossless-spmf-inline1 lossless-gpv-lossless-spmfD [OF
lossless])moreover
fix out c inputassume IO : IO out c ∈ set-spmf (the-gpv (inline callee (GPV p) s))
and input ∈ responses-I I ′ outfrom IO obtain callee ′ rpv
where Inr : Inr (out , callee ′, rpv) ∈ set-spmf (inline1 callee (GPV p) s)and c: c = (λinput . callee ′ input >>= (λ(x , y). inline callee (rpv x ) y))by(clarsimp simp add : inline-sel split : sum.split-asm)
from Inr 〈input ∈ -〉 lossless lp wp have lossless-gpv I ′ (callee ′ input) by(rulelossless-inline1 )
moreover fix x s ′
assume (x , s ′) ∈ results-gpv I ′ (callee ′ input)with Inr have rpv x ∈ sub-gpvs I (GPV p) using 〈input ∈ -〉 wp by(rule
inline1-in-sub-gpvs)hence lossless-gpv I ′ (inline callee (rpv x ) s ′) by(rule lossless-gpv .IH )
ultimately have lossless-gpv I ′ (c input) unfolding c by clarsimp ultimately show ?case by(rule lossless-gpvI )
qed
end
definition id-oracle :: ′s ⇒ ′call ⇒ ( ′ret × ′s, ′call , ′ret) gpvwhere id-oracle s x = Pause x (λx . Done (x , s))
lemma inline1-id-oracle:inline1 id-oracle gpv s =map-spmf (λgenerat . case generat of Pure x ⇒ Inl (x , s) | IO out c ⇒ Inr (out ,
λx . Done (x , s), c)) (the-gpv gpv)by(subst inline1 .simps)(auto simp add : id-oracle-def map-spmf-conv-bind-spmf in-tro!: bind-spmf-cong split : generat .split)
lemma inline-id-oracle [simp]: inline id-oracle gpv s = map-gpv (λx . (x , s)) id
224
gpvby(coinduction arbitrary : gpv s)(auto 4 3 simp add : inline-sel inline1-id-oraclespmf-rel-map gpv .map-sel o-def generat .rel-map intro!: rel-spmf-reflI rel-funI split :generat .split)
7.15 Running GPVs
type-synonym ( ′call , ′ret , ′s) callee = ′s ⇒ ′call ⇒ ( ′ret × ′s) spmf
context fixes callee :: ( ′call , ′ret , ′s) callee notes [[function-internals]] begin
partial-function (spmf ) exec-gpv :: ( ′a, ′call , ′ret) gpv ⇒ ′s ⇒ ( ′a × ′s) spmfwhere
exec-gpv c s =the-gpv c >>=
case-generat (λx . return-spmf (x , s))(λout c. callee s out >>= (λ(x , y). exec-gpv (c x ) y))
abbreviation run-gpv :: ( ′a, ′call , ′ret) gpv ⇒ ′s ⇒ ′a spmfwhere run-gpv gpv s ≡ map-spmf fst (exec-gpv gpv s)
lemma exec-gpv-fixp-induct [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λf . P
(λc s. f (c, s)))and P (λ- -. return-pmf None)and
∧exec-gpv . P exec-gpv =⇒
P (λc s. the-gpv c >>= case-generat (λx . return-spmf (x , s)) (λout c. callee sout >>= (λ(x , y). exec-gpv (c x ) y)))
shows P exec-gpvusing assms(1 )by(rule exec-gpv .fixp-induct [unfolded curry-conv [abs-def ]])(simp-all add : assms(2−))
lemma exec-gpv-fixp-induct-strong [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λf . P
(λc s. f (c, s)))and P (λ- -. return-pmf None)and
∧exec-gpv ′. [[
∧c s. ord-spmf op = (exec-gpv ′ c s) (exec-gpv c s); P exec-gpv ′
]]=⇒ P (λc s. the-gpv c >>= case-generat (λx . return-spmf (x , s)) (λout c. callee
s out >>= (λ(x , y). exec-gpv ′ (c x ) y)))shows P exec-gpv
using assmsby(rule spmf .fixp-strong-induct-uc[where P=λf . P (curry f ) and U =case-prodand C =curry , OF exec-gpv .mono exec-gpv-def , unfolded curry-case-prod , unfoldedcurry-conv [abs-def ] fun-ord-def split-paired-All prod .case case-prod-eta, OF refl ])blast
lemma exec-gpv-fixp-induct-strong2 [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λf . P
225
(λc s. f (c, s)))and P (λ- -. return-pmf None)and
∧exec-gpv ′.
[[∧
c s. ord-spmf op = (exec-gpv ′ c s) (exec-gpv c s);∧c s. ord-spmf op = (exec-gpv ′ c s) (the-gpv c >>= case-generat (λx .
return-spmf (x , s)) (λout c. callee s out >>= (λ(x , y). exec-gpv ′ (c x ) y)));P exec-gpv ′ ]]
=⇒ P (λc s. the-gpv c >>= case-generat (λx . return-spmf (x , s)) (λout c. callees out >>= (λ(x , y). exec-gpv ′ (c x ) y)))
shows P exec-gpvusing assmsby(rule spmf .fixp-induct-strong2-uc[where P=λf . P (curry f ) and U =case-prodand C =curry , OF exec-gpv .mono exec-gpv-def , unfolded curry-case-prod , unfoldedcurry-conv [abs-def ] fun-ord-def split-paired-All prod .case case-prod-eta, OF refl ])blast+
end
lemma exec-gpv-conv-inline1 :exec-gpv callee gpv s = map-spmf projl (inline1 (λs c. lift-spmf (callee s c) :: (-,
unit , unit) gpv) gpv s)proof(induction arbitrary : gpv s rule: parallel-fixp-induct-2-2 [OF partial-function-definitions-spmfpartial-function-definitions-spmf exec-gpv .mono inline1 .mono exec-gpv-def inline1-def ,unfolded lub-spmf-empty , case-names adm bottom step])
case adm show ?caseapply simpapply(rule cont-intro ccpo-rel-prodI )+apply(rule spmf .mcont2mcont [OF mcont-call ])apply(rule mcont-fst)
apply(rule mcont-map-spmf )apply(rule spmf .mcont2mcont [OF mcont-call ])apply(rule mcont-snd)
doneqed(auto simp add : map-spmf-bind-spmf o-def spmf .map-comp bind-map-spmf split-defintro!: bind-spmf-cong [OF refl ] split : generat .split)
lemma exec-gpv-simps:exec-gpv callee gpv s =the-gpv gpv >>=
case-generat (λx . return-spmf (x , s))(λout rpv . callee s out >>= (λ(x , y). exec-gpv callee (rpv x ) y))
by(fact exec-gpv .simps)
lemma exec-gpv-lift-spmf [simp]:exec-gpv callee (lift-spmf p) s = bind-spmf p (λx . return-spmf (x , s))
by(simp add : exec-gpv-conv-inline1 spmf .map-comp o-def map-spmf-conv-bind-spmf )
lemma exec-gpv-Done [simp]: exec-gpv callee (Done x ) s = return-spmf (x , s)by(simp add : exec-gpv-conv-inline1 )
226
lemma exec-gpv-Fail [simp]: exec-gpv callee Fail s = return-pmf Noneby(simp add : exec-gpv-conv-inline1 )
lemma if-distrib-exec-gpv [if-distribs]:exec-gpv callee (if b then x else y) s = (if b then exec-gpv callee x s else exec-gpv
callee y s)by simp
lemmas exec-gpv-fixp-parallel-induct [case-names adm bottom step] =parallel-fixp-induct-2-2 [OF partial-function-definitions-spmf partial-function-definitions-spmf
exec-gpv .mono exec-gpv .mono exec-gpv-def exec-gpv-def , unfolded lub-spmf-empty ]
context begin interpretation lifting-syntax .
lemma exec-gpv-parametric [transfer-rule]:fixes A :: ′a ⇒ ′b ⇒ booland CALL :: ′call ⇒ ′call ′⇒ booland S :: ′s ⇒ ′s ′⇒ boolshows((S ===> CALL ===> rel-spmf (rel-prod (op = :: ′ret ⇒ -) S )) ===> rel-gpv
A CALL ===> S ===> rel-spmf (rel-prod A S ))exec-gpv exec-gpv
apply(rule rel-funI )+apply(unfold spmf-rel-map exec-gpv-conv-inline1 )apply(rule rel-spmf-mono-strong)apply(erule inline1-parametric[THEN rel-funD , THEN rel-funD , THEN rel-funD ,
rotated ])prefer 3apply(drule in-set-inline1-lift-spmf1 )+apply fastforce
subgoal by simpsubgoal premises [transfer-rule] by transfer-proverdone
end
lemma exec-gpv-bind : exec-gpv callee (c >>= f ) s = exec-gpv callee c s >>= (λ(x ,s ′) ⇒ exec-gpv callee (f x ) s ′)by(auto simp add : exec-gpv-conv-inline1 inline1-bind-gpv map-spmf-bind-spmf o-defbind-map-spmf intro!: bind-spmf-cong [OF refl ] dest : in-set-inline1-lift-spmf1 )
lemma exec-gpv-map-gpv-id :exec-gpv oracle (map-gpv f id gpv) σ = map-spmf (apfst f ) (exec-gpv oracle gpv
σ)proof(rule sym)
def gpv ′ ≡ map-gpv f id gpvhave [transfer-rule]: rel-gpv (λx y . y = f x ) op = gpv gpv ′
unfolding gpv ′-def by(simp add : gpv .rel-map gpv .rel-refl)
227
have rel-spmf (rel-prod (λx y . y = f x ) op =) (exec-gpv oracle gpv σ) (exec-gpvoracle gpv ′ σ)
by transfer-proverthus map-spmf (apfst f ) (exec-gpv oracle gpv σ) = exec-gpv oracle (map-gpv f
id gpv) σunfolding spmf-rel-eq [symmetric] gpv ′-def spmf-rel-map by(rule rel-spmf-mono)
clarsimpqed
lemma exec-gpv-Pause [simp]:exec-gpv callee (Pause out f ) s = callee s out >>= (λ(x , s ′). exec-gpv callee (f x )
s ′)by(simp add : inline1-Pause map-spmf-bind-spmf bind-map-spmf o-def exec-gpv-conv-inline1split-def )
lemma exec-gpv-inline:fixes callee :: ′s ⇒ ′c ⇒ ( ′r × ′s) spmfand gpv :: ′s ′⇒ ′c ′⇒ ( ′r ′ × ′s ′, ′c, ′r) gpvshows exec-gpv callee (inline gpv c ′ s ′) s =
map-spmf (λ(x , s ′, s). ((x , s ′), s)) (exec-gpv (λ(s ′, s) y . map-spmf (λ((x , s ′),s). (x , s ′, s)) (exec-gpv callee (gpv s ′ y) s)) c ′ (s ′, s))
(is ?lhs = ?rhs)proof −
have ?lhs = map-spmf projl (map-spmf (map-sum (λ(x , s2 , y). ((x , s2 ), y))(λ(x , rpv ′′ :: ( ′r × ′s, unit , unit) rpv , rpv ′, rpv). (x , rpv ′′, λr1 . bind-gpv
(rpv ′ r1 ) (λ(r2 , y). inline gpv (rpv r2 ) y))))(inline2 (λs c. lift-spmf (callee s c)) gpv c ′ s ′ s))
unfolding exec-gpv-conv-inline1 by(simp add : inline1-inline-conv-inline2 )also have . . . = map-spmf (λ(x , s ′, s). ((x , s ′), s)) (map-spmf projl (map-spmf
(map-sum id(λ(x , rpv ′′ :: ( ′r × ′s, unit , unit) rpv , rpv ′, rpv). (x , λr . bind-gpv (rpv ′′
r) (λ(r1 , s1 ). map-gpv (λ((r2 , s2 ), s1 ). (r2 , s2 , s1 )) id (inline (λs c. lift-spmf(callee s c)) (rpv ′ r1 ) s1 )), rpv)))
(inline2 (λs c. lift-spmf (callee s c)) gpv c ′ s ′ s)))unfolding spmf .map-comp by(rule map-spmf-cong [OF refl ])(auto dest !: in-set-inline2-lift-spmf1 )also have . . . = ?rhs unfolding exec-gpv-conv-inline1
by(subst inline1-inline-conv-inline2 ′[symmetric])(simp add : spmf .map-compsplit-def inline-lift-spmf1 map-lift-spmf )
finally show ?thesis .qed
locale callee-invariant-base =fixes callee :: ′s ⇒ ′a ⇒ ( ′b × ′s) spmfand I :: ′s ⇒ bool
locale callee-invariant = callee-invariant-base+assumes callee-invariant :
∧s x y s ′. [[ (y , s ′) ∈ set-spmf (callee s x ); I s ]] =⇒
I s ′
228
begin
lemma exec-gpv-invariant ′:I s =⇒ set-spmf (exec-gpv callee gpv s) ⊆ (x , s ′). I s ′
proof(induction arbitrary : gpv s rule: exec-gpv-fixp-induct)case adm show ?case by(intro cont-intro ccpo-class.admissible-leI )case bottom show ?case by simpcase step thus ?caseby(auto simp add : set-bind-spmf bind-UNION intro!: UN-least del : subsetI split :
generat .split dest !: callee-invariant)qed
lemma exec-gpv-invariant :[[ (x , s ′) ∈ set-spmf (exec-gpv callee gpv s); I s ]] =⇒ I s ′
by(drule exec-gpv-invariant ′) blast
lemma interaction-bounded-by-exec-gpv-count ′:fixes countassumes bound : interaction-bounded-by gpv nand count :
∧s x y s ′. [[ (y , s ′) ∈ set-spmf (callee s x ); I s ]] =⇒ count s ′ ≤ Suc
(count s)and I : I sshows set-spmf (exec-gpv callee gpv s) ⊆ (x , s ′). count s ′ ≤ n + count s
using bound Iproof(induction arbitrary : gpv s n rule: exec-gpv-fixp-induct)
case adm show ?case by(intro cont-intro ccpo-class.admissible-leI )case bottom show ?case by simpcase (step exec-gpv ′) fix out c input s ′
assume out : IO out c ∈ set-spmf (the-gpv gpv)and input : (input , s ′) ∈ set-spmf (callee s out)
from step.prems out have n > 0and bound ′: interaction-bounded-by (c input) (n − 1 )by(auto dest : interaction-bounded-by-contD)
from input 〈I s〉 have I s ′ by(rule callee-invariant)with bound ′ have set-spmf (exec-gpv ′ (c input) s ′) ⊆ (x , s ′′). count s ′′ ≤ n
− 1 + count s ′by(rule step.IH )
also have . . . ⊆ (x , s ′′). count s ′′ ≤ n + count s using 〈n > 0 〉 count [OFinput 〈I s〉]
by(cases n rule: nat .exhaust)(auto)also note calculation
then show ?caseby(clarsimp simp add : set-bind-spmf bind-UNION del : subsetI intro!: UN-least
split : generat .split)qed
lemma interaction-bounded-by-exec-gpv-count :fixes count
229
assumes bound : interaction-bounded-by gpv nand xs ′: (x , s ′) ∈ set-spmf (exec-gpv callee gpv s)and count :
∧s x y s ′. [[ (y , s ′) ∈ set-spmf (callee s x ); I s ]] =⇒ count s ′ ≤ Suc
(count s)and I : I sshows count s ′ ≤ n + count s
using bound count I by(rule interaction-bounded-by-exec-gpv-count ′[THEN sub-setD , OF - - - xs ′, unfolded mem-Collect-eq prod .case])
lemma interaction-bounded-by-exec-gpv-bad ′:fixes badassumes bound : interaction-bounded-by gpv nand I : I sand not-bad : ¬ bad sand prob-bad :
∧s x . [[ I s; ¬ bad s ]] =⇒ spmf (map-spmf (bad snd) (callee s
x )) True ≤ kshows ereal (spmf (map-spmf (bad snd) (exec-gpv callee gpv s)) True) ≤ ereal
k ∗ nproof −
from prob-bad [OF I not-bad ] have k-nonneg : 0 ≤ k by (meson order-transpmf-nonneg)
show ?thesis using bound I not-badproof(induction arbitrary : n s gpv rule: exec-gpv-fixp-induct)
case adm show ?case by(intro cont-intro ccpo-class.admissible-leI )case bottom show ?case using k-nonneg by(cases n)simp-allcase (step exec-gpv ′)let ?M = restrict-space (measure-spmf (the-gpv gpv)) x . ¬ is-Pure xlet ?O = λgenerat . measure-spmf (callee s (output generat))have ereal (spmf (map-spmf (bad snd) (the-gpv gpv >>= case-generat (λx .
return-spmf (x , s)) (λout c. callee s out >>= (λ(x , y). exec-gpv ′ (c x ) y)))) True)=
∫+ generat . ereal (spmf (map-spmf (bad snd) (case generat of Pure x
⇒ return-spmf (x , s)| IO out c ⇒ callee s out >>= (λ(x , y). exec-gpv ′ (c x ) y))) True)
∂measure-spmf (the-gpv gpv)by(simp add : map-spmf-bind-spmf ereal-spmf-bind)
also have . . . =∫
+ generat . ereal (spmf (bind-spmf (callee s (output generat))(λ(x , s ′). map-spmf (bad snd) (exec-gpv ′ (continuation generat x ) s ′))) True)∂?M
by(auto simp add : nn-integral-restrict-space 〈¬ bad s〉 map-spmf-bind-spmfsplit-def o-def intro: nn-integral-cong split : generat .split)
also have . . . =∫
+ generat .∫
+ (x , s ′). ereal (spmf (map-spmf (bad snd)(exec-gpv ′ (continuation generat x ) s ′)) True) ∂?O generat ∂?M
by(simp add : ereal-spmf-bind split-def )also have . . . ≤
∫+ generat .
∫+ (x , s ′). (if bad s ′ then 1 else ereal k ∗ (n −
1 )) ∂?O generat ∂?Mproof(clarsimp simp add : AE-restrict-space-iff not-is-Pure-conv intro!: nn-integral-mono-AE
split del : split-if )fix out c x s ′
assume IO : IO out c ∈ set-spmf (the-gpv gpv)
230
and xs ′: (x , s ′) ∈ set-spmf (callee s out)from xs ′ 〈I s〉 have I s ′ by(rule callee-invariant)show ereal (spmf (map-spmf (bad snd) (exec-gpv ′ (c x ) s ′)) True) ≤ (if
bad s ′ then 1 else ereal k ∗ (n − 1 ))proof(cases bad s ′)
case Falsefrom step.prems(1 ) IO have interaction-bounded-by (c x ) (n − 1 )
by(blast dest : interaction-bounded-by-contD)then show ?thesis using 〈I s ′〉 False step.IH [of c x n − 1 s ′] by(simp add :
o-def )qed(simp add : pmf-le-1 )
qedalso have . . . =
∫+ generat .
∫+ b. indicator True b + ereal (k ∗ (n −
1 )) ∗ indicator False b ∂measure-spmf (map-spmf (bad snd) (callee s (outputgenerat))) ∂?M
(is - =∫
+ generat .∫
+ -. - ∂?O ′ generat ∂-)by(auto intro!: nn-integral-cong)
also have . . . =∫
+ generat . (∫
+ b. indicator True b ∂?O ′ generat) + erealk ∗ (n − 1 ) ∗
∫+ b. indicator False b ∂?O ′ generat ∂?M
by(subst nn-integral-add)(simp-all add : k-nonneg nn-integral-cmult o-def )also have . . . =
∫+ generat . spmf (map-spmf (bad snd) (callee s (output
generat))) True + k ∗ (n − 1 ) ∗ spmf (map-spmf (bad snd) (callee s (outputgenerat))) False ∂?M
by(simp del : nn-integral-map-spmf add : emeasure-spmf-single)also have . . . ≤
∫+ generat . ereal k ∗ n ∂?M
proof(clarsimp intro!: nn-integral-mono-AE simp add : AE-restrict-space-iffnot-is-Pure-conv simp del : One-nat-def )
fix out cassume IO out c ∈ set-spmf (the-gpv gpv)
hence n > 0 using step.prems(1 ) by(blast dest : interaction-bounded-by-contD)have spmf (map-spmf (bad snd) (callee s out)) True ≤ k (is ?o True ≤ -)
using 〈I s〉 〈¬ bad s〉 by(rule prob-bad)hence ?o True ≤ k by(simp del : o-apply)hence ?o True + k ∗ (n − 1 ) ∗ ?o False ≤ k + k ∗ (n − 1 ) ∗ 1
by(rule add-mono)(rule mult-left-mono, simp-all add : pmf-le-1 k-nonneg)also have . . . ≤ k ∗ n using 〈n > 0 〉
by(cases n)(auto simp add : zero-enat-def gr0-conv-Suc eSuc-enat [symmetric]of-nat-Suc field-simps)
finally show ?o True + k ∗ (n − 1 ) ∗ ?o False ≤ k ∗ n .qedalso have . . . ≤ k ∗ n ∗ 1by(simp add : k-nonneg emeasure-restrict-space measure-spmf .emeasure-eq-measure
space-restrict-space measure-spmf .subprob-measure-le-1 mult-left-mono del : mult-1-right)finally show ?case by(simp del : o-apply)
qedqed
lemma interaction-bounded-by-exec-gpv-bad :[[ interaction-bounded-by gpv n;
231
I s; ¬ bad s;∧s x . [[ I s; ¬ bad s ]] =⇒ spmf (map-spmf (bad snd) (callee s x )) True ≤
k ]]=⇒ spmf (map-spmf (bad snd) (exec-gpv callee gpv s)) True ≤ k ∗ n
by(drule (2 ) interaction-bounded-by-exec-gpv-bad ′;(assumption|simp))
end
interpretation oi-True: callee-invariant callee λ-. True for calleeby unfold-locales (simp-all)
inductive WT-callee :: ( ′call , ′ret) I ⇒ ( ′call ⇒ ( ′ret × ′s) spmf ) ⇒ bool ((-)`c/ (-)
√[100 , 0 ] 99 )
for I calleewhere
WT-callee:[[∧
call ret s. [[ call ∈ outs-I I; (ret , s) ∈ set-spmf (callee call) ]] =⇒ ret ∈responses-I I call ]]
=⇒ I `c callee√
lemmas WT-calleeI = WT-calleehide-fact WT-callee
lemma WT-calleeD : [[ I `c callee√
; (ret , s) ∈ set-spmf (callee out); out ∈ outs-II ]] =⇒ ret ∈ responses-I I outby(rule WT-callee.cases)
lemma WT-callee-top [intro!, simp]: I-top `c callee√
by(rule WT-calleeI ) simp
lemma (in callee-invariant) lossless-exec-gpv :assumes gpv : lossless-gpv I gpvand callee:
∧s out . [[ out ∈ outs-I I; I s ]] =⇒ lossless-spmf (callee s out)
and WT-gpv : I `g gpv√
and WT-callee:∧
s. I s =⇒ I `c callee s√
and I : I sshows lossless-spmf (exec-gpv callee gpv s)
using gpv WT-gpv Iproof(induction arbitrary : s rule: lossless-WT-gpv-induct)
case (lossless-gpv gpv)show ?case using lossless-gpv .hyps lossless-gpv .prems
by(subst exec-gpv .simps)(fastforce split : generat .split simp add : callee intro!:lossless-gpv .IH intro: WT-calleeD [OF WT-callee] elim!: callee-invariant)qed
lemma lossless-exec-gpv :[[ lossless-gpv I gpv ;
∧s out . out ∈ outs-I I =⇒ lossless-spmf (callee s out);
I `g gpv√
;∧
s. I `c callee s√
]]=⇒ lossless-spmf (exec-gpv callee gpv s)
232
by(rule oi-True.lossless-exec-gpv ; simp)
lemma (in callee-invariant) in-set-spmf-exec-gpv-into-results-gpv :assumes ∗: (x , s ′) ∈ set-spmf (exec-gpv callee gpv s)and WT-gpv : I `g gpv
√
and WT-callee:∧
s. I s =⇒ I `c callee s√
and I : I sshows x ∈ results-gpv I gpv
proof −have set-spmf (exec-gpv callee gpv s) ⊆ results-gpv I gpv × UNIV
using WT-gpv Iproof(induction arbitrary : gpv s rule: exec-gpv-fixp-induct) case adm show ?case by(intro cont-intro ccpo-class.admissible-leI ) case bottom show ?case by simp case (step exec-gpv ′) fix out c ret s ′
assume IO : IO out c ∈ set-spmf (the-gpv gpv)and ret : (ret , s ′) ∈ set-spmf (callee s out)
from step.prems(1 ) IO have out ∈ outs-I I by(rule WT-gpvD)with WT-callee[OF 〈I s〉] ret have ret ∈ responses-I I out by(rule WT-calleeD)with step.prems(1 ) IO have I `g c ret
√by(rule WT-gpvD)
moreover from ret 〈I s〉 have I s ′ by(rule callee-invariant)ultimately have set-spmf (exec-gpv ′ (c ret) s ′) ⊆ results-gpv I (c ret) ×
UNIVby(rule step.IH )
also have . . . ⊆ results-gpv I gpv × UNIV using IO 〈ret ∈ -〉
by(auto intro: results-gpv .IO)finally have set-spmf (exec-gpv ′ (c ret) s ′) ⊆ results-gpv I gpv × UNIV .
then show ?case using step.premsby(auto simp add : set-bind-spmf bind-UNION intro!: UN-least del : subsetI
split : generat .split intro: results-gpv .Pure)qedthus x ∈ results-gpv I gpv using ∗ by blast+
qed
endtheory GPV-Bisim imports
Generative-Probabilistic-Valuebegin
7.16 Bisimulation for oracles
Bisimulation is a consequence of parametricity
lemma exec-gpv-oracle-bisim ′:assumes ∗: X s1 s2and bisim:
∧s1 s2 x . X s1 s2 =⇒ rel-spmf (λ(a, s1 ′) (b, s2 ′). a = b ∧ X s1 ′
s2 ′) (oracle1 s1 x ) (oracle2 s2 x )shows rel-spmf (λ(a, s1 ′) (b, s2 ′). a = b ∧ X s1 ′ s2 ′) (exec-gpv oracle1 gpv s1 )
(exec-gpv oracle2 gpv s2 )
233
by(rule exec-gpv-parametric[of X op = op =, unfolded gpv .rel-eq rel-prod-conv ,THEN rel-funD , THEN rel-funD , THEN rel-funD , OF rel-funI refl , OF rel-funI∗])(simp add : bisim)
lemma exec-gpv-oracle-bisim:assumes ∗: X s1 s2and bisim:
∧s1 s2 x . X s1 s2 =⇒ rel-spmf (λ(a, s1 ′) (b, s2 ′). a = b ∧ X s1 ′
s2 ′) (oracle1 s1 x ) (oracle2 s2 x )and R:
∧x s1 ′ s2 ′. [[ X s1 ′ s2 ′; (x , s1 ′) ∈ set-spmf (exec-gpv oracle1 gpv s1 );
(x , s2 ′) ∈ set-spmf (exec-gpv oracle2 gpv s2 ) ]] =⇒ R (x , s1 ′) (x , s2 ′)shows rel-spmf R (exec-gpv oracle1 gpv s1 ) (exec-gpv oracle2 gpv s2 )
apply(rule spmf-rel-mono-strong)apply(rule exec-gpv-oracle-bisim ′[OF ∗ bisim])apply(auto dest : R)done
lemma run-gpv-oracle-bisim:assumes X s1 s2and
∧s1 s2 x . X s1 s2 =⇒ rel-spmf (λ(a, s1 ′) (b, s2 ′). a = b ∧ X s1 ′ s2 ′)
(oracle1 s1 x ) (oracle2 s2 x )shows run-gpv oracle1 gpv s1 = run-gpv oracle2 gpv s2
using exec-gpv-oracle-bisim ′[OF assms]by(fold spmf-rel-eq)(fastforce simp add : spmf-rel-map intro: rel-spmf-mono)
lemma rel-spmf-bindI ′:[[ rel-spmf A p q ;
∧x y . [[ A x y ; x ∈ set-spmf p; y ∈ set-spmf q ]] =⇒ rel-spmf B
(f x ) (g y) ]]=⇒ rel-spmf B (p >>= f ) (q >>= g)
apply(rule rel-spmf-bindI [where R=λx y . A x y ∧ x ∈ set-spmf p ∧ y ∈ set-spmfq ])apply(erule spmf-rel-mono-strong ; simp)
apply simpdone
contextfixes joint-oracle :: ( ′s1 × ′s2 ) ⇒ ′a ⇒ (( ′b × ′s1 ) × ( ′b × ′s2 )) spmfand oracle1 :: ′s1 ⇒ ′a ⇒ ( ′b × ′s1 ) spmfand bad1 :: ′s1 ⇒ booland oracle2 :: ′s2 ⇒ ′a ⇒ ( ′b × ′s2 ) spmfand bad2 :: ′s2 ⇒ bool
begin
partial-function (spmf ) exec-until-bad :: ( ′x , ′a, ′b) gpv ⇒ ′s1 ⇒ ′s2 ⇒ (( ′x ×′s1 ) × ( ′x × ′s2 )) spmfwhere
exec-until-bad gpv s1 s2 =bind-spmf (the-gpv gpv) (λgenerat .
case generat of Pure x ⇒ return-spmf ((x , s1 ), (x , s2 ))| IO out f ⇒ bind-spmf (joint-oracle (s1 , s2 ) out) (λ((x , s1 ′), (y , s2 ′)).
234
if bad1 s1 ′ ∨ bad2 s2 ′ then pair-spmf (exec-gpv oracle1 (f x ) s1 ′) (exec-gpvoracle2 (f y) s2 ′)
else exec-until-bad (f x ) s1 ′ s2 ′))
lemma exec-until-bad-fixp-induct [case-names adm bottom step]:assumes ccpo.admissible (fun-lub lub-spmf ) (fun-ord (ord-spmf op =)) (λf . P
(λgpv s1 s2 . f ((gpv , s1 ), s2 )))and P (λ- - -. return-pmf None)and
∧exec-until-bad ′. P exec-until-bad ′ =⇒
P (λgpv s1 s2 . bind-spmf (the-gpv gpv) (λgenerat .case generat of Pure x ⇒ return-spmf ((x , s1 ), (x , s2 ))| IO out f ⇒ bind-spmf (joint-oracle (s1 , s2 ) out) (λ((x , s1 ′), (y , s2 ′)).
if bad1 s1 ′ ∨ bad2 s2 ′ then pair-spmf (exec-gpv oracle1 (f x ) s1 ′) (exec-gpvoracle2 (f y) s2 ′)
else exec-until-bad ′ (f x ) s1 ′ s2 ′)))shows P exec-until-bad
using assms by(rule exec-until-bad .fixp-induct [unfolded curry-conv [abs-def ]])
end
lemma exec-gpv-oracle-bisim-bad ′:fixes s1 :: ′s1 and s2 :: ′s2 and X :: ′s1 ⇒ ′s2 ⇒ booland oracle1 :: ′s1 ⇒ ′a ⇒ ( ′b × ′s1 ) spmfand oracle2 :: ′s2 ⇒ ′a ⇒ ( ′b × ′s2 ) spmfassumes ∗: X s1 s2and bad : bad1 s1 = bad2 s2and bisim:
∧s1 s2 x . X s1 s2 =⇒ rel-spmf (λ(a, s1 ′) (b, s2 ′). bad1 s1 ′ = bad2
s2 ′ ∧ (¬ bad2 s2 ′ −→ a = b ∧ X s1 ′ s2 ′)) (oracle1 s1 x ) (oracle2 s2 x )and bad-sticky1 : callee-invariant oracle1 bad1and bad-sticky2 : callee-invariant oracle2 bad2and lossless1 :
∧s1 x . bad1 s1 =⇒ lossless-spmf (oracle1 s1 x )
and lossless2 :∧
s2 x . bad2 s2 =⇒ lossless-spmf (oracle2 s2 x )and lossless: lossless-gpv I gpvand WT-oracle1 :
∧s1 . I `c oracle1 s1
√
and WT-oracle2 :∧
s2 . I `c oracle2 s2√
and WT-gpv : I `g gpv√
shows rel-spmf (λ(a, s1 ′) (b, s2 ′). bad1 s1 ′ = bad2 s2 ′ ∧ (¬ bad2 s2 ′ −→ a =b ∧ X s1 ′ s2 ′)) (exec-gpv oracle1 gpv s1 ) (exec-gpv oracle2 gpv s2 )
(is rel-spmf ?R ?p ?q)proof −
let ?R ′ = λ(a, s1 ′) (b, s2 ′). bad1 s1 ′ = bad2 s2 ′ ∧ (¬ bad2 s2 ′ −→ a = b ∧ Xs1 ′ s2 ′)
from bisim have ∀ s1 s2 x . X s1 s2 −→ rel-spmf ?R ′ (oracle1 s1 x ) (oracle2 s2x ) by blast
then obtain joint-oraclewhere oracle1 [symmetric]:
∧s1 s2 x . X s1 s2 =⇒ map-spmf fst (joint-oracle
s1 s2 x ) = oracle1 s1 xand oracle2 [symmetric]:
∧s1 s2 x . X s1 s2 =⇒ map-spmf snd (joint-oracle s1
235
s2 x ) = oracle2 s2 xand 3 [rotated ]:
∧s1 s2 x y y ′ s1 ′ s2 ′. [[ X s1 s2 ; ((y , s1 ′), (y ′, s2 ′)) ∈ set-spmf
(joint-oracle s1 s2 x ) ]]=⇒ bad1 s1 ′ = bad2 s2 ′ ∧ (¬ bad2 s2 ′ −→ y = y ′ ∧ X s1 ′ s2 ′)
apply atomize-elimapply(unfold rel-spmf-simps all-conj-distrib[symmetric] all-simps(6 ) imp-conjR[symmetric])apply(subst choice-iff [symmetric] ex-simps(6 ))+apply fastforcedone
let ?joint-oracle = λ(s1 , s2 ). joint-oracle s1 s2let ?pq = exec-until-bad ?joint-oracle oracle1 bad1 oracle2 bad2 gpv s1 s2
have setD :∧
s1 s2 x y y ′ s1 ′ s2 ′. [[ X s1 s2 ; ((y , s1 ′), (y ′, s2 ′)) ∈ set-spmf(joint-oracle s1 s2 x ) ]]
=⇒ (y , s1 ′) ∈ set-spmf (oracle1 s1 x ) ∧ (y ′, s2 ′) ∈ set-spmf (oracle2 s2 x )unfolding oracle1 oracle2 by(auto intro: rev-image-eqI )
interpret oracle1 : callee-invariant oracle1 bad1 by factinterpret oracle2 : callee-invariant oracle2 bad2 by fact
show ?thesisproof
show map-spmf fst ?pq = exec-gpv oracle1 gpv s1 using lossless WT-gpv ∗proof(induction arbitrary : s1 s2 rule: lossless-WT-gpv-induct)
case (lossless-gpv p)have ∗:
∧out c s input s1 s2 input1 input2 s1 ′ s2 ′. [[ IO out c ∈ set-spmf p;
((input1 , s1 ′), (input2 , s2 ′)) ∈ set-spmf (joint-oracle s1 s2 out); Xs1 s2 ; bad2 s ]]
=⇒ weight-spmf (exec-gpv oracle2 (c input2 ) s) = 1using lossless-gpv .hyps(3 ) lossless2 lossless-gpv .hyps(4 ) unfolding lossless-spmf-def [symmetric]
by(rule oracle2 .lossless-exec-gpv)(auto simp add : WT-oracle2 dest !: setDWT-calleeD [OF WT-oracle2 ])
show ?case using lossless-gpv .premsapply(rewrite exec-gpv .simps)apply(rewrite exec-until-bad .simps)apply(auto simp add : map-spmf-bind-spmf bind-map-spmf o-def oracle1 ∗ 3
lossless-gpv .IH [OF - WT-calleeD [OF WT-oracle1 ], OF - setD [THEN conjunct1 ]]split : generat .split intro!: bind-spmf-cong [OF refl ])
doneqed
show map-spmf snd ?pq = exec-gpv oracle2 gpv s2 using lossless WT-gpv ∗proof(induction arbitrary : s1 s2 rule: lossless-WT-gpv-induct)
case (lossless-gpv p)have ∗:
∧out c s input s1 s2 input1 input2 s1 ′ s2 ′. [[ IO out c ∈ set-spmf p;
((input1 , s1 ′), (input2 , s2 ′)) ∈ set-spmf (joint-oracle s1 s2 out); Xs1 s2 ; bad1 s ]]
=⇒ weight-spmf (exec-gpv oracle1 (c input1 ) s) = 1using lossless-gpv .hyps(3 ) lossless1 lossless-gpv .hyps(4 ) unfolding lossless-spmf-def [symmetric]
236
by(rule oracle1 .lossless-exec-gpv)(auto simp add : WT-oracle1 dest !: setDWT-calleeD [OF WT-oracle1 ])
show ?case using lossless-gpv .premsapply(rewrite exec-gpv .simps)apply(rewrite exec-until-bad .simps)
apply(auto 4 3 simp add : map-spmf-bind-spmf bind-map-spmf o-def oracle2 ∗3 lossless-gpv .IH [OF - WT-calleeD [OF WT-oracle1 ], OF - setD [THEN conjunct1 ]]split : generat .split intro!: bind-spmf-cong [OF refl ] dest : 3 )
doneqed
have set-spmf ?pq ⊆ (as1 , bs2 ). ?R ′ as1 bs2 using ∗ badproof(induction arbitrary : gpv s1 s2 rule: exec-until-bad-fixp-induct)
case adm show ?case by(intro cont-intro ccpo-class.admissible-leI )case bottom show ?case by simpcase stepshow ?case using step.premsapply(clarsimp simp add : set-bind-spmf bind-UNION step.IH 3 del : subsetI
intro!: UN-least split : generat .split)apply(auto dest !: oracle1 .exec-gpv-invariant oracle2 .exec-gpv-invariant 3 )done
qedthen show
∧x y . (x , y) ∈ set-spmf ?pq =⇒ ?R x y by auto
qedqed
lemma exec-gpv-oracle-bisim-bad :assumes ∗: X s1 s2and bad : bad1 s1 = bad2 s2and bisim:
∧s1 s2 x . X s1 s2 =⇒ rel-spmf (λ(a, s1 ′) (b, s2 ′). bad1 s1 ′ = bad2
s2 ′ ∧ (¬ bad2 s2 ′ −→ a = b ∧ X s1 ′ s2 ′)) (oracle1 s1 x ) (oracle2 s2 x )and bad-sticky1 : callee-invariant oracle1 bad1and bad-sticky2 : callee-invariant oracle2 bad2and lossless1 :
∧s1 x . bad1 s1 =⇒ lossless-spmf (oracle1 s1 x )
and lossless2 :∧
s2 x . bad2 s2 =⇒ lossless-spmf (oracle2 s2 x )and lossless: lossless-gpv I gpvand WT-oracle1 :
∧s1 . I `c oracle1 s1
√
and WT-oracle2 :∧
s2 . I `c oracle2 s2√
and WT-gpv : I `g gpv√
and R:∧
a s1 b s2 . [[ bad1 s1 = bad2 s2 ; ¬ bad2 s2 =⇒ a = b ∧ X s1 s2 ]] =⇒R (a, s1 ) (b, s2 )
shows rel-spmf R (exec-gpv oracle1 gpv s1 ) (exec-gpv oracle2 gpv s2 )using exec-gpv-oracle-bisim-bad ′[OF ∗ bad bisim bad-sticky1 bad-sticky2 lossless1lossless2 lossless WT-oracle1 WT-oracle2 WT-gpv ]by(rule rel-spmf-mono)(auto intro: R)
lemma exec-gpv-oracle-bisim-bad-top:assumes X s1 s2and bad1 s1 = bad2 s2
237
and∧
s1 s2 x . X s1 s2 =⇒ rel-spmf (λ(a, s1 ′) (b, s2 ′). bad1 s1 ′ = bad2 s2 ′ ∧(¬ bad2 s2 ′ −→ a = b ∧ X s1 ′ s2 ′)) (oracle1 s1 x ) (oracle2 s2 x )
and callee-invariant oracle1 bad1and callee-invariant oracle2 bad2and
∧s1 x . bad1 s1 =⇒ lossless-spmf (oracle1 s1 x )
and∧
s2 x . bad2 s2 =⇒ lossless-spmf (oracle2 s2 x )and lossless-gpv I-top gpvand R:
∧a s1 b s2 . [[ bad1 s1 = bad2 s2 ; ¬ bad2 s2 =⇒ a = b ∧ X s1 s2 ]] =⇒
R (a, s1 ) (b, s2 )shows rel-spmf R (exec-gpv oracle1 gpv s1 ) (exec-gpv oracle2 gpv s2 )
using assms(1−8 ) - - - Rby(rule exec-gpv-oracle-bisim-bad)(simp-all)
lemma identical-until-bad :assumes bad-eq : map-spmf bad p = map-spmf bad qand not-bad : measure (measure-spmf (map-spmf (λx . (f x , bad x )) p)) (A ×False) = measure (measure-spmf (map-spmf (λx . (f x , bad x )) q)) (A × False)
shows |measure (measure-spmf (map-spmf f p)) A − measure (measure-spmf(map-spmf f q)) A| ≤ spmf (map-spmf bad p) Trueproof −have |ereal (measure (measure-spmf (map-spmf f p)) A) − ereal (measure (measure-spmf
(map-spmf f q)) A)| =|(∫
+ x . indicator A (f x ) ∂measure-spmf p) −∫
+ x . indicator A (f x )∂measure-spmf q |
unfolding measure-spmf .emeasure-eq-measure[symmetric]by(simp add : nn-integral-indicator [symmetric] indicator-vimage[abs-def ] o-def )
also have . . . =|(∫
+ x . indicator (A × False) (f x , bad x ) + indicator (A × True) (f x ,bad x ) ∂measure-spmf p) −
(∫
+ x . indicator (A × False) (f x , bad x ) + indicator (A × True) (f x ,bad x ) ∂measure-spmf q)|
by(intro arg-cong [where f =abs] arg-cong2 [where f =op −] nn-integral-cong)(simp-allsplit : split-indicator)
also have . . . =|emeasure (measure-spmf (map-spmf (λx . (f x , bad x )) p)) (A × False) +
(∫
+ x . indicator (A × True) (f x , bad x ) ∂measure-spmf p) −(emeasure (measure-spmf (map-spmf (λx . (f x , bad x )) q)) (A × False) +
(∫
+ x . indicator (A × True) (f x , bad x ) ∂measure-spmf q))|by(subst (1 2 ) nn-integral-add)(simp-all add : indicator-vimage[abs-def ] o-def
nn-integral-indicator [symmetric])also have . . . = |(
∫+ x . indicator (A × True) (f x , bad x ) ∂measure-spmf p)
− (∫
+ x . indicator (A × True) (f x , bad x ) ∂measure-spmf q)|(is - = |?x − ?y |)
by(simp add : measure-spmf .emeasure-eq-measure not-bad ereal-diff-add-eq-diff-diff-swapereal-diff-add-assoc2 ereal-add-uminus-conv-diff )
also have . . . ≤ max ?x ?yproof(rule ereal-abs-leI )have ?x − ?y ≤ ?x − 0 by(rule ereal-minus-mono)(simp-all add : nn-integral-nonneg)also have . . . ≤ max ?x ?y by simp
238
finally show ?x − ?y ≤ . . . .
have − (?x − ?y) = ?y − ?xby(rule ereal-minus-diff-eq)(simp-all add : measure-spmf .nn-integral-indicator-neq-infty)
also have . . . ≤ ?y − 0 by(rule ereal-minus-mono)(simp-all add : nn-integral-nonneg)also have . . . ≤ max ?x ?y by simpfinally show − (?x − ?y) ≤ . . . .
qedalso have . . . ≤ max (
∫+ x . indicator True (bad x ) ∂measure-spmf p) (
∫+
x . indicator True (bad x ) ∂measure-spmf q)by(intro ereal-max-mono nn-integral-mono)(simp-all split : split-indicator)
also have . . . = ereal (spmf (map-spmf bad p) True)using arg-cong2 [where f =spmf , OF bad-eq refl , of True, THEN arg-cong [where
f =ereal ]]unfolding ereal-spmf-map-conv-nn-integral indicator-vimage[abs-def ] by simp
finally show ?thesis by simpqed
end
8 Oracle combinators
theory Computational-Model importsSPMF
begin
type-synonym security = nattype-synonym advantage = security ⇒ real
type-synonym ( ′σ, ′call , ′ret) oracle ′ = ′σ ⇒ ′call ⇒ ( ′ret × ′σ) spmftype-synonym ( ′σ, ′call , ′ret) oracle = security ⇒ ( ′σ, ′call , ′ret) oracle ′ × ′σ
print-translation — pretty printing for ( ′σ, ′call , ′ret) oracle 〈
letfun tr ′ [Const (@type-syntax nat, -),
Const (@type-syntax prod, -) $(Const (@type-syntax fun, -) $ s1 $
(Const (@type-syntax fun, -) $ call $(Const (@type-syntax pmf , -) $
(Const (@type-syntax option, -) $(Const (@type-syntax prod, -) $ ret $ s2 ))))) $
s3 ] =if s1 = s2 andalso s1 = s3 then Syntax .const @type-syntax oracle $ s1 $
call $ retelse raise Match;
in [(@type-syntax fun, K tr ′)]end
〉
typ ( ′σ, ′call , ′ret) oracle
239
8.1 Combining oracles
contextfixes left :: ( ′s, ′a, ′b) oracle ′
and right :: ( ′s, ′c, ′d) oracle ′
and s :: ′sbegin
fun plus-oracle :: ′a + ′c ⇒ (( ′b + ′d) × ′s) spmfwhere
plus-oracle (Inl a) = map-spmf (apfst Inl) (left s a)| plus-oracle (Inr b) = map-spmf (apfst Inr) (right s b)
lemma lossless-plus-oracleI [intro]:[[∧
a. x = Inl a =⇒ lossless-spmf (left s a);∧b. x = Inr b =⇒ lossless-spmf (right s b) ]]
=⇒ lossless-spmf (plus-oracle x )by(cases x ) simp-all
end
contextfixes left :: ( ′s1 , ′a, ′b) oracle ′
and right :: ( ′s2 , ′c, ′d) oracle ′
begin
fun parallel-oracle :: ( ′s1 × ′s2 , ′a + ′c, ′b + ′d) oracle ′
whereparallel-oracle (s1 , s2 ) (Inl a) = map-spmf (map-prod Inl (λs1 ′. (s1 ′, s2 ))) (left
s1 a)| parallel-oracle (s1 , s2 ) (Inr b) = map-spmf (map-prod Inr (Pair s1 )) (right s2b)
end
definition family-oracle :: ( ′i ⇒ ( ′s, ′a, ′b) oracle ′)⇒ ( ′i ⇒ ′s, ′i × ′a, ′b) oracle ′
where family-oracle f s = (λ(i , x ). map-spmf (λ(y , s ′). (y , s(i := s ′))) (f i (s i)x ))
lemma family-oracle-apply [simp]:family-oracle f s (i , x ) = map-spmf (apsnd (fun-upd s i)) (f i (s i) x )
by(simp add : family-oracle-def apsnd-def map-prod-def )
lemma lossless-family-oracle:lossless-spmf (family-oracle f s ix ) ←→ lossless-spmf (f (fst ix ) (s (fst ix )) (snd
ix ))by(simp add : family-oracle-def split-beta)
end
240
9 Negligibility
theory Negligible importsComplex-Main∼∼/src/HOL/Library/Function-Algebras∼∼/src/HOL/Library/Polynomial
begin
lemma less-power2 :assumes 2 ≤ ashows n < a ˆ n
proof −have n < 2 ˆ n by(induct n) simp-allalso have . . . ≤ a ˆ n
by(rule power-mono)(simp-all add : assms)finally show ?thesis .
qed
lemma le-power2-minus-1 :n ≤ 2 ˆ n − 1
proof(induct n)case (Suc n)hence Suc n ≤ 2 ˆ n by(cases n) autoalso have . . . ≤ 2 ˆ Suc n − 1 by(cases n) autofinally show ?case .
qed simp
lemma less-powr2 :fixes x :: realassumes 2 ≤ a — probably a bound around 1.44467 would also workshows x < a powr x
proof(cases x ≥ 0 )case Falsehence x < 0 by simpalso have a powr x ≥ 0 by simpfinally show ?thesis .
nextcase Truehave x < real (nat (floor x )) + 1 by linarithalso from le-power2-minus-1 [of nat (floor x )]have . . . ≤ real (2 ˆ nat (floor x ) :: nat)unfolding of-nat-1 [symmetric, where ? ′a=real ] of-nat-add [symmetric] of-nat-le-iffby simp (metis Suc-leI le-refl less-power2 )
also have . . . ≤ 2 powr (nat (floor x )) by(simp add : powr-realpow)also have . . . ≤ 2 powr x by(rule powr-mono)(simp-all add : True)also have . . . ≤ a powr x
by(rule powr-mono2 )(simp-all add : True assms)finally show ?thesis .
qed
241
lemma natceiling-gt-0 [simp]: nat (ceiling x ) > 0 ←→ x > 0by simp
lemma choose-2 : (x choose 2 ) = x ∗ (x − 1 ) div 2proof(cases x ≥ 2 )
case Truethen have (x choose 2 ) = fact x div (fact 2 ∗ fact (x − 2 ))
by(rule binomial-altdef-nat)also have fact 2 = 2 by(simp add : eval-nat-numeral)also have fact x = x ∗ (x − 1 ) ∗ fact (x − 2 )
using True by(simp add : fact-reduce eval-nat-numeral)also have . . . div (2 ∗ fact (x − 2 )) = x ∗ (x − 1 ) div 2
by(subst (3 ) mult .commute)(simp add : div-mult2-eq)finally show ?thesis .
nextcase Falsehence x = 0 ∨ x = 1 by autothus ?thesis by auto
qed
lemma numeral-le-nat [simp]: numeral n ≤ nat x ←→ numeral n ≤ xby(cases 0 ≤ x )(auto simp add : le-nat-iff not-le elim: less-le-trans)
lemma ceiling-add-one-left [simp]: d1 + xe = 1 + dxeby(subst add .commute) simp
lemma powr-fast-growth:fixes k :: realassumes k > 1shows ∃n. ∀ x > n. x < k powr x
proof −def d ≡ k − 1from assms have 0 < d by(simp add : d-def )hence [simp]: − 1 < 2 / d2
by(simp add : field-simps)(metis le-less-trans mult-eq-0-iff power2-eq-squarereal-minus-mult-self-le zero-less-numeral)
def n ≡ nat (ceiling (1 + 2 / d ˆ 2 ))have n ≥ 2 using 〈0 < d 〉 by(simp add : n-def ) fix x :: real
assume x > nwith 〈n ≥ 2 〉 have x ≥ 2 and x ≥ 0 by simp-allhave x ≤ 1 + real (nat bxc) ∗ 1 by linarithalso have 2 ≤ real-of-int d2 / d2e ∗ d2
using le-of-int-ceiling [of 2 / d2] 〈0 < d 〉 by(simp add : field-simps del :le-of-int-ceiling)
then have 1 + real (nat bxc) ∗ 1 ≤ 1 + nat bxc ∗ ((n − 1 ) / 2 ∗ d2)by(intro add-left-mono mult-left-mono)(simp-all add : n-def Suc-nat-eq-nat-zadd1 [symmetric])also have . . . ≤ 1 + nat bxc ∗ ((nat bxc − 1 ) / 2 ∗ d2) using 〈x > n〉
242
by(intro add-left-mono mult-left-mono mult-right-mono divide-right-mono)(simp-all ,linarith)
also have . . . = 1 + (nat bxc ∗ (nat bxc − 1 ) div 2 ) ∗ d ˆ 2by(subst real-of-nat-div) auto
also have . . . < (∑
k∈0 ,1 ,2. (nat bxc choose k) ∗ d ˆ k)using 〈d > 0 〉 〈x ≥ 2 〉 by(simp add : choose-2 )
also have . . . ≤ (∑
k = 0 ..nat bxc. (nat bxc choose k) ∗ d ˆ k)apply(rule setsum-mono2 ) using 〈0 < d 〉 〈x ≥ 2 〉 by(simp-all , linarith)
also have . . . = (d + 1 ) ˆ nat bxc by(simp add : binomial-ring)also have . . . ≤ k powr (nat bxc) unfolding d-def using 〈k > 1 〉 by(simp
add : powr-realpow)also have . . . ≤ k powr x using 〈0 ≤ x 〉 〈k > 1 〉 by(intro powr-mono) simp-allfinally have x < k powr x .
thus ?thesis by blastqed
corollary power-fast-growth:fixes k :: realassumes k > 1shows ∃n. ∀ x > n. x < k ˆ x
proof −from powr-fast-growth[OF assms] obtain n where n:
∧x . x > n =⇒ x < k
powr x by blast fix x :: nat
assume x > nat dnehence x > n by linarithhence x < k powr x by(rule n)also have . . . = k ˆ x using 〈k > 1 〉 by(simp add : powr-realpow)finally have x < k ˆ x .
thus ?thesis by blastqed
lemma powr-fast-growth2 :fixes k :: realassumes k > 1 c > 0shows ∃n. ∀ x > n. x powr c < k powr x
proof −def k ′ ≡ k powr (1 / c)have k ′ > 1 using assms unfolding k ′-def
by (meson ge-one-powr-ge-zero le-less-trans less-eq-real-def powr-less-monozero-less-divide-1-iff )
from powr-fast-growth[OF this] obtain n where n:∧
x . x > n =⇒ x < k ′ powrx by blast fix x :: real
assume x > max 0 nhence x > 0 x > n by simp-allfrom 〈x > n〉 have x < k ′ powr x by(rule n)with 〈0 < c〉 〈0 < x 〉 have x powr c < (k ′ powr x ) powr c by(simp add :
powr-less-mono2 )
243
also have . . . = k powr x unfolding k ′-def using 〈0 < c〉 by(simp add :powr-powr)
finally have x powr c < . . . . thus ?thesis by blast
qed
instantiation fun :: (type, abs) abs begindefinition |f | = (λx . |f x |)instance ..end
lemma abs-fun-apply [simp]: |f | x = |f x |by(simp add : abs-fun-def )
instance fun :: (type, ordered-ab-group-add-abs) ordered-ab-group-add-absby intro-classes(auto 4 4 intro: le-funI intro!: abs-leI simp add : abs-ge-self abs-triangle-ineqdest : le-funD)
instance fun :: (type, ordered-ring-abs) ordered-ring-absby intro-classes(auto 4 3 simp add : fun-eq-iff dest : le-funD intro: abs-eq-mult)
instantiation fun :: (type, scaleR) scaleR begindefinition a ∗R f = (λx . a ∗R f x )instance ..end
lemma scaleR-fun-apply [simp]: (a ∗R f ) x = a ∗R f xby(simp add : scaleR-fun-def )
instance fun :: (type, real-vector) real-vectorby intro-classes(auto simp add : fun-eq-iff scaleR-right-distrib scaleR-left-distrib)
instance fun :: (type, real-algebra) real-algebraby intro-classes(simp-all add : fun-eq-iff )
instance fun :: (type, real-algebra-1 ) real-algebra-1 ..
definition powr-fun :: ( ′a ⇒ real) ⇒ real ⇒ ′a ⇒ realwhere powr-fun f e = (λx . if f x ≤ 0 then 0 else f x powr e)
locale powr-syntax beginnotation powr-fun (infixr powr 80 )end
context begin interpretation powr-syntax .
lemma powr-fun-apply : (f powr e) x = (if f x ≤ 0 then 0 else f x powr e)
244
by(simp add : powr-fun-def )
lemma [simp]:shows powr-fun-apply-le0 : f x ≤ 0 =⇒ (f powr e) x = 0and powr-fun-apply-gt0 : f x > 0 =⇒ (f powr e) x = f x powr e
by(simp-all add : powr-fun-apply)
lemma powr-fun-add :fixes f :: ′a ⇒ realshows f powr (a + b) = f powr a ∗ f powr b
by(simp add : powr-fun-def fun-eq-iff powr-add)
lemma powr-fun-1 [simp]:fixes f :: ′a ⇒ realshows f ≥ 0 =⇒ f powr 1 = f
by(auto simp add : powr-fun-def fun-eq-iff le-fun-def intro: antisym)
end
named-theorems negligible-intros
definition negligible :: (nat ⇒ real) ⇒ boolwhere negligible f ←→ (∀ c>0 . ∃n. ∀ x>n. |f x | < 1 / (x powr c))
lemma negligibleI [intro? ]:(∧
c. c > 0 =⇒ ∃n. ∀ x>n. real x powr c ∗ |f x | < 1 ) =⇒ negligible funfolding negligible-def by(auto simp add : field-simps)
lemma negligibleE [elim? ]:assumes negligible f c > 0obtains n where ∀ x>n. real x powr c ∗ |f x | < 1
using assms unfolding negligible-def by(auto simp add : field-simps)
lemma negligible-mono: [[ negligible g ;∧η. |f η| ≤ |g η| ]] =⇒ negligible f
apply(rule negligibleI )apply(erule (1 ) negligibleE )apply(auto 4 3 elim!: le-less-trans[rotated ] intro!: mult-left-mono simp add : abs-fun-defle-fun-def )done
lemma negligible-mono2 : [[ negligible g ;∧η. f η ≤ g η;
∧η. 0 ≤ f η ]] =⇒ negligible
fby(erule negligible-mono)(metis abs-of-nonneg order-trans)
lemma negligible-K0 [negligible-intros, simp, intro!]: negligible (λ-. 0 )by(rule negligibleI ) simp
lemma negligible-0 [negligible-intros, simp, intro!]: negligible 0
245
by(simp add : zero-fun-def )
lemma negligible-const-iff [simp]: negligible (λ-. c) ←→ c = 0proof
assume negligible (λ-. c)show c = 0proof(rule ccontr)
assume c 6= 0have 1 > (0 :: real) by simpwith 〈negligible (λ-. c)〉 obtain n :: nat
where negl [rule-format ]: ∀ x>n. real x powr 1 ∗ |c| < 1 ..
show Falseproof(cases |c| < 1 )
case Truelet ?x = max (n + 1 ) (nat (ceiling (1 / |c|)))have 1 = |c| ∗ (1 / |c|) using 〈c 6= 0 〉 by simpalso have . . . ≤ |c| ∗ (nat (ceiling (1 / |c|)))
by(rule mult-left-mono)(simp-all add : real-nat-ceiling-ge)also have . . . ≤ |c| ∗ ?x by(rule mult-left-mono; simp add : max-def ; linarith)also have n < ?x by(simp add : max-def )note negl [OF this]ultimately show False by(simp add : field-simps)
nextcase Falsehence 1 ≤ |c| ∗ 1 by simpalso have . . . ≤ |c| ∗ (n + 1 ) by(rule mult-left-mono) simp-allalso have . . . < 1 using negl [of n + 1 ] by(simp add : field-simps)finally show False by simp
qedqed
qed simp
lemma not-negligible-1 [simp]: ¬ negligible 1by(simp add : one-fun-def )
lemma negligible-plus [negligible-intros]:assumes f : negligible fand g : negligible gshows negligible (λη. f η + g η)
prooffix c :: realassume 0 < clet ?c = 1 + cfrom 〈0 < c〉 have 0 < ?c by simpfrom f 〈0 < ?c〉 obtain nf where f [rule-format ]: ∀ x>nf . real x powr ?c ∗ |f
x | < 1 ..from g 〈0 < ?c〉 obtain ng where g [rule-format ]: ∀ x>ng . real x powr ?c ∗ |g
x | < 1 ..
246
let ?n = max nf ng + 1 fix x :: nat
let ?xpc = real x powr ?cassume x > ?nhence [simp]: nf < x ng < x 2 ≤ x 0 < x
by(simp-all add : max-def split : split-if-asm)have 2 ∗ real x powr c ∗ |(f + g) x | ≤ ?xpc ∗ |(f + g) x |
unfolding powr-add mult .assoc by(rule mult-right-mono)simp-allalso have . . . ≤ ?xpc ∗ (|f x | + |g x |)
by(rule mult-left-mono)simp-allalso have . . . = ?xpc ∗ |f x | + ?xpc ∗ |g x | by(simp add : field-simps)also have . . . < 1 + 1 by(rule add-strict-mono)(rule f g , simp)+finally have real x powr c ∗ |f x + g x | < 1 by simp
thus ∃n. ∀ x>n. real x powr c ∗ |f x + g x | < 1 by blastqed
lemma negligible-uminus [simp]:negligible (λη. − f η) ←→ negligible f
by(simp add : negligible-def )
lemma negligible-uminusI [negligible-intros]:negligible f =⇒ negligible (λη. − f η)
by simp
lemma negligible-minus [negligible-intros]:[[ negligible f ; negligible g ]] =⇒ negligible (λη. f η − g η)
by(auto simp add : uminus-add-conv-diff [symmetric] negligible-plus simp del : uminus-add-conv-diff )
lemma negligible-cmult :negligible (λη. c ∗ f η) ←→ negligible f ∨ c = 0(is ?lhs ←→ ?rhs)
proofassume ?lhsshow ?rhsproof(rule disjCI )
assume c: c 6= 0show negligible fproof
fix c ′ :: realassume c ′ > 0let ?c ′ = (1 / |c|) + c ′
have 0 < ?c ′ using 〈c ′ > 0 〉 cby(simp add : pos-add-strict)
with 〈?lhs〉 obtain n where ∀ x>n. x powr ?c ′ ∗ |c ∗ f x | < 1 ..hence f :
∧x . x > n =⇒ |c| ∗ real x powr ?c ′ ∗ |f x | < 1
by(auto simp add : field-simps abs-mult)let ?n = n + 1 fix x
assume x > ?n
247
hence [simp]: n < x 2 ≤ x by simp-allhave 1 = |c| ∗ (1 / |c|) by(simp add : c)also have . . . < |c| ∗ real x powr (1 / |c|)
by(rule mult-strict-left-mono)(simp-all add : less-powr2 c)finally have 1 ∗ real x powr c ′ ∗ |f x | ≤ |c| ∗ real x powr ?c ′ ∗ |f x |
unfolding powr-add mult .assoc[symmetric]by(intro mult-right-mono) simp-all
also note f [OF 〈x > n〉]finally have real x powr c ′ ∗ |f x | < 1 by simp
thus ∃n. ∀ x>n. real x powr c ′ ∗ |f x | < 1 by blastqed
qednext
assume ?rhsthus ?lhsproof
assume negligible fshow ?thesisproof
fix c ′ :: realassume 0 < c ′
let ?c = c ′ + |c|have ?c > 0 using 〈0 < c ′〉 by simpwith 〈negligible f 〉 obtain n where f [rule-format ]: ∀ x>n. x powr ?c ∗ |f x |
< 1 ..let ?n = n + nat (ceiling (1 / |c|)) + 2 fix x :: nat
assume x > ?nhence [simp]: 2 ≤ x x > n by simp-allhave real x powr c ′ ∗ |c ∗ f x | = |c| ∗ (real x powr c ′ ∗ |f x |) by(simp add :
abs-mult)also have . . . ≤ real x powr |c| ∗ real x powr c ′ ∗ |f x | unfolding mult .assocby(rule mult-right-mono order .strict-implies-order)+(simp-all add : less-powr2 )also have . . . = real x powr ?c ∗ |f x | by(simp add : powr-add)also note f [OF 〈x > n〉]also note calculation
thus ∃n. ∀ x>n. real x powr c ′ ∗ |c ∗ f x | < 1 by blastqed
qed simpqed
lemma negligible-cmultI [negligible-intros]:(c 6= 0 =⇒ negligible f ) =⇒ negligible (λη. c ∗ f η)
by(auto simp add : negligible-cmult)
lemma negligible-multc:negligible (λη. f η ∗ c) ←→ negligible f ∨ c = 0
by(subst mult .commute)(simp add : negligible-cmult)
248
lemma negligible-multcI [negligible-intros]:(c 6= 0 =⇒ negligible f ) =⇒ negligible (λη. f η ∗ c)
by(auto simp add : negligible-multc)
lemma negligible-times [negligible-intros]:assumes f : negligible fand g : negligible gshows negligible (λη. f η ∗ g η)
prooffix c :: realassume 0 < cfrom f 〈0 < c〉 obtain nf where f [rule-format ]: ∀ x>nf . real x powr c ∗ |f x |
< 1 ..from g 〈0 < c〉 obtain ng where g [rule-format ]: ∀ x>ng . real x powr c ∗ |g x |
< 1 ..let ?n = max nf ng fix x
assume x > ?nhence [simp]: nf < x ng < x 1 ≤ real x
by(simp-all add : max-def split : split-if-asm)have real x powr c ∗ |(f ∗ g) x | ≤ real x powr (c + c) ∗ |(f ∗ g) x |
by(rule mult-right-mono powr-mono)+(insert 〈0 < c〉, simp-all)also have . . . = (real x powr c ∗ |f x |) ∗ (real x powr c ∗ |g x |)
using [[simproc del : field-combine-numerals int-combine-numerals]]by(simp add : abs-mult powr-add)
also have . . . < 1 ∗ 1 by(rule mult-strict-mono)(simp-all add : f g)finally have real x powr c ∗ |f x ∗ g x | < 1 by simp
thus ∃n. ∀ x>n. real x powr c ∗ |f x ∗ g x | < 1 by blastqed
lemma negligible-power [negligible-intros]:assumes negligible fand n > 0shows negligible (λη. f η ˆ n)
using 〈n > 0 〉
proof(induct n)case (Suc n)thus ?case using 〈negligible f 〉
by(cases n)(simp-all add : negligible-times)qed simp
context begin interpretation powr-syntax .
lemma negligible-powr [negligible-intros]:assumes negligible fand e > 0shows negligible (f powr e)
prooffix c :: real
249
let ?c = c / eassume 0 < cwith 〈e > 0 〉 have 0 < ?c by simpwith 〈negligible f 〉 obtain n where n[rule-format ]: ∀ x>n. real x powr ?c ∗ |f x |
< 1 .. fix x
assume x > nhave real x powr c ∗ |(f powr e) x | < 1proof(cases f x ≤ 0 )
case Falsehence f x > 0 by simpwith 〈x > n〉 〈e > 0 〉
have real x powr c ∗ |(f powr e) x | = (real x powr ?c ∗ |f x |) powr eby(simp add : powr-mult powr-powr)
also have 0 ≤ real x powr ?c ∗ |f x | using 〈f x > 0 〉 〈x > n〉 by simpwith 〈e > 0 〉 have . . . powr e < 1 powr e using n
by(rule powr-less-mono2 )(fact 〈x > n〉)also have . . . = 1 by simpfinally show ?thesis .
qed simp thus ∃n. ∀ x>n. real x powr c ∗ |(f powr e) x | < 1 by blast
qed
end
lemma negligible-times-real [simp]:negligible (λη. f η ∗ real η) ←→ negligible f (is ?lhs ←→ ?rhs)
proofassume ?lhsshow ?rhsproof
fix c :: realassume 0 < cwith 〈?lhs〉 obtain n where n[rule-format ]: ∀ x>n. real x powr c ∗ |f x ∗ real
x | < 1 .. fix x
assume x > nhence 1 ≤ |real x | by simphence real x powr c ∗ |f x | ∗ 1 ≤ real x powr c ∗ |f x | ∗ |real x |
by(rule mult-left-mono) simpalso have . . . < 1 using n[of x ] 〈x > n〉 by(simp add : abs-mult)finally have real x powr c ∗ |f x | < 1 by simp
thus ∃n. ∀ x>n. real x powr c ∗ |f x | < 1 by blastqed
nextassume ?rhsshow ?lhsproof
fix c :: real
250
let ?c = c + 1assume 0 < chence 0 < ?c by simpwith 〈?rhs〉 obtain n where n[rule-format ]: ∀ x>n. real x powr ?c ∗ |f x | < 1
.. fix x
assume x > nhence real x > 0 by simphence real x powr c ∗ |f x ∗ real x | < 1
using n[OF 〈x > n〉] by(simp add : abs-mult powr-add algebra-simps) thus ∃n. ∀ x>n. real x powr c ∗ |f x ∗ real x | < 1 by blast
qedqed
lemma negligible-times-realI [negligible-intros]: negligible f =⇒ negligible (λη. f η∗ real η)by(simp)
lemma negligible-abs [simp]: negligible (λx . |f x |) ←→ negligible fby(simp add : negligible-def )
lemma negligible-absI [negligible-intros]: negligible f =⇒ negligible (λx . |f x |)by(simp)
lemma negligible-if-finite:assumes negligible fand finite n. P nshows negligible (λn. if P n then t n else f n)
prooffix c :: realassume c > 0with 〈negligible f 〉 obtain n where n:
∧x . x > n =⇒ x powr c ∗ |f x | < 1
by(rule negligibleE ) blastlet ?A = n. P nlet ?n = max n (Max (insert 0 ?A))let ?f = (λn. if P n then t n else f n) fix x
assume x > ?nhence x > n by simphence x powr c ∗ |f x | < 1 by(rule n)moreover have ¬ P x using 〈x > ?n〉 〈finite ?A〉 by autoultimately have x powr c ∗ |?f x | < 1 by simp
thus ∃n. ∀ x>n. x powr c ∗ |?f x | < 1 by blastqed
lemma negligible-powerI [negligible-intros]:assumes |k | < 1shows negligible (λn. k ˆ n)
proof(cases k = 0 )
251
case Truethus ?thesis by(simp add : power-0-left [abs-def ] negligible-if-finite)
nextcase Falsehence 0 < |k | by autoshow ?thesisproof
fix c :: realassume 0 < clet ?k = 1 / |k |from assms have ?k > 1 using False by(simp add : field-simps)from powr-fast-growth2 [OF this 〈0 < c〉]obtain n where n:
∧x . x > n =⇒ x powr c < ?k powr x by blast
let ?n = nat dne fix x
assume x > ?nhence x > n by linarithwith n[OF this] 〈0 < |k |〉 have x powr c ∗ |k ˆ x | < 1
by(simp add : field-simps power-abs powr-realpow powr-divide) then show ∃n. ∀ x>n. real x powr c ∗ |k ˆ x | < 1 by blast
qedqed
lemma negligible-inverse-powerI [negligible-intros]: |k | > 1 =⇒ negligible (λη. 1/ k ˆ η)using negligible-powerI [of 1 / k ] by(simp add : power-one-over)
inductive polynomial :: ( ′a ⇒ ′a :: comm-semiring-1 ) ⇒ boolwhere
one [simp, intro!]: polynomial 1| id [simp, intro!]: polynomial id| scalar : polynomial f =⇒ polynomial ((λ-. c) ∗ f )| plus: [[ polynomial f ; polynomial g ]] =⇒ polynomial (f + g)| times: [[ polynomial f ; polynomial g ]] =⇒ polynomial (f ∗ g)
lemmas polynomial-1 = oneand polynomial-id = idand polynomial-scalarI = scalarand polynomial-plusI = plusand polynomial-timesI = times
hide-fact (open) one id scalar plus times
lemma polynomial-id ′ [simp, intro!]: polynomial (λx . x )by(simp add : id-def [symmetric])
lemma polynomial-K [simp, intro!]: polynomial (λ-. c)using polynomial-scalarI [where c=c and f =1 ] by simp
252
lemma polynomial-uminus [iff ]:fixes f :: ′a :: comm-ring-1 ⇒ ′ashows polynomial (− f ) ←→ polynomial f
using polynomial-scalarI [where c=− 1 and f =f ] polynomial-scalarI [where c=−1 and f =− f ]by(auto simp add : fun-Compl-def times-fun-def )
lemma polynomial-scalar [simp]:fixes f :: ′a :: field ⇒ ′ashows polynomial ((λ-. c) ∗ f ) ←→ c = 0 ∨ polynomial f
apply(cases c = 0 )apply(simp add : polynomial-scalarI times-fun-def )
using polynomial-scalarI [where c=1 / c and f =(λ-. c) ∗ f ] polynomial-scalarI [wherec=c and f =f ]apply(auto simp add : field-simps times-fun-def )done
lemma polynomial-numeral [simp, intro!]: polynomial (numeral n)by(induct n)(simp-all only : numeral .simps polynomial-plusI polynomial-1 )
lemma polynomial-0 [simp, intro!]: polynomial 0by(simp add : zero-fun-def )
lemma polynomial-minusI :fixes f g :: - :: comm-ring-1 ⇒ -shows [[ polynomial f ; polynomial g ]] =⇒ polynomial (f − g)
by (metis polynomial .simps polynomial-uminus uminus-add-conv-diff )
lemma polynomial-plusD1 :fixes f g :: - :: comm-ring-1 ⇒ -assumes polynomial (f + g) polynomial fshows polynomial g
using polynomial-minusI [OF assms] by simp
lemma polynomial-plusD2 :fixes f g :: - :: comm-ring-1 ⇒ -assumes polynomial (f + g) polynomial gshows polynomial f
using polynomial-minusI [OF assms] by simp
lemma 1-comp [simp]: 1 f = 1by(simp add : one-fun-def o-def )
lemma plus-comp-distrib: f + g h = (f h) + (g h)by(simp add : plus-fun-def fun-eq-iff )
253
lemma times-comp-distrib: f ∗ g h = (f h) ∗ (g h)by(simp add : times-fun-def fun-eq-iff )
lemma K-comp [simp]: (λ-. c) f = (λ-. c)by(simp add : o-def )
lemma polynomial-compI :[[ polynomial f ; polynomial g ]]=⇒ polynomial (f g)
by(induction arbitrary : rule: polynomial .induct)(simp-all add : times-comp-distribplus-comp-distrib polynomial-timesI polynomial-plusI )
lemma polynomial-powerI :polynomial f =⇒ polynomial (f ˆ n)
by(induct n)(simp-all add : polynomial-timesI )
lemma polynomial-SucI : polynomial p =⇒ polynomial (λn. Suc (p n))by(drule polynomial .plus[where g=λ-. 1 ])(simp-all add : plus-fun-def )
lemma negligible-times-polynomial2 [negligible-intros]:assumes g : negligible gand f : polynomial fshows negligible (λη. g η ∗ real (f η))
using f gproof(induction arbitrary : g)
case onethus ?case by simp
nextcase idthus ?case
by(simp only : negligible-times-real o-def id-def )next
case (scalar f c)from scalar .IH [OF scalar .prems]have negligible (λη. c ∗ (g η ∗ real (f η)))
unfolding negligible-cmult ..also have . . . = g ∗ (real (λ-. c) ∗ f ) by(simp add : o-def algebra-simps
times-fun-def )finally show ?case by simp
nextcase (plus f f ′)from plus.IH [OF plus.prems] have negligible (λη. g η ∗ real (f η) + g η ∗ real
(f ′ η))by(rule negligible-plus)
thus ?case by(simp add : o-def algebra-simps)next
case (times f f ′)interpret powr-syntax .let ?g = |g | powr (1 / 2 )
254
from times.prems have negligible |g | by(simp add : abs-fun-def )hence negligible ?g by(rule negligible-powr) simphence negligible (λη. ?g η ∗ real (f η)) negligible (λη. ?g η ∗ real (f ′ η)) by(rule
times.IH )+hence negligible (λη. (?g η ∗ real (f η)) ∗ (?g η ∗ real (f ′ η))) (is negligible
?gff ′)by(rule negligible-times)
also have ?gff ′ = (λη. |g η| ∗ real (f η ∗ f ′ η))by(simp add : algebra-simps powr-fun-apply fun-eq-iff powr-add [symmetric])
also have negligible . . . = negligible (λη. ||g η| ∗ real (f η ∗ f ′ η)|) by simpalso have (λη. ||g η| ∗ real (f η ∗ f ′ η)|) = (λη. |g η ∗ real (f η ∗ f ′ η)|) by(simp
add : fun-eq-iff abs-mult)finally show ?case by(simp only : negligible-abs times-fun-apply)
qed
lemma negligible-times-polynomial1 [negligible-intros]:[[ polynomial f ; negligible g ]] =⇒ negligible (λη. real (f η) ∗ g η)
by(subst mult .commute)(rule negligible-times-polynomial2 )
lemma negligible-divide-polynomial1 [negligible-intros]:[[ polynomial f ; negligible (λη. 1 / g η) ]] =⇒ negligible (λη. real (f η) / g η)
by(drule (1 ) negligible-times-polynomial1 ) simp
lemma poly-pCons ′: poly (pCons a p) = (λ-. a) + id ∗ poly pby(simp add : fun-eq-iff )
lemma polynomial-poly [simp]: polynomial (poly p)proof(induct p)
fix a and p :: ′a polyassume polynomial (poly p)thus polynomial (poly (pCons a p))
by(simp add : poly-pCons ′ polynomial-plusI polynomial-timesI )qed simp
lemma polynomial-ex-poly :fixes f :: ′a :: comm-semiring-1 ⇒ ′aassumes polynomial fshows ∃ p. f = poly p
using assmsproof(induction)
case onethus ∃ p :: ′a poly . 1 = poly p by(rule exI [where x=1 ])(auto)
nextcase idshow ∃ p :: ′a poly . id = poly p
by(rule exI [where x=monom 1 1 ])(simp add : fun-eq-iff poly-monom)next
255
case (scalar f c)from scalar .IH obtain p where [simp]: f = poly p ..show ∃ p. ((λ-. c) ∗ f ) = poly p
by(rule exI [where x=smult c p])(simp add : fun-eq-iff )next
case (plus f g)from plus.IH obtain p q where [simp]: f = poly p g = poly q by blastshow ∃ p. f + g = poly p
by(rule exI [where x=p + q ])(simp add : fun-eq-iff )next
case (times f g)from times.IH obtain p q where [simp]: f = poly p g = poly q by blastshow ∃ p. f ∗ g = poly p
by(rule exI [where x=p ∗ q ])(simp add : fun-eq-iff )qed
lemma range-poly-polynomial : range poly = Collect polynomialby(auto dest : polynomial-ex-poly)
lemma inj-poly [simp]: inj (poly :: ′a :: idom, ring-char-0 poly ⇒ -)by(simp add : inj-on-def poly-eq-poly-eq-iff )
definition poly-of :: ( ′a :: idom, ring-char-0 ⇒ ′a) ⇒ ′a polywhere poly-of f = (if polynomial f then inv poly f else 0 )
lemma poly-of-0 [simp]: poly-of 0 = 0unfolding poly-of-def by(subst inv-f-eq) auto
lemma poly-of-1 [simp]: poly-of 1 = 1unfolding poly-of-def by(subst inv-f-eq) auto
lemma poly-of-id [simp]: poly-of id = monom 1 1unfolding poly-of-def by(subst inv-f-eq)(auto simp add : poly-monom)
lemma poly-of-scalar [simp]:fixes c :: ′a :: field , ring-char-0shows poly-of ((λ-. c) ∗ f ) = smult c (poly-of f )
unfolding poly-of-defapply autoapply(simp add : times-fun-def )apply(subst inv-f-eq)apply(simp-all add : poly-0 [abs-def ])[3 ]
apply(drule polynomial-ex-poly)apply clarsimpapply(subst inv-f-eq)apply(simp-all add : fun-eq-iff )done
256
term degree
lemma real-all-le [simp]: (∀ x ::real . x ≤ y) ←→ Falseby(auto intro: exI [where x=y + 1 ])
inductive degree-rel :: (real ⇒ real) ⇒ nat ⇒ boolwhere degree-rel : (
∧c. c > 0 =⇒ ∃ x . ∀ y>x . |f y | < c ∗ y ˆ n) =⇒ degree-rel f n
lemmas degree-relI = degree-rel
hide-fact (open) degree-rel
lemma degree-relI ′: (∧
c y . [[ c > 0 ; x c < y ]] =⇒ |f y | < c ∗ y ˆ n) =⇒ degree-relf nby(auto simp add : degree-rel .simps)
lemma degree-relE [consumes 2 ]:assumes degree-rel f n 0 < cobtains x where
∧y . y > x =⇒ |f y | < c ∗ y ˆ n
using assms by(auto simp add : degree-rel .simps)
lemma degree-relE ′ [consumes 2 ]:assumes degree-rel f n 0 < cobtains x where y x > x =⇒ |f (y x )| < c ∗ (y x ) ˆ n
using assms by(auto simp add : degree-rel .simps)
lemma degree-rel-0 [simp]: degree-rel 0 nby(auto simp add : degree-rel .simps zero-less-mult-iff zero-less-power-eq)
lemma degree-rel-mono:assumes degree-rel f m
257
and m ≤ nshows degree-rel f n
prooffix c :: realassume 0 < chence [simp]: 0 ≤ c by simpfrom 〈degree-rel f m〉 〈0 < c〉 obtain x
where m:∧
y . y > x =⇒ |f y | < c ∗ y ˆ m by(rule degree-relE ) blast fix y
assume y > max 1 xhence [simp]: 1 ≤ y x < y 0 ≤ y by simp-allhave |f y | < c ∗ y ˆ m ∗ 1 by(simp add : m)also have . . . ≤ c ∗ y ˆ m ∗ y ˆ (n − m)
by(rule mult-left-mono)(simp-all add : zero-le-mult-iff )also have . . . = c ∗ y ˆ n by(simp add : power-add [symmetric] 〈m ≤ n〉)also note calculation
thus ∃ x . ∀ y>x . |f y | < c ∗ y ˆ n by blastqed
lemma degree-rel-mono1 :[[ degree-rel g n; |f | ≤ |g | ]] =⇒ degree-rel f n
by(auto 4 4 simp add : degree-rel .simps le-fun-def intro: order-le-less-trans)
lemma degree-rel-K [simp]:assumes c 6= 0shows degree-rel (λ-. c) n ←→ n > 0 (is ?lhs ←→ ?rhs)
proof(rule iffI , rule ccontr)assume ¬ ?rhshence [simp]: n = 0 by simpassume ?lhsthus False using assms
by cases(auto simp add : not-less elim: meta-allE [where x=|c|])next
assume ?rhsthen obtain n ′ where [simp]: n = Suc n ′ by(cases n) autoshow ?lhs
by(rule degree-relI ′[where x=λc ′. max 1 (|c| / c ′)])(auto simp add : assmsmult .assoc[symmetric] divide-less-eq less-divide-eq mult .commute intro: mult-less-le-imp-less[wherec=1 :: real , simplified ])qed
lemma degree-rel-id [simp]:degree-rel id n ←→ n ≥ 2
proofhave degree-rel id 2proof(rule degree-relI ′)
fix c y :: realassume 0 < c 1 / c < yhence [simp]: 0 ≤ c c 6= 0 0 < c 0 < y 0 ≤ y
258
by(simp-all add : field-simps)(metis order .strict-trans zero-less-mult-pos zero-less-onele-less-linear mult-pos-neg not-one-less-zero order .strict-trans)+
have |id y | = c ∗ y ∗ (1 / c) by simpalso have . . . < c ∗ y ∗ y by(rule mult-strict-left-mono)(simp-all add : 〈1 / c
< y〉 zero-less-mult-iff )also have . . . = c ∗ y2 by(simp add : power2-eq-square)finally show |id y | < c ∗ y2 .
qedmoreoverassume 2 ≤ nultimately show degree-rel id n by(rule degree-rel-mono)
nextassume ∗: degree-rel id nhave n = 0 ∨ n = 1 ∨ 2 ≤ n by autothus 2 ≤ nproof(elim disjE )
assume [simp]: n = 0have 0 < (1 :: real) by simpwith ∗ have Falseby(rule degree-relE ′[where y=λx . max 1 (x + 1 )])(fastforce simp add : max-def
split : split-if-asm)thus ?thesis ..
nextassume [simp]: n = 1have 0 < (1 :: real) by simpwith ∗ have False
by(rule degree-relE ′[where y=λx . x + 1 ]) autothus ?thesis ..
qedqed
lemma degree-rel-scalar :assumes c 6= 0shows degree-rel ((λ-. c) ∗ f ) n ←→ degree-rel f n
proof −def P ≡ λc. ∃ x . ∀ y>x . |f y | < c ∗ y ˆ nhence degree-rel ((λ-. c) ∗ f ) n ←→ (∀ c ′>0 . P (c ′ / |c|))
by(simp add : abs-mult field-simps assms degree-rel .simps)also have . . . ←→ (∀ c ′>0 . P c ′)
by(auto simp add : assms zero-less-mult-iff field-simps elim: allE [where x=c ′
∗ |c| for c ′])finally show ?thesis unfolding P-def by(simp add : degree-rel .simps)
qed
lemma degree-rel-scalar-iff :degree-rel ((λ-. c) ∗ f ) n ←→ c = 0 ∨ degree-rel f n
apply(cases c = 0 )apply(simp add : times-fun-def zero-fun-def [symmetric])
259
apply(simp add : degree-rel-scalar)done
lemma degree-rel-plusI :assumes degree-rel f nand degree-rel g nshows degree-rel (f + g) n
prooffix c :: realassume 0 < chence 0 < c / 2 and [simp]: 0 ≤ c by simp-allwith assms obtain xf xg
where f :∧
y . y > xf =⇒ |f y | < c / 2 ∗ y ˆ nand g :
∧y . y > xg =⇒ |g y | < c / 2 ∗ y ˆ n
by(blast elim: degree-rel .cases)let ?x = max 1 (max xf xg) fix y
assume y > ?xhence [simp]: xf < y xg < y 1 ≤ y by simp-allhave |(f + g) y | ≤ |f y | + |g y | by simpalso have . . . < c / 2 ∗ y ˆ n + c / 2 ∗ y ˆ n
by(rule add-strict-mono)(rule f g , simp)+also have . . . = c ∗ y ˆ n by simpalso note calculation
thus ∃ x . ∀ y>x . |(f + g) y | < c ∗ y ˆ n by blastqed
lemma degree-rel-plus-max :[[ degree-rel f n; degree-rel g m ]] =⇒ degree-rel (f + g) (max n m)
by(rule degree-rel-plusI )(erule degree-rel-mono, simp)+
lemma degree-rel-timesI :assumes degree-rel f n degree-rel g mshows degree-rel (f ∗ g) (n + m)
prooffix c :: realassume 0 < chence 0 < sqrt c by simpwith assms obtain xf xg
where f :∧
y . y > xf =⇒ |f y | < sqrt c ∗ y ˆ nand g :
∧y . y > xg =⇒ |g y | < sqrt c ∗ y ˆ m by(blast elim: degree-rel .cases)
let ?x = max 0 (max xf xg) fix y
assume y > ?xhence [simp]: xf < y xg < y y 6= 0 0 < y by simp-allhave |(f ∗ g) y | = |f y | ∗ |g y | by(simp add : abs-mult)also have . . . < (sqrt c ∗ y ˆ n) ∗ (sqrt c ∗ y ˆ m)
by(rule mult-strict-mono)(rule f g , simp-all add : zero-less-mult-iff 〈0 < c〉
zero-less-power-eq)+
260
also have . . . = c ∗ y ˆ (n + m) using 〈0 < c〉 by(simp add : power-addreal-sqrt-mult [symmetric])
also note calculation thus ∃ x . ∀ y>x . |(f ∗ g) y | < c ∗ y ˆ (n + m) by blast
qed
lemma degree-rel-id-times-id : degree-rel (id ∗ id) n ←→ n ≥ 3proof
assume ∗: degree-rel (id ∗ id) nhave n = 0 ∨ n = 1 ∨ n = 2 ∨ 3 ≤ n by autothus 3 ≤ nproof(elim disjE )
assume n = 0assume [simp]: n = 0have 0 < (1 :: real) by simpwith ∗ have False
apply(rule degree-relE ′[where y=λx . max 1 (x + 1 )])apply(erule meta-impE )apply(simp-all add : max-def split : split-if-asm)
by (metis le-add-same-cancel2 le-less-trans less-irrefl mult-le-cancel-left1not-one-less-zero)
thus ?thesis ..next
assume [simp]: n = 1have 0 < (1 :: real) by simpwith ∗ have Falseby(rule degree-relE ′[where y=λx . max 2 (x + 1 )])(fastforce simp add : max-def
split : split-if-asm)thus ?thesis ..
nextassume [simp]: n = 2have 0 < (1 :: real) by simpwith ∗ have False by(rule degree-relE ′[where y=λx . x + 1 ])(simp add :
power2-eq-square)thus ?thesis ..
qednext
have degree-rel (id ∗ id) 3proof(rule degree-relI ′)
fix c y :: realassume 0 < c 1 / c < yhence [simp]: 0 ≤ c c 6= 0 0 < c 0 < y 0 ≤ yby(simp-all add : field-simps)(metis order .strict-trans zero-less-mult-pos zero-less-one
le-less-linear mult-pos-neg not-one-less-zero order .strict-trans)+
have |(id ∗ id) y | = c ∗ y ∗ y ∗ (1 / c) by simpalso have . . . < c ∗ y ∗ y ∗ y by(rule mult-strict-left-mono)(simp-all add : 〈1
/ c < y〉 zero-less-mult-iff )also have . . . = c ∗ y ˆ 3 by(simp add : numeral-3-eq-3 )
261
finally show |(id ∗ id) y | < c ∗ y ˆ 3 .qedmoreoverassume 3 ≤ nultimately show degree-rel (id ∗ id) n by(rule degree-rel-mono)
qed
lemma polynomial-ex-degree-rel :polynomial f =⇒ ∃n. degree-rel f n
by(induction rule: polynomial .induct)(auto simp add : id-def [symmetric] degree-rel-scalar-iffintro: degree-rel-timesI degree-rel-plus-max simp del : times-fun-apply plus-fun-apply)
definition degree :: (real ⇒ real) ⇒ natwhere degree f = (LEAST n. degree-rel f n)
lemma degree-0 [simp]: degree 0 = 0by(auto simp add : degree-def intro: Least-equality)
lemma degree-K [simp]: c 6= 0 =⇒ degree (λ-. c) = 1by(auto simp add : degree-def intro: Least-equality)
lemma degree-1 [simp]: degree 1 = 1by(simp add : one-fun-def )
lemma degree-id [simp]: degree id = 2by(auto simp add : degree-def intro: Least-equality)
lemma degree-scalar : c 6= 0 =⇒ degree ((λ-. c) ∗ f ) = degree fby(simp add : degree-def degree-rel-scalar)
lemma degree-scalar-iff :degree ((λ-. c) ∗ f ) = (if c = 0 then 0 else degree f )
by(simp add : degree-scalar zero-fun-def [symmetric])
lemma degree-id-times-id : degree (id ∗ id) = 3by(auto simp add : degree-def degree-rel-id-times-id intro: Least-equality)
lemma degree-times-id :assumes polynomial g g 6= 0shows degree (id ∗ g) = 1 + degree g
using assmsproof(induction)
case oneshow ?case by(simp add : id-def [symmetric])
nextcase idshow ?case
by(simp add : id-def [symmetric] degree-id-times-id del : times-fun-apply)
262
nextcase (scalar f c)from scalar .prems have [simp]: c 6= 0 f 6= (λ-. 0 ) by autohave degree (id ∗ ((λ-. c) ∗ f )) = degree ((λ-. c) ∗ (id ∗ f )) by(simp add :
mult-ac)also have . . . = degree (id ∗ f ) by(simp add : degree-scalar)also have . . . = 1 + degree f by(rule scalar .IH ) simpalso have 1 + degree f = 1 + degree ((λ-. c) ∗ f ) by(simp add : degree-scalar)finally show ?case .
nextcase (plus f g)have degree (id ∗ (f + g)) = degree (id ∗ f + id ∗ g) by(simp add : algebra-simps)also have . . . = max (degree (id ∗ f )) (degree (id ∗ g))
oops
lemma degree-times:assumes polynomial fand polynomial gshows degree (f ∗ g) = degree f + degree g − 1
using assmsproof(induct arbitrary : g)
case oneshow ?case by simp
nextcase id
oops
definition polysgn :: (real ⇒ real) ⇒ realwhere
polysgn f = (if ∃n. ∀ x>n. f x > 0 then 1 else if ∃n. ∀ x>n. f x < 0 then −1else 0 )
lemma polysgn-K [simp]: polysgn (λ-. c) = sgn cby(auto simp add : polysgn-def )(rule-tac x=n + 1 in exI , simp)+
lemma [simp]:shows polysgn-0 : polysgn 0 = 0and polysgn-1 : polysgn 1 = 1
by(simp-all add : zero-fun-def one-fun-def )
lemma polysgn-id [simp]: polysgn id = 1by(auto simp add : polysgn-def )
263
lemma polynomial-polysgn-cases-aux :fixes f :: ′a :: linordered-field , ring-1 ⇒ ′aassumes polynomial fshows (∃n. ∀ x>n. f x > 0 ) ∨ (∃n. ∀ x>n. f x < 0 ) ∨ f = 0
using assmsproof(induction)
case oneshow ?case by simp
nextcase idshow ?case by auto
nextcase (scalar f c)have 0 < c ∨ c < 0 ∨ c = 0 by(metis less-linear)with scalar .IH show ?case
by(auto 4 4 simp add : not-less mult-le-0-iff mult-less-0-iff )next
case (plus f g)thus ?case
oops
lemma polysgn-scalar [simp]: polysgn ((λ-. c) ∗ f ) = sgn c ∗ polysgn foops
lemma [[ polynomial f ; polysgn f = 0 ]] =⇒ f = 0apply(induct f rule: polynomial .induct)apply simpapply simpoops
inductive polybounded :: ( ′a :: linordered-idom ⇒ ′a) ⇒ bool wherepolybounded : [[ polynomial g ; |f | ≤ |g | ]] =⇒ polybounded f
hide-fact (open) polybounded
lemmas polyboundedI = polybounded .polybounded
lemma polynomial-polybounded : polynomial f =⇒ polybounded fby(erule polyboundedI ) simp
lemma [simp, intro!]:shows polybounded-const : polybounded (λ-. c)and polybounded-0 : polybounded 0and polybounded-1 : polybounded 1and polybounded-numeral : polybounded (numeral n)and polybounded-id : polybounded id
264
and polybounded-id ′: polybounded (λx . x )by(simp-all add : polynomial-polybounded)
lemma polybounded-plus:[[ polybounded f ; polybounded g ]] =⇒ polybounded (f + g)
apply(clarsimp simp add : polybounded .simps)apply(rule exI conjI )+apply(erule (1 ) polynomial-plusI )oops
end
10 Applicative Functors
theory Applicative-Functor importsMain∼∼/src/Tools/Adhoc-Overloading
begin
10.1 The basic operations of applicative functors
consts pure :: ′a ⇒ ′b
consts ap :: ′a ⇒ ′b ⇒ ′c (infixl 3 70 )
The applicative functor requires the following laws about pure and op 3:
pure id 3 u = u (identity)
pure op 3 u 3 v 3 w = u 3 (v 3 w) (composition)
pure f 3 pure x = pure (f x ) (homomorphism)
u 3 pure x = pure (λf . f x ) 3 u (interchange)
hide-const (open) ap
abbreviation (ap-forw) ap-forw :: ′a ⇒ ′b ⇒ ′c (infixr . 70 )where ap-forw x f ≡ f 3 x
10.2 Applicative functors with combinatorial structure
consts S :: ′a (S)consts K :: ′a (K)consts I :: ′a (I)consts C :: ′a (C)
The combinators must satisfy the following specification:
265
S = pure (λf g x . f x (g x )) S 3 x 3 y 3 z = x 3 z 3 (y 3 z )I = pure id I 3 x = xK = pure (λx y . x ) K 3 x 3 y = xC = pure (λf x y . f y x ) C 3 f 3 x 3 y = f 3 y 3 x
hide-const (open) S K I C
endtheory Environment-Functor imports
MainApplicative-Functor
begin
10.3 The environment functor
type-synonym ( ′i , ′a) envir = ′i ⇒ ′a
definition LIFT :: ′a ⇒ ( ′i , ′a) envirwhere LIFT x = (λ-. x )
lemma LIFT-apply [simp]: LIFT x i = xby(simp add : LIFT-def )
definition ap-envir :: ( ′i , ′a ⇒ ′b) envir ⇒ ( ′i , ′a) envir ⇒ ( ′i , ′b) envirwhere ap-envir f x = (λi . f i (x i))
adhoc-overloading Applicative-Functor .ap ap-envir
lemma ap-envir-apply [simp]: (f 3 x ) i = f i (x i)by(simp add : ap-envir-def )
lemma af-identity-envir : LIFT id 3 x = xby(simp add : ap-envir-def LIFT-def )
lemma af-composition-envir : LIFT op 3 u 3 v 3 w = u 3 (v 3 w)by(simp add : ap-envir-def LIFT-def )
lemma af-homomorphism-envir : LIFT f 3 LIFT x = LIFT (f x )by(simp add : ap-envir-def LIFT-def )
lemma af-interchange-gpv : u 3 LIFT x = LIFT (λf . f x ) 3 uby(simp add : LIFT-def ap-envir-def )
( ′i , ′a) envir has combinators S,K,C
10.4 lifting predicates to the environment functor
definition all-envir :: ( ′i , bool) envir ⇒ boolwhere all-envir p ←→ (∀ x . p x )
266
lemma all-envirI [Pure.intro!, intro!]: (∧
x . p x ) =⇒ all-envir pby(simp add : all-envir-def )
lemma all-envirE [Pure.elim 2 , elim]: all-envir p =⇒ (p x =⇒ thesis) =⇒ thesisby(simp add : all-envir-def )
lemma all-envirD : all-envir p =⇒ p xby(simp add : all-envir-def )
definition pred-envir :: ( ′a ⇒ bool) ⇒ ( ′i , ′a) envir ⇒ boolwhere pred-envir p f = all-envir (LIFT p 3 f )
lemma pred-envir-conv : pred-envir p f ←→ (∀ x . p (f x ))by(auto simp add : pred-envir-def )
lemma pred-envirI [Pure.intro!, intro!]: (∧
x . p (f x )) =⇒ pred-envir p fby(auto simp add : pred-envir-def )
lemma pred-envirD : pred-envir p f =⇒ p (f x )by(auto simp add : pred-envir-def )
lemma pred-envirE [Pure.elim 2 , elim]: pred-envir p f =⇒ (p (f x ) =⇒ thesis)=⇒ thesisby(simp add : pred-envir-conv)
lemma pred-envir-mono: [[ pred-envir p f ;∧
x . p (f x ) =⇒ q (g x ) ]] =⇒ pred-envirq gby blast
definition rel-envir :: ( ′a ⇒ ′b ⇒ bool) ⇒ ( ′i , ′a) envir ⇒ ( ′i , ′b) envir ⇒ boolwhere rel-envir p f g ←→ all-envir (LIFT p 3 f 3 g)
lemma rel-envir-conv : rel-envir p f g ←→ (∀ x . p (f x ) (g x ))by(auto simp add : rel-envir-def )
lemma rel-envir-conv-rel-fun: rel-envir = rel-fun op =by(simp add : rel-envir-conv rel-fun-def fun-eq-iff )
lemma rel-envirI [Pure.intro!, intro!]: (∧
x . p (f x ) (g x )) =⇒ rel-envir p f gby(auto simp add : rel-envir-def )
lemma rel-envirD : rel-envir p f g =⇒ p (f x ) (g x )by(auto simp add : rel-envir-def )
lemma rel-envirE [Pure.elim 2 , elim]: rel-envir p f g =⇒ (p (f x ) (g x ) =⇒ thesis)=⇒ thesisby(simp add : rel-envir-conv)
267
lemma rel-envir-mono: [[ rel-envir p f g ;∧
x . p (f x ) (g x ) =⇒ q (f ′ x ) (g ′ x ) ]]=⇒ rel-envir q f ′ g ′
by blast
lemma rel-envir-mono1 : [[ pred-envir p f ;∧
x . p (f x ) =⇒ q (f ′ x ) (g ′ x ) ]] =⇒rel-envir q f ′ g ′
by blast
lemma pred-envir-mono2 : [[ rel-envir p f g ;∧
x . p (f x ) (g x ) =⇒ q (f ′ x ) ]] =⇒pred-envir q f ′
by blast
end
11 Cyclic groups
theory Cyclic-Group imports∼∼/src/HOL/Algebra/Coset
begin
record ′a cyclic-group = ′a monoid +generator :: ′a (gı)
locale cyclic-group = group Gfor G :: ( ′a, ′b) cyclic-group-scheme (structure)+assumes generator-closed [intro, simp]: generator G ∈ carrier Gand generator : carrier G ⊆ range (λn :: nat . generator G (ˆ)G n)
begin
lemma generatorE [elim? ]:assumes x ∈ carrier Gobtains n :: nat where x = generator G (ˆ) n
using generator assms by auto
lemma inj-on-generator : inj-on (op (ˆ) g) ..<order Gproof(rule inj-onI )
fix n massume n ∈ ..<order G m ∈ ..<order Ghence n: n < order G and m: m < order G by simp-allmoreoverassume g (ˆ) n = g (ˆ) multimately show n = mproof(induction n m rule: linorder-wlog)
case sym thus ?case by simpnext
case (le n m)let ?d = m − n
268
have g (ˆ) (int m − int n) = g (ˆ) int m ⊗ inv (g (ˆ) int n)by(simp add : int-pow-diff )
also have g (ˆ) int m = g (ˆ) int n by(simp add : le.prems int-pow-int)also have . . . ⊗ inv (g (ˆ) (int n)) = 1 by simpfinally have g (ˆ) ?d = 1 using le.hyps by(simp add : zdiff-int int-pow-int) assume n < m
have carrier G ⊆ (λn. g (ˆ) n) ‘ ..<?dproof
fix xassume x ∈ carrier Gthen obtain k :: nat where x = g (ˆ) k ..also have . . . = (g (ˆ) ?d) (ˆ) (k div ?d) ⊗ g (ˆ) (k mod ?d)
by(simp add : nat-pow-pow nat-pow-mult mod-div-equality)also have . . . = g (ˆ) (k mod ?d)
using 〈g (ˆ) ?d = 1〉 by simpfinally show x ∈ (λn. g (ˆ) n) ‘ ..<?d using 〈n < m〉 by auto
qedhence order G ≤ card ((λn. g (ˆ) n) ‘ ..<?d)
by(simp add : order-def card-mono)also have . . . ≤ card ..<?d by(rule card-image-le) simpalso have . . . < order G using 〈m < order G〉 by simpfinally have False by simp
with 〈n ≤ m〉 show n = m by(auto simp add : order .order-iff-strict)qed
qed
lemma carrier-conv-generator :finite (carrier G) =⇒ carrier G = (λn. g (ˆ) n) ‘ ..<order G
proof −assume finite (carrier G)moreover have (λn. g (ˆ) n) ‘ ..<order G ⊆ carrier G by automoreover have card ((λn. g (ˆ) n) ‘ ..<order G) ≥ order G
using inj-on-generator by(simp add : card-image)ultimately show ?thesis unfolding order-def by(rule card-seteq [symmetric])
qed
lemma bij-betw-generator-carrier :finite (carrier G) =⇒ bij-betw (λn :: nat . g (ˆ) n) ..<order G (carrier G)
by(simp add : bij-betw-def inj-on-generator carrier-conv-generator)
end
lemma (in monoid) order-in-range-Suc: order G ∈ range Suc ←→ finite (carrierG)by(cases order G)(auto simp add : order-def carrier-not-empty intro: card-ge-0-finite)
endtheory Cyclic-Group-SPMF imports
Cyclic-Group
269
SPMFbegin
definition sample-uniform :: nat ⇒ nat spmfwhere sample-uniform n = spmf-of-set ..<n
lemma spmf-sample-uniform: spmf (sample-uniform n) x = indicator ..<n x /nby(simp add : sample-uniform-def spmf-of-set)
lemma weight-sample-uniform: weight-spmf (sample-uniform n) = indicator (rangeSuc) nby(auto simp add : sample-uniform-def weight-spmf-of-set split : split-indicator elim:lessE )
lemma weight-sample-uniform-0 [simp]: weight-spmf (sample-uniform 0 ) = 0by(auto simp add : weight-sample-uniform indicator-def )
lemma weight-sample-uniform-gt-0 [simp]: 0 < n =⇒ weight-spmf (sample-uniformn) = 1by(auto simp add : weight-sample-uniform indicator-def gr0-conv-Suc)
lemma lossless-sample-uniform [simp]: lossless-spmf (sample-uniform n) ←→ 0< nby(auto simp add : lossless-spmf-def intro: ccontr)
lemma set-spmf-sample-uniform [simp]: 0 < n =⇒ set-spmf (sample-uniform n)= ..<nby(simp add : sample-uniform-def )
lemma (in cyclic-group) sample-uniform-one-time-pad :assumes [simp]: c ∈ carrier Gshowsmap-spmf (λx . g (ˆ) x ⊗ c) (sample-uniform (order G)) =map-spmf (λx . g (ˆ) x ) (sample-uniform (order G))(is ?lhs = ?rhs)
proof(cases finite (carrier G))case Falsethus ?thesis by(simp add : order-def sample-uniform-def )
nextcase Truehave ?lhs = map-spmf (λx . x ⊗ c) ?rhs
by(simp add : pmf .map-comp o-def option.map-comp)also have rhs: ?rhs = spmf-of-set (carrier G)using True by(simp add : carrier-conv-generator inj-on-generator sample-uniform-def )also have map-spmf (λx . x ⊗ c) . . . = spmf-of-set ((λx . x ⊗ c) ‘ carrier G)
by(simp add : inj-on-multc)also have (λx . x ⊗ c) ‘ carrier G = carrier G
using True by(rule endo-inj-surj )(auto simp add : inj-on-multc)
270
finally show ?thesis using rhs by simpqed
end
12 Bitstrings
theory List-Bits imports Misc ∼∼/src/HOL/Library/Simps-Case-Conv begin
definition xor :: ′a ⇒ ′a ⇒ ′a :: uminus,inf ,sup (infixr ⊕ 67 )where x ⊕ y = inf (sup x y) (− (inf x y))
lemma xor-bool-def [iff ]: fixes x y :: bool shows x ⊕ y ←→ x 6= yby(auto simp add : xor-def )
lemma xor-commute:fixes x y :: ′a :: semilattice-sup,semilattice-inf ,uminusshows x ⊕ y = y ⊕ x
by(simp add : xor-def sup.commute inf .commute)
lemma xor-assoc:fixes x y :: ′a :: boolean-algebrashows (x ⊕ y) ⊕ z = x ⊕ (y ⊕ z )
by(simp add : xor-def inf-sup-aci inf-sup-distrib1 inf-sup-distrib2 )
lemma xor-left-commute:fixes x y :: ′a :: boolean-algebrashows x ⊕ (y ⊕ z ) = y ⊕ (x ⊕ z )
by (metis xor-assoc xor-commute)
lemma [simp]:fixes x :: ′a :: boolean-algebrashows xor-bot : x ⊕ bot = xand bot-xor : bot ⊕ x = xand xor-top: x ⊕ top = − xand top-xor : top ⊕ x = − x
by(simp-all add : xor-def )
lemma xor-inverse [simp]:fixes x :: ′a :: boolean-algebrashows x ⊕ x = bot
by(simp add : xor-def )
lemma xor-left-inverse [simp]:fixes x :: ′a :: boolean-algebrashows x ⊕ x ⊕ y = y
by(metis xor-left-commute xor-inverse xor-bot)
lemmas xor-ac = xor-assoc xor-commute xor-left-commute
271
definition xor-list :: ′a :: uminus,inf ,sup list ⇒ ′a list ⇒ ′a list (infixr [⊕]67 )where xor-list xs ys = map (case-prod op ⊕) (zip xs ys)
lemma xor-list-unfold :xs [⊕] ys = (case xs of [] ⇒ [] | x # xs ′⇒ (case ys of [] ⇒ [] | y # ys ′⇒ x ⊕
y # xs ′ [⊕] ys ′))by(simp add : xor-list-def split : list .split)
lemma xor-list-commute: fixes xs ys :: ′a :: semilattice-sup,semilattice-inf ,uminuslist
shows xs [⊕] ys = ys [⊕] xsunfolding xor-list-def by(subst zip-commute)(auto simp add : split-def xor-commute)
lemma xor-list-assoc [simp]:fixes xs ys :: ′a :: boolean-algebra listshows (xs [⊕] ys) [⊕] zs = xs [⊕] (ys [⊕] zs)
unfolding xor-list-def zip-map1 zip-map2apply(subst (2 ) zip-commute)apply(subst zip-left-commute)apply(subst (2 ) zip-commute)apply(auto simp add : zip-map2 split-def xor-assoc)done
lemma xor-list-left-commute:fixes xs ys zs :: ′a :: boolean-algebra listshows xs [⊕] (ys [⊕] zs) = ys [⊕] (xs [⊕] zs)
by(metis xor-list-assoc xor-list-commute)
lemmas xor-list-ac = xor-list-assoc xor-list-commute xor-list-left-commute
lemma xor-list-inverse [simp]:fixes xs :: ′a :: boolean-algebra listshows xs [⊕] xs = replicate (length xs) bot
by(simp add : xor-list-def zip-same-conv-map o-def map-replicate-const)
lemma xor-replicate-bot-right [simp]:fixes xs :: ′a :: boolean-algebra listshows [[ length xs ≤ n; x = bot ]] =⇒ xs [⊕] replicate n x = xs
by(simp add : xor-list-def zip-replicate2 o-def )
lemma xor-replicate-bot-left [simp]:fixes xs :: ′a :: boolean-algebra listshows [[ length xs ≤ n; x = bot ]] =⇒ replicate n x [⊕] xs = xs
by(simp add : xor-list-commute)
272
lemma xor-list-left-inverse [simp]:fixes xs :: ′a :: boolean-algebra listshows length ys ≤ length xs =⇒ xs [⊕] (xs [⊕] ys) = ys
by(subst xor-list-assoc[symmetric])(simp)
lemma length-xor-list [simp]: length (xor-list xs ys) = min (length xs) (length ys)by(simp add : xor-list-def )
lemma inj-on-xor-list-nlists [simp]:fixes xs :: ′a :: boolean-algebra listshows n ≤ length xs =⇒ inj-on (xor-list xs) (nlists UNIV n)
apply(clarsimp simp add : inj-on-def in-nlists-UNIV )using xor-list-left-inverse by fastforce
endtheory List-Bits-SPMF imports
List-BitsSPMF
begin
lemma one-time-pad :fixes xs :: - :: boolean-algebra listshows length xs ≥ n =⇒ map-spmf (xor-list xs) (spmf-of-set (nlists UNIV n))
= spmf-of-set (nlists UNIV n)by(auto 4 3 simp add : in-nlists-UNIV intro: xor-list-left-inverse[symmetric] rev-image-eqIintro!: arg-cong [where f =spmf-of-set ])
end
13 Examples
theory IND-CPA-PK importsGenerative-Probabilistic-ValueComputational-ModelNegligibleEnvironment-Functor
begin
13.1 The IND-CPA security game for public-key encryptionwith oracle access
locale ind-cpa-pk =fixes key-gen :: ( ′pubkey × ′privkey , ′call , ′ret) gpv — probabilisticand aencrypt :: ′pubkey ⇒ ′plain ⇒ ( ′cipher , ′call , ′ret) gpv — probabilistic w/
access to an oracleand adecrypt :: ′privkey ⇒ ′cipher ⇒ ( ′plain, ′call , ′ret) gpv — not usedand valid-plain :: ′plain ⇒ bool — checks whether a plain text is valid, i.e., has
the right format
273
begin
We cannot incorporate the predicate valid-plain in the type ′plain of plain-texts, because the single ′plain must contain plaintexts for all values of thesecurity parameter, as HOL does not have dependent types. Consequently,the oracle has to ensure that the received plaintexts are valid.
type-synonym ( ′pubkey ′, ′plain ′, ′cipher ′, ′call ′, ′ret ′, ′state) adversary =( ′pubkey ′⇒ (( ′plain ′ × ′plain ′) × ′state, ′call ′, ′ret ′) gpv)× ( ′cipher ′⇒ ′state ⇒ (bool , ′call ′, ′ret ′) gpv)
fun ind-cpa :: ( ′pubkey , ′plain, ′cipher , ′call , ′ret , ′state) adversary ⇒ (bool , ′call ,′ret) gpvwhere
ind-cpa (A1 , A2 ) = TRY do (pk , sk) ← key-gen;b ← lift-spmf coin-spmf ;((m0 , m1 ), σ) ← (A1 pk);assert-gpv (valid-plain m0 ∧ valid-plain m1 );cipher ← aencrypt pk (if b then m0 else m1 );guess ← A2 cipher σ;Done (guess = b) ELSE lift-spmf coin-spmf
definition advantage :: ( ′σ ⇒ ′call ⇒ ( ′ret × ′σ) spmf ) ⇒ ′σ ⇒ ( ′pubkey , ′plain,′cipher , ′call , ′ret , ′state) adversary ⇒ realwhere advantage oracle σ A = |spmf (run-gpv oracle (ind-cpa A) σ) True − 1/2 |
lemma advantage-nonneg : advantage oracle σ A ≥ 0 by(simp add : advantage-def )
definition ibounded-by :: ( ′pubkey , ′plain, ′cipher , ′call , ′ret , ′state) adversary ⇒nat ⇒ boolwhere
ibounded-by = (λ(A1 , A2 ) q .(∃ q1 q2 . (∀ pk . interaction-bounded-by (A1 pk) q1 ) ∧ (∀ cipher σ. interaction-bounded-by
(A2 cipher σ) q2 ) ∧ q1 + q2 ≤ q))
lemma ibounded-by ′E [consumes 1 , case-names ibounded-by ′, elim? ]:assumes ibounded-by (A1 , A2 ) qobtains q1 q2where q1 + q2 ≤ qand
∧pk . interaction-bounded-by (A1 pk) q1
and∧
cipher σ. interaction-bounded-by (A2 cipher σ) q2using assms by(auto simp add : ibounded-by-def )
lemma ibounded-byI [intro? ]:[[∧
pk . interaction-bounded-by (A1 pk) q1 ;∧
cipher σ. interaction-bounded-by(A2 cipher σ) q2 ; q1 + q2 ≤ q ]]
=⇒ ibounded-by (A1 , A2 ) qby(auto simp add : ibounded-by-def )
274
definition lossless :: ( ′pubkey , ′plain, ′cipher , ′call , ′ret , ′state) adversary ⇒ boolwhere lossless = (λ(A1 , A2 ). (∀ pk . lossless-gpv I-top (A1 pk)) ∧ (∀ cipher σ.lossless-gpv I-top (A2 cipher σ)))
end
endtheory IND-CPA-PK-Single imports
Computational-Modelbegin
13.2 The IND-CPA security game (public key, single in-stance)
locale ind-cpa =fixes key-gen :: ( ′pub-key × ′priv-key) spmf — probabilisticand aencrypt :: ′pub-key ⇒ ′plain ⇒ ′cipher spmf — probabilisticand adecrypt :: ′priv-key ⇒ ′cipher ⇒ ′plain option — deterministic, but not
usedand valid-plain :: ′plain ⇒ bool — checks whether a plain text is valid, i.e., has
the right formatbegin
We cannot incorporate the predicate valid-plain in the type ′plain of plain-texts, because the single ′plain must contain plaintexts for all values of thesecurity parameter, as HOL does not have dependent types. Consequently,the oracle has to ensure that the received plaintexts are valid.
type-synonym ( ′pub-key ′, ′plain ′, ′cipher ′, ′state) adversary =( ′pub-key ′⇒ (( ′plain ′ × ′plain ′) × ′state) spmf )× ( ′cipher ′⇒ ′state ⇒ bool spmf )
primrec ind-cpa :: ( ′pub-key , ′plain, ′cipher , ′state) adversary ⇒ bool spmfwhere
ind-cpa (A1 , A2 ) = TRY do (pk , sk) ← key-gen;b ← coin-spmf ;((m0 , m1 ), σ) ← A1 pk ;- :: unit ← assert-spmf (valid-plain m0 ∧ valid-plain m1 );cipher ← aencrypt pk (if b then m0 else m1 );b ′← A2 cipher σ;return-spmf (b = b ′)
ELSE coin-spmf
declare ind-cpa.simps [simp del ]
definition advantage :: ( ′pub-key , ′plain, ′cipher , ′state) adversary ⇒ realwhere advantage A = |spmf (ind-cpa A) True − 1/2 |
275
definition lossless :: ( ′pub-key , ′plain, ′cipher , ′state) adversary ⇒ boolwhere
lossless A ←→((∀ pk . lossless-spmf (fst A pk)) ∧
(∀ cipher σ. lossless-spmf (snd A cipher σ)))
lemma lossless-ind-cpa:[[ lossless A; lossless-spmf (key-gen);∧
key plain. valid-plain plain =⇒ lossless-spmf (aencrypt key plain) ]]=⇒ lossless-spmf (ind-cpa A)
by(auto simp add : lossless-def ind-cpa-def split-def Let-def )
end
endtheory IND-CPA imports
Generative-Probabilistic-ValueComputational-ModelNegligibleEnvironment-Functor
begin
13.3 The IND-CPA security game
locale ind-cpa =fixes key-gen :: ′key spmf — probabilisticand encrypt :: ′key ⇒ ′plain ⇒ ′cipher spmf — probabilisticand decrypt :: ′key ⇒ ′cipher ⇒ ′plain option — deterministic, but not usedand valid-plain :: ′plain ⇒ bool — checks whether a plain text is valid, i.e., has
the right formatbegin
We cannot incorporate the predicate valid-plain in the type ′plain of plain-texts, because the single ′plain must contain plaintexts for all values of thesecurity parameter, as HOL does not have dependent types. Consequently,the oracle has to ensure that the received plaintexts are valid.
type-synonym ( ′plain ′, ′cipher ′, ′state) adversary =(( ′plain ′ × ′plain ′) × ′state, ′plain ′, ′cipher ′) gpv× ( ′cipher ′⇒ ′state ⇒ (bool , ′plain ′, ′cipher ′) gpv)
definition encrypt-oracle :: ′key ⇒ unit ⇒ ′plain ⇒ ( ′cipher × unit) spmfwhere
encrypt-oracle key σ plain = do cipher ← encrypt key plain;return-spmf (cipher , ())
definition ind-cpa :: ( ′plain, ′cipher , ′state) adversary ⇒ bool spmf
276
whereind-cpa A = do
let (A1 , A2 ) = A;key ← key-gen;b ← coin-spmf ;(guess, -) ← exec-gpv (encrypt-oracle key) (do
((m0 , m1 ), σ) ← A1 ;if valid-plain m0 ∧ valid-plain m1 then do
cipher ← lift-spmf (encrypt key (if b then m0 else m1 ));A2 cipher σ else lift-spmf coin-spmf) ();
return-spmf (guess = b)
definition advantage :: ( ′plain, ′cipher , ′state) adversary ⇒ realwhere advantage A = |spmf (ind-cpa A) True − 1/2 |
lemma advantage-nonneg : advantage A ≥ 0 by(simp add : advantage-def )
definition ibounded-by :: ( ′plain, ′cipher , ′state) adversary ⇒ nat ⇒ boolwhere
ibounded-by = (λ(A1 , A2 ) q .(∃ q1 q2 . interaction-bounded-by A1 q1 ∧ (∀ cipher σ. interaction-bounded-by (A2
cipher σ) q2 ) ∧ q1 + q2 ≤ q))
lemma ibounded-byE [consumes 1 , case-names ibounded-by , elim? ]:assumes ibounded-by (A1 , A2 ) qobtains q1 q2where q1 + q2 ≤ qand interaction-bounded-by A1 q1and
∧cipher σ. interaction-bounded-by (A2 cipher σ) q2
using assms by(auto simp add : ibounded-by-def )
lemma ibounded-byI [intro? ]:[[ interaction-bounded-by A1 q1 ;
∧cipher σ. interaction-bounded-by (A2 cipher
σ) q2 ; q1 + q2 ≤ q ]]=⇒ ibounded-by (A1 , A2 ) q
by(auto simp add : ibounded-by-def )
definition lossless :: ( ′plain, ′cipher , ′state) adversary ⇒ boolwhere lossless = (λ(A1 , A2 ). lossless-gpv I-top A1 ∧ (∀ cipher σ. lossless-gpvI-top (A2 cipher σ)))
end
endtheory Diffie-Hellman imports
Cyclic-Group-SPMF
277
Computational-Modelbegin
13.4 The DDH security game
locale ddh =fixes G :: ′grp cyclic-group (structure)
begin
type-synonym ′grp ′ adversary = ′grp ′⇒ ′grp ′⇒ ′grp ′⇒ bool spmf
definition ddh-0 :: ′grp adversary ⇒ bool spmfwhere ddh-0 A = do
x ← sample-uniform (order G);y ← sample-uniform (order G);A (g (ˆ) x ) (g (ˆ) y) (g (ˆ) (x ∗ y))
definition ddh-1 :: ′grp adversary ⇒ bool spmfwhere ddh-1 A = do
x ← sample-uniform (order G);y ← sample-uniform (order G);z ← sample-uniform (order G);A (g (ˆ) x ) (g (ˆ) y) (g (ˆ) z )
definition advantage :: ′grp adversary ⇒ realwhere advantage A = |spmf (ddh-0 A) True − spmf (ddh-1 A) True|
definition lossless :: ′grp adversary ⇒ boolwhere lossless A ←→ (∀α β γ. lossless-spmf (A α β γ))
lemma lossless-ddh-0 :[[ lossless A; 0 < order G ]]=⇒ lossless-spmf (ddh-0 A)
by(auto simp add : lossless-def ddh-0-def split-def Let-def )
lemma lossless-ddh-1 :[[ lossless A; 0 < order G ]]=⇒ lossless-spmf (ddh-1 A)
by(auto simp add : lossless-def ddh-1-def split-def Let-def )
end
13.5 The LCDH security game
locale lcdh =fixes G :: ′grp cyclic-group (structure)
begin
278
type-synonym ′grp ′ adversary = ′grp ′⇒ ′grp ′⇒ ′grp ′ set spmf
definition lcdh :: ′grp adversary ⇒ bool spmfwhere lcdh A = do
x ← sample-uniform (order G);y ← sample-uniform (order G);zs ← A (g (ˆ) x ) (g (ˆ) y);return-spmf (g (ˆ) (x ∗ y) ∈ zs)
definition advantage :: ′grp adversary ⇒ realwhere advantage A = spmf (lcdh A) True
definition lossless :: ′grp adversary ⇒ boolwhere lossless A ←→ (∀α β. lossless-spmf (A α β))
lemma lossless-lcdh:[[ lossless A; 0 < order G ]]=⇒ lossless-spmf (lcdh A)
by(auto simp add : lossless-def lcdh-def split-def Let-def )
end
endtheory Pseudo-Random-Function imports
Generative-Probabilistic-ValueComputational-ModelNegligibleEnvironment-Functor
begin
13.6 Random function construction
locale random-function =fixes p :: ′a spmf
begin
type-synonym ( ′b, ′a ′) dict = ′b ′a ′
definition random-oracle :: ( ′b, ′a) dict ⇒ ′b ⇒ ( ′a × ( ′b, ′a) dict) spmfwhere
random-oracle σ x =(case σ x of Some y ⇒ return-spmf (y , σ)| None ⇒ p >>= (λy . return-spmf (y , σ(x 7→ y))))
definition forgetful-random-oracle :: unit ⇒ ′b ⇒ ( ′a × unit) spmfwhere
forgetful-random-oracle σ x = p >>= (λy . return-spmf (y , ()))
279
lemma weight-random-oracle [simp]:weight-spmf p = 1 =⇒ weight-spmf (random-oracle σ x ) = 1
by(simp add : random-oracle-def weight-bind-spmf integral-spmf-const o-def split :option.split)
lemma lossless-random-oracle [simp]:lossless-spmf p =⇒ lossless-spmf (random-oracle σ x )
by(simp add : lossless-spmf-def )
sublocale finite: callee-invariant random-oracle λσ. finite (dom σ)by(unfold-locales)(auto simp add : random-oracle-def set-bind-spmf split : option.splits)
end
13.7 Pseudo-random functions
locale prf =fixes key-gen :: ′key spmfand prf :: ′key ⇒ ′domain ⇒ ′rangeand rand :: ′range spmf
begin
sublocale random-function rand .
definition prf-oracle :: ′key ⇒ unit ⇒ ′domain ⇒ ( ′range × unit) spmfwhere prf-oracle key σ x = return-spmf (prf key x , ())
type-synonym ( ′domain ′, ′range ′) adversary = (bool , ′domain ′, ′range ′) gpv
definition game-0 :: ( ′domain, ′range) adversary ⇒ bool spmfwhere
game-0 A = do key ← key-gen;(b, -) ← exec-gpv (prf-oracle key) A ();return-spmf b
definition game-1 :: ( ′domain, ′range) adversary ⇒ bool spmfwhere
game-1 A = do (b, -) ← exec-gpv random-oracle A empty ;return-spmf b
definition advantage :: ( ′domain, ′range) adversary ⇒ realwhere advantage A = |spmf (game-0 A) True − spmf (game-1 A) True|
abbreviation lossless :: ( ′domain, ′range) adversary ⇒ boolwhere lossless ≡ lossless-gpv I-top
280
abbreviation (input) ibounded-by :: ( ′domain, ′range) adversary ⇒ nat ⇒ boolwhere ibounded-by ≡ interaction-bounded-by
end
endtheory Bernoulli imports SPMF begin
13.8 The bernoulli distribution built from coin flips
partial-function (spmf ) bernoulli :: real ⇒ bool spmf wherebernoulli p = do
b ← coin-spmf ;if b then return-spmf (p ≥ 1 / 2 )else if p < 1 / 2 then bernoulli (2 ∗ p)else bernoulli (2 ∗ p − 1 )
lemma pmf-bernoulli-None: pmf (bernoulli p) None = 0proof −
have ereal (pmf (bernoulli p) None) ≤ (INF n:UNIV . ereal (1 / 2 ˆ n))proof(rule INF-greatest)
show ereal (pmf (bernoulli p) None) ≤ ereal (1 / 2 ˆ n) for nproof(induction n arbitrary : p)
case (Suc n)show ?case using Suc.IH [of 2 ∗ p] Suc.IH [of 2 ∗ p − 1 ]
by(subst bernoulli .simps)(simp add : UNIV-bool zero-ereal-def one-ereal-defmax-def field-simps spmf-of-pmf-pmf-of-set [symmetric] ereal-pmf-bind nn-integral-pmf-of-setdel : spmf-of-pmf-pmf-of-set)
qed(simp add : pmf-le-1 )qedalso have . . . = ereal 0proof(rule LIMSEQ-unique)
show (λn. ereal (1 / 2 ˆ n)) −−−−→ . . . by(rule LIMSEQ-INF )(simp add :field-simps decseq-SucI )
show (λn. ereal (1 / 2 ˆ n)) −−−−→ ereal 0 by(simp add : LIMSEQ-divide-realpow-zero)qedfinally show ?thesis by simp
qed
lemma lossless-bernoulli [simp]: lossless-spmf (bernoulli p)by(simp add : lossless-iff-pmf-None pmf-bernoulli-None)
lemma [simp]: assumes 0 ≤ p p ≤ 1shows bernoulli-True: spmf (bernoulli p) True = p (is ?True)and bernoulli-False: spmf (bernoulli p) False = 1 − p (is ?False)
proof − have ereal (spmf (bernoulli p) b) ≤ ereal (if b then p else 1 − p) for b using
281
assmsproof(induction arbitrary : p rule: bernoulli .fixp-induct [case-names adm bottom
step])case adm show ?caseby(rule admissible-all admissible-imp admissible-leI [OF complete-lattice-class.complete-lattice-ccpo ′]
mcont2mcont-ereal-spmf )+ simp-allnext
case (step bernoulli ′ p)show ?case using step.prems step.IH [of 2 ∗ p] step.IH [of 2 ∗ p − 1 ]by(auto simp add : UNIV-bool zero-ereal-def one-ereal-def max-def field-simps
spmf-of-pmf-pmf-of-set [symmetric] ereal-pmf-bind nn-integral-pmf-of-set simp del :spmf-of-pmf-pmf-of-set)
qed simp note this[of True] this[of False]moreover have spmf (bernoulli p) True + spmf (bernoulli p) False = 1
by(simp add : spmf-False-conv-True)ultimately show ?True ?False by simp-all
qed
lemma bernoulli-neg [simp]:assumes p ≤ 0shows bernoulli p = return-spmf False
proof −from assms have ord-spmf op = (bernoulli p) (return-spmf False)proof(induction arbitrary : p rule: bernoulli .fixp-induct [case-names adm bottom
step])case (step bernoulli ′ p)show ?case using step.prems step.IH [of 2 ∗ p]by(auto simp add : ord-spmf-return-spmf2 set-bind-spmf bind-UNION field-simps)
qed simp-allfrom ord-spmf-eq-leD [OF this, of True] have spmf (bernoulli p) True = 0 by
simpmoreover then have spmf (bernoulli p) False = 1 by(simp add : spmf-False-conv-True)ultimately show ?thesis by(auto intro: spmf-eqI split : split-indicator)
qed
lemma bernoulli-pos [simp]:assumes 1 ≤ pshows bernoulli p = return-spmf True
proof −from assms have ord-spmf op = (bernoulli p) (return-spmf True)proof(induction arbitrary : p rule: bernoulli .fixp-induct [case-names adm bottom
step])case (step bernoulli ′ p)show ?case using step.prems step.IH [of 2 ∗ p − 1 ]by(auto simp add : ord-spmf-return-spmf2 set-bind-spmf bind-UNION field-simps)
qed simp-allfrom ord-spmf-eq-leD [OF this, of False] have spmf (bernoulli p) False = 0 by
simp
282
moreover then have spmf (bernoulli p) True = 1 by(simp add : spmf-False-conv-True)ultimately show ?thesis by(auto intro: spmf-eqI split : split-indicator)
qed
context begin interpretation pmf-as-function .lemma bernoulli-eq-bernoulli-pmf :
bernoulli p = spmf-of-pmf (bernoulli-pmf p)by(rule spmf-eqI ; simp)(transfer ; auto simp add : max-def min-def )end
endtheory Elgamal imports
Generative-Probabilistic-ValueCyclic-Group-SPMFComputational-ModelDiffie-HellmanIND-CPA-PK-Single
begin
lemma case-prod-distrib-bind-spmf :bind-spmf p (λx . case-prod (f x ) y) = case-prod (λa b. bind-spmf p (λx . f x a b))
yby(cases y) simp
13.9 Elgamal encryption scheme
locale elgamal-base =fixes G :: ′grp cyclic-group (structure)
begin
type-synonym ′grp ′ pub-key = ′grp ′
type-synonym ′grp ′ priv-key = nattype-synonym ′grp ′ plain = ′grp ′
type-synonym ′grp ′ cipher = ′grp ′ × ′grp ′
definition key-gen :: ( ′grp pub-key × ′grp priv-key) spmfwhere
key-gen = do x ← sample-uniform (order G);return-spmf (g (ˆ) x , x )
definition aencrypt :: ′grp pub-key ⇒ ′grp ⇒ ′grp cipher spmfwhere
aencrypt α msg = do y ← sample-uniform (order G);return-spmf (g (ˆ) y , (α (ˆ) y) ⊗ msg)
283
definition adecrypt :: ′grp priv-key ⇒ ′grp cipher ⇒ ′grp optionwhere
adecrypt x = (λ(β, ζ). Some (ζ ⊗ (inv (β (ˆ) x ))))
abbreviation valid-plain :: ′grp ⇒ boolwhere valid-plain msg ≡ msg ∈ carrier G
sublocale ind-cpa: ind-cpa key-gen aencrypt adecrypt valid-plain .sublocale ddh: ddh G .
fun elgamal-adversary:: ( ′grp pub-key , ′grp plain, ′grp cipher , ′state) ind-cpa.adversary⇒ ′grp ddh.adversary
whereelgamal-adversary (A1 , A2 ) α β γ = TRY do
b ← coin-spmf ;((msg1 , msg2 ), σ) ← A1 α;(∗ have to check that the attacker actually sends an element from the group;
otherwise flip a coin ∗)- :: unit ← assert-spmf (valid-plain msg1 ∧ valid-plain msg2 );guess ← A2 (β, γ ⊗ (if b then msg1 else msg2 )) σ;return-spmf (guess = b) ELSE coin-spmf
lemma lossless-key-gen [simp]: lossless-spmf (key-gen) ←→ 0 < order Gby(simp add : key-gen-def Let-def )
lemma lossless-aencrypt [simp]:lossless-spmf (aencrypt key plain) ←→ 0 < order G
by(simp add : aencrypt-def Let-def )
lemma lossless-elgamal-adversary :[[ ind-cpa.lossless A; 0 < order G ]]=⇒ ddh.lossless (elgamal-adversary A)
by(cases A)(simp add : ddh.lossless-def ind-cpa.lossless-def Let-def split-def )
end
locale elgamal = elgamal-base + cyclic-group G +assumes finite-group: finite (carrier G)
begin
lemma advantage-elgamal : ddh.advantage (elgamal-adversary A) = ind-cpa.advantageAproof −
obtain A1 A2 where [simp]: A = (A1 , A2 ) by(cases A)note [simp] = order-gt-0-iff-finite finite-grouphave ddh.ddh-1 (elgamal-adversary A) = TRY do
let q = order G;
284
x ← sample-uniform q ;y ← sample-uniform q ;((msg1 , msg2 ), σ) ← A1 (g (ˆ) x );- :: unit ← assert-spmf (msg1 ∈ carrier G ∧ msg2 ∈ carrier G);b ← coin-spmf ;z ← map-spmf (λz . g (ˆ) z ⊗ (if b then msg1 else msg2 )) (sample-uniform
q);guess ← A2 (g (ˆ) y , z ) σ;return-spmf (guess ←→ b) ELSE coin-spmfapply(clarsimp simp add : Let-def try-spmf-bind-out split-def bind-map-spmf
o-def ddh.ddh-1-def )apply(rewrite bind-commute-spmf [where p=coin-spmf ])apply(rewrite bind-commute-spmf [where q=A1 -])apply(rewrite bind-commute-spmf [where q=coin-spmf ])apply(rewrite bind-commute-spmf [where q=assert-spmf -])apply(rewrite bind-commute-spmf [where q=assert-spmf -])by(simp)
also have . . . = TRY do let q = order G;x ← sample-uniform q ;y ← sample-uniform q ;((msg1 , msg2 ), σ) ← A1 (g (ˆ) x );- :: unit ← assert-spmf (msg1 ∈ carrier G ∧ msg2 ∈ carrier G);z ← map-spmf (λz . g (ˆ) z ) (sample-uniform q);guess ← A2 (g (ˆ) y , z ) σ;map-spmf (op = guess) coin-spmf ELSE coin-spmf
by(clarsimp simp add : Let-def sample-uniform-one-time-pad cong : bind-spmf-cong-simp)(simp add : map-spmf-conv-bind-spmf bind-commute-spmf [where p=coin-spmf ])
also have . . . = coin-spmfby(simp add : map-eq-const-coin-spmf Let-def split-def bind-spmf-const try-bind-spmf-lossless2 ′
scale-bind-spmf weight-spmf-le-1 scale-scale-spmf del : try-spmf-lossless)(simp add : bind-spmf-const)
also have ddh.ddh-0 (elgamal-adversary A) = ind-cpa.ind-cpa Aunfolding ddh.ddh-0-def IND-CPA-PK-Single.ind-cpa.ind-cpa-def key-gen-def
aencrypt-defapply(clarsimp simp add : Let-def try-spmf-bind-out split-def )apply(rewrite bind-commute-spmf [where q=coin-spmf ])apply(rewrite bind-commute-spmf [where q=A1 -])apply(rewrite bind-commute-spmf [where q=assert-spmf -])by(simp add : nat-pow-pow eq-commute)
ultimately show ?thesis unfolding ddh.advantage-def ind-cpa.advantage-defby(simp add : spmf-of-set)qed
end
end
285
13.10 Formalisation of Hashed Elgamal in the Random Or-acle Model
theory Hashed-Elgamal importsGPV-BisimCyclic-Group-SPMFList-Bits-SPMFIND-CPA-PKDiffie-Hellman
begin
type-synonym bitstring = bool list
locale hash-oracle = fixes len :: nat begin
type-synonym ′a state = ′a bitstring
definition oracle :: ′a state ⇒ ′a ⇒ (bitstring × ′a state) spmfwhere
oracle σ x =(case σ x of None ⇒ do
bs ← spmf-of-set (nlists UNIV len);return-spmf (bs, σ(x 7→ bs)) | Some bs ⇒ return-spmf (bs, σ))
abbreviation (input) initial :: ′a state where initial ≡ empty
inductive invariant :: ′a state ⇒ boolwhere
invariant : [[ finite (dom σ); length ‘ ran σ ⊆ len ]] =⇒ invariant σ
lemma invariant-initial [simp]: invariant initialby(rule invariant .intros) auto
lemma invariant-update [simp]: [[ invariant σ; length bs = len ]] =⇒ invariant(σ(x 7→ bs))by(auto simp add : invariant .simps ran-def )
lemma invariant [intro!, simp]: callee-invariant oracle invariantby unfold-locales(simp add : oracle-def set-bind-spmf in-nlists-UNIV split : option.split-asm)
lemma invariant-in-dom [simp]: callee-invariant oracle (λσ. x ∈ dom σ)by unfold-locales(simp add : oracle-def set-bind-spmf split : option.split-asm)
lemma lossless-oracle [simp]: lossless-spmf (oracle σ x )by(simp add : oracle-def split : option.split)
lemma card-dom-state:assumes σ ′: (x , σ ′) ∈ set-spmf (exec-gpv oracle gpv σ)and ibound : interaction-bounded-by gpv n
286
shows card (dom σ ′) ≤ n + card (dom σ)proof(cases finite (dom σ))
case Trueinterpret callee-invariant oracle λσ. finite (dom σ)by unfold-locales(auto simp add : oracle-def set-bind-spmf split : option.split-asm)
from ibound σ ′ - True show ?thesisby(rule interaction-bounded-by-exec-gpv-count)(auto simp add : oracle-def set-bind-spmf
card-insert-if simp del : fun-upd-apply split : option.split-asm)next
case Falseinterpret callee-invariant oracle λσ ′. dom σ ⊆ dom σ ′
by unfold-locales(auto simp add : oracle-def set-bind-spmf split : option.split-asm)from σ ′ have dom σ ⊆ dom σ ′ by(rule exec-gpv-invariant) simpwith False have infinite (dom σ ′) by(auto intro: finite-subset)with False show ?thesis by simp
qed
end
locale elgamal-base =fixes G :: ′grp cyclic-group (structure)and len-plain :: nat
begin
sublocale hash: hash-oracle len-plain .abbreviation hash :: ′grp ⇒ (bitstring , ′grp, bitstring) gpvwhere hash x ≡ Pause x Done
type-synonym ′grp ′ pub-key = ′grp ′
type-synonym ′grp ′ priv-key = nattype-synonym plain = bitstringtype-synonym ′grp ′ cipher = ′grp ′ × bitstring
definition key-gen :: ( ′grp pub-key × ′grp priv-key) spmfwhere
key-gen = do x ← sample-uniform (order G);return-spmf (g (ˆ) x , x )
definition aencrypt :: ′grp pub-key ⇒ plain ⇒ ( ′grp cipher , ′grp, bitstring) gpvwhere
aencrypt α msg = do y ← lift-spmf (sample-uniform (order G));h ← hash (α (ˆ) y);Done (g (ˆ) y , h [⊕] msg)
definition adecrypt :: ′grp priv-key ⇒ ′grp cipher ⇒ (plain, ′grp, bitstring) gpv
287
whereadecrypt x = (λ(β, ζ). do
h ← hash (β (ˆ) x );Done (ζ [⊕] h))
definition valid-plain :: plain ⇒ boolwhere valid-plain msg ←→ length msg = len-plain
lemma lossless-aencrypt [simp]: lossless-gpv I (aencrypt α msg) ←→ 0 < orderGby(simp add : aencrypt-def Let-def )
lemma interaction-bounded-by-aencrypt [interaction-bound , simp]:interaction-bounded-by (aencrypt α msg) (Suc 0 )
proof −have TERM (aencrypt α msg) .then guess
apply(rule interaction-bounded-by-start)apply(unfold aencrypt-def Let-def split-def )[1 ]apply(rule interaction-bound)+done
thus ?thesis by simpqed
sublocale ind-cpa: ind-cpa-pk lift-spmf key-gen aencrypt adecrypt valid-plain .sublocale lcdh: lcdh G .
fun elgamal-adversary:: ( ′grp pub-key , plain, ′grp cipher , ′grp, bitstring , ′state) ind-cpa.adversary⇒ ′grp lcdh.adversary
whereelgamal-adversary (A1 , A2 ) α β = do
(((msg1 , msg2 ), σ), s) ← exec-gpv hash.oracle (A1 α) hash.initial ;(∗ have to check that the attacker actually sends an element from the group;
otherwise stop early ∗)TRY do
- :: unit ← assert-spmf (valid-plain msg1 ∧ valid-plain msg2 );h ′← spmf-of-set (nlists UNIV len-plain);(guess, s ′) ← exec-gpv hash.oracle (A2 (β, h ′) σ) s;return-spmf (dom s ′) ELSE return-spmf (dom s)
lemma lossless-key-gen [simp]: lossless-spmf key-gen ←→ 0 < order Gby(simp add : key-gen-def Let-def )
lemma lossless-elgamal-adversary :[[ ind-cpa.lossless A;
∧η. 0 < order G ]]
288
=⇒ lcdh.lossless (elgamal-adversary A)by(cases A)(auto simp add : lcdh.lossless-def ind-cpa.lossless-def split-def Let-defintro!: lossless-exec-gpv [where I=I-top] lossless-inline)
end
locale elgamal = elgamal-base +assumes cyclic-group: cyclic-group G
begin
interpretation cyclic-group G by(fact cyclic-group)
lemma advantage-elgamal :assumes finite-group: finite (carrier G)and lossless: ind-cpa.lossless Ashows ind-cpa.advantage hash.oracle hash.initial A ≤ lcdh.advantage (elgamal-adversaryA)
(is ?lhs ≤ ?rhs)proof −
interpret lifting-syntax .note [cong del ] = if-weak-cong and [split del ] = split-if
and [simp] = map-lift-spmf gpv .map-id set-bind-spmf lossless-weight-spmfDmap-spmf-bind-spmf bind-spmf-const
obtain A1 A2 where A [simp]: A = (A1 , A2 ) by(cases A)
interpret cyclic-group: cyclic-group G by(rule cyclic-group)from finite-group have [simp]: order G > 0 using order-gt-0-iff-finite by(simp)
from lossless have lossless1 [simp]:∧
pk . lossless-gpv I-top (A1 pk)and lossless2 [simp]:
∧σ cipher . lossless-gpv I-top (A2 σ cipher)
by(auto simp add : ind-cpa.lossless-def )
We change the adversary’s oracle to record the queries made by the adver-sary
def hash-oracle ′ ≡ λσ x . do h ← hash x ;Done (h, insert x σ)
have [simp]: lossless-gpv I-top (hash-oracle ′ σ x ) for σ x by(simp add : hash-oracle ′-def )have [simp]: lossless-gpv I-top (inline hash-oracle ′ (A1 α) s) for α s
by(rule lossless-inline[where I=I-top]) simp-alldef game0 ≡ TRY do
x ← lift-spmf (sample-uniform (order G));b ← lift-spmf coin-spmf ;(((msg1 , msg2 ), σ), s) ← inline hash-oracle ′ (A1 (g (ˆ) x )) ;assert-gpv (valid-plain msg1 ∧ valid-plain msg2 );cipher ← aencrypt (g (ˆ) x ) (if b then msg1 else msg2 );(guess, s ′) ← inline hash-oracle ′ (A2 cipher σ) s;Done (guess = b)
289
ELSE lift-spmf coin-spmf def cr ≡ λ- :: unit . λ- :: ′a set . True
have [transfer-rule]: cr () by(simp add : cr-def )have [transfer-rule]: (op = ===> cr ===> cr) (λ- σ. σ) insert by(simp add :
rel-fun-def cr-def )have [transfer-rule]: (cr ===> op = ===> rel-gpv (rel-prod op = cr) op =)
id-oracle hash-oracle ′
unfolding hash-oracle ′-def id-oracle-def [abs-def ] bind-gpv-Pause bind-rpv-Doneby transfer-prover
have ind-cpa.ind-cpa A = game0 unfolding game0-def Aby(transfer fixing : G len-plain A1 A2 )(simp add : bind-map-gpv o-def ind-cpa-pk .ind-cpa.simps
split-def key-gen-def lift-spmf-bind-spmf bind-gpv-assoc) note game0 = thishave game0-alt-def : game0 = do
x ← lift-spmf (sample-uniform (order G));b ← lift-spmf coin-spmf ;(((msg1 , msg2 ), σ), s) ← inline hash-oracle ′ (A1 (g (ˆ) x )) ;TRY do
- :: unit ← assert-gpv (valid-plain msg1 ∧ valid-plain msg2 );cipher ← aencrypt (g (ˆ) x ) (if b then msg1 else msg2 );(guess, s ′) ← inline hash-oracle ′ (A2 cipher σ) s;Done (guess = b) ELSE lift-spmf coin-spmfby(simp add : split-def game0-def try-gpv-bind-lossless[symmetric])
def hash-oracle ′′ ≡ λ(s, σ) (x :: ′a). do (h, σ ′) ← case σ x of
None ⇒ bind-spmf (spmf-of-set (nlists UNIV len-plain)) (λbs. return-spmf(bs, σ(x 7→ bs)))
| Some (bs :: bitstring) ⇒ return-spmf (bs, σ);return-spmf (h, insert x s, σ ′)
have ∗: exec-gpv hash.oracle (inline hash-oracle ′ A s) σ =map-spmf (λ(a, b, c). ((a, b), c)) (exec-gpv hash-oracle ′′ A (s, σ)) for A σ s
by(simp add : hash-oracle ′-def hash-oracle ′′-def hash.oracle-def Let-def exec-gpv-inlineexec-gpv-bind o-def split-def cong del : option.case-cong-weak)
have [simp]: lossless-spmf (hash-oracle ′′ s plain) for s plainby(simp add : hash-oracle ′′-def Let-def split : prod .split option.split)
have [simp]: lossless-spmf (exec-gpv hash-oracle ′′ (A1 α) s) for s αby(rule lossless-exec-gpv [where I=I-top]) simp-all
have [simp]: lossless-spmf (exec-gpv hash-oracle ′′ (A2 σ cipher) s) for σ ciphers
by(rule lossless-exec-gpv [where I=I-top]) simp-all
let ?sample = λf . bind-spmf (sample-uniform (order G)) (λx . bind-spmf (sample-uniform(order G)) (f x ))
def game1 ≡ λ(x :: nat) (y :: nat). do b ← coin-spmf ;
290
(((msg1 , msg2 ), σ), (s, s-h)) ← exec-gpv hash-oracle ′′ (A1 (g (ˆ) x )) (,hash.initial);
TRY do - :: unit ← assert-spmf (valid-plain msg1 ∧ valid-plain msg2 );(h, s-h ′) ← hash.oracle s-h (g (ˆ) (x ∗ y));let cipher = (g (ˆ) y , h [⊕] (if b then msg1 else msg2 ));(guess, (s ′, s-h ′′)) ← exec-gpv hash-oracle ′′ (A2 cipher σ) (s, s-h ′);return-spmf (guess = b, g (ˆ) (x ∗ y) ∈ s ′) ELSE do
b ← coin-spmf ;return-spmf (b, g (ˆ) (x ∗ y) ∈ s)
have game01 : run-gpv hash.oracle game0 hash.initial = map-spmf fst (?samplegame1 )
apply(simp add : exec-gpv-bind split-def bind-gpv-assoc aencrypt-def game0-alt-defgame1-def o-def bind-map-spmf if-distribs ∗ try-bind-assert-gpv try-bind-assert-spmflossless-inline[where I=I-top] del : bind-spmf-const)
apply(rewrite in - = bind-spmf - ◊ bind-commute-spmf )apply(rewrite in - = bind-spmf - (λ-. bind-spmf - ◊) bind-commute-spmf )apply(rewrite if-distrib-bind-spmf2 )apply(simp add : bind-rpv-def nat-pow-pow)done
def game2 ≡ λ(x :: nat) (y :: nat). do b ← coin-spmf ;(((msg1 , msg2 ), σ), (s, s-h)) ← exec-gpv hash-oracle ′′ (A1 (g (ˆ) x )) (,
hash.initial);TRY do
- :: unit ← assert-spmf (valid-plain msg1 ∧ valid-plain msg2 );h ← spmf-of-set (nlists UNIV len-plain);(∗ We do not do the lookup in s-h here, so the rest differs only if the adversary
guessed y ∗)let cipher = (g (ˆ) y , h [⊕] (if b then msg1 else msg2 ));(guess, (s ′, s-h ′)) ← exec-gpv hash-oracle ′′ (A2 cipher σ) (s, s-h);return-spmf (guess = b, g (ˆ) (x ∗ y) ∈ s ′) ELSE do
b ← coin-spmf ;return-spmf (b, g (ˆ) (x ∗ y) ∈ s)interpret inv ′′: callee-invariant hash-oracle ′′ λ(s, s-h). s = dom s-hby unfold-locales(auto simp add : hash-oracle ′′-def split : option.split-asm split-if )
have in-encrypt-oracle: callee-invariant hash-oracle ′′ (λ(s, -). x ∈ s) for xby unfold-locales(auto simp add : hash-oracle ′′-def )
fix x y :: natlet ?bad = λ(s, s-h). g (ˆ) (x ∗ y) ∈ slet ?X = λ(s, s-h) (s ′, s-h ′). s = dom s-h ∧ s ′ = s ∧ s-h = s-h ′(g (ˆ) (x ∗ y)
291
:= None)have bisim:
rel-spmf (λ(a, s1 ′) (b, s2 ′). ?bad s1 ′ = ?bad s2 ′ ∧ (¬ ?bad s2 ′ −→ a = b ∧?X s1 ′ s2 ′))
(hash-oracle ′′ s1 plain) (hash-oracle ′′ s2 plain)if ?X s1 s2 for s1 s2 plain using thatby(auto split : prod .splits intro!: rel-spmf-bind-reflI simp add : hash-oracle ′′-def
rel-spmf-return-spmf2 fun-upd-twist split : option.split dest !: fun-upd-eqD)have inv : callee-invariant hash-oracle ′′ ?bad
by(unfold-locales)(auto simp add : hash-oracle ′′-def split : option.split-asm)have rel-spmf (λ(win, bad) (win ′, bad ′). bad = bad ′ ∧ (¬ bad ′ −→ win =
win ′)) (game2 x y) (game1 x y)unfolding game1-def game2-defapply(clarsimp simp add : split-def o-def hash.oracle-def rel-spmf-bind-reflI
if-distribs intro!: rel-spmf-bind-reflI simp del : bind-spmf-const)apply(rule rel-spmf-try-spmf )subgoal for b msg1 msg2 σ s s-h
apply(rule rel-spmf-bind-reflI )apply(drule inv ′′.exec-gpv-invariant ; clarsimp)apply(cases s-h (g (ˆ) (x ∗ y)))subgoal — case None
apply(clarsimp intro!: rel-spmf-bind-reflI )apply(rule rel-spmf-bindI )
apply(rule exec-gpv-oracle-bisim-bad-top[OF - - bisim inv inv , whereR=λ(x , s1 ) (y , s2 ). ?bad s1 = ?bad s2 ∧ (¬ ?bad s2 −→ x = y)]; clarsimp simpadd : fun-upd-idem; fail)
apply clarsimpdone
subgoal by(auto intro!: rel-spmf-bindI1 rel-spmf-bindI2 lossless-exec-gpv [whereI=I-top] dest !: callee-invariant .exec-gpv-invariant [OF in-encrypt-oracle])
donesubgoal by(rule rel-spmf-reflI ) simpdone
hence rel-spmf (λ(win, bad) (win ′, bad ′). (bad ←→ bad ′) ∧ (¬ bad ′ −→ win←→ win ′)) (?sample game2 ) (?sample game1 )
by(intro rel-spmf-bind-reflI )hence |measure (measure-spmf (?sample game2 )) (x , -). x − measure (measure-spmf
(?sample game1 )) (y , -). y|≤ measure (measure-spmf (?sample game2 )) (-, bad). bad
unfolding split-def by(rule fundamental-lemma)moreover have measure (measure-spmf (?sample game2 )) (x , -). x = spmf
(map-spmf fst (?sample game2 )) Trueand measure (measure-spmf (?sample game1 )) (y , -). y = spmf (map-spmf
fst (?sample game1 )) Trueand measure (measure-spmf (?sample game2 )) (-, bad). bad = spmf (map-spmf
snd (?sample game2 )) Trueunfolding spmf-conv-measure-spmf measure-map-spmf by(rule arg-cong2 [where
f =measure]; fastforce)+ultimately have hop23 : |spmf (map-spmf fst (?sample game2 )) True − spmf
292
(map-spmf fst (?sample game1 )) True| ≤ spmf (map-spmf snd (?sample game2 ))True by simp
def game3 ≡ λf :: - ⇒ - ⇒ - ⇒ bitstring spmf ⇒ - spmf . λ(x :: nat) (y :: nat).do
b ← coin-spmf ;(((msg1 , msg2 ), σ), (s, s-h)) ← exec-gpv hash-oracle ′′ (A1 (g (ˆ) x )) (,
hash.initial);TRY do
- :: unit ← assert-spmf (valid-plain msg1 ∧ valid-plain msg2 );h ′← f b msg1 msg2 (spmf-of-set (nlists UNIV len-plain));let cipher = (g (ˆ) y , h ′);(guess, (s ′, s-h ′)) ← exec-gpv hash-oracle ′′ (A2 cipher σ) (s, s-h);return-spmf (guess = b, g (ˆ) (x ∗ y) ∈ s ′) ELSE do
b ← coin-spmf ;return-spmf (b, g (ˆ) (x ∗ y) ∈ s)let ?f = λb msg1 msg2 . map-spmf (λh. (if b then msg1 else msg2 ) [⊕] h)have game2 x y = game3 ?f x y for x yunfolding game2-def game3-def by(simp add : Let-def bind-map-spmf xor-list-commute
o-def nat-pow-pow)also have game3 ?f x y = game3 (λ- - - x . x ) x y for x y
unfolding game3-defby(auto intro!: try-spmf-cong bind-spmf-cong [OF refl ] if-cong [OF refl ] simp add :
split-def one-time-pad valid-plain-def simp del : map-spmf-of-set-inj-on bind-spmf-constsplit : split-if )
finally have game23 : game2 x y = game3 (λ- - - x . x ) x y for x y .
def hash-oracle ′′′ ≡ λ(σ :: ′a ⇒ -). hash.oracle σ def bisim ≡ λσ (s :: ′a set , σ ′ :: ′a bitstring). s = dom σ ∧ σ = σ ′
have [transfer-rule]: bisim Map-empty (, Map-empty) by(simp add : bisim-def )have [transfer-rule]: (bisim ===> op = ===> rel-spmf (rel-prod op = bisim))
hash-oracle ′′′ hash-oracle ′′
by(auto simp add : hash-oracle ′′-def split-def hash-oracle ′′′-def spmf-rel-maphash.oracle-def rel-fun-def bisim-def split : option.split intro!: rel-spmf-bind-reflI )
have ∗ [transfer-rule]: (bisim ===> op =) dom fst by(simp add : bisim-defrel-fun-def )
have ∗ [transfer-rule]: (bisim ===> op =) (λx . x ) snd by(simp add : rel-fun-defbisim-def )
have game3 (λ- - - x . x ) x y = do b ← coin-spmf ;
(((msg1 , msg2 ), σ), s) ← exec-gpv hash-oracle ′′′ (A1 (g (ˆ) x )) hash.initial ;TRY do
- :: unit ← assert-spmf (valid-plain msg1 ∧ valid-plain msg2 );h ′← spmf-of-set (nlists UNIV len-plain);let cipher = (g (ˆ) y , h ′);(guess, s ′) ← exec-gpv hash-oracle ′′′ (A2 cipher σ) s;
293
return-spmf (guess = b, g (ˆ) (x ∗ y) ∈ dom s ′) ELSE do
b ← coin-spmf ;return-spmf (b, g (ˆ) (x ∗ y) ∈ dom s) for x yunfolding game3-def Map-empty-def [symmetric] split-def fst-conv snd-conv
prod .collapseby(transfer fixing : A1 G len-plain x y A2 ) simp
moreover have map-spmf snd (. . . x y) = do zs ← elgamal-adversary A (g (ˆ) x ) (g (ˆ) y);return-spmf (g (ˆ) (x ∗ y) ∈ zs) for x yby(simp add : o-def split-def hash-oracle ′′′-def map-try-spmf map-scale-spmf
map-spmf-conv-bind-spmf [symmetric] spmf .map-comp map-const-spmf-of-set)ultimately have map-spmf snd (?sample (game3 (λ- - - x . x ))) = lcdh.lcdh
(elgamal-adversary A)by(simp add : o-def lcdh.lcdh-def Let-def nat-pow-pow)
then have game2-snd : map-spmf snd (?sample game2 ) = lcdh.lcdh (elgamal-adversaryA)
using game23 by(simp add : o-def )
have game3-fst : map-spmf fst (game3 (λ- - - x . x ) x y) = coin-spmf for x yunfolding game3-def Let-def split-def try-bind-assert-spmfapply(rewrite bind-commute-spmf )apply(rewrite if-distribs)apply(rewrite try-spmf-bind-out , simp)apply(rewrite in try-spmf ◊ bind-commute-spmf )apply(rewrite in bind-spmf - ◊ in try-spmf ◊ bind-commute-spmf )
apply(simp add : o-def if-distribs map-spmf-conv-bind-spmf [symmetric] spmf .map-compmap-eq-const-coin-spmf )
done
have ?lhs = |spmf (map-spmf fst (?sample game1 )) True − 1 / 2 |using game0 by(simp add : ind-cpa-pk .advantage-def game01 o-def )
also have . . . = |1 / 2 − spmf (map-spmf fst (?sample game1 )) True|by(simp add : abs-minus-commute)
also have 1 / 2 = spmf (map-spmf fst (?sample game2 )) Trueby(simp add : game23 o-def game3-fst spmf-of-set)
also note hop23 also note game2-sndfinally show ?thesis by(simp add : lcdh.advantage-def )
qed
end
end
294
13.11 IND-CPA from PRF
theory PRF-IND-CPA importsGPV-BisimList-Bits-SPMFPseudo-Random-FunctionIND-CPA
begin
Formalises the PRF example from Petcher, Morrisett (POST 2014).
declare [[simproc del : let-simp]]
type-synonym key = bool listtype-synonym plain = bool listtype-synonym cipher = bool list ∗ bool list
locale otp =fixes f :: key ⇒ bool list ⇒ bool listand len :: natassumes length-f :
∧xs ys. [[ length xs = len; length ys = len ]] =⇒ length (f xs
ys) = lenbegin
definition key-gen :: bool list spmfwhere key-gen = spmf-of-set (nlists UNIV len)
definition valid-plain :: plain ⇒ boolwhere valid-plain plain ←→ length plain = len
definition encrypt :: key ⇒ plain ⇒ cipher spmfwhere
encrypt key plain = do r ← spmf-of-set (nlists UNIV len);return-spmf (r , xor-list plain (f key r))
fun decrypt :: key ⇒ cipher ⇒ plain optionwhere decrypt key (r , c) = Some (xor-list (f key r) c)
lemma encrypt-decrypt-correct :[[ length key = len; length plain = len ]]=⇒ encrypt key plain >>= (λcipher . return-spmf (decrypt key cipher)) = return-spmf
(Some plain)by(simp add : encrypt-def zip-map2 o-def split-def bind-eq-return-spmf length-f in-nlists-UNIVxor-list-left-commute)
interpretation ind-cpa: ind-cpa key-gen encrypt decrypt valid-plain .interpretation prf : prf key-gen f spmf-of-set (nlists UNIV len) .
definition prf-encrypt-oracle :: unit ⇒ plain ⇒ (cipher × unit , plain, plain) gpv
295
whereprf-encrypt-oracle x plain = do
r ← lift-spmf (spmf-of-set (nlists UNIV len));Pause r (λpad . Done ((r , xor-list plain pad), ()))
lemma interaction-bounded-by-prf-encrypt-oracle [interaction-bound ]:interaction-bounded-by (prf-encrypt-oracle σ plain) 1
unfolding prf-encrypt-oracle-def by simp
lemma lossless-prf-encyrpt-oracle [simp]: lossless-gpv I-top (prf-encrypt-oracle sx )by(simp add : prf-encrypt-oracle-def )
definition prf-adversary :: (plain, cipher , ′state) ind-cpa.adversary ⇒ (plain,plain) prf .adversarywhere
prf-adversary A = do let (A1 , A2 ) = A;(((p1 , p2 ), σ), n) ← inline prf-encrypt-oracle A1 ();if valid-plain p1 ∧ valid-plain p2 then do
b ← lift-spmf coin-spmf ;let pb = (if b then p1 else p2 );r ← lift-spmf (spmf-of-set (nlists UNIV len));pad ← Pause r Done;let c = (r , xor-list pb pad);(b ′, -) ← inline prf-encrypt-oracle (A2 c σ) n;Done (b ′ = b) else lift-spmf coin-spmf
theorem prf-encrypt-advantage:assumes ind-cpa.ibounded-by A qand lossless-gpv I-top (fst A)and
∧cipher σ. lossless-gpv I-top (snd A cipher σ)
shows ind-cpa.advantage A ≤ prf .advantage (prf-adversary A) + q / 2 ˆ lenproof −
note [split del ] = split-ifand [cong del ] = if-weak-congand [simp] =
bind-spmf-const map-spmf-bind-spmf bind-map-spmfexec-gpv-bind exec-gpv-inlinerel-spmf-bind-reflI rel-spmf-reflI
obtain A1 A2 where A: A = (A1 , A2 ) by(cases A)from 〈ind-cpa.ibounded-by - -〉
obtain q1 q2where q1 : interaction-bounded-by A1 q1and q2 :
∧cipher σ. interaction-bounded-by (A2 cipher σ) q2
and q1 + q2 ≤ q
296
unfolding A by(rule ind-cpa.ibounded-byE ) blastfrom A assms have lossless1 : lossless-gpv I-top A1
and lossless2 :∧
cipher σ. lossless-gpv I-top (A2 cipher σ) by simp-allhave weight1 :
∧oracle s. (
∧s x . lossless-spmf (oracle s x ))
=⇒ weight-spmf (exec-gpv oracle A1 s) = 1by(rule lossless-weight-spmfD)(rule lossless-exec-gpv [OF lossless1 ], simp-all)
have weight2 :∧
oracle s cipher σ. (∧
s x . lossless-spmf (oracle s x ))=⇒ weight-spmf (exec-gpv oracle (A2 cipher σ) s) = 1by(rule lossless-weight-spmfD)(rule lossless-exec-gpv [OF lossless2 ], simp-all)
let ?oracle1 = λkey (s ′, s) y . map-spmf (λ((x , s ′), s). (x , (), ())) (exec-gpv(prf .prf-oracle key) (prf-encrypt-oracle () y) ())
have bisim1 :∧
key . rel-spmf (λ(x , -) (y , -). x = y)(exec-gpv (ind-cpa.encrypt-oracle key) A1 ())(exec-gpv (?oracle1 key) A1 ((), ()))
using TrueIby(rule exec-gpv-oracle-bisim)(auto simp add : encrypt-def prf-encrypt-oracle-def
ind-cpa.encrypt-oracle-def prf .prf-oracle-def o-def )have bisim2 :
∧key cipher σ. rel-spmf (λ(x , -) (y , -). x = y)
(exec-gpv (ind-cpa.encrypt-oracle key) (A2 cipher σ) ())(exec-gpv (?oracle1 key) (A2 cipher σ) ((), ()))
using TrueIby(rule exec-gpv-oracle-bisim)(auto simp add : encrypt-def prf-encrypt-oracle-def
ind-cpa.encrypt-oracle-def prf .prf-oracle-def o-def )
have ind-cpa-0 : rel-spmf op = (ind-cpa.ind-cpa A) (prf .game-0 (prf-adversaryA))
unfolding IND-CPA.ind-cpa.ind-cpa-def A key-gen-def Let-def prf-adversary-defPseudo-Random-Function.prf .game-0-def
apply(simp)apply(rewrite in bind-spmf - ◊ bind-commute-spmf )apply(rule rel-spmf-bind-reflI )apply(rule rel-spmf-bindI [OF bisim1 ])apply(clarsimp simp add : if-distribs bind-coin-spmf-eq-const ′)apply(auto intro: rel-spmf-bindI [OF bisim2 ] intro!: rel-spmf-bind-reflI simp
add : encrypt-def prf .prf-oracle-def cong del : if-cong)done
def rf-encrypt ≡ λs plain. bind-spmf (spmf-of-set (nlists UNIV len)) (λr :: boollist .
bind-spmf (prf .random-oracle s r) (λ(pad , s ′).return-spmf ((r , xor-list plain pad), s ′))
)interpret rf-finite: callee-invariant rf-encrypt λs. finite (dom s)by unfold-locales(auto simp add : set-bind-spmf rf-encrypt-def dest : prf .finite.callee-invariant)have lossless-rf-encrypt [simp]:
∧s plain. lossless-spmf (rf-encrypt s plain)
by(auto simp add : rf-encrypt-def )
def game2 ≡ do
297
(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );(cipher , s2 ) ← rf-encrypt s1 pb;(b ′, s3 ) ← exec-gpv rf-encrypt (A2 cipher σ) s2 ;return-spmf (b ′ = b) else coin-spmf
let ?oracle2 = λ(s ′, s) y . map-spmf (λ((x , s ′), s). (x , (), s)) (exec-gpv prf .random-oracle(prf-encrypt-oracle () y) s)
let ?I = λ(x , -, s) (y , s ′). x = y ∧ s = s ′
have bisim1 : rel-spmf ?I (exec-gpv ?oracle2 A1 ((), Map.empty)) (exec-gpvrf-encrypt A1 Map.empty)
by(rule exec-gpv-oracle-bisim[where X =λ(-, s) s ′. s = s ′])(auto simp add : rf-encrypt-def prf-encrypt-oracle-def intro!: rel-spmf-bind-reflI )
have bisim2 :∧
cipher σ s. rel-spmf ?I (exec-gpv ?oracle2 (A2 cipher σ) ((), s))(exec-gpv rf-encrypt (A2 cipher σ) s)
by(rule exec-gpv-oracle-bisim[where X =λ(-, s) s ′. s = s ′])(auto simp add : prf-encrypt-oracle-def rf-encrypt-def intro!: rel-spmf-bind-reflI )
have game1-2 [unfolded spmf-rel-eq ]: rel-spmf op = (prf .game-1 (prf-adversaryA)) game2
unfolding prf .game-1-def game2-def prf-adversary-defby(rewrite in if - then ◊ else - rf-encrypt-def )(auto simp add : Let-def A if-distribs intro!: rel-spmf-bindI [OF bisim2 ] rel-spmf-bind-reflI
rel-spmf-bindI [OF bisim1 ])
def game2-a ≡ do r ← spmf-of-set (nlists UNIV len);(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;let bad = r ∈ dom s1 ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );(pad , s2 ) ← prf .random-oracle s1 r ;let cipher = (r , xor-list pb pad);(b ′, s3 ) ← exec-gpv rf-encrypt (A2 cipher σ) s2 ;return-spmf (b ′ = b, bad) else coin-spmf >>= (λb. return-spmf (b, bad))def game2-b ≡ do
r ← spmf-of-set (nlists UNIV len);(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;let bad = r ∈ dom s1 ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );pad ← spmf-of-set (nlists UNIV len);
298
let cipher = (r , xor-list pb pad);(b ′, s3 ) ← exec-gpv rf-encrypt (A2 cipher σ) (s1 (r 7→ pad));return-spmf (b ′ = b, bad) else coin-spmf >>= (λb. return-spmf (b, bad))
have game2 = do r ← spmf-of-set (nlists UNIV len);(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );(pad , s2 ) ← prf .random-oracle s1 r ;let cipher = (r , xor-list pb pad);(b ′, s3 ) ← exec-gpv rf-encrypt (A2 cipher σ) s2 ;return-spmf (b ′ = b) else coin-spmfunfolding game2-def Let-def if-distribsapply(rewrite bind-commute-spmf )apply(rule bind-spmf-cong [OF refl ])apply(clarsimp simp add : if-distribs)apply(rewrite in if - then ◊ else - in - = ◊ bind-commute-spmf )apply(simp add : rf-encrypt-def split-def )done
also have . . . = map-spmf fst game2-a unfolding game2-a-defby(clarsimp simp add : map-spmf-conv-bind-spmf Let-def cond-application-beta
if-distrib split-def cong : if-cong)finally have game2-2a: game2 = . . . .
have map-spmf snd game2-a = map-spmf snd game2-b unfolding game2-a-defgame2-b-def
by(auto simp add : o-def Let-def split-def if-distribs weight2 split : option.splitintro: bind-spmf-cong [OF refl ])
moreoverhave rel-spmf op = (map-spmf fst (game2-a (snd −‘ False))) (map-spmf fst
(game2-b (snd −‘ False)))unfolding game2-a-def game2-b-def
by(clarsimp simp add : restrict-bind-spmf o-def Let-def if-distribs split-def restrict-return-spmfprf .random-oracle-def intro!: rel-spmf-bind-reflI split : option.splits)
hence spmf game2-a (True, False) = spmf game2-b (True, False)unfolding spmf-rel-eq by(subst (1 2 ) spmf-map-restrict [symmetric]) simp
ultimatelyhave game2a-2b: |spmf (map-spmf fst game2-a) True − spmf (map-spmf fst
game2-b) True| ≤ spmf (map-spmf snd game2-a) Trueby(subst (1 2 ) spmf-conv-measure-spmf )(rule identical-until-bad ; simp add :
spmf .map-id [unfolded id-def ] spmf-conv-measure-spmf )
def game2-a-bad ≡ do
299
r ← spmf-of-set (nlists UNIV len);(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;return-spmf (r ∈ dom s1 )
have game2a-bad : map-spmf snd game2-a = game2-a-badunfolding game2-a-def game2-a-bad-defby(auto intro!: bind-spmf-cong [OF refl ] simp add : o-def weight2 Let-def split-def
split : split-if )have card :
∧B :: bool list set . card (B ∩ nlists UNIV len) ≤ card (nlists UNIV
len :: bool list set)by(rule card-mono) simp-all
then have spmf game2-a-bad True =∫
+ x . card (dom (snd x ) ∩ nlists UNIVlen) / 2 ˆ len ∂measure-spmf (exec-gpv rf-encrypt A1 Map.empty)
unfolding game2-a-bad-defby(rewrite bind-commute-spmf )(simp add : ereal-spmf-bind split-def map-mem-spmf-of-set [unfolded
map-spmf-conv-bind-spmf ] card-nlists)also fix x s
assume ∗: (x , s) ∈ set-spmf (exec-gpv rf-encrypt A1 Map.empty)hence finite (dom s) by(rule rf-finite.exec-gpv-invariant) simphence 1 : card (dom s ∩ nlists UNIV len) ≤ card (dom s) by(intro card-mono)
simp-allmoreover from q1 ∗have card (dom s) ≤ q1 + card (dom (Map.empty :: (plain, plain) prf .dict))
by(rule rf-finite.interaction-bounded-by-exec-gpv-count)(auto simp add : rf-encrypt-def set-bind-spmf eSuc-enat prf .random-oracle-def
card-insert-if split : option.split-asm split-if )ultimately have card (dom s ∩ nlists UNIV len) ≤ q1 by(simp)
then have . . . ≤∫
+ x . q1 / 2 ˆ len ∂measure-spmf (exec-gpv rf-encrypt A1Map.empty)
by(intro nn-integral-mono-AE )(clarsimp simp add : field-simps)also have . . . ≤ q1 / 2 ˆ lenby(simp add : measure-spmf .emeasure-eq-measure field-simps mult-left-le weight1 )
finally have game2a-bad-bound : spmf game2-a-bad True ≤ q1 / 2 ˆ len by simp
def rf-encrypt-bad ≡ λsecret (s :: (plain, plain) prf .dict , bad) plain. bind-spmf(spmf-of-set (nlists UNIV len)) (λr .bind-spmf (prf .random-oracle s r) (λ(pad , s ′).return-spmf ((r , xor-list plain pad), (s ′, bad ∨ r = secret))))
have rf-encrypt-bad-sticky [simp]:∧
s. callee-invariant (rf-encrypt-bad s) sndby(unfold-locales)(auto simp add : rf-encrypt-bad-def set-bind-spmf )
have lossless-rf-encrypt [simp]:∧
challenge s plain. lossless-spmf (rf-encrypt-badchallenge s plain)
by(clarsimp simp add : rf-encrypt-bad-def prf .random-oracle-def split : option.split)
def game2-c ≡ do r ← spmf-of-set (nlists UNIV len);(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;
300
let pb = (if b then p0 else p1 );pad ← spmf-of-set (nlists UNIV len);let cipher = (r , xor-list pb pad);(b ′, (s2 , bad)) ← exec-gpv (rf-encrypt-bad r) (A2 cipher σ) (s1 (r 7→ pad),
False);return-spmf (b ′ = b, bad) else coin-spmf >>= (λb. return-spmf (b, False))
have bisim2c-bad :∧
cipher σ s x r . rel-spmf (λ(x , -) (y , -). x = y)(exec-gpv rf-encrypt (A2 cipher σ) (s(x 7→ r)))(exec-gpv (rf-encrypt-bad x ) (A2 cipher σ) (s(x 7→ r), False))by(rule exec-gpv-oracle-bisim[where X =λs (s ′, -). s = s ′])
(auto simp add : rf-encrypt-bad-def rf-encrypt-def intro!: rel-spmf-bind-reflI )
have game2b-c [unfolded spmf-rel-eq ]: rel-spmf op = (map-spmf fst game2-b)(map-spmf fst game2-c)
by(auto simp add : game2-b-def game2-c-def o-def split-def Let-def if-distribsintro!: rel-spmf-bind-reflI rel-spmf-bindI [OF bisim2c-bad ])
def game2-d ≡ do r ← spmf-of-set (nlists UNIV len);(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );pad ← spmf-of-set (nlists UNIV len);let cipher = (r , xor-list pb pad);(b ′, (s2 , bad)) ← exec-gpv (rf-encrypt-bad r) (A2 cipher σ) (s1 , False);return-spmf (b ′ = b, bad) else coin-spmf >>= (λb. return-spmf (b, False))
fix cipher σ and x :: plain and s rlet ?I = (λ(x , s, bad) (y , s ′, bad ′). (bad ←→ bad ′) ∧ (¬ bad ′ −→ x ←→ y))let ?X = λ(s, bad) (s ′, bad ′). bad = bad ′ ∧ (∀ z . z 6= x −→ s z = s ′ z )have
∧s1 s2 x ′. ?X s1 s2 =⇒ rel-spmf (λ(a, s1 ′) (b, s2 ′). snd s1 ′ = snd s2 ′
∧ (¬ snd s2 ′ −→ a = b ∧ ?X s1 ′ s2 ′))(rf-encrypt-bad x s1 x ′) (rf-encrypt-bad x s2 x ′)
by(case-tac x = x ′)(clarsimp simp add : rf-encrypt-bad-def prf .random-oracle-defrel-spmf-return-spmf1 rel-spmf-return-spmf2 Let-def split-def set-bind-spmf bind-UNIONintro!: rel-spmf-bind-reflI split : option.split)+
with - - have rel-spmf ?I(exec-gpv (rf-encrypt-bad x ) (A2 cipher σ) (s(x 7→ r), False))(exec-gpv (rf-encrypt-bad x ) (A2 cipher σ) (s, False))
by(rule exec-gpv-oracle-bisim-bad)(auto simp add : lossless2 ) note bisim-bad = thishave game2c-2d-bad [unfolded spmf-rel-eq ]: rel-spmf op = (map-spmf snd game2-c)
301
(map-spmf snd game2-d)by(auto simp add : game2-c-def game2-d-def o-def Let-def split-def if-distribs
intro!: rel-spmf-bind-reflI rel-spmf-bindI [OF bisim-bad ])moreoverhave rel-spmf op = (map-spmf fst (game2-c (snd −‘ False))) (map-spmf fst
(game2-d (snd −‘ False)))unfolding game2-c-def game2-d-def
by(clarsimp simp add : restrict-bind-spmf o-def Let-def if-distribs split-def restrict-return-spmfintro!: rel-spmf-bind-reflI rel-spmf-bindI [OF bisim-bad ])
hence spmf game2-c (True, False) = spmf game2-d (True, False)unfolding spmf-rel-eq by(subst (1 2 ) spmf-map-restrict [symmetric]) simp
ultimately have game2c-2d : |spmf (map-spmf fst game2-c) True − spmf (map-spmffst game2-d) True| ≤ spmf (map-spmf snd game2-c) True
apply(subst (1 2 ) spmf-conv-measure-spmf )apply(intro identical-until-bad)apply(simp-all add : spmf .map-id [unfolded id-def ] spmf-conv-measure-spmf )done
fix cipher σ and challenge :: plain and shave card (nlists UNIV len ∩ (λx . x = challenge) −‘ True) ≤ card challenge
by(rule card-mono) autothen have spmf (map-spmf (snd snd) (exec-gpv (rf-encrypt-bad challenge)
(A2 cipher σ) (s, False))) True ≤ (1 / 2 ˆ len) ∗ q2by(intro oi-True.interaction-bounded-by-exec-gpv-bad [OF q2 ])(simp-all add :
rf-encrypt-bad-def o-def split-beta map-spmf-conv-bind-spmf [symmetric] spmf-mapmeasure-spmf-of-set field-simps card-nlists)
hence (∫
+ x . ereal (indicator True x ) ∂measure-spmf (map-spmf (snd snd) (exec-gpv (rf-encrypt-bad challenge) (A2 cipher σ) (s, False)))) ≤ (1 / 2 ˆlen) ∗ q2
by(simp only : ereal-indicator nn-integral-indicator sets-measure-spmf sets-count-spacePow-UNIV UNIV-I emeasure-spmf-single ereal-less-eq)
then have spmf (map-spmf snd game2-d) True ≤∫+ (r :: plain).
∫+ (((p0 , p1 ), σ), s). (if valid-plain p0 ∧ valid-plain p1
then ∫+ b .
∫+ (pad :: plain). q2 / 2 ˆ len ∂measure-spmf (spmf-of-set
(nlists UNIV len)) ∂measure-spmf coin-spmfelse 0 )∂measure-spmf (exec-gpv rf-encrypt A1 Map.empty) ∂measure-spmf
(spmf-of-set (nlists UNIV len))unfolding game2-d-defby(simp add : ereal-spmf-bind o-def split-def Let-def if-distribs if-distrib[where
f =λx . ereal (spmf x -)] indicator-single-Some nn-integral-mono if-mono-cong del :nn-integral-const cong : if-cong)
also have . . . ≤∫
+ (r :: plain).∫
+ (((p0 , p1 ), σ), s). (if valid-plain p0 ∧valid-plain p1 then ereal (q2 / 2 ˆ len) else q2 / 2 ˆ len)
∂measure-spmf (exec-gpv rf-encrypt A1 Map.empty) ∂measure-spmf(spmf-of-set (nlists UNIV len))
unfolding split-defby(intro nn-integral-mono if-mono-cong)(auto simp add : measure-spmf .emeasure-eq-measure)
also have . . . ≤ q2 / 2 ˆ len by(simp add : split-def weight1 measure-spmf .emeasure-eq-measure)
302
finally have game2-d-bad : spmf (map-spmf snd game2-d) True ≤ q2 / 2 ˆ lenby simp
def game3 ≡ do (((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );r ← spmf-of-set (nlists UNIV len);pad ← spmf-of-set (nlists UNIV len);let cipher = (r , xor-list pb pad);(b ′, s2 ) ← exec-gpv rf-encrypt (A2 cipher σ) s1 ;return-spmf (b ′ = b) else coin-spmf
have bisim2d-3 :∧
cipher σ s r . rel-spmf (λ(x , -) (y , -). x = y)(exec-gpv (rf-encrypt-bad r) (A2 cipher σ) (s, False))(exec-gpv rf-encrypt (A2 cipher σ) s)
by(rule exec-gpv-oracle-bisim[where X =λ(s1 , -) s2 . s1 = s2 ])(auto simp add :rf-encrypt-bad-def rf-encrypt-def intro!: rel-spmf-bind-reflI )
have game2d-3 : rel-spmf op = (map-spmf fst game2-d) game3unfolding game2-d-def game3-def Let-defapply(rewrite bind-commute-spmf )apply(rewrite in rel-spmf - - ◊ bind-commute-spmf )
apply(clarsimp simp add : o-def split-def if-distribs cong : if-cong intro!: rel-spmf-bind-reflIrel-spmf-bindI [OF bisim2d-3 ])
done
have |spmf game2 True − 1 / 2 | ≤|spmf (map-spmf fst game2-a) True − spmf (map-spmf fst game2-b) True| +
|spmf (map-spmf fst game2-b) True − 1 / 2 |unfolding game2-2a by(rule abs-diff-triangle-ineq2 )
also have . . . ≤ q1 / 2 ˆ len + |spmf (map-spmf fst game2-b) True − 1 / 2 |using game2a-2b game2a-bad-bound unfolding game2a-bad by(intro add-right-mono)
simpalso have |spmf (map-spmf fst game2-b) True − 1 / 2 | ≤|spmf (map-spmf fst game2-c) True − spmf (map-spmf fst game2-d) True| +
|spmf (map-spmf fst game2-d) True − 1 / 2 |unfolding game2b-c by(rule abs-diff-triangle-ineq2 )
also (add-left-mono-trans) have . . . ≤ q2 / 2 ˆ len + |spmf (map-spmf fstgame2-d) True − 1 / 2 |
using game2c-2d game2-d-bad unfolding game2c-2d-bad by(intro add-right-mono)simp
finally (add-left-mono-trans)have game2 : |spmf game2 True − 1 / 2 | ≤ q1 / 2 ˆ len + q2 / 2 ˆ len + |spmf
game3 True − 1 / 2 |using game2d-3 by(simp add : field-simps spmf-rel-eq)
have game3 = do
303
(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );r ← spmf-of-set (nlists UNIV len);pad ← map-spmf (xor-list pb) (spmf-of-set (nlists UNIV len));let cipher = (r , xor-list pb pad);(b ′, s2 ) ← exec-gpv rf-encrypt (A2 cipher σ) s1 ;return-spmf (b ′ = b) else coin-spmfby(simp add : valid-plain-def game3-def Let-def one-time-pad del : bind-map-spmf
map-spmf-of-set-inj-on cong : bind-spmf-cong-simp if-cong split : split-if )also have . . . = do
(((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
b ← coin-spmf ;let pb = (if b then p0 else p1 );r ← spmf-of-set (nlists UNIV len);pad ← spmf-of-set (nlists UNIV len);let cipher = (r , pad);(b ′, -) ← exec-gpv rf-encrypt (A2 cipher σ) s1 ;return-spmf (b ′ = b) else coin-spmf
by(simp add : game3-def Let-def valid-plain-def in-nlists-UNIV cong : bind-spmf-cong-simpif-cong split : split-if )
also have . . . = do (((p0 , p1 ), σ), s1 ) ← exec-gpv rf-encrypt A1 Map.empty ;if valid-plain p0 ∧ valid-plain p1 then do
r ← spmf-of-set (nlists UNIV len);pad ← spmf-of-set (nlists UNIV len);let cipher = (r , pad);(b ′, -) ← exec-gpv rf-encrypt (A2 cipher σ) s1 ;map-spmf (op = b ′) coin-spmf else coin-spmfunfolding Let-defapply(rewrite in if - then ◊ else - bind-commute-spmf )apply(rewrite in if - then bind-spmf - ◊ else - bind-commute-spmf )
apply(rewrite in if - then bind-spmf - (λ-. bind-spmf - ◊) else - bind-commute-spmf )apply(simp add : map-spmf-conv-bind-spmf split-def )done
also have . . . = coin-spmfby(simp add : map-eq-const-coin-spmf Let-def split-def weight2 weight1 )
finally have game3 : game3 = coin-spmf .
have ind-cpa.advantage A ≤ prf .advantage (prf-adversary A) + |spmf (prf .game-1(prf-adversary A)) True − 1 / 2 |
304
unfolding ind-cpa.advantage-def prf .advantage-def ind-cpa-0 [unfolded spmf-rel-eq ]by(rule abs-diff-triangle-ineq2 )
also have |spmf (prf .game-1 (prf-adversary A)) True − 1 / 2 | ≤ q1 / 2 ˆ len+ q2 / 2 ˆ len
using game1-2 game2 game3 by(simp add : spmf-of-set)also have . . . = (q1 + q2 ) / 2 ˆ len by(simp add : field-simps)also have . . . ≤ q / 2 ˆ len using 〈q1 + q2 ≤ q〉 by(simp add : divide-right-mono)finally show ?thesis by(simp add : field-simps)
qed
lemma interaction-bounded-prf-adversary :assumes ind-cpa.ibounded-by A qshows prf .ibounded-by (prf-adversary A) (1 + q)
proof −fix ηfrom assms have ind-cpa.ibounded-by A q by blastthen obtain q1 q2 where q : q1 + q2 ≤ q
and [interaction-bound ]: interaction-bounded-by (fst A) q1∧x σ. interaction-bounded-by (snd A x σ) q2
unfolding ind-cpa.ibounded-by-def by(auto simp add : split-beta)have TERM (prf-adversary A) .then guess
apply(rule interaction-bounded-by-start)apply(unfold prf-adversary-def Let-def split-def )[1 ]apply(rule interaction-bound)+done
thus prf .ibounded-by (prf-adversary A) (1 + q)by(rule interaction-bounded-by-mono)(simp add : q)
qed
lemma lossless-prf-adversary : ind-cpa.lossless A =⇒ prf .lossless (prf-adversaryA)by(fastforce simp add : prf-adversary-def Let-def split-def ind-cpa.lossless-def intro:lossless-inline)
end
locale otp-η =fixes f :: security ⇒ key ⇒ bool list ⇒ bool listand len :: security ⇒ natassumes length-f :
∧η xs ys. [[ length xs = len η; length ys = len η ]] =⇒ length
(f η xs ys) = len ηand negligible-len [negligible-intros]: negligible (λη. 1 / 2 ˆ (len η))
begin
interpretation otp f η len η for η by(unfold-locales)(rule length-f )interpretation ind-cpa: ind-cpa key-gen η encrypt η decrypt η valid-plain η forη .interpretation prf : prf key-gen η f η spmf-of-set (nlists UNIV (len η)) for η .
305
lemma prf-encrypt-secure-for :assumes [negligible-intros]: negligible (λη. prf .advantage η (prf-adversary η (A
η)))and q :
∧η. ind-cpa.ibounded-by (A η) (q η) and [negligible-intros]: polynomial q
and lossless: pred-envir ind-cpa.lossless Ashows negligible (λη. ind-cpa.advantage η (A η))
proof −have negligible (λη. prf .advantage η (prf-adversary η (A η)) + q η / 2 ˆ len η)
by(intro negligible-intros)moreover
fix ηfrom 〈ind-cpa.ibounded-by - -〉 have ind-cpa.ibounded-by (A η) (q η) by blastmoreover from lossless have ind-cpa.lossless (A η) by blasthence lossless-gpv I-top (fst (A η))
∧cipher σ. lossless-gpv I-top (snd (A η)
cipher σ)by(auto simp add : ind-cpa.lossless-def )
ultimately have ind-cpa.advantage η (A η) ≤ prf .advantage η (prf-adversaryη (A η)) + q η / 2 ˆ len η
by(rule prf-encrypt-advantage) ultimately show ?thesis
by(rule negligible-mono2 )(simp add : ind-cpa.advantage-nonneg)qed
end
endtheory Examples imports
Hashed-ElgamalPRF-IND-CPAElgamalBernoulli
begin
end
306