Theory HOL.Random_Pred
section ‹The Random-Predicate Monad›
theory Random_Pred
imports Quickcheck_Random
begin
fun iter' :: "'a itself ⇒ natural ⇒ natural ⇒ Random.seed ⇒ ('a::random) Predicate.pred"
where
"iter' T nrandom sz seed = (if nrandom = 0 then bot_class.bot else
let ((x, _), seed') = Quickcheck_Random.random sz seed
in Predicate.Seq (%u. Predicate.Insert x (iter' T (nrandom - 1) sz seed')))"
definition iter :: "natural ⇒ natural ⇒ Random.seed ⇒ ('a::random) Predicate.pred"
where
"iter nrandom sz seed = iter' (TYPE('a)) nrandom sz seed"
lemma [code]:
"iter nrandom sz seed = (if nrandom = 0 then bot_class.bot else
let ((x, _), seed') = Quickcheck_Random.random sz seed
in Predicate.Seq (%u. Predicate.Insert x (iter (nrandom - 1) sz seed')))"
unfolding iter_def iter'.simps [of _ nrandom] ..
type_synonym 'a random_pred = "Random.seed ⇒ ('a Predicate.pred × Random.seed)"
definition empty :: "'a random_pred"
where "empty = Pair bot"
definition single :: "'a => 'a random_pred"
where "single x = Pair (Predicate.single x)"
definition bind :: "'a random_pred ⇒ ('a ⇒ 'b random_pred) ⇒ 'b random_pred"
where
"bind R f = (λs. let
(P, s') = R s;
(s1, s2) = Random.split_seed s'
in (Predicate.bind P (%a. fst (f a s1)), s2))"
definition union :: "'a random_pred ⇒ 'a random_pred ⇒ 'a random_pred"
where
"union R1 R2 = (λs. let
(P1, s') = R1 s; (P2, s'') = R2 s'
in (sup_class.sup P1 P2, s''))"
definition if_randompred :: "bool ⇒ unit random_pred"
where
"if_randompred b = (if b then single () else empty)"
definition iterate_upto :: "(natural ⇒ 'a) => natural ⇒ natural ⇒ 'a random_pred"
where
"iterate_upto f n m = Pair (Predicate.iterate_upto f n m)"
definition not_randompred :: "unit random_pred ⇒ unit random_pred"
where
"not_randompred P = (λs. let
(P', s') = P s
in if Predicate.eval P' () then (Orderings.bot, s') else (Predicate.single (), s'))"
definition Random :: "(Random.seed ⇒ ('a × (unit ⇒ term)) × Random.seed) ⇒ 'a random_pred"
where "Random g = scomp g (Pair ∘ (Predicate.single ∘ fst))"
definition map :: "('a ⇒ 'b) ⇒ 'a random_pred ⇒ 'b random_pred"
where "map f P = bind P (single ∘ f)"
hide_const (open) iter' iter empty single bind union if_randompred
iterate_upto not_randompred Random map
hide_fact iter'.simps
hide_fact (open) iter_def empty_def single_def bind_def union_def
if_randompred_def iterate_upto_def not_randompred_def Random_def map_def
end