gen
Monad #
THIS FILE IS SYNCHRONIZED WITH MATHLIB4. Any changes to this file require a corresponding PR to mathlib4.
This monad is used to formulate randomized computations with a parameter to specify the desired size of the result.
This is a port of the Haskell QuickCheck library.
Main definitions #
gen
monad
Local notation #
i .. j
:Icc i j
, the set of values betweeni
andj
inclusively;
Tags #
random testing
References #
Execute a gen
inside the io
monad using i
as the example
size and with a fresh random number generator.
Equations
- slim_check.io.run_gen x i = io.run_rand (x.run {down := i})
Lift random.random
to the gen
monad.
Equations
- slim_check.gen.choose_any α = ⟨λ (_x : ulift ℕ), rand.random α⟩
Lift random.random_r
to the gen
monad.
Equations
- slim_check.gen.choose x y p = ⟨λ (_x : ulift ℕ), rand.random_r x y p⟩
Generate a nat
example between x
and y
.
Equations
- slim_check.gen.choose_nat x y p = slim_check.gen.choose x y p
Equations
- slim_check.gen.has_orelse = {orelse := λ (α : Type u) (x y : slim_check.gen α), uliftable.up (slim_check.gen.choose_any bool) >>= λ (b : ulift bool), ite ↥(b.down) x y}
Get access to the size parameter of the gen
monad. For
reasons of universe polymorphism, it is specified in
continuation passing style.
Apply a function to the size parameter.
Create n
examples using cmd
.
Equations
- slim_check.gen.vector_of n.succ cmd = vector.cons <$> cmd <*> slim_check.gen.vector_of n cmd
- slim_check.gen.vector_of 0 _x = return vector.nil
Create a list of examples using cmd
. The size is controlled
by the size parameter of gen
.
Equations
- cmd.list_of = slim_check.gen.sized (λ (sz : ℕ), uliftable.up (slim_check.gen.choose_nat 0 (sz + 1) _) >>= λ (_p : ulift ↥(set.Icc 0 (sz + 1))), slim_check.gen.list_of._match_1 cmd sz _p)
- slim_check.gen.list_of._match_1 cmd sz {down := n} = slim_check.gen.vector_of n.val cmd >>= λ (v : vector α n.val), return v.to_list
Given a list of example generators, choose one to create an example.
Equations
- slim_check.gen.one_of xs pos = uliftable.up (slim_check.gen.choose_nat' 0 xs.length pos) >>= λ (_p : ulift ↥(set.Ico 0 xs.length)), slim_check.gen.one_of._match_1 xs _p
- slim_check.gen.one_of._match_1 xs {down := ⟨n, _⟩} = xs.nth_le n h'
Given a list of example generators, choose one to create an example.
Equations
- slim_check.gen.elements xs pos = uliftable.up (slim_check.gen.choose_nat' 0 xs.length pos) >>= λ (_p : ulift ↥(set.Ico 0 xs.length)), slim_check.gen.elements._match_1 xs _p
- slim_check.gen.elements._match_1 xs {down := ⟨n, _⟩} = has_pure.pure (xs.nth_le n h₁)
freq_aux xs i _
takes a weighted list of generator and a number meant to select one of the
generators.
If we consider freq_aux [(1, gena), (3, genb), (5, genc)] 4 _
, we choose a generator by splitting
the interval 1-9 into 1-1, 2-4, 5-9 so that the width of each interval corresponds to one of the
number in the list of generators. Then, we check which interval 4 falls into: it selects genb
.
freq [(1, gena), (3, genb), (5, genc)] _
will choose one of gena
, genb
, genc
with
probabilities proportional to the number accompanying them. In this example, the sum of
those numbers is 9, gena
will be chosen with probability ~1/9, genb
with ~3/9 (i.e. 1/3)
and genc
with probability 5/9.
Equations
- slim_check.gen.freq xs pos = let s : ℕ := (list.map (subtype.val ∘ prod.fst) xs).sum in have ha : 1 ≤ s, from _, have this : 0 ≤ s - 1, from _, uliftable.adapt_up slim_check.gen slim_check.gen (slim_check.gen.choose_nat 0 (s - 1) this) (λ (i : ↥(set.Icc 0 (s - 1))), slim_check.gen.freq_aux xs i.val _)
Generate a random permutation of a given list.
Equations
- slim_check.gen.permutation_of (x :: xs) = slim_check.gen.permutation_of xs >>= λ (_p : subtype xs.perm), slim_check.gen.permutation_of._match_2 x xs _p
- slim_check.gen.permutation_of list.nil = has_pure.pure ⟨list.nil α, _⟩
- slim_check.gen.permutation_of._match_2 x xs ⟨xs', h⟩ = uliftable.up (slim_check.gen.choose_nat 0 xs'.length _) >>= λ (_p : ulift ↥(set.Icc 0 xs'.length)), slim_check.gen.permutation_of._match_1 x xs xs' h _p
- slim_check.gen.permutation_of._match_1 x xs xs' h {down := ⟨n, _⟩} = has_pure.pure ⟨list.insert_nth n x xs', _⟩