l3lab/ntp-mathlib huggingface dataset:
/-- To check convex independence, one only has to check finsets thanks to Carathéodory's theorem. -/
theorem convexIndependent_iff_finset {p : ι → E} :
    ConvexIndependent 𝕜 p ↔
      ∀ (s : Finset ι) (x : ι), p x ∈ convexHull 𝕜 (s.image p : Set E) → x ∈ s := by
  refine' ⟨fun hc s x hx => hc s x _, fun h s x hx => _⟩
  · rwa [Finset.coe_image] at hx
  have hp : Injective p := by
    rintro a b hab
    rw [← mem_singleton]
    refine' h {b} a _
    rw [hab, image_singleton, coe_singleton, convexHull_singleton]
    exact Set.mem_singleton _
  rw [convexHull_eq_union_convexHull_finite_subsets] at hx
  simp_rw [Set.mem_iUnion] at hx
  obtain ⟨t, ht, hx⟩ := hx
  rw [← hp.mem_set_image]
  refine' ht _
  suffices x ∈ t.preimage p (hp.injOn _) by rwa [mem_preimage, ← mem_coe] at this
  refine' h _ x _
  

Proof state:
case refine'_2.intro.intro
𝕜 : Type u_1
E : Type u_2
ι : Type u_3
inst✝² : LinearOrderedField 𝕜
inst✝¹ : AddCommGroup E
inst✝ : Module 𝕜 E
s✝ : Set E
p : ι → E
h : ∀ (s : Finset ι) (x : ι), p x ∈ (convexHull 𝕜) ↑(image p s) → x ∈ s
s : Set ι
x : ι
hp : Injective p
t : Finset E
ht : ↑t ⊆ p '' s
hx : p x ∈ (convexHull 𝕜) ↑t
⊢ p x ∈ (convexHull 𝕜) ↑(image p (preimage t p (_ : Set.InjOn p (p ⁻¹' ↑t))))

Next tactic:
rwa [t.image_preimage p (hp.injOn _), filter_true_of_mem]
/-- To check convex independence, one only has to check finsets thanks to Carathéodory's theorem. -/
theorem convexIndependent_iff_finset {p : ι → E} :
    ConvexIndependent 𝕜 p ↔
      ∀ (s : Finset ι) (x : ι), p x ∈ convexHull 𝕜 (s.image p : Set E) → x ∈ s := by
  refine' ⟨fun hc s x hx => hc s x _, fun h s x hx => _⟩
  · rwa [Finset.coe_image] at hx
  have hp : Injective p := by
    rintro a b hab
    rw [← mem_singleton]
    refine' h {b} a _
    rw [hab, image_singleton, coe_singleton, convexHull_singleton]
    exact Set.mem_singleton _
  rw [convexHull_eq_union_convexHull_finite_subsets] at hx
  simp_rw [Set.mem_iUnion] at hx
  obtain ⟨t, ht, hx⟩ := hx
  rw [← hp.mem_set_image]
  refine' ht _
  suffices x ∈ t.preimage p (hp.injOn _) by rwa [mem_preimage, ← mem_coe] at this
  refine' h _ x _
  rwa [t.image_preimage p (hp.injOn _), filter_true_of_mem]
  · 

Proof state:
case refine'_2.intro.intro
𝕜 : Type u_1
E : Type u_2
ι : Type u_3
inst✝² : LinearOrderedField 𝕜
inst✝¹ : AddCommGroup E
inst✝ : Module 𝕜 E
s✝ : Set E
p : ι → E
h : ∀ (s : Finset ι) (x : ι), p x ∈ (convexHull 𝕜) ↑(image p s) → x ∈ s
s : Set ι
x : ι
hp : Injective p
t : Finset E
ht : ↑t ⊆ p '' s
hx : p x ∈ (convexHull 𝕜) ↑t
⊢ ∀ x ∈ t, x ∈ Set.range p

Next tactic:
exact fun y hy => s.image_subset_range p (ht <| mem_coe.2 hy)
/-- Given an element of the iterated product `l.Prod α`, take a projection into direction `i`.
  If `i` appears multiple times in `l`, this chooses the first component in direction `i`. -/
protected def elim : ∀ {l : List ι} (_ : TProd α l) {i : ι} (_ : i ∈ l), α i
  | i :: is, v, j, hj =>
    if hji : j = i then by
      

Proof state:
ι : Type u
α : ι → Type v
i✝ j✝ : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
v : TProd α (i :: is)
j : ι
hj : j ∈ i :: is
hji : j = i
⊢ α j

Next tactic:
subst hji
/-- Given an element of the iterated product `l.Prod α`, take a projection into direction `i`.
  If `i` appears multiple times in `l`, this chooses the first component in direction `i`. -/
protected def elim : ∀ {l : List ι} (_ : TProd α l) {i : ι} (_ : i ∈ l), α i
  | i :: is, v, j, hj =>
    if hji : j = i then by
      subst hji
      

Proof state:
ι : Type u
α : ι → Type v
i j✝ : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
is : List ι
j : ι
v : TProd α (j :: is)
hj : j ∈ j :: is
⊢ α j

Next tactic:
exact v.1
@[simp]
theorem elim_self (v : TProd α (i :: l)) : v.elim (l.mem_cons_self i) = v.1 := by 

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
v : TProd α (i :: l)
⊢ TProd.elim v (_ : i ∈ i :: l) = v.1

Next tactic:
simp [TProd.elim]
@[simp]
theorem elim_of_ne (hj : j ∈ i :: l) (hji : j ≠ i) (v : TProd α (i :: l)) :
    v.elim hj = TProd.elim v.2 ((List.mem_cons.mp hj).resolve_left hji) := by 

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
hj : j ∈ i :: l
hji : j ≠ i
v : TProd α (i :: l)
⊢ TProd.elim v hj = TProd.elim v.2 (_ : j ∈ l)

Next tactic:
simp [TProd.elim, hji]
@[simp]
theorem elim_of_mem (hl : (i :: l).Nodup) (hj : j ∈ l) (v : TProd α (i :: l)) :
    v.elim (mem_cons_of_mem _ hj) = TProd.elim v.2 hj := by
  

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
hl : Nodup (i :: l)
hj : j ∈ l
v : TProd α (i :: l)
⊢ TProd.elim v (_ : j ∈ i :: l) = TProd.elim v.2 hj

Next tactic:
apply elim_of_ne
@[simp]
theorem elim_of_mem (hl : (i :: l).Nodup) (hj : j ∈ l) (v : TProd α (i :: l)) :
    v.elim (mem_cons_of_mem _ hj) = TProd.elim v.2 hj := by
  apply elim_of_ne
  

Proof state:
case hji
ι : Type u
α : ι → Type v
i j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
hl : Nodup (i :: l)
hj : j ∈ l
v : TProd α (i :: l)
⊢ j ≠ i

Next tactic:
rintro rfl
@[simp]
theorem elim_of_mem (hl : (i :: l).Nodup) (hj : j ∈ l) (v : TProd α (i :: l)) :
    v.elim (mem_cons_of_mem _ hj) = TProd.elim v.2 hj := by
  apply elim_of_ne
  rintro rfl
  

Proof state:
case hji
ι : Type u
α : ι → Type v
j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
hj : j ∈ l
hl : Nodup (j :: l)
v : TProd α (j :: l)
⊢ False

Next tactic:
exact hl.not_mem hj
theorem elim_mk : ∀ (l : List ι) (f : ∀ i, α i) {i : ι} (hi : i ∈ l), (TProd.mk l f).elim hi = f i
  | i :: is, f, j, hj => by
    

Proof state:
ι : Type u
α : ι → Type v
i✝ j✝ : ι
l : List ι
f✝ : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
f : (i : ι) → α i
j : ι
hj : j ∈ i :: is
⊢ TProd.elim (TProd.mk (i :: is) f) hj = f j

Next tactic:
by_cases hji : j = i
theorem elim_mk : ∀ (l : List ι) (f : ∀ i, α i) {i : ι} (hi : i ∈ l), (TProd.mk l f).elim hi = f i
  | i :: is, f, j, hj => by
    by_cases hji : j = i
    · 

Proof state:
case pos
ι : Type u
α : ι → Type v
i✝ j✝ : ι
l : List ι
f✝ : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
f : (i : ι) → α i
j : ι
hj : j ∈ i :: is
hji : j = i
⊢ TProd.elim (TProd.mk (i :: is) f) hj = f j

Next tactic:
subst hji
theorem elim_mk : ∀ (l : List ι) (f : ∀ i, α i) {i : ι} (hi : i ∈ l), (TProd.mk l f).elim hi = f i
  | i :: is, f, j, hj => by
    by_cases hji : j = i
    · subst hji
      

Proof state:
case pos
ι : Type u
α : ι → Type v
i j✝ : ι
l : List ι
f✝ : (i : ι) → α i
inst✝ : DecidableEq ι
is : List ι
f : (i : ι) → α i
j : ι
hj : j ∈ j :: is
⊢ TProd.elim (TProd.mk (j :: is) f) hj = f j

Next tactic:
simp
theorem elim_mk : ∀ (l : List ι) (f : ∀ i, α i) {i : ι} (hi : i ∈ l), (TProd.mk l f).elim hi = f i
  | i :: is, f, j, hj => by
    by_cases hji : j = i
    · subst hji
      simp
    · 

Proof state:
case neg
ι : Type u
α : ι → Type v
i✝ j✝ : ι
l : List ι
f✝ : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
f : (i : ι) → α i
j : ι
hj : j ∈ i :: is
hji : ¬j = i
⊢ TProd.elim (TProd.mk (i :: is) f) hj = f j

Next tactic:
rw [TProd.elim_of_ne _ hji, snd_mk, elim_mk is]
@[ext]
theorem ext :
    ∀ {l : List ι} (_ : l.Nodup) {v w : TProd α l}
      (_ : ∀ (i) (hi : i ∈ l), v.elim hi = w.elim hi), v = w
  | [], _, v, w, _ => PUnit.ext v w
  | i :: is, hl, v, w, hvw => by
    

Proof state:
ι : Type u
α : ι → Type v
i✝ j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
hl : Nodup (i :: is)
v w : TProd α (i :: is)
hvw : ∀ (i_1 : ι) (hi : i_1 ∈ i :: is), TProd.elim v hi = TProd.elim w hi
⊢ v = w

Next tactic:
apply Prod.ext
@[ext]
theorem ext :
    ∀ {l : List ι} (_ : l.Nodup) {v w : TProd α l}
      (_ : ∀ (i) (hi : i ∈ l), v.elim hi = w.elim hi), v = w
  | [], _, v, w, _ => PUnit.ext v w
  | i :: is, hl, v, w, hvw => by
    apply Prod.ext; 

Proof state:
case a
ι : Type u
α : ι → Type v
i✝ j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
hl : Nodup (i :: is)
v w : TProd α (i :: is)
hvw : ∀ (i_1 : ι) (hi : i_1 ∈ i :: is), TProd.elim v hi = TProd.elim w hi
⊢ v.1 = w.1
case a
ι : Type u
α : ι → Type v
i✝ j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
hl : Nodup (i :: is)
v w : TProd α (i :: is)
hvw : ∀ (i_1 : ι) (hi : i_1 ∈ i :: is), TProd.elim v hi = TProd.elim w hi
⊢ v.2 = w.2

Next tactic:
rw [← elim_self v, hvw, elim_self]
@[ext]
theorem ext :
    ∀ {l : List ι} (_ : l.Nodup) {v w : TProd α l}
      (_ : ∀ (i) (hi : i ∈ l), v.elim hi = w.elim hi), v = w
  | [], _, v, w, _ => PUnit.ext v w
  | i :: is, hl, v, w, hvw => by
    apply Prod.ext; rw [← elim_self v, hvw, elim_self]
    

Proof state:
case a
ι : Type u
α : ι → Type v
i✝ j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
hl : Nodup (i :: is)
v w : TProd α (i :: is)
hvw : ∀ (i_1 : ι) (hi : i_1 ∈ i :: is), TProd.elim v hi = TProd.elim w hi
⊢ v.2 = w.2

Next tactic:
refine' ext (nodup_cons.mp hl).2 fun j hj => _
@[ext]
theorem ext :
    ∀ {l : List ι} (_ : l.Nodup) {v w : TProd α l}
      (_ : ∀ (i) (hi : i ∈ l), v.elim hi = w.elim hi), v = w
  | [], _, v, w, _ => PUnit.ext v w
  | i :: is, hl, v, w, hvw => by
    apply Prod.ext; rw [← elim_self v, hvw, elim_self]
    refine' ext (nodup_cons.mp hl).2 fun j hj => _
    

Proof state:
case a
ι : Type u
α : ι → Type v
i✝ j✝ : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
i : ι
is : List ι
hl : Nodup (i :: is)
v w : TProd α (i :: is)
hvw : ∀ (i_1 : ι) (hi : i_1 ∈ i :: is), TProd.elim v hi = TProd.elim w hi
j : ι
hj : j ∈ is
⊢ TProd.elim v.2 hj = TProd.elim w.2 hj

Next tactic:
rw [← elim_of_mem hl, hvw, elim_of_mem hl]
theorem mk_elim (hnd : l.Nodup) (h : ∀ i, i ∈ l) (v : TProd α l) : TProd.mk l (v.elim' h) = v :=
  TProd.ext hnd fun i hi => by 

Proof state:
ι : Type u
α : ι → Type v
i✝ j : ι
l : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
hnd : Nodup l
h : ∀ (i : ι), i ∈ l
v : TProd α l
i : ι
hi : i ∈ l
⊢ TProd.elim (TProd.mk l (TProd.elim' h v)) hi = TProd.elim v hi

Next tactic:
simp [elim_mk]
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by 

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l : List ι
f : (i : ι) → α i
t : (i : ι) → Set (α i)
⊢ TProd.mk [] ⁻¹' Set.tprod [] t = pi {i | i ∈ []} t

Next tactic:
simp [Set.tprod]
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    

Proof state:
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
⊢ TProd.mk (i :: l) ⁻¹' Set.tprod (i :: l) t = pi {i_1 | i_1 ∈ i :: l} t

Next tactic:
ext f
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    ext f
    

Proof state:
case h
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f✝ : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
f : (i : ι) → α i
⊢ f ∈ TProd.mk (i :: l) ⁻¹' Set.tprod (i :: l) t ↔ f ∈ pi {i_1 | i_1 ∈ i :: l} t

Next tactic:
have h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i : ι, i ∈ l → f i ∈ t i := by
      change f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ { x | x ∈ l }.pi t
      rw [mk_preimage_tprod l t]
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    ext f
    have h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i : ι, i ∈ l → f i ∈ t i := by
      

Proof state:
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f✝ : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
f : (i : ι) → α i
⊢ TProd.mk l f ∈ Set.tprod l t ↔ ∀ i ∈ l, f i ∈ t i

Next tactic:
change f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ { x | x ∈ l }.pi t
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    ext f
    have h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i : ι, i ∈ l → f i ∈ t i := by
      change f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ { x | x ∈ l }.pi t
      

Proof state:
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f✝ : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
f : (i : ι) → α i
⊢ f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ pi {x | x ∈ l} t

Next tactic:
rw [mk_preimage_tprod l t]
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    ext f
    have h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i : ι, i ∈ l → f i ∈ t i := by
      change f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ { x | x ∈ l }.pi t
      rw [mk_preimage_tprod l t]

    -- `simp [Set.TProd, TProd.mk, this]` can close this goal but is slow.
    

Proof state:
case h
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f✝ : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
f : (i : ι) → α i
h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i ∈ l, f i ∈ t i
⊢ f ∈ TProd.mk (i :: l) ⁻¹' Set.tprod (i :: l) t ↔ f ∈ pi {i_1 | i_1 ∈ i :: l} t

Next tactic:
rw [Set.tprod, TProd.mk, mem_preimage, mem_pi, prod_mk_mem_set_prod_eq]
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    ext f
    have h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i : ι, i ∈ l → f i ∈ t i := by
      change f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ { x | x ∈ l }.pi t
      rw [mk_preimage_tprod l t]

    -- `simp [Set.TProd, TProd.mk, this]` can close this goal but is slow.
    rw [Set.tprod, TProd.mk, mem_preimage, mem_pi, prod_mk_mem_set_prod_eq]
    

Proof state:
case h
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f✝ : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
f : (i : ι) → α i
h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i ∈ l, f i ∈ t i
⊢ f i ∈ t i ∧ TProd.mk l f ∈ Set.tprod l t ↔ ∀ i_1 ∈ {i_2 | i_2 ∈ i :: l}, f i_1 ∈ t i_1

Next tactic:
simp_rw [mem_setOf_eq, mem_cons]
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    ext f
    have h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i : ι, i ∈ l → f i ∈ t i := by
      change f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ { x | x ∈ l }.pi t
      rw [mk_preimage_tprod l t]

    -- `simp [Set.TProd, TProd.mk, this]` can close this goal but is slow.
    rw [Set.tprod, TProd.mk, mem_preimage, mem_pi, prod_mk_mem_set_prod_eq]
    simp_rw [mem_setOf_eq, mem_cons]
    

Proof state:
case h
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f✝ : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
f : (i : ι) → α i
h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i ∈ l, f i ∈ t i
⊢ f i ∈ t i ∧ TProd.mk l f ∈ Set.tprod l t ↔ ∀ (i_1 : ι), i_1 = i ∨ i_1 ∈ l → f i_1 ∈ t i_1

Next tactic:
rw [forall_eq_or_imp, and_congr_right_iff]
theorem mk_preimage_tprod :
    ∀ (l : List ι) (t : ∀ i, Set (α i)), TProd.mk l ⁻¹' Set.tprod l t = { i | i ∈ l }.pi t
  | [], t => by simp [Set.tprod]
  | i :: l, t => by
    ext f
    have h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i : ι, i ∈ l → f i ∈ t i := by
      change f ∈ TProd.mk l ⁻¹' Set.tprod l t ↔ f ∈ { x | x ∈ l }.pi t
      rw [mk_preimage_tprod l t]

    -- `simp [Set.TProd, TProd.mk, this]` can close this goal but is slow.
    rw [Set.tprod, TProd.mk, mem_preimage, mem_pi, prod_mk_mem_set_prod_eq]
    simp_rw [mem_setOf_eq, mem_cons]
    rw [forall_eq_or_imp, and_congr_right_iff]
    

Proof state:
case h
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f✝ : (i : ι) → α i
i : ι
l : List ι
t : (i : ι) → Set (α i)
f : (i : ι) → α i
h : TProd.mk l f ∈ Set.tprod l t ↔ ∀ i ∈ l, f i ∈ t i
⊢ f i ∈ t i → (TProd.mk l f ∈ Set.tprod l t ↔ ∀ a ∈ l, f a ∈ t a)

Next tactic:
exact fun _ => h
theorem elim_preimage_pi [DecidableEq ι] {l : List ι} (hnd : l.Nodup) (h : ∀ i, i ∈ l)
    (t : ∀ i, Set (α i)) : TProd.elim' h ⁻¹' pi univ t = Set.tprod l t := by
  

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l✝ : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
l : List ι
hnd : Nodup l
h : ∀ (i : ι), i ∈ l
t : (i : ι) → Set (α i)
⊢ TProd.elim' h ⁻¹' pi univ t = Set.tprod l t

Next tactic:
have h2 : { i | i ∈ l } = univ := by
    ext i
    simp [h]
theorem elim_preimage_pi [DecidableEq ι] {l : List ι} (hnd : l.Nodup) (h : ∀ i, i ∈ l)
    (t : ∀ i, Set (α i)) : TProd.elim' h ⁻¹' pi univ t = Set.tprod l t := by
  have h2 : { i | i ∈ l } = univ := by
    

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l✝ : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
l : List ι
hnd : Nodup l
h : ∀ (i : ι), i ∈ l
t : (i : ι) → Set (α i)
⊢ {i | i ∈ l} = univ

Next tactic:
ext i
theorem elim_preimage_pi [DecidableEq ι] {l : List ι} (hnd : l.Nodup) (h : ∀ i, i ∈ l)
    (t : ∀ i, Set (α i)) : TProd.elim' h ⁻¹' pi univ t = Set.tprod l t := by
  have h2 : { i | i ∈ l } = univ := by
    ext i
    

Proof state:
case h
ι : Type u
α : ι → Type v
i✝ j : ι
l✝ : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
l : List ι
hnd : Nodup l
h : ∀ (i : ι), i ∈ l
t : (i : ι) → Set (α i)
i : ι
⊢ i ∈ {i | i ∈ l} ↔ i ∈ univ

Next tactic:
simp [h]
theorem elim_preimage_pi [DecidableEq ι] {l : List ι} (hnd : l.Nodup) (h : ∀ i, i ∈ l)
    (t : ∀ i, Set (α i)) : TProd.elim' h ⁻¹' pi univ t = Set.tprod l t := by
  have h2 : { i | i ∈ l } = univ := by
    ext i
    simp [h]
  

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l✝ : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
l : List ι
hnd : Nodup l
h : ∀ (i : ι), i ∈ l
t : (i : ι) → Set (α i)
h2 : {i | i ∈ l} = univ
⊢ TProd.elim' h ⁻¹' pi univ t = Set.tprod l t

Next tactic:
rw [← h2, ← mk_preimage_tprod, preimage_preimage]
theorem elim_preimage_pi [DecidableEq ι] {l : List ι} (hnd : l.Nodup) (h : ∀ i, i ∈ l)
    (t : ∀ i, Set (α i)) : TProd.elim' h ⁻¹' pi univ t = Set.tprod l t := by
  have h2 : { i | i ∈ l } = univ := by
    ext i
    simp [h]
  rw [← h2, ← mk_preimage_tprod, preimage_preimage]
  

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l✝ : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
l : List ι
hnd : Nodup l
h : ∀ (i : ι), i ∈ l
t : (i : ι) → Set (α i)
h2 : {i | i ∈ l} = univ
⊢ (fun x => TProd.mk l (TProd.elim' h x)) ⁻¹' Set.tprod l t = Set.tprod l t

Next tactic:
simp only [TProd.mk_elim hnd h]
theorem elim_preimage_pi [DecidableEq ι] {l : List ι} (hnd : l.Nodup) (h : ∀ i, i ∈ l)
    (t : ∀ i, Set (α i)) : TProd.elim' h ⁻¹' pi univ t = Set.tprod l t := by
  have h2 : { i | i ∈ l } = univ := by
    ext i
    simp [h]
  rw [← h2, ← mk_preimage_tprod, preimage_preimage]
  simp only [TProd.mk_elim hnd h]
  

Proof state:
ι : Type u
α : ι → Type v
i j : ι
l✝ : List ι
f : (i : ι) → α i
inst✝ : DecidableEq ι
l : List ι
hnd : Nodup l
h : ∀ (i : ι), i ∈ l
t : (i : ι) → Set (α i)
h2 : {i | i ∈ l} = univ
⊢ (fun x => x) ⁻¹' Set.tprod l t = Set.tprod l t

Next tactic:
dsimp
theorem polynomial_eval_eval₂ [CommSemiring R] [CommSemiring S]
    (f : R →+* Polynomial S) (g : σ → Polynomial S) (p : MvPolynomial σ R) :
    Polynomial.eval x (eval₂ f g p) =
      eval₂ ((Polynomial.evalRingHom x).comp f) (fun s => Polynomial.eval x (g s)) p := by
  

Proof state:
R : Type u_1
S : Type u_2
σ : Type u_3
x : S
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
f : R →+* Polynomial S
g : σ → Polynomial S
p : MvPolynomial σ R
⊢ Polynomial.eval x (eval₂ f g p) =
    eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) p

Next tactic:
apply induction_on p
theorem polynomial_eval_eval₂ [CommSemiring R] [CommSemiring S]
    (f : R →+* Polynomial S) (g : σ → Polynomial S) (p : MvPolynomial σ R) :
    Polynomial.eval x (eval₂ f g p) =
      eval₂ ((Polynomial.evalRingHom x).comp f) (fun s => Polynomial.eval x (g s)) p := by
  apply induction_on p
  · 

Proof state:
case h_C
R : Type u_1
S : Type u_2
σ : Type u_3
x : S
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
f : R →+* Polynomial S
g : σ → Polynomial S
p : MvPolynomial σ R
⊢ ∀ (a : R),
    Polynomial.eval x (eval₂ f g (C a)) =
      eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) (C a)

Next tactic:
simp
theorem polynomial_eval_eval₂ [CommSemiring R] [CommSemiring S]
    (f : R →+* Polynomial S) (g : σ → Polynomial S) (p : MvPolynomial σ R) :
    Polynomial.eval x (eval₂ f g p) =
      eval₂ ((Polynomial.evalRingHom x).comp f) (fun s => Polynomial.eval x (g s)) p := by
  apply induction_on p
  · simp
  · 

Proof state:
case h_add
R : Type u_1
S : Type u_2
σ : Type u_3
x : S
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
f : R →+* Polynomial S
g : σ → Polynomial S
p : MvPolynomial σ R
⊢ ∀ (p q : MvPolynomial σ R),
    Polynomial.eval x (eval₂ f g p) =
        eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) p →
      Polynomial.eval x (eval₂ f g q) =
          eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) q →
        Polynomial.eval x (eval₂ f g (p + q)) =
          eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) (p + q)

Next tactic:
intro p q hp hq
theorem polynomial_eval_eval₂ [CommSemiring R] [CommSemiring S]
    (f : R →+* Polynomial S) (g : σ → Polynomial S) (p : MvPolynomial σ R) :
    Polynomial.eval x (eval₂ f g p) =
      eval₂ ((Polynomial.evalRingHom x).comp f) (fun s => Polynomial.eval x (g s)) p := by
  apply induction_on p
  · simp
  · intro p q hp hq
    

Proof state:
case h_add
R : Type u_1
S : Type u_2
σ : Type u_3
x : S
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
f : R →+* Polynomial S
g : σ → Polynomial S
p✝ p q : MvPolynomial σ R
hp :
  Polynomial.eval x (eval₂ f g p) =
    eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) p
hq :
  Polynomial.eval x (eval₂ f g q) =
    eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) q
⊢ Polynomial.eval x (eval₂ f g (p + q)) =
    eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) (p + q)

Next tactic:
simp [hp, hq]
theorem polynomial_eval_eval₂ [CommSemiring R] [CommSemiring S]
    (f : R →+* Polynomial S) (g : σ → Polynomial S) (p : MvPolynomial σ R) :
    Polynomial.eval x (eval₂ f g p) =
      eval₂ ((Polynomial.evalRingHom x).comp f) (fun s => Polynomial.eval x (g s)) p := by
  apply induction_on p
  · simp
  · intro p q hp hq
    simp [hp, hq]
  · 

Proof state:
case h_X
R : Type u_1
S : Type u_2
σ : Type u_3
x : S
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
f : R →+* Polynomial S
g : σ → Polynomial S
p : MvPolynomial σ R
⊢ ∀ (p : MvPolynomial σ R) (n : σ),
    Polynomial.eval x (eval₂ f g p) =
        eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) p →
      Polynomial.eval x (eval₂ f g (p * X n)) =
        eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) (p * X n)

