l3lab/ntp-mathlib huggingface dataset:
/-- If `S` a finite-dimensional ring extension of a PID `R` which is free as an `R`-module,
then any nonzero `S`-ideal `I` is free as an `R`-submodule of `S`, and we can
find a basis for `S` and `I` such that the inclusion map is a square diagonal
matrix.

See also `Ideal.smithNormalForm` for a version of this theorem that returns
a `Basis.SmithNormalForm`.

The definitions `Ideal.ringBasis`, `Ideal.selfBasis`, `Ideal.smithCoeffs` are (noncomputable)
choices of values for this existential quantifier.
-/
theorem Ideal.exists_smith_normal_form (b : Basis ι R S) (I : Ideal S) (hI : I ≠ ⊥) :
    ∃ (b' : Basis ι R S) (a : ι → R) (ab' : Basis ι R I), ∀ i, (ab' i : S) = a i • b' i := by
  cases nonempty_fintype ι
  let ⟨bS, bI, f, a, snf⟩ := I.smithNormalForm b hI
  let e : Fin (Fintype.card ι) ≃ ι :=
    Equiv.ofBijective f
      ((Fintype.bijective_iff_injective_and_card f).mpr ⟨f.injective, Fintype.card_fin _⟩)
  have fe : ∀ i, f (e.symm i) = i := e.apply_symm_apply
  

Proof state:
case intro
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
M : Type u_3
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
b✝ : ι → M
S : Type u_4
inst✝³ : CommRing S
inst✝² : IsDomain S
inst✝¹ : Algebra R S
inst✝ : Finite ι
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
val✝ : Fintype ι
bS : Basis ι R S
bI : Basis (Fin (Fintype.card ι)) R ↥(restrictScalars R I)
f : Fin (Fintype.card ι) ↪ ι
a : Fin (Fintype.card ι) → R
snf : ∀ (i : Fin (Fintype.card ι)), ↑(bI i) = a i • bS (f i)
e : Fin (Fintype.card ι) ≃ ι := Equiv.ofBijective ⇑f (_ : Function.Bijective ⇑f)
fe : ∀ (i : ι), f (e.symm i) = i
⊢ ∃ b' a ab', ∀ (i : ι), ↑(ab' i) = a i • b' i

Next tactic:
exact
    ⟨bS, a ∘ e.symm, (bI.reindex e).map ((restrictScalarsEquiv R S _ _).restrictScalars R),
      fun i ↦ by
        simp only [snf, fe, Basis.map_apply, LinearEquiv.restrictScalars_apply R,
          Submodule.restrictScalarsEquiv_apply, Basis.coe_reindex, (· ∘ ·)]⟩
/-- If `S` a finite-dimensional ring extension of a PID `R` which is free as an `R`-module,
then any nonzero `S`-ideal `I` is free as an `R`-submodule of `S`, and we can
find a basis for `S` and `I` such that the inclusion map is a square diagonal
matrix.

See also `Ideal.smithNormalForm` for a version of this theorem that returns
a `Basis.SmithNormalForm`.

The definitions `Ideal.ringBasis`, `Ideal.selfBasis`, `Ideal.smithCoeffs` are (noncomputable)
choices of values for this existential quantifier.
-/
theorem Ideal.exists_smith_normal_form (b : Basis ι R S) (I : Ideal S) (hI : I ≠ ⊥) :
    ∃ (b' : Basis ι R S) (a : ι → R) (ab' : Basis ι R I), ∀ i, (ab' i : S) = a i • b' i := by
  cases nonempty_fintype ι
  let ⟨bS, bI, f, a, snf⟩ := I.smithNormalForm b hI
  let e : Fin (Fintype.card ι) ≃ ι :=
    Equiv.ofBijective f
      ((Fintype.bijective_iff_injective_and_card f).mpr ⟨f.injective, Fintype.card_fin _⟩)
  have fe : ∀ i, f (e.symm i) = i := e.apply_symm_apply
  exact
    ⟨bS, a ∘ e.symm, (bI.reindex e).map ((restrictScalarsEquiv R S _ _).restrictScalars R),
      fun i ↦ by
        

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
M : Type u_3
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
b✝ : ι → M
S : Type u_4
inst✝³ : CommRing S
inst✝² : IsDomain S
inst✝¹ : Algebra R S
inst✝ : Finite ι
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
val✝ : Fintype ι
bS : Basis ι R S
bI : Basis (Fin (Fintype.card ι)) R ↥(restrictScalars R I)
f : Fin (Fintype.card ι) ↪ ι
a : Fin (Fintype.card ι) → R
snf : ∀ (i : Fin (Fintype.card ι)), ↑(bI i) = a i • bS (f i)
e : Fin (Fintype.card ι) ≃ ι := Equiv.ofBijective ⇑f (_ : Function.Bijective ⇑f)
fe : ∀ (i : ι), f (e.symm i) = i
i : ι
⊢ ↑((Basis.map (Basis.reindex bI e) (LinearEquiv.restrictScalars R (restrictScalarsEquiv R S S I))) i) =
    (a ∘ ⇑e.symm) i • bS i

Next tactic:
simp only [snf, fe, Basis.map_apply, LinearEquiv.restrictScalars_apply R,
          Submodule.restrictScalarsEquiv_apply, Basis.coe_reindex, (· ∘ ·)]
@[simp]
theorem Ideal.smithCoeffs_ne_zero (b : Basis ι R S) (I : Ideal S) (hI : I ≠ ⊥) (i) :
    Ideal.smithCoeffs b I hI i ≠ 0 := by
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
M : Type u_3
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
b✝ : ι → M
S : Type u_4
inst✝³ : CommRing S
inst✝² : IsDomain S
inst✝¹ : Algebra R S
inst✝ : Finite ι
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
i : ι
⊢ smithCoeffs b I hI i ≠ 0

Next tactic:
intro hi
@[simp]
theorem Ideal.smithCoeffs_ne_zero (b : Basis ι R S) (I : Ideal S) (hI : I ≠ ⊥) (i) :
    Ideal.smithCoeffs b I hI i ≠ 0 := by
  intro hi
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
M : Type u_3
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
b✝ : ι → M
S : Type u_4
inst✝³ : CommRing S
inst✝² : IsDomain S
inst✝¹ : Algebra R S
inst✝ : Finite ι
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
i : ι
hi : smithCoeffs b I hI i = 0
⊢ False

Next tactic:
apply Basis.ne_zero (Ideal.selfBasis b I hI) i
@[simp]
theorem Ideal.smithCoeffs_ne_zero (b : Basis ι R S) (I : Ideal S) (hI : I ≠ ⊥) (i) :
    Ideal.smithCoeffs b I hI i ≠ 0 := by
  intro hi
  apply Basis.ne_zero (Ideal.selfBasis b I hI) i
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
M : Type u_3
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
b✝ : ι → M
S : Type u_4
inst✝³ : CommRing S
inst✝² : IsDomain S
inst✝¹ : Algebra R S
inst✝ : Finite ι
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
i : ι
hi : smithCoeffs b I hI i = 0
⊢ (selfBasis b I hI) i = 0

Next tactic:
refine' Subtype.coe_injective _
@[simp]
theorem Ideal.smithCoeffs_ne_zero (b : Basis ι R S) (I : Ideal S) (hI : I ≠ ⊥) (i) :
    Ideal.smithCoeffs b I hI i ≠ 0 := by
  intro hi
  apply Basis.ne_zero (Ideal.selfBasis b I hI) i
  refine' Subtype.coe_injective _
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
M : Type u_3
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
b✝ : ι → M
S : Type u_4
inst✝³ : CommRing S
inst✝² : IsDomain S
inst✝¹ : Algebra R S
inst✝ : Finite ι
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
i : ι
hi : smithCoeffs b I hI i = 0
⊢ (fun a => ↑a) ((selfBasis b I hI) i) = (fun a => ↑a) 0

Next tactic:
simp [hi]
/-- A set of linearly independent vectors in a module `M` over a semiring `S` is also linearly
independent over a subring `R` of `K`. -/
theorem LinearIndependent.restrict_scalars_algebras {R S M ι : Type*} [CommSemiring R] [Semiring S]
    [AddCommMonoid M] [Algebra R S] [Module R M] [Module S M] [IsScalarTower R S M]
    (hinj : Function.Injective (algebraMap R S)) {v : ι → M} (li : LinearIndependent S v) :
    LinearIndependent R v :=
  LinearIndependent.restrict_scalars (by 

Proof state:
R : Type u_1
S : Type u_2
M : Type u_3
ι : Type u_4
inst✝⁶ : CommSemiring R
inst✝⁵ : Semiring S
inst✝⁴ : AddCommMonoid M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
hinj : Function.Injective ⇑(algebraMap R S)
v : ι → M
li : LinearIndependent S v
⊢ Function.Injective fun r => r • 1

Next tactic:
rwa [Algebra.algebraMap_eq_smul_one'] at hinj
/-- The antidiagonal of `s : α →₀ ℕ` is the finset of all pairs `(t₁, t₂) : (α →₀ ℕ) × (α →₀ ℕ)`
such that `t₁ + t₂ = s`. -/
instance instHasAntidiagonal : HasAntidiagonal (α →₀ ℕ) where
  antidiagonal f := f.antidiagonal'.support
  mem_antidiagonal {f} {p} := by
    

Proof state:
α : Type u
inst✝ : DecidableEq α
f : α →₀ ℕ
p : (α →₀ ℕ) × (α →₀ ℕ)
⊢ p ∈ (fun f => (antidiagonal' f).support) f ↔ p.1 + p.2 = f

Next tactic:
rcases p with ⟨p₁, p₂⟩
/-- The antidiagonal of `s : α →₀ ℕ` is the finset of all pairs `(t₁, t₂) : (α →₀ ℕ) × (α →₀ ℕ)`
such that `t₁ + t₂ = s`. -/
instance instHasAntidiagonal : HasAntidiagonal (α →₀ ℕ) where
  antidiagonal f := f.antidiagonal'.support
  mem_antidiagonal {f} {p} := by
    rcases p with ⟨p₁, p₂⟩
    

Proof state:
case mk
α : Type u
inst✝ : DecidableEq α
f p₁ p₂ : α →₀ ℕ
⊢ (p₁, p₂) ∈ (fun f => (antidiagonal' f).support) f ↔ (p₁, p₂).1 + (p₁, p₂).2 = f

Next tactic:
simp [antidiagonal', ← and_assoc, Multiset.toFinsupp_eq_iff,
    ← Multiset.toFinsupp_eq_iff (f := f)]
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  

Proof state:
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
⊢ (antidiagonal fun₀ | a => n) =
    map
      (Function.Embedding.prodMap { toFun := single a, inj' := (_ : Function.Injective (single a)) }
        { toFun := single a, inj' := (_ : Function.Injective (single a)) })
      (antidiagonal n)

Next tactic:
ext ⟨x, y⟩
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  

Proof state:
case a.mk
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
⊢ ((x, y) ∈ antidiagonal fun₀ | a => n) ↔
    (x, y) ∈
      map
        (Function.Embedding.prodMap { toFun := single a, inj' := (_ : Function.Injective (single a)) }
          { toFun := single a, inj' := (_ : Function.Injective (single a)) })
        (antidiagonal n)

Next tactic:
simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  

Proof state:
case a.mk
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
⊢ (x + y = fun₀ | a => n) ↔ ∃ a_1 b, a_1 + b = n ∧ (fun₀ | a => a_1) = x ∧ (fun₀ | a => b) = y

Next tactic:
constructor
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · 

Proof state:
case a.mk.mp
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
⊢ (x + y = fun₀ | a => n) → ∃ a_2 b, a_2 + b = n ∧ (fun₀ | a => a_2) = x ∧ (fun₀ | a => b) = y

Next tactic:
intro h
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    

Proof state:
case a.mk.mp
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
h : x + y = fun₀ | a => n
⊢ ∃ a_1 b, a_1 + b = n ∧ (fun₀ | a => a_1) = x ∧ (fun₀ | a => b) = y

Next tactic:
refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    

Proof state:
case a.mk.mp
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
h : x + y = fun₀ | a => n
⊢ (fun₀ | a => x a) = x ∧ (fun₀ | a => y a) = y

Next tactic:
simp_rw [FunLike.ext_iff, ← forall_and]
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    

Proof state:
case a.mk.mp
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
h : x + y = fun₀ | a => n
⊢ ∀ (x_1 : α), (fun₀ | a => x a) x_1 = x x_1 ∧ (fun₀ | a => y a) x_1 = y x_1

Next tactic:
intro i
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    

Proof state:
case a.mk.mp
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
h : x + y = fun₀ | a => n
i : α
⊢ (fun₀ | a => x a) i = x i ∧ (fun₀ | a => y a) i = y i

Next tactic:
replace h := FunLike.congr_fun h i
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    replace h := FunLike.congr_fun h i
    

Proof state:
case a.mk.mp
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
i : α
h : (x + y) i = (fun₀ | a => n) i
⊢ (fun₀ | a => x a) i = x i ∧ (fun₀ | a => y a) i = y i

Next tactic:
simp_rw [single_apply, Finsupp.add_apply] at h ⊢
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    replace h := FunLike.congr_fun h i
    simp_rw [single_apply, Finsupp.add_apply] at h ⊢
    

Proof state:
case a.mk.mp
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
i : α
h : x i + y i = if a = i then n else 0
⊢ (if a = i then x a else 0) = x i ∧ (if a = i then y a else 0) = y i

Next tactic:
obtain rfl | hai := Decidable.eq_or_ne a i
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    replace h := FunLike.congr_fun h i
    simp_rw [single_apply, Finsupp.add_apply] at h ⊢
    obtain rfl | hai := Decidable.eq_or_ne a i
    · 

Proof state:
case a.mk.mp.inl
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
h : x a + y a = if a = a then n else 0
⊢ (if a = a then x a else 0) = x a ∧ (if a = a then y a else 0) = y a

Next tactic:
exact ⟨if_pos rfl, if_pos rfl⟩
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    replace h := FunLike.congr_fun h i
    simp_rw [single_apply, Finsupp.add_apply] at h ⊢
    obtain rfl | hai := Decidable.eq_or_ne a i
    · exact ⟨if_pos rfl, if_pos rfl⟩
    · 

Proof state:
case a.mk.mp.inr
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
i : α
h : x i + y i = if a = i then n else 0
hai : a ≠ i
⊢ (if a = i then x a else 0) = x i ∧ (if a = i then y a else 0) = y i

Next tactic:
simp_rw [if_neg hai, _root_.add_eq_zero_iff] at h ⊢
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    replace h := FunLike.congr_fun h i
    simp_rw [single_apply, Finsupp.add_apply] at h ⊢
    obtain rfl | hai := Decidable.eq_or_ne a i
    · exact ⟨if_pos rfl, if_pos rfl⟩
    · simp_rw [if_neg hai, _root_.add_eq_zero_iff] at h ⊢
      

Proof state:
case a.mk.mp.inr
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
i : α
hai : a ≠ i
h : x i = 0 ∧ y i = 0
⊢ 0 = x i ∧ 0 = y i

Next tactic:
exact h.imp Eq.symm Eq.symm
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    replace h := FunLike.congr_fun h i
    simp_rw [single_apply, Finsupp.add_apply] at h ⊢
    obtain rfl | hai := Decidable.eq_or_ne a i
    · exact ⟨if_pos rfl, if_pos rfl⟩
    · simp_rw [if_neg hai, _root_.add_eq_zero_iff] at h ⊢
      exact h.imp Eq.symm Eq.symm
  · 

Proof state:
case a.mk.mpr
α : Type u
inst✝ : DecidableEq α
a : α
n : ℕ
x y : α →₀ ℕ
⊢ (∃ a_1 b, a_1 + b = n ∧ (fun₀ | a => a_1) = x ∧ (fun₀ | a => b) = y) → x + y = fun₀ | a => n

Next tactic:
rintro ⟨a, b, rfl, rfl, rfl⟩
@[simp]
theorem antidiagonal_single (a : α) (n : ℕ) :
    antidiagonal (single a n) = (antidiagonal n).map
      (Function.Embedding.prodMap ⟨_, single_injective a⟩ ⟨_, single_injective a⟩) := by
  ext ⟨x, y⟩
  simp only [mem_antidiagonal, mem_map, mem_antidiagonal, Function.Embedding.coe_prodMap,
    Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists]
  constructor
  · intro h
    refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩
    simp_rw [FunLike.ext_iff, ← forall_and]
    intro i
    replace h := FunLike.congr_fun h i
    simp_rw [single_apply, Finsupp.add_apply] at h ⊢
    obtain rfl | hai := Decidable.eq_or_ne a i
    · exact ⟨if_pos rfl, if_pos rfl⟩
    · simp_rw [if_neg hai, _root_.add_eq_zero_iff] at h ⊢
      exact h.imp Eq.symm Eq.symm
  · rintro ⟨a, b, rfl, rfl, rfl⟩
    

Proof state:
case a.mk.mpr.intro.intro.intro.intro
α : Type u
inst✝ : DecidableEq α
a✝ : α
a b : ℕ
⊢ ((fun₀ | a✝ => a) + fun₀ | a✝ => b) = fun₀ | a✝ => a + b

Next tactic:
exact (single_add _ _ _).symm
/-- If `X` is a topological space, `s` is a set in `X` such that the induced topology is T₀ and is
second countable, then there exists a countable family of open sets in `X` that separates points
of `s`. -/
instance [TopologicalSpace X] {s : Set X} [T0Space s] [SecondCountableTopology s] :
    HasCountableSeparatingOn X IsOpen s := by
  

Proof state:
X : Type ?u.7
inst✝² : TopologicalSpace X
s : Set X
inst✝¹ : T0Space ↑s
inst✝ : SecondCountableTopology ↑s
⊢ HasCountableSeparatingOn X IsOpen s

Next tactic:
suffices HasCountableSeparatingOn s IsOpen univ from .of_subtype fun _ ↦ isOpen_induced_iff.1
/-- If `X` is a topological space, `s` is a set in `X` such that the induced topology is T₀ and is
second countable, then there exists a countable family of open sets in `X` that separates points
of `s`. -/
instance [TopologicalSpace X] {s : Set X} [T0Space s] [SecondCountableTopology s] :
    HasCountableSeparatingOn X IsOpen s := by
  suffices HasCountableSeparatingOn s IsOpen univ from .of_subtype fun _ ↦ isOpen_induced_iff.1
  

Proof state:
X : Type ?u.7
inst✝² : TopologicalSpace X
s : Set X
inst✝¹ : T0Space ↑s
inst✝ : SecondCountableTopology ↑s
⊢ HasCountableSeparatingOn (↑s) IsOpen univ

Next tactic:
refine ⟨⟨countableBasis s, countable_countableBasis _, fun _ ↦ isOpen_of_mem_countableBasis,
    fun x _ y _ h ↦ ?_⟩⟩
/-- If `X` is a topological space, `s` is a set in `X` such that the induced topology is T₀ and is
second countable, then there exists a countable family of open sets in `X` that separates points
of `s`. -/
instance [TopologicalSpace X] {s : Set X} [T0Space s] [SecondCountableTopology s] :
    HasCountableSeparatingOn X IsOpen s := by
  suffices HasCountableSeparatingOn s IsOpen univ from .of_subtype fun _ ↦ isOpen_induced_iff.1
  refine ⟨⟨countableBasis s, countable_countableBasis _, fun _ ↦ isOpen_of_mem_countableBasis,
    fun x _ y _ h ↦ ?_⟩⟩
  

Proof state:
X : Type ?u.7
inst✝² : TopologicalSpace X
s : Set X
inst✝¹ : T0Space ↑s
inst✝ : SecondCountableTopology ↑s
x : ↑s
x✝¹ : x ∈ univ
y : ↑s
x✝ : y ∈ univ
h : ∀ s_1 ∈ countableBasis ↑s, x ∈ s_1 ↔ y ∈ s_1
⊢ x = y

Next tactic:
exact ((isBasis_countableBasis _).inseparable_iff.2 h).eq
theorem det_comm [DecidableEq n] (M N : Matrix n n A) : det (M * N) = det (N * M) := by
  

Proof state:
R : Type u_1
inst✝¹⁰ : CommRing R
M✝ : Type u_2
inst✝⁹ : AddCommGroup M✝
inst✝⁸ : Module R M✝
M' : Type u_3
inst✝⁷ : AddCommGroup M'
inst✝⁶ : Module R M'
ι : Type u_4
inst✝⁵ : DecidableEq ι
inst✝⁴ : Fintype ι
e : Basis ι R M✝
A : Type u_5
inst✝³ : CommRing A
m : Type u_6
n : Type u_7
inst✝² : Fintype m
inst✝¹ : Fintype n
inst✝ : DecidableEq n
M N : Matrix n n A
⊢ det (M * N) = det (N * M)

Next tactic:
rw [det_mul, det_mul, mul_comm]
/-- If there exists a two-sided inverse `M'` for `M` (indexed differently),
then `det (N * M) = det (M * N)`. -/
theorem det_comm' [DecidableEq m] [DecidableEq n] {M : Matrix n m A} {N : Matrix m n A}
    {M' : Matrix m n A} (hMM' : M * M' = 1) (hM'M : M' * M = 1) : det (M * N) = det (N * M) := by
  

Proof state:
R : Type u_1
inst✝¹¹ : CommRing R
M✝ : Type u_2
inst✝¹⁰ : AddCommGroup M✝
inst✝⁹ : Module R M✝
M'✝ : Type u_3
inst✝⁸ : AddCommGroup M'✝
inst✝⁷ : Module R M'✝
ι : Type u_4
inst✝⁶ : DecidableEq ι
inst✝⁵ : Fintype ι
e : Basis ι R M✝
A : Type u_5
inst✝⁴ : CommRing A
m : Type u_6
n : Type u_7
inst✝³ : Fintype m
inst✝² : Fintype n
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
M : Matrix n m A
N M' : Matrix m n A
hMM' : M * M' = 1
hM'M : M' * M = 1
⊢ det (M * N) = det (N * M)

Next tactic:
nontriviality A