import Mathlib /-! # Random sampling for an element We implement sampling to find an element with a given property, for instance being prime or being coprime to a given number. For this we need a hypothesis that such an element exists. We use the `IO` monad to generate random numbers. This is because a random number is not a function, in the sense of having value determined by arguments. -/ /-! The basic way we sample is to choose an element at random from the list, and then check if it satisfies the property. If it does, we return it. If not, we remove it from the list and try again. To show termination we see (following a lab) that the length of the list decreases by at least one each time. -/ universe u /-- Removing an element from a list does not increase length -/ theoremremove_length_le {remove_length_le: ∀ {α : Type u} [inst : DecidableEq α] (a : α) (l : List α), List.length (List.remove a l) ≤ List.length lα :α: Type uType u} [DecidableEqType u: Type (u+1)α](α: Type ua :a: αα) (α: Type ul : Listl: List αα) : (α: Type uList.removeList.remove: {α : Type ?u.19} → [inst : DecidableEq α] → α → List α → List αaa: αl).length ≤l: List αl.length :=l: List αGoals accomplished! 🐙List.length (List.remove a l) ≤ List.length lList.length (List.remove a l) ≤ List.length l
nilList.length (List.remove a []) ≤ List.length []Goals accomplished! 🐙List.length (List.remove a l) ≤ List.length l
consList.length (List.remove a (h' :: t)) ≤ List.length (h' :: t)
consList.length (if a = h' then List.remove a t else h' :: List.remove a t) ≤ Nat.succ (List.length t)
consList.length (List.remove a (h' :: t)) ≤ List.length (h' :: t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: a = h'
cons.inlList.length (List.remove a t) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) ≤ Nat.succ (List.length t)
consList.length (List.remove a (h' :: t)) ≤ List.length (h' :: t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: a = h'
cons.inlList.length (List.remove a t) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: a = h'
cons.inl.hList.length (List.remove a t) ≤ List.length tα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: a = h'
cons.inlList.length (List.remove a t) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) ≤ Nat.succ (List.length t)Goals accomplished! 🐙
consList.length (List.remove a (h' :: t)) ≤ List.length (h' :: t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrNat.succ (List.length (List.remove a t)) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrNat.succ (List.length (List.remove a t)) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) ≤ Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inr.aList.length (List.remove a t) ≤ List.length tα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: List.length (List.remove a t) ≤ List.length t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) ≤ Nat.succ (List.length t)/-- Removing a member from a list shortens the list -/ theoremGoals accomplished! 🐙remove_mem_length {remove_mem_length: ∀ {α : Type u} [inst : DecidableEq α] {a : α} {l : List α}, a ∈ l → List.length (List.remove a l) < List.length lα :α: Type uType u} [DecidableEqType u: Type (u+1)α]{α: Type ua :a: αα } {α: Type ul : Listl: List αα} (α: Type uhyp :hyp: a ∈ la ∈a: αl) : (l: List αList.removeList.remove: {α : Type ?u.2403} → [inst : DecidableEq α] → α → List α → List αaa: αl).length <l: List αl.length :=l: List αGoals accomplished! 🐙List.length (List.remove a l) < List.length lList.length (List.remove a l) < List.length l
nilList.length (List.remove a []) < List.length []Goals accomplished! 🐙List.length (List.remove a l) < List.length lα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
consList.length (List.remove a (h' :: t)) < List.length (h' :: t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
consList.length (if a = h' then List.remove a t else h' :: List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
consList.length (List.remove a (h' :: t)) < List.length (h' :: t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: a = h'
cons.inlList.length (List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
consList.length (List.remove a (h' :: t)) < List.length (h' :: t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: a = h'
cons.inlList.length (List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: a = h'
cons.inl.aList.length (List.remove a t) ≤ List.length tα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: a = h'
cons.inlList.length (List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)Goals accomplished! 🐙α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
consList.length (List.remove a (h' :: t)) < List.length (h' :: t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrNat.succ (List.length (List.remove a t)) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrNat.succ (List.length (List.remove a t)) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inr.aList.length (List.remove a t) < List.length tα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inr.aList.length (List.remove a t) < List.length tGoals accomplished! 🐙α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'a ∈ tα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'a ∈ tGoals accomplished! 🐙α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'Goals accomplished! 🐙α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'a ∈ tα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
h✝, this: ¬a = h'
hyp: a ∈ ta ∈ tα: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'a ∈ tGoals accomplished! 🐙α: Type u
inst✝: DecidableEq α
a, h': α
t: List α
ih: a ∈ t → List.length (List.remove a t) < List.length t
hyp: a ∈ h' :: t
h✝: ¬a = h'
cons.inrList.length (h' :: List.remove a t) < Nat.succ (List.length t)/-! We pick an index of the list `l`, which is of type `Fin l.length`. Rather than proving that the random number generator has this property we pass `mod n`. -/ /-- A random number in `Fin n` -/ def IO.randFin (Goals accomplished! 🐙n :n: ℕℕ)(ℕ: Typeh :h: 0 < n0 <0: ?m.6449n ) : IO <| Finn: ℕn := do letn: ℕr ← IO.randr: ?m.65920 (0: ?m.6530n -n: ℕ1) pure ⟨1: ?m.6536r %r: ?m.6592n, Nat.mod_ltn: ℕrr: ?m.6592h⟩h: 0 < nList.mem_remove_iff -- ∀ {α : Type u_1} [inst : DecidableEq α] {a b : α} {as : List α}, b ∈ List.remove a as ↔ b ∈ as ∧ b ≠ aList.mem_remove_iff: ∀ {α : Type u_1} [inst : DecidableEq α] {a b : α} {as : List α}, b ∈ List.remove a as ↔ b ∈ as ∧ b ≠ aList.length_pos_of_mem -- ∀ {α : Type u_1} {a : α} {l : List α}, a ∈ l → 0 < List.length l List.get_mem -- ∀ {α : Type u_1} (l : List α) (n : ℕ) (h : n < List.length l), List.get l { val := n, isLt := h } ∈ l /-- A random element with a given property from a list, within `IO` -/ defList.length_pos_of_mem: ∀ {α : Type u_1} {a : α} {l : List α}, a ∈ l → 0 < List.length lpickElemIO [DecidableEqα](α: ?m.6946l: Listl: List αα)(α: ?m.6946p:p: α → Boolα →α: ?m.6946Bool)(h : ∃Bool: Typet :t: αα,α: ?m.6946t ∈t: αl ∧l: List αpp: α → Boolt =t: αtrue) : IO {true: Boolt :t: αα //α: ?m.6946t ∈t: αl ∧l: List αpp: α → Boolt =t: αtrue} := do havetrue: Boolh' :h': 0 < List.length l0 <0: ?m.7049l.length :=l: List αGoals accomplished! 🐙0 < List.length l0 < List.length lletGoals accomplished! 🐙index ← IO.randFinindex: ?m.7114l.lengthl: List αh' leth': 0 < List.length la :=a: ?m.7117l.l: List αgetget: {α : Type ?u.7118} → (as : List α) → Fin (List.length as) → αindex ifindex: ?m.7114c:c: ?m.7208pp: α → Boola =a: ?m.7117true then return ⟨true: Boola,a: ?m.7117Goals accomplished! 🐙⟩ else letGoals accomplished! 🐙l' :=l': ?m.7211l.l: List αremoveremove: {α : Type ?u.7212} → [inst : DecidableEq α] → α → List α → List αa have h' : ∃a: ?m.7117t :t: αα,α: Typet ∈t: αl' ∧l': ?m.7211pp: α → Boolt =t: αtrue :=true: BoolGoals accomplished! 🐙have :Goals accomplished! 🐙l'.length <l': ?m.7211l.length :=l: List αGoals accomplished! 🐙α: Type
inst✝: DecidableEq α
l: List α
p: α → Bool
h: ∃ t, t ∈ l ∧ p t = true
h'✝: 0 < List.length l
index: Fin (List.length l)
a:= List.get l index: α
c: ¬p a = true
l':= List.remove a l: List α
h': ∃ t, t ∈ l' ∧ p t = trueList.length l' < List.length lα: Type
inst✝: DecidableEq α
l: List α
p: α → Bool
h: ∃ t, t ∈ l ∧ p t = true
h'✝: 0 < List.length l
index: Fin (List.length l)
a:= List.get l index: α
c: ¬p a = true
l':= List.remove a l: List α
h': ∃ t, t ∈ l' ∧ p t = trueList.length l' < List.length llet ⟨Goals accomplished! 🐙t,t: αh₁, h₂⟩ ←h₁: t ∈ l'pickElemIOl'l': ?m.7211p h' havep: α → Boolm :m: t ∈ lt ∈t: αl :=l: List αList.mem_of_mem_removeList.mem_of_mem_remove: ∀ {α : Type ?u.7518} [inst : DecidableEq α] {a b : α} {as : List α}, b ∈ List.remove a as → b ∈ ash₁ return ⟨h₁: t ∈ l't,t: αm, h₂⟩ termination_by _ _ _ l _ _ =>m: t ∈ ll.length /-- A random element with a given property from a list. As IO may in principle give an error, we specify a default to fallback and the conditions that this is in the list and has the property `p` -/ defl: List αpickElemD [DecidableEqα](α: ?m.34031l: Listl: List αα)(α: ?m.34031p:p: α → Boolα →α: ?m.34031Bool)(Bool: Typedefault :default: αα)(α: ?m.34031h₁ :h₁: default ∈ ldefault ∈default: αl)(h₂ :l: List αpp: α → Booldefault =default: αtrue) : {true: Boolt :t: αα //α: ?m.34031t ∈t: αl ∧l: List αpp: α → Boolt =t: αtrue} := (pickElemIOtrue: Boolll: List αp ⟨p: α → Booldefault,default: αh₁, h₂⟩).run'h₁: default ∈ l() |>.getD ⟨(): Unitdefault,default: αh₁, h₂⟩ /-! ## Random Monad We used the IO Monad which has a lot of stuff besides randomness. -/h₁: default ∈ l