Next tactic:
intro p n hp
theorem polynomial_eval_eval₂ [CommSemiring R] [CommSemiring S]
    (f : R →+* Polynomial S) (g : σ → Polynomial S) (p : MvPolynomial σ R) :
    Polynomial.eval x (eval₂ f g p) =
      eval₂ ((Polynomial.evalRingHom x).comp f) (fun s => Polynomial.eval x (g s)) p := by
  apply induction_on p
  · simp
  · intro p q hp hq
    simp [hp, hq]
  · intro p n hp
    

Proof state:
case h_X
R : Type u_1
S : Type u_2
σ : Type u_3
x : S
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
f : R →+* Polynomial S
g : σ → Polynomial S
p✝ p : MvPolynomial σ R
n : σ
hp :
  Polynomial.eval x (eval₂ f g p) =
    eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) p
⊢ Polynomial.eval x (eval₂ f g (p * X n)) =
    eval₂ (RingHom.comp (Polynomial.evalRingHom x) f) (fun s => Polynomial.eval x (g s)) (p * X n)

Next tactic:
simp [hp]
theorem eval_polynomial_eval_finSuccEquiv
    [CommSemiring R] (f : MvPolynomial (Fin (n + 1)) R) (q : MvPolynomial (Fin n) R) :
    (eval x) (Polynomial.eval q (finSuccEquiv R n f)) = eval (Fin.cases (eval x q) x) f := by
  

Proof state:
R : Type u_1
n : ℕ
x : Fin n → R
inst✝ : CommSemiring R
f : MvPolynomial (Fin (n + 1)) R
q : MvPolynomial (Fin n) R
⊢ (eval x) (Polynomial.eval q ((finSuccEquiv R n) f)) = (eval fun i => Fin.cases ((eval x) q) x i) f

Next tactic:
simp only [finSuccEquiv_apply, coe_eval₂Hom, polynomial_eval_eval₂, eval_eval₂]