l3lab/ntp-mathlib huggingface dataset:
theorem isNilpotent_jacobson_bot : IsNilpotent (Ideal.jacobson (⊥ : Ideal R)) := by
  let Jac := Ideal.jacobson (⊥ : Ideal R)
  let f : ℕ →o (Ideal R)ᵒᵈ := ⟨fun n => Jac ^ n, fun _ _ h => Ideal.pow_le_pow_right h⟩
  obtain ⟨n, hn⟩ : ∃ n, ∀ m, n ≤ m → Jac ^ n = Jac ^ m := IsArtinian.monotone_stabilizes f
  refine' ⟨n, _⟩
  let J : Ideal R := annihilator (Jac ^ n)
  suffices J = ⊤ by
    have hJ : J • Jac ^ n = ⊥ := annihilator_smul (Jac ^ n)
    simpa only [this, top_smul, Ideal.zero_eq_bot] using hJ
  by_contra hJ
  change J ≠ ⊤ at hJ
  rcases IsArtinian.set_has_minimal { J' : Ideal R | J < J' } ⟨⊤, hJ.lt_top⟩ with
    ⟨J', hJJ' : J < J', hJ' : ∀ I, J < I → ¬I < J'⟩
  rcases SetLike.exists_of_lt hJJ' with ⟨x, hxJ', hxJ⟩
  obtain rfl : J ⊔ Ideal.span {x} = J' := by
    apply eq_of_le_of_not_lt _ (hJ' (J ⊔ Ideal.span {x}) _)
    · exact sup_le hJJ'.le (span_le.2 (singleton_subset_iff.2 hxJ'))
    · rw [SetLike.lt_iff_le_and_exists]
      exact ⟨le_sup_left, ⟨x, mem_sup_right (mem_span_singleton_self x), hxJ⟩⟩
  have : J ⊔ Jac • Ideal.span {x} ≤ J ⊔ Ideal.span {x} :=
    sup_le_sup_left (smul_le.2 fun _ _ _ => Submodule.smul_mem _ _) _
  have : Jac * Ideal.span {x} ≤ J := by -- Need version 4 of Nakayama's lemma on Stacks
    by_contra H
    refine' H (smul_le_of_le_smul_of_le_jacobson_bot (fg_span_singleton _) le_rfl
      (this.eq_of_not_lt (hJ' _ _)).ge)
    exact lt_of_le_of_ne le_sup_left fun h => H <| h.symm ▸ le_sup_right
  have : Ideal.span {x} * Jac ^ (n + 1) ≤ ⊥
  calc
    Ideal.span {x} * Jac ^ (n + 1) = Ideal.span {x} * Jac * Jac ^ n := by rw [pow_succ, ← mul_assoc]
    _ ≤ J * Jac ^ n := (mul_le_mul (by rwa [mul_comm]) le_rfl)
    _ = ⊥ := by simp
  refine' hxJ (mem_annihilator.2 fun y hy => (mem_bot R).1 _)
  refine' this (mul_mem_mul (mem_span_singleton_self x) _)
  

Proof state:
case intro.intro.intro.intro.intro
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Jac : Ideal R := Ideal.jacobson ⊥
f : ℕ →o (Ideal R)ᵒᵈ := { toFun := fun n => Jac ^ n, monotone' := (_ : ∀ (x x_1 : ℕ), x ≤ x_1 → Jac ^ x_1 ≤ Jac ^ x) }
n : ℕ
hn : ∀ (m : ℕ), n ≤ m → Jac ^ n = Jac ^ m
J : Ideal R := annihilator (Jac ^ n)
hJ : J ≠ ⊤
x : R
hxJ : x ∉ J
hJJ' : J < J ⊔ Ideal.span {x}
hJ' : ∀ (I : Ideal R), J < I → ¬I < J ⊔ Ideal.span {x}
hxJ' : x ∈ J ⊔ Ideal.span {x}
this✝¹ : J ⊔ Jac • Ideal.span {x} ≤ J ⊔ Ideal.span {x}
this✝ : Jac * Ideal.span {x} ≤ J
this : Ideal.span {x} * Jac ^ (n + 1) ≤ ⊥
y : R
hy : y ∈ Jac ^ n
⊢ y ∈ Jac ^ (n + 1)

Next tactic:
rwa [← hn (n + 1) (Nat.le_succ _)]
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  

Proof state:
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
⊢ Surjective ⇑(algebraMap R L)

Next tactic:
intro r'
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  

Proof state:
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r' : L
⊢ ∃ a, (algebraMap R L) a = r'

Next tactic:
obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  

Proof state:
case intro.intro
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
⊢ ∃ a, (algebraMap R L) a = IsLocalization.mk' L r₁ s

Next tactic:
obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  

Proof state:
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
⊢ ∃ r, IsLocalization.mk' L 1 s = (algebraMap R L) r
case intro.intro.intro
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
r₂ : R
h : IsLocalization.mk' L 1 s = (algebraMap R L) r₂
⊢ ∃ a, (algebraMap R L) a = IsLocalization.mk' L r₁ s

Next tactic:
swap
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · 

Proof state:
case intro.intro.intro
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
r₂ : R
h : IsLocalization.mk' L 1 s = (algebraMap R L) r₂
⊢ ∃ a, (algebraMap R L) a = IsLocalization.mk' L r₁ s

Next tactic:
exact ⟨r₁ * r₂, by rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]⟩
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · exact ⟨r₁ * r₂, by 

Proof state:
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
r₂ : R
h : IsLocalization.mk' L 1 s = (algebraMap R L) r₂
⊢ (algebraMap R L) (r₁ * r₂) = IsLocalization.mk' L r₁ s

Next tactic:
rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · exact ⟨r₁ * r₂, by rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]⟩
  

Proof state:
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
⊢ ∃ r, IsLocalization.mk' L 1 s = (algebraMap R L) r

Next tactic:
obtain ⟨n, r, hr⟩ := IsArtinian.exists_pow_succ_smul_dvd (s : R) (1 : R)
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · exact ⟨r₁ * r₂, by rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]⟩
  obtain ⟨n, r, hr⟩ := IsArtinian.exists_pow_succ_smul_dvd (s : R) (1 : R)
  

