l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem toFinset_insert [DecidableEq α] {a : α} {s : Set α} [Fintype (insert a s : Set α)]
    [Fintype s] : (insert a s).toFinset = insert a s.toFinset := by
  ext
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ t : Set α
inst✝² : DecidableEq α
a : α
s : Set α
inst✝¹ : Fintype ↑(insert a s)
inst✝ : Fintype ↑s
a✝ : α
⊢ a✝ ∈ toFinset (insert a s) ↔ a✝ ∈ insert a (toFinset s)

Next tactic:
simp
theorem filter_mem_univ_eq_toFinset [Fintype α] (s : Set α) [Fintype s] [DecidablePred (· ∈ s)] :
    Finset.univ.filter (· ∈ s) = s.toFinset := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ t : Set α
inst✝² : Fintype α
s : Set α
inst✝¹ : Fintype ↑s
inst✝ : DecidablePred fun x => x ∈ s
⊢ filter (fun x => x ∈ s) Finset.univ = toFinset s

Next tactic:
ext
theorem filter_mem_univ_eq_toFinset [Fintype α] (s : Set α) [Fintype s] [DecidablePred (· ∈ s)] :
    Finset.univ.filter (· ∈ s) = s.toFinset := by
  ext
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ t : Set α
inst✝² : Fintype α
s : Set α
inst✝¹ : Fintype ↑s
inst✝ : DecidablePred fun x => x ∈ s
a✝ : α
⊢ a✝ ∈ filter (fun x => x ∈ s) Finset.univ ↔ a✝ ∈ toFinset s

Next tactic:
simp only [Finset.mem_univ, decide_eq_true_eq, forall_true_left, mem_filter,
    true_and, mem_toFinset]
@[simp] theorem List.toFinset_finRange (n : ℕ) : (List.finRange n).toFinset = Finset.univ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
⊢ toFinset (finRange n) = univ

Next tactic:
ext
@[simp] theorem List.toFinset_finRange (n : ℕ) : (List.finRange n).toFinset = Finset.univ := by
  ext; 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
a✝ : Fin n
⊢ a✝ ∈ toFinset (finRange n) ↔ a✝ ∈ univ

Next tactic:
simp
@[simp]
theorem Fin.image_succAbove_univ {n : ℕ} (i : Fin (n + 1)) : univ.image i.succAbove = {i}ᶜ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
i : Fin (n + 1)
⊢ image (succAbove i) univ = {i}ᶜ

Next tactic:
ext m
@[simp]
theorem Fin.image_succAbove_univ {n : ℕ} (i : Fin (n + 1)) : univ.image i.succAbove = {i}ᶜ := by
  ext m
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
i m : Fin (n + 1)
⊢ m ∈ image (succAbove i) univ ↔ m ∈ {i}ᶜ

Next tactic:
simp
@[simp]
theorem Fin.image_succ_univ (n : ℕ) : (univ : Finset (Fin n)).image Fin.succ = {0}ᶜ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
⊢ image succ univ = {0}ᶜ

Next tactic:
rw [← Fin.succAbove_zero, Fin.image_succAbove_univ]
@[simp]
theorem Fin.image_castSucc (n : ℕ) :
    (univ : Finset (Fin n)).image Fin.castSucc = {Fin.last n}ᶜ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
⊢ image castSucc univ = {last n}ᶜ

