l3lab/ntp-mathlib huggingface dataset:
/-- See also `Basis.toMatrix_reindex` which gives the `simp` normal form of this result. -/
theorem Basis.toMatrix_reindex' [DecidableEq ι] [DecidableEq ι'] (b : Basis ι R M) (v : ι' → M)
    (e : ι ≃ ι') : (b.reindex e).toMatrix v = Matrix.reindexAlgEquiv _ e (b.toMatrix (v ∘ e)) := by
  ext
  

Proof state:
case a.h
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝¹³ : CommSemiring R
inst✝¹² : AddCommMonoid M
inst✝¹¹ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝¹⁰ : CommRing R₂
inst✝⁹ : AddCommGroup M₂
inst✝⁸ : Module R₂ M₂
e✝ : Basis ι R M
v✝ : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝⁷ : AddCommMonoid N
inst✝⁶ : Module R N
b✝ : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
inst✝⁵ : Fintype ι'
inst✝⁴ : Fintype κ
inst✝³ : Fintype κ'
inst✝² : Fintype ι
inst✝¹ : DecidableEq ι
inst✝ : DecidableEq ι'
b : Basis ι R M
v : ι' → M
e : ι ≃ ι'
i✝ x✝ : ι'
⊢ toMatrix (reindex b e) v i✝ x✝ = (reindexAlgEquiv R e) (toMatrix b (v ∘ ⇑e)) i✝ x✝

Next tactic:
simp only [Basis.toMatrix_apply, Basis.repr_reindex, Matrix.reindexAlgEquiv_apply,
    Matrix.reindex_apply, Matrix.submatrix_apply, Function.comp_apply, e.apply_symm_apply,
    Finsupp.mapDomain_equiv_apply]
/-- A generalization of `Basis.toMatrix_self`, in the opposite direction. -/
@[simp]
theorem Basis.toMatrix_mul_toMatrix {ι'' : Type*} [Fintype ι'] (b'' : ι'' → M) :
    b.toMatrix b' * b'.toMatrix b'' = b.toMatrix b'' := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁸ : CommSemiring R
inst✝⁷ : AddCommMonoid M
inst✝⁶ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁵ : CommRing R₂
inst✝⁴ : AddCommGroup M₂
inst✝³ : Module R₂ M₂
e : Basis ι R M
v : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
b : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
ι'' : Type u_10
inst✝ : Fintype ι'
b'' : ι'' → M
⊢ toMatrix b ⇑b' * toMatrix b' b'' = toMatrix b b''

Next tactic:
haveI := Classical.decEq ι
/-- A generalization of `Basis.toMatrix_self`, in the opposite direction. -/
@[simp]
theorem Basis.toMatrix_mul_toMatrix {ι'' : Type*} [Fintype ι'] (b'' : ι'' → M) :
    b.toMatrix b' * b'.toMatrix b'' = b.toMatrix b'' := by
  haveI := Classical.decEq ι
  

Proof state:
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁸ : CommSemiring R
inst✝⁷ : AddCommMonoid M
inst✝⁶ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁵ : CommRing R₂
inst✝⁴ : AddCommGroup M₂
inst✝³ : Module R₂ M₂
e : Basis ι R M
v : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
b : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
ι'' : Type u_10
inst✝ : Fintype ι'
b'' : ι'' → M
this : DecidableEq ι
⊢ toMatrix b ⇑b' * toMatrix b' b'' = toMatrix b b''

Next tactic:
haveI := Classical.decEq ι'
/-- A generalization of `Basis.toMatrix_self`, in the opposite direction. -/
@[simp]
theorem Basis.toMatrix_mul_toMatrix {ι'' : Type*} [Fintype ι'] (b'' : ι'' → M) :
    b.toMatrix b' * b'.toMatrix b'' = b.toMatrix b'' := by
  haveI := Classical.decEq ι
  haveI := Classical.decEq ι'
  

Proof state:
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁸ : CommSemiring R
inst✝⁷ : AddCommMonoid M
inst✝⁶ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁵ : CommRing R₂
inst✝⁴ : AddCommGroup M₂
inst✝³ : Module R₂ M₂
e : Basis ι R M
v : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
b : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
ι'' : Type u_10
inst✝ : Fintype ι'
b'' : ι'' → M
this✝ : DecidableEq ι
this : DecidableEq ι'
⊢ toMatrix b ⇑b' * toMatrix b' b'' = toMatrix b b''

Next tactic:
haveI := Classical.decEq ι''
/-- A generalization of `Basis.toMatrix_self`, in the opposite direction. -/
@[simp]
theorem Basis.toMatrix_mul_toMatrix {ι'' : Type*} [Fintype ι'] (b'' : ι'' → M) :
    b.toMatrix b' * b'.toMatrix b'' = b.toMatrix b'' := by
  haveI := Classical.decEq ι
  haveI := Classical.decEq ι'
  haveI := Classical.decEq ι''
  

Proof state:
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁸ : CommSemiring R
inst✝⁷ : AddCommMonoid M
inst✝⁶ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁵ : CommRing R₂
inst✝⁴ : AddCommGroup M₂
inst✝³ : Module R₂ M₂
e : Basis ι R M
v : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
b : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
ι'' : Type u_10
inst✝ : Fintype ι'
b'' : ι'' → M
this✝¹ : DecidableEq ι
this✝ : DecidableEq ι'
this : DecidableEq ι''
⊢ toMatrix b ⇑b' * toMatrix b' b'' = toMatrix b b''

Next tactic:
ext i j
/-- A generalization of `Basis.toMatrix_self`, in the opposite direction. -/
@[simp]
theorem Basis.toMatrix_mul_toMatrix {ι'' : Type*} [Fintype ι'] (b'' : ι'' → M) :
    b.toMatrix b' * b'.toMatrix b'' = b.toMatrix b'' := by
  haveI := Classical.decEq ι
  haveI := Classical.decEq ι'
  haveI := Classical.decEq ι''
  ext i j
  

Proof state:
case a.h
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁸ : CommSemiring R
inst✝⁷ : AddCommMonoid M
inst✝⁶ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁵ : CommRing R₂
inst✝⁴ : AddCommGroup M₂
inst✝³ : Module R₂ M₂
e : Basis ι R M
v : ι' → M
i✝ : ι
j✝ : ι'
N : Type u_9
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
b : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
ι'' : Type u_10
inst✝ : Fintype ι'
b'' : ι'' → M
this✝¹ : DecidableEq ι
this✝ : DecidableEq ι'
this : DecidableEq ι''
i : ι
j : ι''
⊢ (toMatrix b ⇑b' * toMatrix b' b'') i j = toMatrix b b'' i j

Next tactic:
simp only [Matrix.mul_apply, Basis.toMatrix_apply, Basis.sum_repr_mul_repr]
/-- `b.toMatrix b'` and `b'.toMatrix b` are inverses. -/
theorem Basis.toMatrix_mul_toMatrix_flip [DecidableEq ι] [Fintype ι'] :
    b.toMatrix b' * b'.toMatrix b = 1 := by 

Proof state:
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁹ : CommSemiring R
inst✝⁸ : AddCommMonoid M
inst✝⁷ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁶ : CommRing R₂
inst✝⁵ : AddCommGroup M₂
inst✝⁴ : Module R₂ M₂
e : Basis ι R M
v : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝³ : AddCommMonoid N
inst✝² : Module R N
b : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι'
⊢ toMatrix b ⇑b' * toMatrix b' ⇑b = 1

Next tactic:
rw [Basis.toMatrix_mul_toMatrix, Basis.toMatrix_self]
@[simp]
theorem Basis.toMatrix_reindex (b : Basis ι R M) (v : ι' → M) (e : ι ≃ ι') :
    (b.reindex e).toMatrix v = (b.toMatrix v).submatrix e.symm _root_.id := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁷ : CommSemiring R
inst✝⁶ : AddCommMonoid M
inst✝⁵ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁴ : CommRing R₂
inst✝³ : AddCommGroup M₂
inst✝² : Module R₂ M₂
e✝ : Basis ι R M
v✝ : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
b✝ : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
b : Basis ι R M
v : ι' → M
e : ι ≃ ι'
⊢ toMatrix (reindex b e) v = submatrix (toMatrix b v) (⇑e.symm) _root_.id

Next tactic:
ext
@[simp]
theorem Basis.toMatrix_reindex (b : Basis ι R M) (v : ι' → M) (e : ι ≃ ι') :
    (b.reindex e).toMatrix v = (b.toMatrix v).submatrix e.symm _root_.id := by
  ext
  

Proof state:
case a.h
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁷ : CommSemiring R
inst✝⁶ : AddCommMonoid M
inst✝⁵ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁴ : CommRing R₂
inst✝³ : AddCommGroup M₂
inst✝² : Module R₂ M₂
e✝ : Basis ι R M
v✝ : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
b✝ : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f : M →ₗ[R] N
b : Basis ι R M
v : ι' → M
e : ι ≃ ι'
i✝ x✝ : ι'
⊢ toMatrix (reindex b e) v i✝ x✝ = submatrix (toMatrix b v) (⇑e.symm) _root_.id i✝ x✝

Next tactic:
simp only [Basis.toMatrix_apply, Basis.repr_reindex, Matrix.submatrix_apply, id.def,
    Finsupp.mapDomain_equiv_apply]
@[simp]
theorem Basis.toMatrix_map (b : Basis ι R M) (f : M ≃ₗ[R] N) (v : ι → N) :
    (b.map f).toMatrix v = b.toMatrix (f.symm ∘ v) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁷ : CommSemiring R
inst✝⁶ : AddCommMonoid M
inst✝⁵ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁴ : CommRing R₂
inst✝³ : AddCommGroup M₂
inst✝² : Module R₂ M₂
e : Basis ι R M
v✝ : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
b✝ : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f✝ : M →ₗ[R] N
b : Basis ι R M
f : M ≃ₗ[R] N
v : ι → N
⊢ toMatrix (Basis.map b f) v = toMatrix b (⇑(LinearEquiv.symm f) ∘ v)

Next tactic:
ext
@[simp]
theorem Basis.toMatrix_map (b : Basis ι R M) (f : M ≃ₗ[R] N) (v : ι → N) :
    (b.map f).toMatrix v = b.toMatrix (f.symm ∘ v) := by
  ext
  

Proof state:
case a.h
ι : Type u_1
ι' : Type u_2
κ : Type u_3
κ' : Type u_4
R : Type u_5
M : Type u_6
inst✝⁷ : CommSemiring R
inst✝⁶ : AddCommMonoid M
inst✝⁵ : Module R M
R₂ : Type u_7
M₂ : Type u_8
inst✝⁴ : CommRing R₂
inst✝³ : AddCommGroup M₂
inst✝² : Module R₂ M₂
e : Basis ι R M
v✝ : ι' → M
i : ι
j : ι'
N : Type u_9
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
b✝ : Basis ι R M
b' : Basis ι' R M
c : Basis κ R N
c' : Basis κ' R N
f✝ : M →ₗ[R] N
b : Basis ι R M
f : M ≃ₗ[R] N
v : ι → N
i✝ x✝ : ι
⊢ toMatrix (Basis.map b f) v i✝ x✝ = toMatrix b (⇑(LinearEquiv.symm f) ∘ v) i✝ x✝

Next tactic:
simp only [Basis.toMatrix_apply, Basis.map, LinearEquiv.trans_apply, (· ∘ ·)]
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  

Proof state:
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι → Finset α
⊢ f ∈ Finset.finsupp s t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i

Next tactic:
refine' mem_map.trans ⟨_, _⟩
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  refine' mem_map.trans ⟨_, _⟩
  · 

Proof state:
case refine'_1
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι → Finset α
⊢ (∃ a ∈ pi s t, { toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } a = f) →
    f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i

Next tactic:
rintro ⟨f, hf, rfl⟩
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  refine' mem_map.trans ⟨_, _⟩
  · rintro ⟨f, hf, rfl⟩
    

Proof state:
case refine'_1.intro.intro
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
t : ι → Finset α
f : (i : ι) → i ∈ s → α
hf : f ∈ pi s t
⊢ ({ toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } f).support ⊆ s ∧
    ∀ i ∈ s, ({ toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } f) i ∈ t i

Next tactic:
refine' ⟨support_indicator_subset _ _, fun i hi => _⟩
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  refine' mem_map.trans ⟨_, _⟩
  · rintro ⟨f, hf, rfl⟩
    refine' ⟨support_indicator_subset _ _, fun i hi => _⟩
    

Proof state:
case refine'_1.intro.intro
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
t : ι → Finset α
f : (i : ι) → i ∈ s → α
hf : f ∈ pi s t
i : ι
hi : i ∈ s
⊢ ({ toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } f) i ∈ t i

Next tactic:
convert mem_pi.1 hf i hi
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  refine' mem_map.trans ⟨_, _⟩
  · rintro ⟨f, hf, rfl⟩
    refine' ⟨support_indicator_subset _ _, fun i hi => _⟩
    convert mem_pi.1 hf i hi
    

Proof state:
case h.e'_4
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
t : ι → Finset α
f : (i : ι) → i ∈ s → α
hf : f ∈ pi s t
i : ι
hi : i ∈ s
⊢ ({ toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } f) i = f i hi

Next tactic:
exact indicator_of_mem hi _
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  refine' mem_map.trans ⟨_, _⟩
  · rintro ⟨f, hf, rfl⟩
    refine' ⟨support_indicator_subset _ _, fun i hi => _⟩
    convert mem_pi.1 hf i hi
    exact indicator_of_mem hi _
  · 

Proof state:
case refine'_2
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι → Finset α
⊢ (f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i) →
    ∃ a ∈ pi s t, { toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } a = f

Next tactic:
refine' fun h => ⟨fun i _ => f i, mem_pi.2 h.2, _⟩
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  refine' mem_map.trans ⟨_, _⟩
  · rintro ⟨f, hf, rfl⟩
    refine' ⟨support_indicator_subset _ _, fun i hi => _⟩
    convert mem_pi.1 hf i hi
    exact indicator_of_mem hi _
  · refine' fun h => ⟨fun i _ => f i, mem_pi.2 h.2, _⟩
    

Proof state:
case refine'_2
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι → Finset α
h : f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i
⊢ ({ toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } fun i x => f i) = f

Next tactic:
ext i
theorem mem_finsupp_iff {t : ι → Finset α} :
    f ∈ s.finsupp t ↔ f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i := by
  refine' mem_map.trans ⟨_, _⟩
  · rintro ⟨f, hf, rfl⟩
    refine' ⟨support_indicator_subset _ _, fun i hi => _⟩
    convert mem_pi.1 hf i hi
    exact indicator_of_mem hi _
  · refine' fun h => ⟨fun i _ => f i, mem_pi.2 h.2, _⟩
    ext i
    

Proof state:
case refine'_2.h
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι → Finset α
h : f.support ⊆ s ∧ ∀ i ∈ s, f i ∈ t i
i : ι
⊢ ({ toFun := indicator s, inj' := (_ : Function.Injective fun f => indicator s f) } fun i x => f i) i = f i

Next tactic:
exact ite_eq_left_iff.2 fun hi => (not_mem_support_iff.1 fun H => hi <| h.1 H).symm
/-- When `t` is supported on `s`, `f ∈ s.finsupp t` precisely means that `f` is pointwise in `t`. -/
@[simp]
theorem mem_finsupp_iff_of_support_subset {t : ι →₀ Finset α} (ht : t.support ⊆ s) :
    f ∈ s.finsupp t ↔ ∀ i, f i ∈ t i := by
  

Proof state:
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι →₀ Finset α
ht : t.support ⊆ s
⊢ f ∈ Finset.finsupp s ⇑t ↔ ∀ (i : ι), f i ∈ t i

Next tactic:
refine'
    mem_finsupp_iff.trans
      (forall_and.symm.trans <|
        forall_congr' fun i =>
          ⟨fun h => _, fun h =>
            ⟨fun hi => ht <| mem_support_iff.2 fun H => mem_support_iff.1 hi _, fun _ => h⟩⟩)
/-- When `t` is supported on `s`, `f ∈ s.finsupp t` precisely means that `f` is pointwise in `t`. -/
@[simp]
theorem mem_finsupp_iff_of_support_subset {t : ι →₀ Finset α} (ht : t.support ⊆ s) :
    f ∈ s.finsupp t ↔ ∀ i, f i ∈ t i := by
  refine'
    mem_finsupp_iff.trans
      (forall_and.symm.trans <|
        forall_congr' fun i =>
          ⟨fun h => _, fun h =>
            ⟨fun hi => ht <| mem_support_iff.2 fun H => mem_support_iff.1 hi _, fun _ => h⟩⟩)
  · 

Proof state:
case refine'_1
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι →₀ Finset α
ht : t.support ⊆ s
i : ι
h : (i ∈ f.support → i ∈ s) ∧ (i ∈ s → f i ∈ t i)
⊢ f i ∈ t i

Next tactic:
by_cases hi : i ∈ s
/-- When `t` is supported on `s`, `f ∈ s.finsupp t` precisely means that `f` is pointwise in `t`. -/
@[simp]
theorem mem_finsupp_iff_of_support_subset {t : ι →₀ Finset α} (ht : t.support ⊆ s) :
    f ∈ s.finsupp t ↔ ∀ i, f i ∈ t i := by
  refine'
    mem_finsupp_iff.trans
      (forall_and.symm.trans <|
        forall_congr' fun i =>
          ⟨fun h => _, fun h =>
            ⟨fun hi => ht <| mem_support_iff.2 fun H => mem_support_iff.1 hi _, fun _ => h⟩⟩)
  · by_cases hi : i ∈ s
    · 

Proof state:
case pos
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι →₀ Finset α
ht : t.support ⊆ s
i : ι
h : (i ∈ f.support → i ∈ s) ∧ (i ∈ s → f i ∈ t i)
hi : i ∈ s
⊢ f i ∈ t i

Next tactic:
exact h.2 hi
/-- When `t` is supported on `s`, `f ∈ s.finsupp t` precisely means that `f` is pointwise in `t`. -/
@[simp]
theorem mem_finsupp_iff_of_support_subset {t : ι →₀ Finset α} (ht : t.support ⊆ s) :
    f ∈ s.finsupp t ↔ ∀ i, f i ∈ t i := by
  refine'
    mem_finsupp_iff.trans
      (forall_and.symm.trans <|
        forall_congr' fun i =>
          ⟨fun h => _, fun h =>
            ⟨fun hi => ht <| mem_support_iff.2 fun H => mem_support_iff.1 hi _, fun _ => h⟩⟩)
  · by_cases hi : i ∈ s
    · exact h.2 hi
    · 

Proof state:
case neg
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι →₀ Finset α
ht : t.support ⊆ s
i : ι
h : (i ∈ f.support → i ∈ s) ∧ (i ∈ s → f i ∈ t i)
hi : i ∉ s
⊢ f i ∈ t i

Next tactic:
rw [not_mem_support_iff.1 (mt h.1 hi), not_mem_support_iff.1 fun H => hi <| ht H]
/-- When `t` is supported on `s`, `f ∈ s.finsupp t` precisely means that `f` is pointwise in `t`. -/
@[simp]
theorem mem_finsupp_iff_of_support_subset {t : ι →₀ Finset α} (ht : t.support ⊆ s) :
    f ∈ s.finsupp t ↔ ∀ i, f i ∈ t i := by
  refine'
    mem_finsupp_iff.trans
      (forall_and.symm.trans <|
        forall_congr' fun i =>
          ⟨fun h => _, fun h =>
            ⟨fun hi => ht <| mem_support_iff.2 fun H => mem_support_iff.1 hi _, fun _ => h⟩⟩)
  · by_cases hi : i ∈ s
    · exact h.2 hi
    · rw [not_mem_support_iff.1 (mt h.1 hi), not_mem_support_iff.1 fun H => hi <| ht H]
      

Proof state:
case neg
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι →₀ Finset α
ht : t.support ⊆ s
i : ι
h : (i ∈ f.support → i ∈ s) ∧ (i ∈ s → f i ∈ t i)
hi : i ∉ s
⊢ 0 ∈ 0

Next tactic:
exact zero_mem_zero
/-- When `t` is supported on `s`, `f ∈ s.finsupp t` precisely means that `f` is pointwise in `t`. -/
@[simp]
theorem mem_finsupp_iff_of_support_subset {t : ι →₀ Finset α} (ht : t.support ⊆ s) :
    f ∈ s.finsupp t ↔ ∀ i, f i ∈ t i := by
  refine'
    mem_finsupp_iff.trans
      (forall_and.symm.trans <|
        forall_congr' fun i =>
          ⟨fun h => _, fun h =>
            ⟨fun hi => ht <| mem_support_iff.2 fun H => mem_support_iff.1 hi _, fun _ => h⟩⟩)
  · by_cases hi : i ∈ s
    · exact h.2 hi
    · rw [not_mem_support_iff.1 (mt h.1 hi), not_mem_support_iff.1 fun H => hi <| ht H]
      exact zero_mem_zero
  · 

Proof state:
case refine'_2
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f : ι →₀ α
t : ι →₀ Finset α
ht : t.support ⊆ s
i : ι
h : f i ∈ t i
hi : i ∈ f.support
H : t i = 0
⊢ f i = 0

Next tactic:
rwa [H, mem_zero] at h
@[simp]
theorem card_pi (f : ι →₀ Finset α) : f.pi.card = f.prod fun i => (f i).card := by
  

Proof state:
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f✝ : ι →₀ α
f : ι →₀ Finset α
⊢ card (pi f) = prod f fun i => ↑(card (f i))

Next tactic:
rw [pi, card_finsupp]
@[simp]
theorem card_pi (f : ι →₀ Finset α) : f.pi.card = f.prod fun i => (f i).card := by
  rw [pi, card_finsupp]
  

Proof state:
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f✝ : ι →₀ α
f : ι →₀ Finset α
⊢ ∏ i in f.support, card (f i) = prod f fun i => ↑(card (f i))

Next tactic:
exact Finset.prod_congr rfl fun i _ => by simp only [Pi.nat_apply, Nat.cast_id]
@[simp]
theorem card_pi (f : ι →₀ Finset α) : f.pi.card = f.prod fun i => (f i).card := by
  rw [pi, card_finsupp]
  exact Finset.prod_congr rfl fun i _ => by 

Proof state:
ι : Type u_1
α : Type u_2
inst✝ : Zero α
s : Finset ι
f✝ : ι →₀ α
f : ι →₀ Finset α
i : ι
x✝ : i ∈ f.support
⊢ card (f i) = (fun i => ↑(card (f i))) i (f i)

Next tactic:
simp only [Pi.nat_apply, Nat.cast_id]
instance : EquivLike (α ≃ β) α β where
  coe := Equiv.toFun
  inv := Equiv.invFun
  left_inv := Equiv.left_inv
  right_inv := Equiv.right_inv
  coe_injective' e₁ e₂ h₁ h₂ := by 

Proof state:
α : Sort u
β : Sort v
γ : Sort w
e₁ e₂ : α ≃ β
h₁ : e₁.toFun = e₂.toFun
h₂ : e₁.invFun = e₂.invFun
⊢ e₁ = e₂

Next tactic:
cases e₁
instance : EquivLike (α ≃ β) α β where
  coe := Equiv.toFun
  inv := Equiv.invFun
  left_inv := Equiv.left_inv
  right_inv := Equiv.right_inv
  coe_injective' e₁ e₂ h₁ h₂ := by cases e₁; 

Proof state:
case mk
α : Sort u
β : Sort v
γ : Sort w
e₂ : α ≃ β
toFun✝ : α → β
invFun✝ : β → α
left_inv✝ : LeftInverse invFun✝ toFun✝
right_inv✝ : Function.RightInverse invFun✝ toFun✝
h₁ : { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ }.toFun = e₂.toFun
h₂ : { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ }.invFun = e₂.invFun
⊢ { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ } = e₂

Next tactic:
cases e₂
instance : EquivLike (α ≃ β) α β where
  coe := Equiv.toFun
  inv := Equiv.invFun
  left_inv := Equiv.left_inv
  right_inv := Equiv.right_inv
  coe_injective' e₁ e₂ h₁ h₂ := by cases e₁; cases e₂; 

Proof state:
case mk.mk
α : Sort u
β : Sort v
γ : Sort w
toFun✝¹ : α → β
invFun✝¹ : β → α
left_inv✝¹ : LeftInverse invFun✝¹ toFun✝¹
right_inv✝¹ : Function.RightInverse invFun✝¹ toFun✝¹
toFun✝ : α → β
invFun✝ : β → α
left_inv✝ : LeftInverse invFun✝ toFun✝
right_inv✝ : Function.RightInverse invFun✝ toFun✝
h₁ :
  { toFun := toFun✝¹, invFun := invFun✝¹, left_inv := left_inv✝¹, right_inv := right_inv✝¹ }.toFun =
    { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ }.toFun
h₂ :
  { toFun := toFun✝¹, invFun := invFun✝¹, left_inv := left_inv✝¹, right_inv := right_inv✝¹ }.invFun =
    { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ }.invFun
⊢ { toFun := toFun✝¹, invFun := invFun✝¹, left_inv := left_inv✝¹, right_inv := right_inv✝¹ } =
    { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ }

Next tactic:
congr
/-- Equivalence between equal types. -/
protected def cast {α β : Sort _} (h : α = β) : α ≃ β :=
  ⟨cast h, cast h.symm, fun _ => by 

Proof state:
α✝ : Sort u
β✝ : Sort v
γ : Sort w
α β : Sort ?u.16874
h : α = β
x✝ : α
⊢ cast (_ : β = α) (cast h x✝) = x✝

Next tactic:
cases h
/-- Equivalence between equal types. -/
protected def cast {α β : Sort _} (h : α = β) : α ≃ β :=
  ⟨cast h, cast h.symm, fun _ => by cases h; 

Proof state:
case refl
α✝ : Sort u
β : Sort v
γ : Sort w
α : Sort ?u.16874
x✝ : α
⊢ cast (_ : α = α) (cast (_ : α = α) x✝) = x✝

Next tactic:
rfl
/-- Equivalence between equal types. -/
protected def cast {α β : Sort _} (h : α = β) : α ≃ β :=
  ⟨cast h, cast h.symm, fun _ => by cases h; rfl, fun _ => by 

Proof state:
α✝ : Sort u
β✝ : Sort v
γ : Sort w
α β : Sort ?u.16874
h : α = β
x✝ : β
⊢ cast h (cast (_ : β = α) x✝) = x✝

Next tactic:
cases h
/-- Equivalence between equal types. -/
protected def cast {α β : Sort _} (h : α = β) : α ≃ β :=
  ⟨cast h, cast h.symm, fun _ => by cases h; rfl, fun _ => by cases h; 

Proof state:
case refl
α✝ : Sort u
β : Sort v
γ : Sort w
α : Sort ?u.16874
x✝ : α
⊢ cast (_ : α = α) (cast (_ : α = α) x✝) = x✝

Next tactic:
rfl
/-- This cannot be a `simp` lemmas as it incorrectly matches against `e : α ≃ synonym α`, when
`synonym α` is semireducible. This makes a mess of `Multiplicative.ofAdd` etc. -/
theorem Perm.coe_subsingleton {α : Type*} [Subsingleton α] (e : Perm α) : (e : α → α) = id := by
  

Proof state:
α✝ : Sort u
β : Sort v
γ : Sort w
α : Type u_1
inst✝ : Subsingleton α
e : Perm α
⊢ ⇑e = id

Next tactic:
rw [Perm.subsingleton_eq_refl e, coe_refl]
theorem apply_eq_iff_eq_symm_apply (f : α ≃ β) : f x = y ↔ x = f.symm y := by
  

Proof state:
α : Sort u
β : Sort v
γ : Sort w
x : α
y : β
f : α ≃ β
⊢ f x = y ↔ x = f.symm y

Next tactic:
conv_lhs => rw [← apply_symm_apply f y]
theorem apply_eq_iff_eq_symm_apply (f : α ≃ β) : f x = y ↔ x = f.symm y := by
  conv_lhs => 

Proof state:
α : Sort u
β : Sort v
γ : Sort w
x : α
y : β
f : α ≃ β
| f x = y

Next tactic:
rw [← apply_symm_apply f y]
theorem apply_eq_iff_eq_symm_apply (f : α ≃ β) : f x = y ↔ x = f.symm y := by
  conv_lhs => rw [← apply_symm_apply f y]
  

Proof state:
α : Sort u
β : Sort v
γ : Sort w
x : α
y : β
f : α ≃ β
⊢ f x = f (f.symm y) ↔ x = f.symm y

Next tactic:
rw [apply_eq_iff_eq]