Documentation

VCVio.OracleComp.Constructions.SampleableType

Uniform Selection Over a Type #

This file defines a typeclass SampleableType β for types β with a canonical uniform selection operation, using the ProbComp monad.

As compared to HasUniformSelect this provides much more structure on the behavior, enforcing that every possible output has the same output probability never fails.

class SampleableType (β : Type) :

A SampleableType β instance means that β is a finite inhabited type, with a computation selectElem that selects uniformly at random from the type. This generally requires choosing some "canonical" ordering for the type, so we include this to get a computable version of selection. We also require that each element has the same probability of being chosen from by selectElem, see SampleableType.probOutput_uniformSample for the reduction when α has a fintype instance involving the explicit cardinality of the type.

Instances
    def uniformSample (β : Type) [h : SampleableType β] :

    Select uniformly from the type β using a type-class provided definition. NOTE: naming is somewhat strange now that Fintype isn't explicitly required.

    Equations
    Instances For
      @[simp]
      theorem probOutput_uniformSample (α : Type) [ : SampleableType α] [Fintype α] (x : α) :
      theorem probOutput_map_bijective_uniformSample (α : Type) [ : SampleableType α] [Fintype α] {f : αα} (hf : Function.Bijective f) (x : α) :
      Pr[=x | f <$> ($ᵗα)] = Pr[=x | $ᵗα]
      theorem probOutput_map_bijective_uniform_cross (α : Type) [ : SampleableType α] {β : Type} [SampleableType β] [Fintype α] [Fintype β] (f : αβ) (hf : Function.Bijective f) (y : β) :
      Pr[=y | f <$> ($ᵗα)] = Pr[=y | $ᵗβ]

      Pushing forward uniform sampling along a bijection preserves output probabilities.

      theorem probOutput_bind_bijective_uniform_cross (α : Type) [ : SampleableType α] {β γ : Type} [SampleableType β] [Fintype α] (f : αβ) (hf : Function.Bijective f) (g : βProbComp γ) (z : γ) :
      Pr[=z | do let x$ᵗα g (f x)] = Pr[=z | do let y$ᵗβ g y]

      Binding after pushing forward uniform sampling along a bijection preserves output probabilities.

      theorem probOutput_add_left_uniform (α : Type) [ : SampleableType α] [AddGroup α] (m x : α) :
      Pr[=x | (fun (x : α) => m + x) <$> ($ᵗα)] = Pr[=x | $ᵗα]
      theorem probOutput_bind_add_left_uniform (α : Type) [ : SampleableType α] [AddGroup α] {β : Type} (m : α) (f : αProbComp β) (z : β) :
      Pr[=z | do let y$ᵗα f (m + y)] = Pr[=z | do let y$ᵗα f y]
      @[simp]
      theorem evalDist_add_left_uniform (α : Type) [ : SampleableType α] [AddGroup α] (m : α) :
      evalDist ((fun (x : α) => m + x) <$> ($ᵗα)) = evalDist ($ᵗα)

      Translating a uniform additive sample preserves the full evaluation distribution.

      theorem evalDist_add_left_uniform_eq (α : Type) [ : SampleableType α] [AddGroup α] (m₁ m₂ : α) :
      evalDist ((fun (x : α) => m₁ + x) <$> ($ᵗα)) = evalDist ((fun (x : α) => m₂ + x) <$> ($ᵗα))

      Two additive translations of a uniform sample have the same evaluation distribution.

      theorem evalDist_map_bijective_uniform_cross (α : Type) [ : SampleableType α] {β : Type} [SampleableType β] [Fintype α] [Fintype β] (f : αβ) (hf : Function.Bijective f) :

      Pushing forward uniform sampling along a bijection preserves the full evaluation distribution.

      @[simp]
      theorem mem_support_uniformSample (α : Type) [ : SampleableType α] {x : α} :
      @[simp]
      theorem probEvent_uniformSample (α : Type) [ : SampleableType α] [Fintype α] (p : αProp) [DecidablePred p] :
      Equations

      Select a uniform element from α × β by independently selecting from α and β.

      Equations

      Nonempty Fin types can be selected from, using implicit casting of Fin (n - 1 + 1).

      Equations

      Version of Fin selection using the NeZero typeclass, avoiding the need for n + 1.

      Equations

      Version of ZMod selection using the NeZero typeclass, matching Fin n.

      Equations

      Choose a random bit-vector by converting a random number between 0 and 2 ^ n.

      Equations

      Select a uniform element from Vector α n by independently selecting α at each index.

      Equations
      • One or more equations did not get rendered due to their size.

      A type equivalent to a SampleableType is also SampleableType.

      Equations
      Instances For

        Unsigned machine words inherit uniform sampling from the corresponding fixed-width bitvectors.

        Equations
        • One or more equations did not get rendered due to their size.
        Equations
        • One or more equations did not get rendered due to their size.
        Equations
        • One or more equations did not get rendered due to their size.
        Equations
        • One or more equations did not get rendered due to their size.
        instance instSampleableTypeFinFunc {n : } {α : Type} [SampleableType α] [DecidableEq α] :
        SampleableType (Fin nα)

        A function from Fin n to a SampleableType is also SampleableType.

        Equations

        Select a uniform element from Matrix α n by selecting each row independently.

        Equations
        theorem probOutput_uniformBool_not_decide_eq_decide {ob : ProbComp Bool} :
        Pr[=true | do let b$ᵗBool let b'ob pure !decide (b = b')] = Pr[=true | do let b$ᵗBool let b'ob pure (decide (b = b'))]

        Given an independent probabilistic computation ob : ProbComp Bool, the probability that its output b' differs from a uniformly chosen boolean b is the same as the probability that they are equal. In other words, P(b ≠ b') = P(b = b') where b is uniform.

        theorem probOutput_bind_uniformBool {α : Type} (f : BoolProbComp α) (x : α) :
        Pr[=x | do let b$ᵗBool f b] = (Pr[=x | f true] + Pr[=x | f false]) / 2

        Conditioning on a uniform boolean averages the two branch probabilities.

        theorem probOutput_uniformBool_branch_toReal_sub_half (real rand : ProbComp Bool) :
        Pr[=true | do let b$ᵗBool have __do_jp : BoolProbComp Bool := fun (z : Bool) => pure (b == z) if b = true then do let yreal __do_jp y else do let yrand __do_jp y].toReal - 1 / 2 = (Pr[=true | real].toReal - Pr[=true | rand].toReal) / 2

        Guessing a uniformly random bit after branching between real and rand decomposes into the difference of the branch success probabilities.

        theorem probOutput_decide_eq_uniformBool_half (f : BoolProbComp Bool) (heq : evalDist (f true) = evalDist (f false)) :
        Pr[=true | do let b$ᵗBool let b'f b pure (decide (b = b'))] = 1 / 2

        If the distribution of f b is independent of b, then guessing a uniformly random bit by running f has success probability exactly 1/2. This is the core lemma behind "all-random hybrid has probability 1/2" arguments.