Next tactic:
rw [← Fin.succAbove_last, Fin.image_succAbove_univ]
/-- Embed `Fin n` into `Fin (n + 1)` by prepending zero to the `univ` -/
theorem Fin.univ_succ (n : ℕ) :
    (univ : Finset (Fin (n + 1))) =
      cons 0 (univ.map ⟨Fin.succ, Fin.succ_injective _⟩) (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
⊢ 0 ∉ map { toFun := succ, inj' := (_ : Injective succ) } univ

Next tactic:
simp [map_eq_image]
/-- Embed `Fin n` into `Fin (n + 1)` by prepending zero to the `univ` -/
theorem Fin.univ_succ (n : ℕ) :
    (univ : Finset (Fin (n + 1))) =
      cons 0 (univ.map ⟨Fin.succ, Fin.succ_injective _⟩) (by simp [map_eq_image]) :=
  by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
⊢ univ =
    cons 0 (map { toFun := succ, inj' := (_ : Injective succ) } univ)
      (_ : 0 ∉ map { toFun := succ, inj' := (_ : Injective succ) } univ)

Next tactic:
simp [map_eq_image]
/-- Embed `Fin n` into `Fin (n + 1)` by appending a new `Fin.last n` to the `univ` -/
theorem Fin.univ_castSuccEmb (n : ℕ) :
    (univ : Finset (Fin (n + 1))) =
      cons (Fin.last n) (univ.map Fin.castSuccEmb.toEmbedding) (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
⊢ last n ∉ map castSuccEmb.toEmbedding univ

Next tactic:
simp [map_eq_image]
/-- Embed `Fin n` into `Fin (n + 1)` by appending a new `Fin.last n` to the `univ` -/
theorem Fin.univ_castSuccEmb (n : ℕ) :
    (univ : Finset (Fin (n + 1))) =
      cons (Fin.last n) (univ.map Fin.castSuccEmb.toEmbedding) (by simp [map_eq_image]) :=
  by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
⊢ univ =
    cons (last n) (map castSuccEmb.toEmbedding univ)
      (_ :
        last n ∉ map { toFun := castSucc, inj' := (_ : ∀ (x x_1 : Fin n), castSucc x = castSucc x_1 → x = x_1) } univ)

Next tactic:
simp [map_eq_image]
/-- Embed `Fin n` into `Fin (n + 1)` by inserting
around a specified pivot `p : Fin (n + 1)` into the `univ` -/
theorem Fin.univ_succAbove (n : ℕ) (p : Fin (n + 1)) :
    (univ : Finset (Fin (n + 1))) =
      cons p (univ.map <| (Fin.succAboveEmb p).toEmbedding) (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
p : Fin (n + 1)
⊢ p ∉ map (succAboveEmb p).toEmbedding univ

Next tactic:
simp
/-- Embed `Fin n` into `Fin (n + 1)` by inserting
around a specified pivot `p : Fin (n + 1)` into the `univ` -/
theorem Fin.univ_succAbove (n : ℕ) (p : Fin (n + 1)) :
    (univ : Finset (Fin (n + 1))) =
      cons p (univ.map <| (Fin.succAboveEmb p).toEmbedding) (by simp) :=
  by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
n : ℕ
p : Fin (n + 1)
⊢ univ =
    cons p (map (succAboveEmb p).toEmbedding univ)
      (_ :
        p ∉
          map { toFun := succAbove p, inj' := (_ : ∀ (x x_1 : Fin n), succAbove p x = succAbove p x_1 → x = x_1) } univ)

Next tactic:
simp [map_eq_image]
/-- Short-circuit instance to decrease search for `Unique.fintype`,
since that relies on a subsingleton elimination for `Unique`. -/
instance Fintype.subtypeEq (y : α) : Fintype { x // x = y } :=
  Fintype.subtype {y} (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
y : α
⊢ ∀ (x : α), x ∈ {y} ↔ x = y

Next tactic:
simp
/-- Short-circuit instance to decrease search for `Unique.fintype`,
since that relies on a subsingleton elimination for `Unique`. -/
instance Fintype.subtypeEq' (y : α) : Fintype { x // y = x } :=
  Fintype.subtype {y} (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
y : α
⊢ ∀ (x : α), x ∈ {y} ↔ y = x

Next tactic:
simp [eq_comm]
instance Bool.fintype : Fintype Bool :=
  ⟨⟨{true, false}, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ Multiset.Nodup {true, false}

Next tactic:
simp
instance Bool.fintype : Fintype Bool :=
  ⟨⟨{true, false}, by simp⟩, fun x => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
x : Bool
⊢ x ∈ { val := {true, false}, nodup := (_ : Multiset.Nodup (true ::ₘ {false})) }

Next tactic:
cases x
instance Bool.fintype : Fintype Bool :=
  ⟨⟨{true, false}, by simp⟩, fun x => by cases x <;> 

Proof state:
case false
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ false ∈ { val := {true, false}, nodup := (_ : Multiset.Nodup (true ::ₘ {false})) }

Next tactic:
simp
instance Bool.fintype : Fintype Bool :=
  ⟨⟨{true, false}, by simp⟩, fun x => by cases x <;> 

Proof state:
case true
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ true ∈ { val := {true, false}, nodup := (_ : Multiset.Nodup (true ::ₘ {false})) }

Next tactic:
simp
/-- Given that `α × β` is a fintype, `α` is also a fintype. -/
def Fintype.prodLeft {α β} [DecidableEq α] [Fintype (α × β)] [Nonempty β] : Fintype α :=
  ⟨(@univ (α × β) _).image Prod.fst, fun a => by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
α : Type ?u.117296
β : Type ?u.117295
inst✝² : DecidableEq α
inst✝¹ : Fintype (α × β)
inst✝ : Nonempty β
a : α
⊢ a ∈ image Prod.fst univ

Next tactic:
simp
/-- Given that `α × β` is a fintype, `β` is also a fintype. -/
def Fintype.prodRight {α β} [DecidableEq β] [Fintype (α × β)] [Nonempty α] : Fintype β :=
  ⟨(@univ (α × β) _).image Prod.snd, fun b => by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
α : Type ?u.119429
β : Type ?u.119428
inst✝² : DecidableEq β
inst✝¹ : Fintype (α × β)
inst✝ : Nonempty α
b : β
⊢ b ∈ image Prod.snd univ

Next tactic:
simp
theorem Fintype.coe_image_univ [Fintype α] [DecidableEq β] {f : α → β} :
    ↑(Finset.image f Finset.univ) = Set.range f := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
inst✝ : DecidableEq β
f : α → β
⊢ ↑(image f univ) = Set.range f

Next tactic:
ext x
theorem Fintype.coe_image_univ [Fintype α] [DecidableEq β] {f : α → β} :
    ↑(Finset.image f Finset.univ) = Set.range f := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
inst✝ : DecidableEq β
f : α → β
x : β
⊢ x ∈ ↑(image f univ) ↔ x ∈ Set.range f

Next tactic:
simp
instance PLift.fintypeProp (p : Prop) [Decidable p] : Fintype (PLift p) :=
  ⟨if h : p then {⟨h⟩} else ∅, fun ⟨h⟩ => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : Prop
inst✝ : Decidable p
x✝ : PLift p
h : p
⊢ { down := h } ∈ if h : p then {{ down := h }} else ∅

Next tactic:
simp [h]
instance Prop.fintype : Fintype Prop :=
  ⟨⟨{True, False}, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ Multiset.Nodup {True, False}

Next tactic:
simp [true_ne_false]
instance Prop.fintype : Fintype Prop :=
  ⟨⟨{True, False}, by simp [true_ne_false]⟩, Classical.cases (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ True ∈ { val := {True, False}, nodup := (_ : Multiset.Nodup (True ::ₘ {False})) }

Next tactic:
simp
instance Prop.fintype : Fintype Prop :=
  ⟨⟨{True, False}, by simp [true_ne_false]⟩, Classical.cases (by simp) (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ False ∈ { val := {True, False}, nodup := (_ : Multiset.Nodup (True ::ₘ {False})) }

Next tactic:
simp
@[simp]
theorem Fintype.univ_Prop : (Finset.univ : Finset Prop) = {True, False} :=
  Finset.eq_of_veq <| by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ univ.val = {True, False}.val

Next tactic:
simp
@[simp]
theorem Fintype.univ_Prop : (Finset.univ : Finset Prop) = {True, False} :=
  Finset.eq_of_veq <| by simp; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ univ.val = True ::ₘ {False}

Next tactic:
rfl
instance Subtype.fintype (p : α → Prop) [DecidablePred p] [Fintype α] : Fintype { x // p x } :=
  Fintype.subtype (univ.filter p) (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : α → Prop
inst✝¹ : DecidablePred p
inst✝ : Fintype α
⊢ ∀ (x : α), x ∈ filter p univ ↔ p x

Next tactic:
simp
/-- Given `Fintype α`, `finsetEquivSet` is the equiv between `Finset α` and `Set α`. (All
sets on a finite type are finite.) -/
noncomputable def finsetEquivSet : Finset α ≃ Set α where
  toFun := (↑)
  invFun := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Fintype α
⊢ Set α → Finset α

Next tactic:
classical exact fun s => s.toFinset
/-- Given `Fintype α`, `finsetEquivSet` is the equiv between `Finset α` and `Set α`. (All
sets on a finite type are finite.) -/
noncomputable def finsetEquivSet : Finset α ≃ Set α where
  toFun := (↑)
  invFun := by classical 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Fintype α
⊢ Set α → Finset α

Next tactic:
exact fun s => s.toFinset
/-- Given `Fintype α`, `finsetEquivSet` is the equiv between `Finset α` and `Set α`. (All
sets on a finite type are finite.) -/
noncomputable def finsetEquivSet : Finset α ≃ Set α where
  toFun := (↑)
  invFun := by classical exact fun s => s.toFinset
  left_inv s := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Fintype α
s : Finset α
⊢ Set.toFinset ↑s = s

Next tactic:
convert Finset.toFinset_coe s
/-- Given `Fintype α`, `finsetEquivSet` is the equiv between `Finset α` and `Set α`. (All
sets on a finite type are finite.) -/
noncomputable def finsetEquivSet : Finset α ≃ Set α where
  toFun := (↑)
  invFun := by classical exact fun s => s.toFinset
  left_inv s := by convert Finset.toFinset_coe s
  right_inv s := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Fintype α
s : Set α
⊢ ↑(Set.toFinset s) = s

Next tactic:
classical exact s.coe_toFinset
/-- Given `Fintype α`, `finsetEquivSet` is the equiv between `Finset α` and `Set α`. (All
sets on a finite type are finite.) -/
noncomputable def finsetEquivSet : Finset α ≃ Set α where
  toFun := (↑)
  invFun := by classical exact fun s => s.toFinset
  left_inv s := by convert Finset.toFinset_coe s
  right_inv s := by classical 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : Fintype α
s : Set α
⊢ ↑(Set.toFinset s) = s

Next tactic:
exact s.coe_toFinset
@[simp] lemma finsetEquivSet_symm_apply (s : Set α) [Fintype s] :
    finsetEquivSet.symm s = s.toFinset := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
s : Set α
inst✝ : Fintype ↑s
⊢ finsetEquivSet.symm s = Set.toFinset s

Next tactic:
simp [finsetEquivSet]
@[simp] lemma finsetEquivSet_symm_apply (s : Set α) [Fintype s] :
    finsetEquivSet.symm s = s.toFinset := by
  simp [finsetEquivSet]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
s : Set α
inst✝ : Fintype ↑s
⊢ Set.toFinset s = Set.toFinset s

Next tactic:
congr
@[simp] lemma finsetEquivSet_symm_apply (s : Set α) [Fintype s] :
    finsetEquivSet.symm s = s.toFinset := by
  simp [finsetEquivSet]; congr; 

Proof state:
case h.e_3.h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
s : Set α
inst✝ : Fintype ↑s
⊢ (Subtype.fintype fun x => x ∈ s) = inst✝

Next tactic:
exact Subsingleton.elim _ _
instance PSigma.fintypePropProp {α : Prop} {β : α → Prop} [Decidable α] [∀ a, Decidable (β a)] :
    Fintype (Σ'a, β a) :=
  if h : ∃ a, β a then ⟨{⟨h.fst, h.snd⟩}, fun ⟨_, _⟩ => by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
α : Prop
β : α → Prop
inst✝¹ : Decidable α
inst✝ : (a : α) → Decidable (β a)
h : ∃ (a : α), β a
x✝ : (a : α) ×' β a
fst✝ : α
snd✝ : β fst✝
⊢ { fst := fst✝, snd := snd✝ } ∈ {{ fst := (_ : α), snd := (_ : β (_ : α)) }}

Next tactic:
simp
instance pfunFintype (p : Prop) [Decidable p] (α : p → Type*) [∀ hp, Fintype (α hp)] :
    Fintype (∀ hp : p, α hp) :=
  if hp : p then Fintype.ofEquiv (α hp) ⟨fun a _ => a, fun f => f hp, fun _ => rfl, fun _ => rfl⟩
  else ⟨singleton fun h => (hp h).elim, fun h => mem_singleton.2
    (funext $ fun x => by 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
p : Prop
inst✝¹ : Decidable p
α : p → Type u_4
inst✝ : (hp : p) → Fintype (α hp)
hp : ¬p
h : (hp : p) → α hp
x : p
⊢ h x = (_ : False).elim

Next tactic:
contradiction
theorem mem_image_univ_iff_mem_range {α β : Type*} [Fintype α] [DecidableEq β] {f : α → β}
    {b : β} : b ∈ univ.image f ↔ b ∈ Set.range f := by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
α : Type u_4
β : Type u_5
inst✝¹ : Fintype α
inst✝ : DecidableEq β
f : α → β
b : β
⊢ b ∈ image f univ ↔ b ∈ Set.range f

Next tactic:
simp
/-- Given a fintype `α` and a predicate `p`, associate to a proof that there is a unique element of
`α` satisfying `p` this unique element, as an element of the corresponding subtype. -/
def chooseX (hp : ∃! a : α, p a) : { a // p a } :=
  ⟨Finset.choose p univ (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
p : α → Prop
inst✝ : DecidablePred p
hp : ∃! a, p a
⊢ ∃! a, a ∈ univ ∧ p a

Next tactic:
simp
/-- Given a fintype `α` and a predicate `p`, associate to a proof that there is a unique element of
`α` satisfying `p` this unique element, as an element of the corresponding subtype. -/
def chooseX (hp : ∃! a : α, p a) : { a // p a } :=
  ⟨Finset.choose p univ (by simp; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
p : α → Prop
inst✝ : DecidablePred p
hp : ∃! a, p a
⊢ ∃! a, p a

Next tactic:
exact hp
theorem choose_subtype_eq {α : Type*} (p : α → Prop) [Fintype { a : α // p a }] [DecidableEq α]
    (x : { a : α // p a })
    (h : ∃! a : { a // p a }, (a : α) = x :=
      ⟨x, rfl, fun y hy => by 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : Fintype α✝
p✝ : α✝ → Prop
inst✝² : DecidablePred p✝
α : Type u_4
p : α → Prop
inst✝¹ : Fintype { a // p a }
inst✝ : DecidableEq α
x y : { a // p a }
hy : (fun a => ↑a = ↑x) y
⊢ y = x

Next tactic:
simpa [Subtype.ext_iff] using hy
theorem choose_subtype_eq {α : Type*} (p : α → Prop) [Fintype { a : α // p a }] [DecidableEq α]
    (x : { a : α // p a })
    (h : ∃! a : { a // p a }, (a : α) = x :=
      ⟨x, rfl, fun y hy => by simpa [Subtype.ext_iff] using hy⟩) :
    Fintype.choose (fun y : { a : α // p a } => (y : α) = x) h = x := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
inst✝³ : Fintype α✝
p✝ : α✝ → Prop
inst✝² : DecidablePred p✝
α : Type u_4
p : α → Prop
inst✝¹ : Fintype { a // p a }
inst✝ : DecidableEq α
x : { a // p a }
h : optParam (∃! a, ↑a = ↑x) (_ : ∃ x_1, (fun a => ↑a = ↑x) x_1 ∧ ∀ (y : { a // p a }), (fun a => ↑a = ↑x) y → y = x_1)
⊢ choose (fun y => ↑y = ↑x) h = x

Next tactic:
rw [Subtype.ext_iff, Fintype.choose_spec (fun y : { a : α // p a } => (y : α) = x) _]
/-- `bijInv f` is the unique inverse to a bijection `f`. This acts
  as a computable alternative to `Function.invFun`. -/
def bijInv (f_bij : Bijective f) (b : β) : α :=
  Fintype.choose (fun a => f a = b)
    (by
      

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
inst✝ : DecidableEq β
f : α → β
f_bij : Bijective f
b : β
⊢ ∃! a, (fun a => f a = b) a

Next tactic:
rcases f_bij.right b with ⟨a', fa_eq_b⟩
/-- `bijInv f` is the unique inverse to a bijection `f`. This acts
  as a computable alternative to `Function.invFun`. -/
def bijInv (f_bij : Bijective f) (b : β) : α :=
  Fintype.choose (fun a => f a = b)
    (by
      rcases f_bij.right b with ⟨a', fa_eq_b⟩
      

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
inst✝ : DecidableEq β
f : α → β
f_bij : Bijective f
b : β
a' : α
fa_eq_b : f a' = b
⊢ ∃! a, (fun a => f a = b) a

Next tactic:
rw [← fa_eq_b]
/-- `bijInv f` is the unique inverse to a bijection `f`. This acts
  as a computable alternative to `Function.invFun`. -/
def bijInv (f_bij : Bijective f) (b : β) : α :=
  Fintype.choose (fun a => f a = b)
    (by
      rcases f_bij.right b with ⟨a', fa_eq_b⟩
      rw [← fa_eq_b]
      

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
inst✝ : DecidableEq β
f : α → β
f_bij : Bijective f
b : β
a' : α
fa_eq_b : f a' = b
⊢ ∃! a, (fun a => f a = f a') a

Next tactic:
exact ⟨a', ⟨rfl, fun a h => f_bij.left h⟩⟩
/-- For `s : Multiset α`, we can lift the existential statement that `∃ x, x ∈ s` to a `Trunc α`.
-/
def truncOfMultisetExistsMem {α} (s : Multiset α) : (∃ x, x ∈ s) → Trunc α :=
  Quotient.recOnSubsingleton s fun l h =>
    match l, h with
    | [], _ => False.elim (by 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type ?u.150609
s : Multiset α
l : List α
h : ∃ x, x ∈ ⟦l⟧
x✝ : ∃ x, x ∈ ⟦[]⟧
⊢ False

Next tactic:
tauto
/-- A `Nonempty` `Fintype` constructively contains an element.
-/
def truncOfNonemptyFintype (α) [Nonempty α] [Fintype α] : Trunc α :=
  truncOfMultisetExistsMem Finset.univ.val (by 

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type ?u.151650
inst✝¹ : Nonempty α
inst✝ : Fintype α
⊢ ∃ x, x ∈ univ.val

Next tactic:
simp
@[simp]
theorem map_univ_val_equiv (e : α ≃ β) :
    map e univ.val = univ.val := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : Fintype α
inst✝ : Fintype β
e : α ≃ β
⊢ map (⇑e) univ.val = univ.val

Next tactic:
rw [← congr_arg Finset.val (Finset.map_univ_equiv e), Finset.map_val, Equiv.coe_toEmbedding]
/-- Auxiliary definition to show `exists_seq_of_forall_finset_exists`. -/
noncomputable def seqOfForallFinsetExistsAux {α : Type*} [DecidableEq α] (P : α → Prop)
    (r : α → α → Prop) (h : ∀ s : Finset α, ∃ y, (∀ x ∈ s, P x) → P y ∧ ∀ x ∈ s, r x y) : ℕ → α
  | n =>
    Classical.choose
      (h
        (Finset.image (fun i : Fin n => seqOfForallFinsetExistsAux P r h i)
          (Finset.univ : Finset (Fin n))))
  decreasing_by 

Proof state:
a✝ : ℕ
n : ℕ := a✝
i : Fin n
⊢ (invImage (fun a => sizeOf a) instWellFoundedRelation).1 (↑i) a✝

Next tactic:
exact i.2
/-- Auxiliary definition to show `exists_seq_of_forall_finset_exists`. -/
noncomputable def seqOfForallFinsetExistsAux {α : Type*} [DecidableEq α] (P : α → Prop)
    (r : α → α → Prop) (h : ∀ s : Finset α, ∃ y, (∀ x ∈ s, P x) → P y ∧ ∀ x ∈ s, r x y) : ℕ → α
  | n =>
    Classical.choose
      (h
        (Finset.image (fun i : Fin n => seqOfForallFinsetExistsAux P r h i)
          (Finset.univ : Finset (Fin n))))
  decreasing_by 

Proof state:
α : Type u_4
inst✝ : DecidableEq α
P : α → Prop
r : α → α → Prop
h : ∀ (s : Finset α), ∃ y, (∀ x ∈ s, P x) → P y ∧ ∀ x ∈ s, r x y
a✝² : ℕ
a✝¹ : (y : ℕ) → (invImage (fun a => sizeOf a) instWellFoundedRelation).1 y a✝² → α
n : ℕ := a✝²
a✝ : ∀ x ∈ image (fun i => a✝¹ ↑i (_ : ↑i < n)) univ, P x
i : Fin n
⊢ (invImage (fun a => sizeOf a) instWellFoundedRelation).1 (↑i) a✝²

Next tactic:
exact i.2
/-- Induction principle to build a sequence, by adding one point at a time satisfying a given
relation with respect to all the previously chosen points.

More precisely, Assume that, for any finite set `s`, one can find another point satisfying
some relation `r` with respect to all the points in `s`. Then one may construct a
function `f : ℕ → α` such that `r (f m) (f n)` holds whenever `m < n`.
We also ensure that all constructed points satisfy a given predicate `P`. -/
theorem exists_seq_of_forall_finset_exists {α : Type*} (P : α → Prop) (r : α → α → Prop)
    (h : ∀ s : Finset α, (∀ x ∈ s, P x) → ∃ y, P y ∧ ∀ x ∈ s, r x y) :
    ∃ f : ℕ → α, (∀ n, P (f n)) ∧ ∀ m n, m < n → r (f m) (f n) := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
P : α → Prop
r : α → α → Prop
h : ∀ (s : Finset α), (∀ x ∈ s, P x) → ∃ y, P y ∧ ∀ x ∈ s, r x y
⊢ ∃ f, (∀ (n : ℕ), P (f n)) ∧ ∀ (m n : ℕ), m < n → r (f m) (f n)

Next tactic:
classical
    have : Nonempty α := by
      rcases h ∅ (by simp) with ⟨y, _⟩
      exact ⟨y⟩
    choose! F hF using h
    have h' : ∀ s : Finset α, ∃ y, (∀ x ∈ s, P x) → P y ∧ ∀ x ∈ s, r x y := fun s => ⟨F s, hF s⟩
    set f := seqOfForallFinsetExistsAux P r h' with hf
    have A : ∀ n : ℕ, P (f n) := by
      intro n
      induction' n using Nat.strong_induction_on with n IH
      have IH' : ∀ x : Fin n, P (f x) := fun n => IH n.1 n.2
      rw [hf, seqOfForallFinsetExistsAux]
      exact
        (Classical.choose_spec
            (h' (Finset.image (fun i : Fin n => f i) (Finset.univ : Finset (Fin n))))
            (by simp [IH'])).1
    refine' ⟨f, A, fun m n hmn => _⟩
    conv_rhs => rw [hf]
    rw [seqOfForallFinsetExistsAux]
    apply
      (Classical.choose_spec
          (h' (Finset.image (fun i : Fin n => f i) (Finset.univ : Finset (Fin n)))) (by simp [A])).2
    exact Finset.mem_image.2 ⟨⟨m, hmn⟩, Finset.mem_univ _, rfl⟩
/-- Induction principle to build a sequence, by adding one point at a time satisfying a given
relation with respect to all the previously chosen points.

More precisely, Assume that, for any finite set `s`, one can find another point satisfying
some relation `r` with respect to all the points in `s`. Then one may construct a
function `f : ℕ → α` such that `r (f m) (f n)` holds whenever `m < n`.
We also ensure that all constructed points satisfy a given predicate `P`. -/
theorem exists_seq_of_forall_finset_exists {α : Type*} (P : α → Prop) (r : α → α → Prop)
    (h : ∀ s : Finset α, (∀ x ∈ s, P x) → ∃ y, P y ∧ ∀ x ∈ s, r x y) :
    ∃ f : ℕ → α, (∀ n, P (f n)) ∧ ∀ m n, m < n → r (f m) (f n) := by
  classical
    

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
α : Type u_4
P : α → Prop
r : α → α → Prop
h : ∀ (s : Finset α), (∀ x ∈ s, P x) → ∃ y, P y ∧ ∀ x ∈ s, r x y
⊢ ∃ f, (∀ (n : ℕ), P (f n)) ∧ ∀ (m n : ℕ), m < n → r (f m) (f n)

Next tactic:
have : Nonempty α := by
      rcases h ∅ (by simp) with ⟨y, _⟩
      exact ⟨y⟩