Proof state:
case intro.intro
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
n : ℕ
r : R
hr : ↑s ^ Nat.succ n • r = ↑s ^ n • 1
⊢ ∃ r, IsLocalization.mk' L 1 s = (algebraMap R L) r

Next tactic:
use r
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · exact ⟨r₁ * r₂, by rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]⟩
  obtain ⟨n, r, hr⟩ := IsArtinian.exists_pow_succ_smul_dvd (s : R) (1 : R)
  use r
  

Proof state:
case h
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
n : ℕ
r : R
hr : ↑s ^ Nat.succ n • r = ↑s ^ n • 1
⊢ IsLocalization.mk' L 1 s = (algebraMap R L) r

Next tactic:
rw [smul_eq_mul, smul_eq_mul, pow_succ', mul_assoc] at hr
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · exact ⟨r₁ * r₂, by rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]⟩
  obtain ⟨n, r, hr⟩ := IsArtinian.exists_pow_succ_smul_dvd (s : R) (1 : R)
  use r
  rw [smul_eq_mul, smul_eq_mul, pow_succ', mul_assoc] at hr
  

Proof state:
case h
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
n : ℕ
r : R
hr : ↑s ^ n * (↑s * r) = ↑s ^ n * 1
⊢ IsLocalization.mk' L 1 s = (algebraMap R L) r

Next tactic:
apply_fun algebraMap R L at hr
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · exact ⟨r₁ * r₂, by rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]⟩
  obtain ⟨n, r, hr⟩ := IsArtinian.exists_pow_succ_smul_dvd (s : R) (1 : R)
  use r
  rw [smul_eq_mul, smul_eq_mul, pow_succ', mul_assoc] at hr
  apply_fun algebraMap R L at hr
  

Proof state:
case h
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
n : ℕ
r : R
hr : (algebraMap R L) (↑s ^ n * (↑s * r)) = (algebraMap R L) (↑s ^ n * 1)
⊢ IsLocalization.mk' L 1 s = (algebraMap R L) r

Next tactic:
simp only [map_mul] at hr
/-- Localizing an artinian ring can only reduce the amount of elements. -/
theorem localization_surjective : Function.Surjective (algebraMap R L) := by
  intro r'
  obtain ⟨r₁, s, rfl⟩ := IsLocalization.mk'_surjective S r'
  obtain ⟨r₂, h⟩ : ∃ r : R, IsLocalization.mk' L 1 s = algebraMap R L r
  swap
  · exact ⟨r₁ * r₂, by rw [IsLocalization.mk'_eq_mul_mk'_one, map_mul, h]⟩
  obtain ⟨n, r, hr⟩ := IsArtinian.exists_pow_succ_smul_dvd (s : R) (1 : R)
  use r
  rw [smul_eq_mul, smul_eq_mul, pow_succ', mul_assoc] at hr
  apply_fun algebraMap R L at hr
  simp only [map_mul] at hr
  

Proof state:
case h
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : IsArtinianRing R
S : Submonoid R
L : Type u_2
inst✝² : CommRing L
inst✝¹ : Algebra R L
inst✝ : IsLocalization S L
r₁ : R
s : ↥S
n : ℕ
r : R
hr :
  (algebraMap R L) (↑s ^ n) * ((algebraMap R L) ↑s * (algebraMap R L) r) =
    (algebraMap R L) (↑s ^ n) * (algebraMap R L) 1
⊢ IsLocalization.mk' L 1 s = (algebraMap R L) r

Next tactic:
rw [← IsLocalization.mk'_one (M := S) L, IsLocalization.mk'_eq_iff_eq, mul_one, Submonoid.coe_one,
    ← (IsLocalization.map_units L (s ^ n)).mul_left_cancel hr, map_mul]
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
⊢ Set.Finite {I | Ideal.IsPrime I}

Next tactic:
set Spec := {I : Ideal R | I.IsPrime}
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  set Spec := {I : Ideal R | I.IsPrime}
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Spec : Set (Ideal R) := {I | Ideal.IsPrime I}
⊢ Set.Finite Spec

Next tactic:
obtain ⟨_, ⟨s, rfl⟩, H⟩ := set_has_minimal
    (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  set Spec := {I : Ideal R | I.IsPrime}
  obtain ⟨_, ⟨s, rfl⟩, H⟩ := set_has_minimal
    (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by 

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Spec : Set (Ideal R) := {I | Ideal.IsPrime I}
⊢ (fun x => Finset.inf x Subtype.val) ∅ = ⊤

Next tactic:
simp
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  set Spec := {I : Ideal R | I.IsPrime}
  obtain ⟨_, ⟨s, rfl⟩, H⟩ := set_has_minimal
    (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩
  

Proof state:
case intro.intro.intro
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Spec : Set (Ideal R) := {I | Ideal.IsPrime I}
s : Finset ↑Spec
H : ∀ I ∈ range fun x => Finset.inf x Subtype.val, ¬I < (fun x => Finset.inf x Subtype.val) s
⊢ Set.Finite Spec

Next tactic:
refine ⟨⟨s, fun p ↦ ?_⟩⟩
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  set Spec := {I : Ideal R | I.IsPrime}
  obtain ⟨_, ⟨s, rfl⟩, H⟩ := set_has_minimal
    (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩
  refine ⟨⟨s, fun p ↦ ?_⟩⟩
  

Proof state:
case intro.intro.intro
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Spec : Set (Ideal R) := {I | Ideal.IsPrime I}
s : Finset ↑Spec
H : ∀ I ∈ range fun x => Finset.inf x Subtype.val, ¬I < (fun x => Finset.inf x Subtype.val) s
p : ↑Spec
⊢ p ∈ s

Next tactic:
classical
  obtain ⟨q, hq1, hq2⟩ := p.2.inf_le'.mp <| inf_eq_right.mp <|
    inf_le_right.eq_of_not_lt (H (p ⊓ s.inf Subtype.val) ⟨insert p s, by simp⟩)
  rwa [← Subtype.ext <| (@isMaximal_of_isPrime _ _ _ _ q.2).eq_of_le p.2.1 hq2]
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  set Spec := {I : Ideal R | I.IsPrime}
  obtain ⟨_, ⟨s, rfl⟩, H⟩ := set_has_minimal
    (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩
  refine ⟨⟨s, fun p ↦ ?_⟩⟩
  classical
  

Proof state:
case intro.intro.intro
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Spec : Set (Ideal R) := {I | Ideal.IsPrime I}
s : Finset ↑Spec
H : ∀ I ∈ range fun x => Finset.inf x Subtype.val, ¬I < (fun x => Finset.inf x Subtype.val) s
p : ↑Spec
⊢ p ∈ s

Next tactic:
obtain ⟨q, hq1, hq2⟩ := p.2.inf_le'.mp <| inf_eq_right.mp <|
    inf_le_right.eq_of_not_lt (H (p ⊓ s.inf Subtype.val) ⟨insert p s, by simp⟩)
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  set Spec := {I : Ideal R | I.IsPrime}
  obtain ⟨_, ⟨s, rfl⟩, H⟩ := set_has_minimal
    (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩
  refine ⟨⟨s, fun p ↦ ?_⟩⟩
  classical
  obtain ⟨q, hq1, hq2⟩ := p.2.inf_le'.mp <| inf_eq_right.mp <|
    inf_le_right.eq_of_not_lt (H (p ⊓ s.inf Subtype.val) ⟨insert p s, by 

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Spec : Set (Ideal R) := {I | Ideal.IsPrime I}
s : Finset ↑Spec
H : ∀ I ∈ range fun x => Finset.inf x Subtype.val, ¬I < (fun x => Finset.inf x Subtype.val) s
p : ↑Spec
⊢ (fun x => Finset.inf x Subtype.val) (insert p s) = ↑p ⊓ Finset.inf s Subtype.val

Next tactic:
simp
variable (R) in
lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by
  set Spec := {I : Ideal R | I.IsPrime}
  obtain ⟨_, ⟨s, rfl⟩, H⟩ := set_has_minimal
    (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩
  refine ⟨⟨s, fun p ↦ ?_⟩⟩
  classical
  obtain ⟨q, hq1, hq2⟩ := p.2.inf_le'.mp <| inf_eq_right.mp <|
    inf_le_right.eq_of_not_lt (H (p ⊓ s.inf Subtype.val) ⟨insert p s, by simp⟩)
  

Proof state:
case intro.intro.intro.intro.intro
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
Spec : Set (Ideal R) := {I | Ideal.IsPrime I}
s : Finset ↑Spec
H : ∀ I ∈ range fun x => Finset.inf x Subtype.val, ¬I < (fun x => Finset.inf x Subtype.val) s
p q : ↑Spec
hq1 : q ∈ s
hq2 : ↑q ≤ ↑p
⊢ p ∈ s

Next tactic:
rwa [← Subtype.ext <| (@isMaximal_of_isPrime _ _ _ _ q.2).eq_of_le p.2.1 hq2]
variable (R) in
/--
[Stacks Lemma 00J7](https://stacks.math.columbia.edu/tag/00J7)
-/
lemma maximal_ideals_finite : {I : Ideal R | I.IsMaximal}.Finite := by
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
⊢ Set.Finite {I | Ideal.IsMaximal I}

Next tactic:
simp_rw [← isPrime_iff_isMaximal]
variable (R) in
/--
[Stacks Lemma 00J7](https://stacks.math.columbia.edu/tag/00J7)
-/
lemma maximal_ideals_finite : {I : Ideal R | I.IsMaximal}.Finite := by
  simp_rw [← isPrime_iff_isMaximal]
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsArtinianRing R
⊢ Set.Finite {I | Ideal.IsPrime I}

Next tactic:
apply primeSpectrum_finite R
/-- The change-of-basis matrix between two orthonormal bases with the same orientation has
determinant 1. -/
theorem det_to_matrix_orthonormalBasis_of_same_orientation
    (h : e.toBasis.orientation = f.toBasis.orientation) : e.toBasis.det f = 1 := by
  

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)
⊢ (Basis.det (OrthonormalBasis.toBasis e)) ⇑f = 1

Next tactic:
apply (e.det_to_matrix_orthonormalBasis_real f).resolve_right
/-- The change-of-basis matrix between two orthonormal bases with the same orientation has
determinant 1. -/
theorem det_to_matrix_orthonormalBasis_of_same_orientation
    (h : e.toBasis.orientation = f.toBasis.orientation) : e.toBasis.det f = 1 := by
  apply (e.det_to_matrix_orthonormalBasis_real f).resolve_right
  

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)
⊢ ¬(Basis.det (OrthonormalBasis.toBasis e)) ⇑f = -1

Next tactic:
have : 0 < e.toBasis.det f := by
    rw [e.toBasis.orientation_eq_iff_det_pos] at h
    simpa using h
/-- The change-of-basis matrix between two orthonormal bases with the same orientation has
determinant 1. -/
theorem det_to_matrix_orthonormalBasis_of_same_orientation
    (h : e.toBasis.orientation = f.toBasis.orientation) : e.toBasis.det f = 1 := by
  apply (e.det_to_matrix_orthonormalBasis_real f).resolve_right
  have : 0 < e.toBasis.det f := by
    

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)
⊢ 0 < (Basis.det (OrthonormalBasis.toBasis e)) ⇑f

Next tactic:
rw [e.toBasis.orientation_eq_iff_det_pos] at h
/-- The change-of-basis matrix between two orthonormal bases with the same orientation has
determinant 1. -/
theorem det_to_matrix_orthonormalBasis_of_same_orientation
    (h : e.toBasis.orientation = f.toBasis.orientation) : e.toBasis.det f = 1 := by
  apply (e.det_to_matrix_orthonormalBasis_real f).resolve_right
  have : 0 < e.toBasis.det f := by
    rw [e.toBasis.orientation_eq_iff_det_pos] at h
    

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : 0 < (Basis.det (OrthonormalBasis.toBasis e)) ⇑(OrthonormalBasis.toBasis f)
⊢ 0 < (Basis.det (OrthonormalBasis.toBasis e)) ⇑f

Next tactic:
simpa using h
/-- The change-of-basis matrix between two orthonormal bases with the same orientation has
determinant 1. -/
theorem det_to_matrix_orthonormalBasis_of_same_orientation
    (h : e.toBasis.orientation = f.toBasis.orientation) : e.toBasis.det f = 1 := by
  apply (e.det_to_matrix_orthonormalBasis_real f).resolve_right
  have : 0 < e.toBasis.det f := by
    rw [e.toBasis.orientation_eq_iff_det_pos] at h
    simpa using h
  

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)
this : 0 < (Basis.det (OrthonormalBasis.toBasis e)) ⇑f
⊢ ¬(Basis.det (OrthonormalBasis.toBasis e)) ⇑f = -1

Next tactic:
linarith
/-- The change-of-basis matrix between two orthonormal bases with the opposite orientations has
determinant -1. -/
theorem det_to_matrix_orthonormalBasis_of_opposite_orientation
    (h : e.toBasis.orientation ≠ f.toBasis.orientation) : e.toBasis.det f = -1 := by
  

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : Basis.orientation (OrthonormalBasis.toBasis e) ≠ Basis.orientation (OrthonormalBasis.toBasis f)
⊢ (Basis.det (OrthonormalBasis.toBasis e)) ⇑f = -1

Next tactic:
contrapose! h
/-- The change-of-basis matrix between two orthonormal bases with the opposite orientations has
determinant -1. -/
theorem det_to_matrix_orthonormalBasis_of_opposite_orientation
    (h : e.toBasis.orientation ≠ f.toBasis.orientation) : e.toBasis.det f = -1 := by
  contrapose! h
  

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : (Basis.det (OrthonormalBasis.toBasis e)) ⇑f ≠ -1
⊢ Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)

Next tactic:
simp [e.toBasis.orientation_eq_iff_det_pos,
    (e.det_to_matrix_orthonormalBasis_real f).resolve_right h]
/-- Two orthonormal bases with the same orientation determine the same "determinant" top-dimensional
form on `E`, and conversely. -/
theorem same_orientation_iff_det_eq_det :
    e.toBasis.det = f.toBasis.det ↔ e.toBasis.orientation = f.toBasis.orientation := by
  

Proof state:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
⊢ Basis.det (OrthonormalBasis.toBasis e) = Basis.det (OrthonormalBasis.toBasis f) ↔
    Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)

Next tactic:
constructor
/-- Two orthonormal bases with the same orientation determine the same "determinant" top-dimensional
form on `E`, and conversely. -/
theorem same_orientation_iff_det_eq_det :
    e.toBasis.det = f.toBasis.det ↔ e.toBasis.orientation = f.toBasis.orientation := by
  constructor
  · 

Proof state:
case mp
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
⊢ Basis.det (OrthonormalBasis.toBasis e) = Basis.det (OrthonormalBasis.toBasis f) →
    Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)

Next tactic:
intro h
/-- Two orthonormal bases with the same orientation determine the same "determinant" top-dimensional
form on `E`, and conversely. -/
theorem same_orientation_iff_det_eq_det :
    e.toBasis.det = f.toBasis.det ↔ e.toBasis.orientation = f.toBasis.orientation := by
  constructor
  · intro h
    

Proof state:
case mp
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
ι : Type u_2
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
ne : Nonempty ι
e f : OrthonormalBasis ι ℝ E
x : Orientation ℝ E ι
h : Basis.det (OrthonormalBasis.toBasis e) = Basis.det (OrthonormalBasis.toBasis f)
⊢ Basis.orientation (OrthonormalBasis.toBasis e) = Basis.orientation (OrthonormalBasis.toBasis f)

Next tactic:
dsimp [Basis.orientation]