ring_theory.class_groupMathlib.RingTheory.ClassGroup

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -315,7 +315,7 @@ theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
 #align class_group.equiv_mk0 ClassGroup.equiv_mk0
 -/
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
 #print ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring /-
 theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _) (_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
Diff
@@ -148,7 +148,7 @@ theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| Fractio
   constructor
   · rintro ⟨x, rfl⟩
     rw [Units.val_mul, hI, coe_toPrincipalIdeal, mul_comm,
-      span_singleton_mul_coe_ideal_eq_coe_ideal] at hJ 
+      span_singleton_mul_coe_ideal_eq_coe_ideal] at hJ
     exact ⟨_, _, sec_fst_ne_zero le_rfl x.ne_zero, sec_snd_ne_zero le_rfl ↑x, hJ⟩
   · rintro ⟨x, y, hx, hy, h⟩
     constructor; rw [mul_comm, ← Units.eq_iff, Units.val_mul, coe_toPrincipalIdeal]
@@ -168,10 +168,10 @@ theorem ClassGroup.mk_eq_one_of_coe_ideal {I : (FractionalIdeal R⁰ <| Fraction
   any_goals rfl
   constructor
   · rintro ⟨x, y, hx, hy, h⟩
-    rw [Ideal.mul_top] at h 
+    rw [Ideal.mul_top] at h
     rcases ideal.mem_span_singleton_mul.mp ((Ideal.span_singleton_le_iff_mem _).mp h.ge) with
       ⟨i, hi, rfl⟩
-    rw [← Ideal.span_singleton_mul_span_singleton, Ideal.span_singleton_mul_right_inj hx] at h 
+    rw [← Ideal.span_singleton_mul_span_singleton, Ideal.span_singleton_mul_right_inj hx] at h
     exact ⟨i, right_ne_zero_of_mul hy, h⟩
   · rintro ⟨x, hx, rfl⟩
     exact ⟨1, x, one_ne_zero, hx, by rw [Ideal.span_singleton_one, Ideal.top_mul, Ideal.mul_top]⟩
@@ -353,7 +353,7 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     refine' ⟨IsLocalization.mk' _ x ⟨y, hy'⟩, _, _⟩
     · contrapose! hx
       rwa [mk'_eq_iff_eq_mul, MulZeroClass.zero_mul, ← (algebraMap R (FractionRing R)).map_zero,
-        (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx 
+        (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx
     · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy').mpr h
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
 -/
Diff
@@ -3,8 +3,8 @@ Copyright (c) 2021 Anne Baanen. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Anne Baanen
 -/
-import Mathbin.GroupTheory.QuotientGroup
-import Mathbin.RingTheory.DedekindDomain.Ideal
+import GroupTheory.QuotientGroup
+import RingTheory.DedekindDomain.Ideal
 
 #align_import ring_theory.class_group from "leanprover-community/mathlib"@"7e5137f579de09a059a5ce98f364a04e221aabf0"
 
@@ -315,7 +315,7 @@ theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
 #align class_group.equiv_mk0 ClassGroup.equiv_mk0
 -/
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
 #print ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring /-
 theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _) (_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
Diff
@@ -2,15 +2,12 @@
 Copyright (c) 2021 Anne Baanen. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Anne Baanen
-
-! This file was ported from Lean 3 source module ring_theory.class_group
-! leanprover-community/mathlib commit 7e5137f579de09a059a5ce98f364a04e221aabf0
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.GroupTheory.QuotientGroup
 import Mathbin.RingTheory.DedekindDomain.Ideal
 
+#align_import ring_theory.class_group from "leanprover-community/mathlib"@"7e5137f579de09a059a5ce98f364a04e221aabf0"
+
 /-!
 # The ideal class group
 
@@ -318,7 +315,7 @@ theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
 #align class_group.equiv_mk0 ClassGroup.equiv_mk0
 -/
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
 #print ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring /-
 theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _) (_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
Diff
@@ -54,6 +54,7 @@ section
 
 variable (R K)
 
+#print toPrincipalIdeal /-
 /-- `to_principal_ideal R K x` sends `x ≠ 0 : K` to the fractional `R`-ideal generated by `x` -/
 irreducible_def toPrincipalIdeal : Kˣ →* (FractionalIdeal R⁰ K)ˣ :=
   { toFun := fun x =>
@@ -64,21 +65,27 @@ irreducible_def toPrincipalIdeal : Kˣ →* (FractionalIdeal R⁰ K)ˣ :=
       ext (by simp only [Units.val_mk, Units.val_mul, span_singleton_mul_span_singleton])
     map_one' := ext (by simp only [span_singleton_one, Units.val_mk, Units.val_one]) }
 #align to_principal_ideal toPrincipalIdeal
+-/
 
 variable {R K}
 
+#print coe_toPrincipalIdeal /-
 @[simp]
 theorem coe_toPrincipalIdeal (x : Kˣ) :
     (toPrincipalIdeal R K x : FractionalIdeal R⁰ K) = spanSingleton _ x := by
   simp only [toPrincipalIdeal]; rfl
 #align coe_to_principal_ideal coe_toPrincipalIdeal
+-/
 
+#print toPrincipalIdeal_eq_iff /-
 @[simp]
 theorem toPrincipalIdeal_eq_iff {I : (FractionalIdeal R⁰ K)ˣ} {x : Kˣ} :
     toPrincipalIdeal R K x = I ↔ spanSingleton R⁰ (x : K) = I := by simp only [toPrincipalIdeal];
   exact Units.ext_iff
 #align to_principal_ideal_eq_iff toPrincipalIdeal_eq_iff
+-/
 
+#print mem_principal_ideals_iff /-
 theorem mem_principal_ideals_iff {I : (FractionalIdeal R⁰ K)ˣ} :
     I ∈ (toPrincipalIdeal R K).range ↔ ∃ x : K, spanSingleton R⁰ x = I :=
   by
@@ -89,10 +96,13 @@ theorem mem_principal_ideals_iff {I : (FractionalIdeal R⁰ K)ˣ} :
     rintro rfl
     simpa [I.ne_zero.symm] using hx
 #align mem_principal_ideals_iff mem_principal_ideals_iff
+-/
 
+#print PrincipalIdeals.normal /-
 instance PrincipalIdeals.normal : (toPrincipalIdeal R K).range.Normal :=
   Subgroup.normal_of_comm _
 #align principal_ideals.normal PrincipalIdeals.normal
+-/
 
 end
 
@@ -112,12 +122,15 @@ noncomputable instance : Inhabited (ClassGroup R) :=
 
 variable {R K}
 
+#print ClassGroup.mk /-
 /-- Send a nonzero fractional ideal to the corresponding class in the class group. -/
 noncomputable def ClassGroup.mk : (FractionalIdeal R⁰ K)ˣ →* ClassGroup R :=
   (QuotientGroup.mk' (toPrincipalIdeal R (FractionRing R)).range).comp
     (Units.map (FractionalIdeal.canonicalEquiv R⁰ K (FractionRing R)))
 #align class_group.mk ClassGroup.mk
+-/
 
+#print ClassGroup.mk_eq_mk /-
 theorem ClassGroup.mk_eq_mk {I J : (FractionalIdeal R⁰ <| FractionRing R)ˣ} :
     ClassGroup.mk I = ClassGroup.mk J ↔
       ∃ x : (FractionRing R)ˣ, I * toPrincipalIdeal R (FractionRing R) x = J :=
@@ -125,7 +138,9 @@ theorem ClassGroup.mk_eq_mk {I J : (FractionalIdeal R⁰ <| FractionRing R)ˣ} :
   erw [QuotientGroup.mk'_eq_mk', canonical_equiv_self, Units.map_id, Set.exists_range_iff]
   rfl
 #align class_group.mk_eq_mk ClassGroup.mk_eq_mk
+-/
 
+#print ClassGroup.mk_eq_mk_of_coe_ideal /-
 theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| FractionRing R)ˣ}
     {I' J' : Ideal R} (hI : (I : FractionalIdeal R⁰ <| FractionRing R) = I')
     (hJ : (J : FractionalIdeal R⁰ <| FractionRing R) = J') :
@@ -145,7 +160,9 @@ theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| Fractio
     apply (Ne.isUnit _).unit_spec
     rwa [Ne, mk'_eq_zero_iff_eq_zero]
 #align class_group.mk_eq_mk_of_coe_ideal ClassGroup.mk_eq_mk_of_coe_ideal
+-/
 
+#print ClassGroup.mk_eq_one_of_coe_ideal /-
 theorem ClassGroup.mk_eq_one_of_coe_ideal {I : (FractionalIdeal R⁰ <| FractionRing R)ˣ}
     {I' : Ideal R} (hI : (I : FractionalIdeal R⁰ <| FractionRing R) = I') :
     ClassGroup.mk I = 1 ↔ ∃ x : R, x ≠ 0 ∧ I' = Ideal.span {x} :=
@@ -162,9 +179,11 @@ theorem ClassGroup.mk_eq_one_of_coe_ideal {I : (FractionalIdeal R⁰ <| Fraction
   · rintro ⟨x, hx, rfl⟩
     exact ⟨1, x, one_ne_zero, hx, by rw [Ideal.span_singleton_one, Ideal.top_mul, Ideal.mul_top]⟩
 #align class_group.mk_eq_one_of_coe_ideal ClassGroup.mk_eq_one_of_coe_ideal
+-/
 
 variable (K)
 
+#print ClassGroup.induction /-
 /-- Induction principle for the class group: to show something holds for all `x : class_group R`,
 we can choose a fraction field `K` and show it holds for the equivalence class of each
 `I : fractional_ideal R⁰ K`. -/
@@ -178,7 +197,9 @@ theorem ClassGroup.induction {P : ClassGroup R → Prop}
     rw [Units.coe_map, Units.coe_mapEquiv]
     exact (canonical_equiv_flip R⁰ K (FractionRing R) I).symm
 #align class_group.induction ClassGroup.induction
+-/
 
+#print ClassGroup.equiv /-
 /-- The definition of the class group does not depend on the choice of field of fractions. -/
 noncomputable def ClassGroup.equiv :
     ClassGroup R ≃* (FractionalIdeal R⁰ K)ˣ ⧸ (toPrincipalIdeal R K).range :=
@@ -202,7 +223,9 @@ noncomputable def ClassGroup.equiv :
         rfl
       simp only [RingEquiv.coe_toMulEquiv, canonical_equiv_flip, Units.coe_mapEquiv]
 #align class_group.equiv ClassGroup.equiv
+-/
 
+#print ClassGroup.equiv_mk /-
 @[simp]
 theorem ClassGroup.equiv_mk (K' : Type _) [Field K'] [Algebra R K'] [IsFractionRing R K']
     (I : (FractionalIdeal R⁰ K)ˣ) :
@@ -215,7 +238,9 @@ theorem ClassGroup.equiv_mk (K' : Type _) [Field K'] [Algebra R K'] [IsFractionR
   rw [Units.coe_mapEquiv, Units.coe_mapEquiv, Units.coe_map]
   exact FractionalIdeal.canonicalEquiv_canonicalEquiv _ _ _ _ _
 #align class_group.equiv_mk ClassGroup.equiv_mk
+-/
 
+#print ClassGroup.mk_canonicalEquiv /-
 @[simp]
 theorem ClassGroup.mk_canonicalEquiv (K' : Type _) [Field K'] [Algebra R K'] [IsFractionRing R K']
     (I : (FractionalIdeal R⁰ K)ˣ) :
@@ -226,7 +251,9 @@ theorem ClassGroup.mk_canonicalEquiv (K' : Type _) [Field K'] [Algebra R K'] [Is
       RingEquiv.coe_monoidHom_trans, FractionalIdeal.canonicalEquiv_trans_canonicalEquiv] <;>
     rfl
 #align class_group.mk_canonical_equiv ClassGroup.mk_canonicalEquiv
+-/
 
+#print FractionalIdeal.mk0 /-
 /-- Send a nonzero integral ideal to an invertible fractional ideal. -/
 noncomputable def FractionalIdeal.mk0 [IsDedekindDomain R] : (Ideal R)⁰ →* (FractionalIdeal R⁰ K)ˣ
     where
@@ -234,19 +261,25 @@ noncomputable def FractionalIdeal.mk0 [IsDedekindDomain R] : (Ideal R)⁰ →* (
   map_one' := by simp
   map_mul' x y := by simp
 #align fractional_ideal.mk0 FractionalIdeal.mk0
+-/
 
+#print FractionalIdeal.coe_mk0 /-
 @[simp]
 theorem FractionalIdeal.coe_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
     (FractionalIdeal.mk0 K I : FractionalIdeal R⁰ K) = I :=
   rfl
 #align fractional_ideal.coe_mk0 FractionalIdeal.coe_mk0
+-/
 
+#print FractionalIdeal.canonicalEquiv_mk0 /-
 theorem FractionalIdeal.canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type _) [Field K']
     [Algebra R K'] [IsFractionRing R K'] (I : (Ideal R)⁰) :
     FractionalIdeal.canonicalEquiv R⁰ K K' (FractionalIdeal.mk0 K I) = FractionalIdeal.mk0 K' I :=
   by simp only [FractionalIdeal.coe_mk0, coe_coe, FractionalIdeal.canonicalEquiv_coeIdeal]
 #align fractional_ideal.canonical_equiv_mk0 FractionalIdeal.canonicalEquiv_mk0
+-/
 
+#print FractionalIdeal.map_canonicalEquiv_mk0 /-
 @[simp]
 theorem FractionalIdeal.map_canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type _) [Field K']
     [Algebra R K'] [IsFractionRing R K'] (I : (Ideal R)⁰) :
@@ -254,19 +287,25 @@ theorem FractionalIdeal.map_canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type _
       FractionalIdeal.mk0 K' I :=
   Units.ext (FractionalIdeal.canonicalEquiv_mk0 K K' I)
 #align fractional_ideal.map_canonical_equiv_mk0 FractionalIdeal.map_canonicalEquiv_mk0
+-/
 
+#print ClassGroup.mk0 /-
 /-- Send a nonzero ideal to the corresponding class in the class group. -/
 noncomputable def ClassGroup.mk0 [IsDedekindDomain R] : (Ideal R)⁰ →* ClassGroup R :=
   ClassGroup.mk.comp (FractionalIdeal.mk0 (FractionRing R))
 #align class_group.mk0 ClassGroup.mk0
+-/
 
+#print ClassGroup.mk_mk0 /-
 @[simp]
 theorem ClassGroup.mk_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
     ClassGroup.mk (FractionalIdeal.mk0 K I) = ClassGroup.mk0 I := by
   rw [ClassGroup.mk0, MonoidHom.comp_apply, ← ClassGroup.mk_canonicalEquiv K (FractionRing R),
     FractionalIdeal.map_canonicalEquiv_mk0]
 #align class_group.mk_mk0 ClassGroup.mk_mk0
+-/
 
+#print ClassGroup.equiv_mk0 /-
 @[simp]
 theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
     ClassGroup.equiv K (ClassGroup.mk0 I) =
@@ -277,8 +316,10 @@ theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
   ext
   simp
 #align class_group.equiv_mk0 ClassGroup.equiv_mk0
+-/
 
 /- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
+#print ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring /-
 theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _) (_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
   by
@@ -294,9 +335,11 @@ theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J
     refine' ⟨Units.mk0 _ (span_singleton_ne_zero_iff.mpr hx), ⟨x, rfl⟩, _⟩
     simpa only [mul_comm] using eq_J
 #align class_group.mk0_eq_mk0_iff_exists_fraction_ring ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring
+-/
 
 variable {K}
 
+#print ClassGroup.mk0_eq_mk0_iff /-
 theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔
       ∃ (x y : R) (hx : x ≠ 0) (hy : y ≠ 0), Ideal.span {x} * (I : Ideal R) = Ideal.span {y} * J :=
@@ -316,7 +359,9 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
         (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx 
     · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy').mpr h
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
+-/
 
+#print ClassGroup.mk0_surjective /-
 theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
     Function.Surjective (ClassGroup.mk0 : (Ideal R)⁰ → ClassGroup R) :=
   by
@@ -363,7 +408,9 @@ theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
       show (algebraMap R _ a)⁻¹ * algebraMap R _ y ∈ (I : FractionalIdeal R⁰ (FractionRing R))
       rwa [hy, Algebra.smul_def, ← mul_assoc, inv_mul_cancel fa_ne_zero, one_mul]
 #align class_group.mk0_surjective ClassGroup.mk0_surjective
+-/
 
+#print ClassGroup.mk_eq_one_iff /-
 theorem ClassGroup.mk_eq_one_iff {I : (FractionalIdeal R⁰ K)ˣ} :
     ClassGroup.mk I = 1 ↔ (I : Submodule R K).IsPrincipal :=
   by
@@ -380,11 +427,14 @@ theorem ClassGroup.mk_eq_one_iff {I : (FractionalIdeal R⁰ K)ˣ} :
   · intro x_eq; apply Units.ne_zero I; simp [hx', x_eq]
   simp [hx']
 #align class_group.mk_eq_one_iff ClassGroup.mk_eq_one_iff
+-/
 
+#print ClassGroup.mk0_eq_one_iff /-
 theorem ClassGroup.mk0_eq_one_iff [IsDedekindDomain R] {I : Ideal R} (hI : I ∈ (Ideal R)⁰) :
     ClassGroup.mk0 ⟨I, hI⟩ = 1 ↔ I.IsPrincipal :=
   ClassGroup.mk_eq_one_iff.trans (coeSubmodule_isPrincipal R _)
 #align class_group.mk0_eq_one_iff ClassGroup.mk0_eq_one_iff
+-/
 
 /-- The class group of principal ideal domain is finite (in fact a singleton).
 
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Anne Baanen
 
 ! This file was ported from Lean 3 source module ring_theory.class_group
-! leanprover-community/mathlib commit 565eb991e264d0db702722b4bde52ee5173c9950
+! leanprover-community/mathlib commit 7e5137f579de09a059a5ce98f364a04e221aabf0
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -14,6 +14,9 @@ import Mathbin.RingTheory.DedekindDomain.Ideal
 /-!
 # The ideal class group
 
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
 This file defines the ideal class group `class_group R` of fractional ideals of `R`
 inside its field of fractions.
 
Diff
@@ -275,7 +275,7 @@ theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
   simp
 #align class_group.equiv_mk0 ClassGroup.equiv_mk0
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
 theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _) (_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
   by
Diff
@@ -95,12 +95,14 @@ end
 
 variable (R) [IsDomain R]
 
+#print ClassGroup /-
 /-- The ideal class group of `R` is the group of invertible fractional ideals
 modulo the principal ideals. -/
 def ClassGroup :=
   (FractionalIdeal R⁰ (FractionRing R))ˣ ⧸ (toPrincipalIdeal R (FractionRing R)).range
 deriving CommGroup
 #align class_group ClassGroup
+-/
 
 noncomputable instance : Inhabited (ClassGroup R) :=
   ⟨1⟩
@@ -394,6 +396,7 @@ noncomputable instance [IsPrincipalIdealRing R] : Fintype (ClassGroup R)
     rw [Finset.mem_singleton]
     exact class_group.mk_eq_one_iff.mpr (I : FractionalIdeal R⁰ (FractionRing R)).IsPrincipal
 
+#print card_classGroup_eq_one /-
 /-- The class number of a principal ideal domain is `1`. -/
 theorem card_classGroup_eq_one [IsPrincipalIdealRing R] : Fintype.card (ClassGroup R) = 1 :=
   by
@@ -402,7 +405,9 @@ theorem card_classGroup_eq_one [IsPrincipalIdealRing R] : Fintype.card (ClassGro
   refine' ClassGroup.induction (FractionRing R) fun I => _
   exact class_group.mk_eq_one_iff.mpr (I : FractionalIdeal R⁰ (FractionRing R)).IsPrincipal
 #align card_class_group_eq_one card_classGroup_eq_one
+-/
 
+#print card_classGroup_eq_one_iff /-
 /-- The class number is `1` iff the ring of integers is a principal ideal domain. -/
 theorem card_classGroup_eq_one_iff [IsDedekindDomain R] [Fintype (ClassGroup R)] :
     Fintype.card (ClassGroup R) = 1 ↔ IsPrincipalIdealRing R :=
@@ -416,4 +421,5 @@ theorem card_classGroup_eq_one_iff [IsDedekindDomain R] [Fintype (ClassGroup R)]
   · rw [hI]; exact bot_isPrincipal
   exact (ClassGroup.mk0_eq_one_iff (mem_non_zero_divisors_iff_ne_zero.mpr hI)).mp (eq_one _)
 #align card_class_group_eq_one_iff card_classGroup_eq_one_iff
+-/
 
Diff
@@ -135,8 +135,8 @@ theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| Fractio
     exact ⟨_, _, sec_fst_ne_zero le_rfl x.ne_zero, sec_snd_ne_zero le_rfl ↑x, hJ⟩
   · rintro ⟨x, y, hx, hy, h⟩
     constructor; rw [mul_comm, ← Units.eq_iff, Units.val_mul, coe_toPrincipalIdeal]
-    convert(mk'_mul_coe_ideal_eq_coe_ideal (FractionRing R) <| mem_nonZeroDivisors_of_ne_zero hy).2
-        h
+    convert
+      (mk'_mul_coe_ideal_eq_coe_ideal (FractionRing R) <| mem_nonZeroDivisors_of_ne_zero hy).2 h
     apply (Ne.isUnit _).unit_spec
     rwa [Ne, mk'_eq_zero_iff_eq_zero]
 #align class_group.mk_eq_mk_of_coe_ideal ClassGroup.mk_eq_mk_of_coe_ideal
@@ -320,7 +320,7 @@ theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
   have a_ne_zero := mem_non_zero_divisors_iff_ne_zero.mp a_ne_zero'
   have fa_ne_zero : (algebraMap R (FractionRing R)) a ≠ 0 :=
     IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors a_ne_zero'
-  refine' ⟨⟨{ carrier := { x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1 } .. }, _⟩, _⟩
+  refine' ⟨⟨{ carrier := {x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1} .. }, _⟩, _⟩
   · simp only [RingHom.map_add, Set.mem_setOf_eq, MulZeroClass.mul_zero, RingHom.map_mul, mul_add]
     exact fun _ _ ha hb => Submodule.add_mem I ha hb
   · simp only [RingHom.map_zero, Set.mem_setOf_eq, MulZeroClass.mul_zero, RingHom.map_mul]
Diff
@@ -98,8 +98,8 @@ variable (R) [IsDomain R]
 /-- The ideal class group of `R` is the group of invertible fractional ideals
 modulo the principal ideals. -/
 def ClassGroup :=
-  (FractionalIdeal R⁰ (FractionRing R))ˣ ⧸ (toPrincipalIdeal R (FractionRing R)).range deriving
-  CommGroup
+  (FractionalIdeal R⁰ (FractionRing R))ˣ ⧸ (toPrincipalIdeal R (FractionRing R)).range
+deriving CommGroup
 #align class_group ClassGroup
 
 noncomputable instance : Inhabited (ClassGroup R) :=
@@ -131,7 +131,7 @@ theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| Fractio
   constructor
   · rintro ⟨x, rfl⟩
     rw [Units.val_mul, hI, coe_toPrincipalIdeal, mul_comm,
-      span_singleton_mul_coe_ideal_eq_coe_ideal] at hJ
+      span_singleton_mul_coe_ideal_eq_coe_ideal] at hJ 
     exact ⟨_, _, sec_fst_ne_zero le_rfl x.ne_zero, sec_snd_ne_zero le_rfl ↑x, hJ⟩
   · rintro ⟨x, y, hx, hy, h⟩
     constructor; rw [mul_comm, ← Units.eq_iff, Units.val_mul, coe_toPrincipalIdeal]
@@ -149,10 +149,10 @@ theorem ClassGroup.mk_eq_one_of_coe_ideal {I : (FractionalIdeal R⁰ <| Fraction
   any_goals rfl
   constructor
   · rintro ⟨x, y, hx, hy, h⟩
-    rw [Ideal.mul_top] at h
+    rw [Ideal.mul_top] at h 
     rcases ideal.mem_span_singleton_mul.mp ((Ideal.span_singleton_le_iff_mem _).mp h.ge) with
       ⟨i, hi, rfl⟩
-    rw [← Ideal.span_singleton_mul_span_singleton, Ideal.span_singleton_mul_right_inj hx] at h
+    rw [← Ideal.span_singleton_mul_span_singleton, Ideal.span_singleton_mul_right_inj hx] at h 
     exact ⟨i, right_ne_zero_of_mul hy, h⟩
   · rintro ⟨x, hx, rfl⟩
     exact ⟨1, x, one_ne_zero, hx, by rw [Ideal.span_singleton_one, Ideal.top_mul, Ideal.mul_top]⟩
@@ -275,7 +275,7 @@ theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
 
 /- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
 theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J : (Ideal R)⁰} :
-    ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _)(_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
+    ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _) (_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
   by
   refine' (ClassGroup.equiv K).Injective.eq_iff.symm.trans _
   simp only [ClassGroup.equiv_mk0, QuotientGroup.mk'_eq_mk', mem_principal_ideals_iff, coe_coe,
@@ -294,7 +294,7 @@ variable {K}
 
 theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔
-      ∃ (x y : R)(hx : x ≠ 0)(hy : y ≠ 0), Ideal.span {x} * (I : Ideal R) = Ideal.span {y} * J :=
+      ∃ (x y : R) (hx : x ≠ 0) (hy : y ≠ 0), Ideal.span {x} * (I : Ideal R) = Ideal.span {y} * J :=
   by
   refine' (ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring (FractionRing R)).trans ⟨_, _⟩
   · rintro ⟨z, hz, h⟩
@@ -308,7 +308,7 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     refine' ⟨IsLocalization.mk' _ x ⟨y, hy'⟩, _, _⟩
     · contrapose! hx
       rwa [mk'_eq_iff_eq_mul, MulZeroClass.zero_mul, ← (algebraMap R (FractionRing R)).map_zero,
-        (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx
+        (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx 
     · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy').mpr h
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
 
@@ -320,7 +320,7 @@ theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
   have a_ne_zero := mem_non_zero_divisors_iff_ne_zero.mp a_ne_zero'
   have fa_ne_zero : (algebraMap R (FractionRing R)) a ≠ 0 :=
     IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors a_ne_zero'
-  refine' ⟨⟨{ carrier := { x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1 }.. }, _⟩, _⟩
+  refine' ⟨⟨{ carrier := { x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1 } .. }, _⟩, _⟩
   · simp only [RingHom.map_add, Set.mem_setOf_eq, MulZeroClass.mul_zero, RingHom.map_mul, mul_add]
     exact fun _ _ ha hb => Submodule.add_mem I ha hb
   · simp only [RingHom.map_zero, Set.mem_setOf_eq, MulZeroClass.mul_zero, RingHom.map_mul]
@@ -407,7 +407,7 @@ theorem card_classGroup_eq_one [IsPrincipalIdealRing R] : Fintype.card (ClassGro
 theorem card_classGroup_eq_one_iff [IsDedekindDomain R] [Fintype (ClassGroup R)] :
     Fintype.card (ClassGroup R) = 1 ↔ IsPrincipalIdealRing R :=
   by
-  constructor; swap; · intros ; convert card_classGroup_eq_one; assumption
+  constructor; swap; · intros; convert card_classGroup_eq_one; assumption
   rw [Fintype.card_eq_one_iff]
   rintro ⟨I, hI⟩
   have eq_one : ∀ J : ClassGroup R, J = 1 := fun J => trans (hI J) (hI 1).symm
Diff
@@ -342,7 +342,7 @@ theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
     refine' ⟨Units.mk0 (algebraMap R _ a) fa_ne_zero, _⟩
     rw [_root_.eq_inv_mul_iff_mul_eq, eq_comm, mul_comm I]
     apply Units.ext
-    simp only [FractionalIdeal.coe_mk0, FractionalIdeal.map_canonicalEquiv_mk0, [anonymous],
+    simp only [FractionalIdeal.coe_mk0, FractionalIdeal.map_canonicalEquiv_mk0, SetLike.coe_mk,
       Units.val_mk0, coe_toPrincipalIdeal, coe_coe, Units.val_mul,
       FractionalIdeal.eq_spanSingleton_mul]
     constructor
Diff
@@ -43,7 +43,7 @@ variable [Algebra K L] [FiniteDimensional K L]
 
 variable [Algebra R L] [IsScalarTower R K L]
 
-open nonZeroDivisors
+open scoped nonZeroDivisors
 
 open IsLocalization IsFractionRing FractionalIdeal Units
 
Diff
@@ -66,17 +66,13 @@ variable {R K}
 
 @[simp]
 theorem coe_toPrincipalIdeal (x : Kˣ) :
-    (toPrincipalIdeal R K x : FractionalIdeal R⁰ K) = spanSingleton _ x :=
-  by
-  simp only [toPrincipalIdeal]
-  rfl
+    (toPrincipalIdeal R K x : FractionalIdeal R⁰ K) = spanSingleton _ x := by
+  simp only [toPrincipalIdeal]; rfl
 #align coe_to_principal_ideal coe_toPrincipalIdeal
 
 @[simp]
 theorem toPrincipalIdeal_eq_iff {I : (FractionalIdeal R⁰ K)ˣ} {x : Kˣ} :
-    toPrincipalIdeal R K x = I ↔ spanSingleton R⁰ (x : K) = I :=
-  by
-  simp only [toPrincipalIdeal]
+    toPrincipalIdeal R K x = I ↔ spanSingleton R⁰ (x : K) = I := by simp only [toPrincipalIdeal];
   exact Units.ext_iff
 #align to_principal_ideal_eq_iff toPrincipalIdeal_eq_iff
 
@@ -138,8 +134,7 @@ theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| Fractio
       span_singleton_mul_coe_ideal_eq_coe_ideal] at hJ
     exact ⟨_, _, sec_fst_ne_zero le_rfl x.ne_zero, sec_snd_ne_zero le_rfl ↑x, hJ⟩
   · rintro ⟨x, y, hx, hy, h⟩
-    constructor
-    rw [mul_comm, ← Units.eq_iff, Units.val_mul, coe_toPrincipalIdeal]
+    constructor; rw [mul_comm, ← Units.eq_iff, Units.val_mul, coe_toPrincipalIdeal]
     convert(mk'_mul_coe_ideal_eq_coe_ideal (FractionRing R) <| mem_nonZeroDivisors_of_ne_zero hy).2
         h
     apply (Ne.isUnit _).unit_spec
@@ -288,8 +283,7 @@ theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J
   constructor
   · rintro ⟨X, ⟨x, hX⟩, hx⟩
     refine' ⟨x, _, _⟩
-    · rintro rfl
-      simpa [X.ne_zero.symm] using hX
+    · rintro rfl; simpa [X.ne_zero.symm] using hX
     simpa only [hX, mul_comm] using hx
   · rintro ⟨x, hx, eq_J⟩
     refine' ⟨Units.mk0 _ (span_singleton_ne_zero_iff.mpr hx), ⟨x, rfl⟩, _⟩
@@ -306,8 +300,7 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
   · rintro ⟨z, hz, h⟩
     obtain ⟨x, ⟨y, hy⟩, rfl⟩ := IsLocalization.mk'_surjective R⁰ z
     refine' ⟨x, y, _, mem_non_zero_divisors_iff_ne_zero.mp hy, _⟩
-    · rintro hx
-      apply hz
+    · rintro hx; apply hz
       rw [hx, IsFractionRing.mk'_eq_div, _root_.map_zero, zero_div]
     · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy).mp h
   · rintro ⟨x, y, hx, hy, h⟩
@@ -376,14 +369,10 @@ theorem ClassGroup.mk_eq_one_iff {I : (FractionalIdeal R⁰ K)ˣ} :
   refine' ⟨fun ⟨x, hx⟩ => ⟨⟨x, by rw [← hx, coe_span_singleton]⟩⟩, _⟩
   intro hI
   obtain ⟨x, hx⟩ := @Submodule.IsPrincipal.principal _ _ _ _ _ _ hI
-  have hx' : (I : FractionalIdeal R⁰ K) = span_singleton R⁰ x :=
-    by
-    apply Subtype.coe_injective
+  have hx' : (I : FractionalIdeal R⁰ K) = span_singleton R⁰ x := by apply Subtype.coe_injective;
     rw [hx, coe_span_singleton]
   refine' ⟨Units.mk0 x _, _⟩
-  · intro x_eq
-    apply Units.ne_zero I
-    simp [hx', x_eq]
+  · intro x_eq; apply Units.ne_zero I; simp [hx', x_eq]
   simp [hx']
 #align class_group.mk_eq_one_iff ClassGroup.mk_eq_one_iff
 
@@ -418,17 +407,13 @@ theorem card_classGroup_eq_one [IsPrincipalIdealRing R] : Fintype.card (ClassGro
 theorem card_classGroup_eq_one_iff [IsDedekindDomain R] [Fintype (ClassGroup R)] :
     Fintype.card (ClassGroup R) = 1 ↔ IsPrincipalIdealRing R :=
   by
-  constructor; swap;
-  · intros
-    convert card_classGroup_eq_one
-    assumption
+  constructor; swap; · intros ; convert card_classGroup_eq_one; assumption
   rw [Fintype.card_eq_one_iff]
   rintro ⟨I, hI⟩
   have eq_one : ∀ J : ClassGroup R, J = 1 := fun J => trans (hI J) (hI 1).symm
   refine' ⟨fun I => _⟩
   by_cases hI : I = ⊥
-  · rw [hI]
-    exact bot_isPrincipal
+  · rw [hI]; exact bot_isPrincipal
   exact (ClassGroup.mk0_eq_one_iff (mem_non_zero_divisors_iff_ne_zero.mpr hI)).mp (eq_one _)
 #align card_class_group_eq_one_iff card_classGroup_eq_one_iff
 
Diff
@@ -230,7 +230,7 @@ theorem ClassGroup.mk_canonicalEquiv (K' : Type _) [Field K'] [Algebra R K'] [Is
 /-- Send a nonzero integral ideal to an invertible fractional ideal. -/
 noncomputable def FractionalIdeal.mk0 [IsDedekindDomain R] : (Ideal R)⁰ →* (FractionalIdeal R⁰ K)ˣ
     where
-  toFun I := Units.mk0 I (coe_ideal_ne_zero.mpr <| mem_nonZeroDivisors_iff_ne_zero.mp I.2)
+  toFun I := Units.mk0 I (coeIdeal_ne_zero.mpr <| mem_nonZeroDivisors_iff_ne_zero.mp I.2)
   map_one' := by simp
   map_mul' x y := by simp
 #align fractional_ideal.mk0 FractionalIdeal.mk0
@@ -244,7 +244,7 @@ theorem FractionalIdeal.coe_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
 theorem FractionalIdeal.canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type _) [Field K']
     [Algebra R K'] [IsFractionRing R K'] (I : (Ideal R)⁰) :
     FractionalIdeal.canonicalEquiv R⁰ K K' (FractionalIdeal.mk0 K I) = FractionalIdeal.mk0 K' I :=
-  by simp only [FractionalIdeal.coe_mk0, coe_coe, FractionalIdeal.canonicalEquiv_coe_ideal]
+  by simp only [FractionalIdeal.coe_mk0, coe_coe, FractionalIdeal.canonicalEquiv_coeIdeal]
 #align fractional_ideal.canonical_equiv_mk0 FractionalIdeal.canonicalEquiv_mk0
 
 @[simp]
@@ -309,14 +309,14 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     · rintro hx
       apply hz
       rw [hx, IsFractionRing.mk'_eq_div, _root_.map_zero, zero_div]
-    · exact (FractionalIdeal.mk'_mul_coe_ideal_eq_coe_ideal _ hy).mp h
+    · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy).mp h
   · rintro ⟨x, y, hx, hy, h⟩
     have hy' : y ∈ R⁰ := mem_non_zero_divisors_iff_ne_zero.mpr hy
     refine' ⟨IsLocalization.mk' _ x ⟨y, hy'⟩, _, _⟩
     · contrapose! hx
       rwa [mk'_eq_iff_eq_mul, MulZeroClass.zero_mul, ← (algebraMap R (FractionRing R)).map_zero,
         (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx
-    · exact (FractionalIdeal.mk'_mul_coe_ideal_eq_coe_ideal _ hy').mpr h
+    · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy').mpr h
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
 
 theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
Diff
@@ -140,8 +140,8 @@ theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| Fractio
   · rintro ⟨x, y, hx, hy, h⟩
     constructor
     rw [mul_comm, ← Units.eq_iff, Units.val_mul, coe_toPrincipalIdeal]
-    convert
-      (mk'_mul_coe_ideal_eq_coe_ideal (FractionRing R) <| mem_nonZeroDivisors_of_ne_zero hy).2 h
+    convert(mk'_mul_coe_ideal_eq_coe_ideal (FractionRing R) <| mem_nonZeroDivisors_of_ne_zero hy).2
+        h
     apply (Ne.isUnit _).unit_spec
     rwa [Ne, mk'_eq_zero_iff_eq_zero]
 #align class_group.mk_eq_mk_of_coe_ideal ClassGroup.mk_eq_mk_of_coe_ideal
Diff
@@ -314,7 +314,7 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     have hy' : y ∈ R⁰ := mem_non_zero_divisors_iff_ne_zero.mpr hy
     refine' ⟨IsLocalization.mk' _ x ⟨y, hy'⟩, _, _⟩
     · contrapose! hx
-      rwa [mk'_eq_iff_eq_mul, zero_mul, ← (algebraMap R (FractionRing R)).map_zero,
+      rwa [mk'_eq_iff_eq_mul, MulZeroClass.zero_mul, ← (algebraMap R (FractionRing R)).map_zero,
         (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx
     · exact (FractionalIdeal.mk'_mul_coe_ideal_eq_coe_ideal _ hy').mpr h
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
@@ -328,12 +328,12 @@ theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
   have fa_ne_zero : (algebraMap R (FractionRing R)) a ≠ 0 :=
     IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors a_ne_zero'
   refine' ⟨⟨{ carrier := { x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1 }.. }, _⟩, _⟩
-  · simp only [RingHom.map_add, Set.mem_setOf_eq, mul_zero, RingHom.map_mul, mul_add]
+  · simp only [RingHom.map_add, Set.mem_setOf_eq, MulZeroClass.mul_zero, RingHom.map_mul, mul_add]
     exact fun _ _ ha hb => Submodule.add_mem I ha hb
-  · simp only [RingHom.map_zero, Set.mem_setOf_eq, mul_zero, RingHom.map_mul]
+  · simp only [RingHom.map_zero, Set.mem_setOf_eq, MulZeroClass.mul_zero, RingHom.map_mul]
     exact Submodule.zero_mem I
   · intro c _ hb
-    simp only [smul_eq_mul, Set.mem_setOf_eq, mul_zero, RingHom.map_mul, mul_add,
+    simp only [smul_eq_mul, Set.mem_setOf_eq, MulZeroClass.mul_zero, RingHom.map_mul, mul_add,
       mul_left_comm ((algebraMap R (FractionRing R)) a)⁻¹]
     rw [← Algebra.smul_def c]
     exact Submodule.smul_mem I c hb
Diff
@@ -278,7 +278,7 @@ theorem ClassGroup.equiv_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
   simp
 #align class_group.equiv_mk0 ClassGroup.equiv_mk0
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (x «expr ≠ » (0 : K)) -/
 theorem ClassGroup.mk0_eq_mk0_iff_exists_fraction_ring [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     ClassGroup.mk0 I = ClassGroup.mk0 J ↔ ∃ (x : _)(_ : x ≠ (0 : K)), spanSingleton R⁰ x * I = J :=
   by

Changes in mathlib4

mathlib3
mathlib4
chore(*): remove empty lines between variable statements (#11418)

Empty lines were removed by executing the following Python script twice

import os
import re


# Loop through each file in the repository
for dir_path, dirs, files in os.walk('.'):
  for filename in files:
    if filename.endswith('.lean'):
      file_path = os.path.join(dir_path, filename)

      # Open the file and read its contents
      with open(file_path, 'r') as file:
        content = file.read()

      # Use a regular expression to replace sequences of "variable" lines separated by empty lines
      # with sequences without empty lines
      modified_content = re.sub(r'(variable.*\n)\n(variable(?! .* in))', r'\1\2', content)

      # Write the modified content back to the file
      with open(file_path, 'w') as file:
        file.write(modified_content)
Diff
@@ -31,13 +31,9 @@ identical no matter the choice of field of fractions for `R`.
 
 
 variable {R K L : Type*} [CommRing R]
-
 variable [Field K] [Field L] [DecidableEq L]
-
 variable [Algebra R K] [IsFractionRing R K]
-
 variable [Algebra K L] [FiniteDimensional K L]
-
 variable [Algebra R L] [IsScalarTower R K L]
 
 open scoped nonZeroDivisors
@@ -90,7 +86,6 @@ instance PrincipalIdeals.normal : (toPrincipalIdeal R K).range.Normal :=
 end
 
 variable (R)
-
 variable [IsDomain R]
 
 /-- The ideal class group of `R` is the group of invertible fractional ideals
chore: remove terminal, terminal refines (#10762)

I replaced a few "terminal" refine/refine's with exact.

The strategy was very simple-minded: essentially any refine whose following line had smaller indentation got replaced by exact and then I cleaned up the mess.

This PR certainly leaves some further terminal refines, but maybe the current change is beneficial.

Diff
@@ -335,7 +335,7 @@ theorem ClassGroup.mk0_integralRep [IsDedekindDomain R]
       = ClassGroup.mk I := by
   rw [← ClassGroup.mk_mk0 (FractionRing R), eq_comm, ClassGroup.mk_eq_mk]
   have fd_ne_zero : (algebraMap R (FractionRing R)) I.1.den ≠ 0 := by
-    refine IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors (SetLike.coe_mem _)
+    exact IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors (SetLike.coe_mem _)
   refine ⟨Units.mk0 (algebraMap R _ I.1.den) fd_ne_zero, ?_⟩
   apply Units.ext
   rw [mul_comm, val_mul, coe_toPrincipalIdeal, val_mk0]
chore: Golf some proofs in ClassGroup using FractionalIdeal.num and FractionalIdeal.den (#9853)
Diff
@@ -321,70 +321,25 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
 
 /-- Maps a nonzero fractional ideal to an integral representative in the class group. -/
-noncomputable def ClassGroup.integralRep
-    (I : FractionalIdeal R⁰ (FractionRing R)) :
-    Ideal R :=
-  let a := I.2.choose
-  { carrier := {x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1}
-    add_mem' := by
-      simp only [Set.mem_setOf_eq, RingHom.map_add, mul_add]
-      exact fun ha hb => Submodule.add_mem _ ha hb
-    zero_mem' := by
-      simp only [Set.mem_setOf_eq, RingHom.map_zero, mul_zero]
-      exact Submodule.zero_mem _
-    smul_mem' := by
-      intro c _ hb
-      simp only [smul_eq_mul, Set.mem_setOf_eq, RingHom.map_mul,
-        mul_left_comm ((algebraMap R (FractionRing R)) a)⁻¹]
-      rw [← Algebra.smul_def c]
-      exact Submodule.smul_mem _ c hb }
+noncomputable def ClassGroup.integralRep (I : FractionalIdeal R⁰ (FractionRing R)) :
+    Ideal R := I.num
 
 theorem ClassGroup.integralRep_mem_nonZeroDivisors
-    {I} (hI : I ≠ 0) :
-    ClassGroup.integralRep I ∈ (Ideal R)⁰ := by
-  let a := I.2.choose
-  have a_ne_zero' := I.2.choose_spec.1
-  have a_ne_zero := mem_nonZeroDivisors_iff_ne_zero.mp a_ne_zero'
-  have fa_ne_zero : (algebraMap R (FractionRing R)) a ≠ 0 :=
-    IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors a_ne_zero'
-  rw [mem_nonZeroDivisors_iff_ne_zero, Submodule.zero_eq_bot, Submodule.ne_bot_iff]
-  obtain ⟨x, x_ne, x_mem⟩ := exists_ne_zero_mem_isInteger hI
-  refine ⟨a*x, ?_, mul_ne_zero a_ne_zero x_ne⟩
-  change ((algebraMap R _) a)⁻¹ * (algebraMap R _) (a * x) ∈ I
-  rwa [RingHom.map_mul, ← mul_assoc, inv_mul_cancel fa_ne_zero, one_mul]
+    {I : FractionalIdeal R⁰ (FractionRing R)} (hI : I ≠ 0) :
+    I.num ∈ (Ideal R)⁰ := by
+  rwa [mem_nonZeroDivisors_iff_ne_zero, ne_eq, FractionalIdeal.num_eq_zero_iff]
 
 theorem ClassGroup.mk0_integralRep [IsDedekindDomain R]
     (I : (FractionalIdeal R⁰ (FractionRing R))ˣ) :
     ClassGroup.mk0 ⟨ClassGroup.integralRep I, ClassGroup.integralRep_mem_nonZeroDivisors I.ne_zero⟩
       = ClassGroup.mk I := by
-  let a := I.1.2.choose
-  have a_ne_zero' := I.1.2.choose_spec.1
-  have ha := I.1.2.choose_spec.2
-  have fa_ne_zero : (algebraMap R (FractionRing R)) a ≠ 0 :=
-    IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors a_ne_zero'
-  symm
-  apply Quotient.sound
-  change @Setoid.r _
-    (QuotientGroup.leftRel (toPrincipalIdeal R (FractionRing R)).range) _ _
-  rw [canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id, MonoidHom.id_apply,
-      MonoidHom.id_apply, QuotientGroup.leftRel_apply]
-  refine ⟨Units.mk0 (algebraMap R _ a) fa_ne_zero, ?_⟩
-  rw [_root_.eq_inv_mul_iff_mul_eq, eq_comm, mul_comm I]
+  rw [← ClassGroup.mk_mk0 (FractionRing R), eq_comm, ClassGroup.mk_eq_mk]
+  have fd_ne_zero : (algebraMap R (FractionRing R)) I.1.den ≠ 0 := by
+    refine IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors (SetLike.coe_mem _)
+  refine ⟨Units.mk0 (algebraMap R _ I.1.den) fd_ne_zero, ?_⟩
   apply Units.ext
-  simp only [FractionalIdeal.coe_mk0, FractionalIdeal.map_canonicalEquiv_mk0,
-    Units.val_mk0, coe_toPrincipalIdeal, Units.val_mul,
-    FractionalIdeal.eq_spanSingleton_mul]
-  constructor
-  · intro zJ' hzJ'
-    obtain ⟨zJ, hzJ, rfl⟩ := (mem_coeIdeal R⁰).mp hzJ'
-    refine ⟨_, hzJ, ?_⟩
-    rw [← mul_assoc, mul_inv_cancel fa_ne_zero, one_mul]
-  · intro zI' hzI'
-    obtain ⟨y, hy⟩ := ha zI' hzI'
-    rw [← Algebra.smul_def, mem_coeIdeal]
-    refine' ⟨y, _, hy⟩
-    show (algebraMap R _ a)⁻¹ * algebraMap R _ y ∈ (I : FractionalIdeal R⁰ (FractionRing R))
-    rwa [hy, Algebra.smul_def, ← mul_assoc, inv_mul_cancel fa_ne_zero, one_mul]
+  rw [mul_comm, val_mul, coe_toPrincipalIdeal, val_mk0]
+  exact FractionalIdeal.den_mul_self_eq_num' R⁰ (FractionRing R) I
 
 theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
     Function.Surjective (ClassGroup.mk0 : (Ideal R)⁰ → ClassGroup R) := by
feat: Add exists_ideal_in_class_of_norm_le (#9084)

Prove that each class of the classgroup of a number field contains an integral ideal of small norm.

Diff
@@ -415,6 +415,16 @@ theorem ClassGroup.mk0_eq_one_iff [IsDedekindDomain R] {I : Ideal R} (hI : I ∈
   ClassGroup.mk_eq_one_iff.trans (coeSubmodule_isPrincipal R _)
 #align class_group.mk0_eq_one_iff ClassGroup.mk0_eq_one_iff
 
+theorem ClassGroup.mk0_eq_mk0_inv_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
+    ClassGroup.mk0 I = (ClassGroup.mk0 J)⁻¹ ↔
+      ∃ x ≠ (0 : R), I * J = Ideal.span {x} := by
+  rw [eq_inv_iff_mul_eq_one, ← _root_.map_mul, ClassGroup.mk0_eq_one_iff,
+    Submodule.isPrincipal_iff, Submonoid.coe_mul]
+  refine ⟨fun ⟨a, ha⟩ ↦ ⟨a, ?_, ha⟩, fun ⟨a, _, ha⟩ ↦ ⟨a, ha⟩⟩
+  by_contra!
+  rw [this, Submodule.span_zero_singleton] at ha
+  exact nonZeroDivisors.coe_ne_zero _ <| J.prop _ ha
+
 /-- The class group of principal ideal domain is finite (in fact a singleton).
 
 See `ClassGroup.fintypeOfAdmissibleOfFinite` for a finiteness proof that works for rings of integers
chore: uneven spacing for ⟨ ⟩ (#10014)

This cleans up instances of

⟨ foo, bar⟩

and

⟨foo, bar ⟩

where spaces a on the inside one side, but not on the other side. Fixing this by removing the extra space.

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -389,7 +389,7 @@ theorem ClassGroup.mk0_integralRep [IsDedekindDomain R]
 theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
     Function.Surjective (ClassGroup.mk0 : (Ideal R)⁰ → ClassGroup R) := by
   rintro ⟨I⟩
-  refine ⟨⟨ ClassGroup.integralRep I.1, ClassGroup.integralRep_mem_nonZeroDivisors I.ne_zero⟩, ?_⟩
+  refine ⟨⟨ClassGroup.integralRep I.1, ClassGroup.integralRep_mem_nonZeroDivisors I.ne_zero⟩, ?_⟩
   rw [ClassGroup.mk0_integralRep, ClassGroup.Quot_mk_eq_mk]
 #align class_group.mk0_surjective ClassGroup.mk0_surjective
 
refactor(Data/FunLike): use unbundled inheritance from FunLike (#8386)

The FunLike hierarchy is very big and gets scanned through each time we need a coercion (via the CoeFun instance). It looks like unbundled inheritance suits Lean 4 better here. The only class that still extends FunLike is EquivLike, since that has a custom coe_injective' field that is easier to implement. All other classes should take FunLike or EquivLike as a parameter.

Zulip thread

Important changes

Previously, morphism classes would be Type-valued and extend FunLike:

/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
  extends FunLike F A B :=
(map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))

After this PR, they should be Prop-valued and take FunLike as a parameter:

/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
  [FunLike F A B] : Prop :=
(map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))

(Note that A B stay marked as outParam even though they are not purely required to be so due to the FunLike parameter already filling them in. This is required to see through type synonyms, which is important in the category theory library. Also, I think keeping them as outParam is slightly faster.)

Similarly, MyEquivClass should take EquivLike as a parameter.

As a result, every mention of [MyHomClass F A B] should become [FunLike F A B] [MyHomClass F A B].

Remaining issues

Slower (failing) search

While overall this gives some great speedups, there are some cases that are noticeably slower. In particular, a failing application of a lemma such as map_mul is more expensive. This is due to suboptimal processing of arguments. For example:

variable [FunLike F M N] [Mul M] [Mul N] (f : F) (x : M) (y : M)

theorem map_mul [MulHomClass F M N] : f (x * y) = f x * f y

example [AddHomClass F A B] : f (x * y) = f x * f y := map_mul f _ _

Before this PR, applying map_mul f gives the goals [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]. Since M and N are out_params, [MulHomClass F ?M ?N] is synthesized first, supplies values for ?M and ?N and then the Mul M and Mul N instances can be found.

After this PR, the goals become [FunLike F ?M ?N] [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]. Now [FunLike F ?M ?N] is synthesized first, supplies values for ?M and ?N and then the Mul M and Mul N instances can be found, before trying MulHomClass F M N which fails. Since the Mul hierarchy is very big, this can be slow to fail, especially when there is no such Mul instance.

A long-term but harder to achieve solution would be to specify the order in which instance goals get solved. For example, we'd like to change the arguments to map_mul to look like [FunLike F M N] [Mul M] [Mul N] [highPriority <| MulHomClass F M N] because MulHomClass fails or succeeds much faster than the others.

As a consequence, the simpNF linter is much slower since by design it tries and fails to apply many map_ lemmas. The same issue occurs a few times in existing calls to simp [map_mul], where map_mul is tried "too soon" and fails. Thanks to the speedup of leanprover/lean4#2478 the impact is very limited, only in files that already were close to the timeout.

simp not firing sometimes

This affects map_smulₛₗ and related definitions. For simp lemmas Lean apparently uses a slightly different mechanism to find instances, so that rw can find every argument to map_smulₛₗ successfully but simp can't: leanprover/lean4#3701.

Missing instances due to unification failing

Especially in the category theory library, we might sometimes have a type A which is also accessible as a synonym (Bundled A hA).1. Instance synthesis doesn't always work if we have f : A →* B but x * y : (Bundled A hA).1 or vice versa. This seems to be mostly fixed by keeping A B as outParams in MulHomClass F A B. (Presumably because Lean will do a definitional check A =?= (Bundled A hA).1 instead of using the syntax in the discrimination tree.)

Workaround for issues

The timeouts can be worked around for now by specifying which map_mul we mean, either as map_mul f for some explicit f, or as e.g. MonoidHomClass.map_mul.

map_smulₛₗ not firing as simp lemma can be worked around by going back to the pre-FunLike situation and making LinearMap.map_smulₛₗ a simp lemma instead of the generic map_smulₛₗ. Writing simp [map_smulₛₗ _] also works.

Co-authored-by: Matthew Ballard <matt@mrb.email> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Scott Morrison <scott@tqft.net> Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>

Diff
@@ -152,7 +152,7 @@ theorem ClassGroup.mk_eq_mk_of_coe_ideal {I J : (FractionalIdeal R⁰ <| Fractio
 theorem ClassGroup.mk_eq_one_of_coe_ideal {I : (FractionalIdeal R⁰ <| FractionRing R)ˣ}
     {I' : Ideal R} (hI : (I : FractionalIdeal R⁰ <| FractionRing R) = I') :
     ClassGroup.mk I = 1 ↔ ∃ x : R, x ≠ 0 ∧ I' = Ideal.span {x} := by
-  rw [← map_one (ClassGroup.mk (R := R) (K := FractionRing R)),
+  rw [← _root_.map_one (ClassGroup.mk (R := R) (K := FractionRing R)),
     ClassGroup.mk_eq_mk_of_coe_ideal hI (?_ : _ = ↑(⊤ : Ideal R))]
   any_goals rfl
   constructor
Revert "chore: revert #7703 (#7710)"

This reverts commit f3695eb2.

Diff
@@ -115,8 +115,10 @@ noncomputable def ClassGroup.mk : (FractionalIdeal R⁰ K)ˣ →* ClassGroup R :
 -- Can't be `@[simp]` because it can't figure out the quotient relation.
 theorem ClassGroup.Quot_mk_eq_mk (I : (FractionalIdeal R⁰ (FractionRing R))ˣ) :
     Quot.mk _ I = ClassGroup.mk I := by
-  rw [ClassGroup.mk, canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id,
-      MonoidHom.comp_apply, MonoidHom.id_apply, QuotientGroup.mk'_apply]
+  rw [ClassGroup.mk, canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id]
+  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+  erw [MonoidHom.comp_apply]
+  rw [MonoidHom.id_apply, QuotientGroup.mk'_apply]
   rfl
 
 theorem ClassGroup.mk_eq_mk {I J : (FractionalIdeal R⁰ <| FractionRing R)ˣ} :
@@ -213,7 +215,8 @@ theorem ClassGroup.equiv_mk (K' : Type*) [Field K'] [Algebra R K'] [IsFractionRi
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.equiv K' (ClassGroup.mk I) =
       QuotientGroup.mk' _ (Units.mapEquiv (↑(FractionalIdeal.canonicalEquiv R⁰ K K')) I) := by
-  rw [ClassGroup.equiv, ClassGroup.mk, MonoidHom.comp_apply, QuotientGroup.congr_mk']
+  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+  erw [ClassGroup.equiv, ClassGroup.mk, MonoidHom.comp_apply, QuotientGroup.congr_mk']
   congr
   rw [← Units.eq_iff, Units.coe_mapEquiv, Units.coe_mapEquiv, Units.coe_map]
   exact FractionalIdeal.canonicalEquiv_canonicalEquiv _ _ _ _ _
@@ -224,8 +227,10 @@ theorem ClassGroup.mk_canonicalEquiv (K' : Type*) [Field K'] [Algebra R K'] [IsF
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.mk (Units.map (↑(canonicalEquiv R⁰ K K')) I : (FractionalIdeal R⁰ K')ˣ) =
       ClassGroup.mk I := by
-  rw [ClassGroup.mk, MonoidHom.comp_apply, ← MonoidHom.comp_apply (Units.map _), ← Units.map_comp, ←
-      RingEquiv.coe_monoidHom_trans, FractionalIdeal.canonicalEquiv_trans_canonicalEquiv]
+  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+  erw [ClassGroup.mk, MonoidHom.comp_apply, ← MonoidHom.comp_apply (Units.map _),
+      ← Units.map_comp, ← RingEquiv.coe_monoidHom_trans,
+      FractionalIdeal.canonicalEquiv_trans_canonicalEquiv]
   rfl
 #align class_group.mk_canonical_equiv ClassGroup.mk_canonicalEquiv
 
chore: revert #7703 (#7710)

This reverts commit 26eb2b0a.

Diff
@@ -115,10 +115,8 @@ noncomputable def ClassGroup.mk : (FractionalIdeal R⁰ K)ˣ →* ClassGroup R :
 -- Can't be `@[simp]` because it can't figure out the quotient relation.
 theorem ClassGroup.Quot_mk_eq_mk (I : (FractionalIdeal R⁰ (FractionRing R))ˣ) :
     Quot.mk _ I = ClassGroup.mk I := by
-  rw [ClassGroup.mk, canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id]
-  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
-  erw [MonoidHom.comp_apply]
-  rw [MonoidHom.id_apply, QuotientGroup.mk'_apply]
+  rw [ClassGroup.mk, canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id,
+      MonoidHom.comp_apply, MonoidHom.id_apply, QuotientGroup.mk'_apply]
   rfl
 
 theorem ClassGroup.mk_eq_mk {I J : (FractionalIdeal R⁰ <| FractionRing R)ˣ} :
@@ -215,8 +213,7 @@ theorem ClassGroup.equiv_mk (K' : Type*) [Field K'] [Algebra R K'] [IsFractionRi
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.equiv K' (ClassGroup.mk I) =
       QuotientGroup.mk' _ (Units.mapEquiv (↑(FractionalIdeal.canonicalEquiv R⁰ K K')) I) := by
-  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
-  erw [ClassGroup.equiv, ClassGroup.mk, MonoidHom.comp_apply, QuotientGroup.congr_mk']
+  rw [ClassGroup.equiv, ClassGroup.mk, MonoidHom.comp_apply, QuotientGroup.congr_mk']
   congr
   rw [← Units.eq_iff, Units.coe_mapEquiv, Units.coe_mapEquiv, Units.coe_map]
   exact FractionalIdeal.canonicalEquiv_canonicalEquiv _ _ _ _ _
@@ -227,10 +224,8 @@ theorem ClassGroup.mk_canonicalEquiv (K' : Type*) [Field K'] [Algebra R K'] [IsF
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.mk (Units.map (↑(canonicalEquiv R⁰ K K')) I : (FractionalIdeal R⁰ K')ˣ) =
       ClassGroup.mk I := by
-  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
-  erw [ClassGroup.mk, MonoidHom.comp_apply, ← MonoidHom.comp_apply (Units.map _),
-      ← Units.map_comp, ← RingEquiv.coe_monoidHom_trans,
-      FractionalIdeal.canonicalEquiv_trans_canonicalEquiv]
+  rw [ClassGroup.mk, MonoidHom.comp_apply, ← MonoidHom.comp_apply (Units.map _), ← Units.map_comp, ←
+      RingEquiv.coe_monoidHom_trans, FractionalIdeal.canonicalEquiv_trans_canonicalEquiv]
   rfl
 #align class_group.mk_canonical_equiv ClassGroup.mk_canonicalEquiv
 
chore: bump toolchain to v4.2.0-rc2 (#7703)

This includes all the changes from #7606.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -115,8 +115,10 @@ noncomputable def ClassGroup.mk : (FractionalIdeal R⁰ K)ˣ →* ClassGroup R :
 -- Can't be `@[simp]` because it can't figure out the quotient relation.
 theorem ClassGroup.Quot_mk_eq_mk (I : (FractionalIdeal R⁰ (FractionRing R))ˣ) :
     Quot.mk _ I = ClassGroup.mk I := by
-  rw [ClassGroup.mk, canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id,
-      MonoidHom.comp_apply, MonoidHom.id_apply, QuotientGroup.mk'_apply]
+  rw [ClassGroup.mk, canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id]
+  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+  erw [MonoidHom.comp_apply]
+  rw [MonoidHom.id_apply, QuotientGroup.mk'_apply]
   rfl
 
 theorem ClassGroup.mk_eq_mk {I J : (FractionalIdeal R⁰ <| FractionRing R)ˣ} :
@@ -213,7 +215,8 @@ theorem ClassGroup.equiv_mk (K' : Type*) [Field K'] [Algebra R K'] [IsFractionRi
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.equiv K' (ClassGroup.mk I) =
       QuotientGroup.mk' _ (Units.mapEquiv (↑(FractionalIdeal.canonicalEquiv R⁰ K K')) I) := by
-  rw [ClassGroup.equiv, ClassGroup.mk, MonoidHom.comp_apply, QuotientGroup.congr_mk']
+  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+  erw [ClassGroup.equiv, ClassGroup.mk, MonoidHom.comp_apply, QuotientGroup.congr_mk']
   congr
   rw [← Units.eq_iff, Units.coe_mapEquiv, Units.coe_mapEquiv, Units.coe_map]
   exact FractionalIdeal.canonicalEquiv_canonicalEquiv _ _ _ _ _
@@ -224,8 +227,10 @@ theorem ClassGroup.mk_canonicalEquiv (K' : Type*) [Field K'] [Algebra R K'] [IsF
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.mk (Units.map (↑(canonicalEquiv R⁰ K K')) I : (FractionalIdeal R⁰ K')ˣ) =
       ClassGroup.mk I := by
-  rw [ClassGroup.mk, MonoidHom.comp_apply, ← MonoidHom.comp_apply (Units.map _), ← Units.map_comp, ←
-      RingEquiv.coe_monoidHom_trans, FractionalIdeal.canonicalEquiv_trans_canonicalEquiv]
+  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+  erw [ClassGroup.mk, MonoidHom.comp_apply, ← MonoidHom.comp_apply (Units.map _),
+      ← Units.map_comp, ← RingEquiv.coe_monoidHom_trans,
+      FractionalIdeal.canonicalEquiv_trans_canonicalEquiv]
   rfl
 #align class_group.mk_canonical_equiv ClassGroup.mk_canonicalEquiv
 
chore: drop MulZeroClass. in mul_zero/zero_mul (#6682)

Search&replace MulZeroClass.mul_zero -> mul_zero, MulZeroClass.zero_mul -> zero_mul.

These were introduced by Mathport, as the full name of mul_zero is actually MulZeroClass.mul_zero (it's exported with the short name).

Diff
@@ -310,7 +310,7 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     have hy' : y ∈ R⁰ := mem_nonZeroDivisors_iff_ne_zero.mpr hy
     refine ⟨IsLocalization.mk' _ x ⟨y, hy'⟩, ?_, ?_⟩
     · contrapose! hx
-      rwa [mk'_eq_iff_eq_mul, MulZeroClass.zero_mul, ← (algebraMap R (FractionRing R)).map_zero,
+      rwa [mk'_eq_iff_eq_mul, zero_mul, ← (algebraMap R (FractionRing R)).map_zero,
         (IsFractionRing.injective R (FractionRing R)).eq_iff] at hx
     · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy').mpr h
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -30,7 +30,7 @@ identical no matter the choice of field of fractions for `R`.
 -/
 
 
-variable {R K L : Type _} [CommRing R]
+variable {R K L : Type*} [CommRing R]
 
 variable [Field K] [Field L] [DecidableEq L]
 
@@ -209,7 +209,7 @@ noncomputable def ClassGroup.equiv :
 #align class_group.equiv ClassGroup.equiv
 
 @[simp]
-theorem ClassGroup.equiv_mk (K' : Type _) [Field K'] [Algebra R K'] [IsFractionRing R K']
+theorem ClassGroup.equiv_mk (K' : Type*) [Field K'] [Algebra R K'] [IsFractionRing R K']
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.equiv K' (ClassGroup.mk I) =
       QuotientGroup.mk' _ (Units.mapEquiv (↑(FractionalIdeal.canonicalEquiv R⁰ K K')) I) := by
@@ -220,7 +220,7 @@ theorem ClassGroup.equiv_mk (K' : Type _) [Field K'] [Algebra R K'] [IsFractionR
 #align class_group.equiv_mk ClassGroup.equiv_mk
 
 @[simp]
-theorem ClassGroup.mk_canonicalEquiv (K' : Type _) [Field K'] [Algebra R K'] [IsFractionRing R K']
+theorem ClassGroup.mk_canonicalEquiv (K' : Type*) [Field K'] [Algebra R K'] [IsFractionRing R K']
     (I : (FractionalIdeal R⁰ K)ˣ) :
     ClassGroup.mk (Units.map (↑(canonicalEquiv R⁰ K K')) I : (FractionalIdeal R⁰ K')ˣ) =
       ClassGroup.mk I := by
@@ -242,14 +242,14 @@ theorem FractionalIdeal.coe_mk0 [IsDedekindDomain R] (I : (Ideal R)⁰) :
     (FractionalIdeal.mk0 K I : FractionalIdeal R⁰ K) = I := rfl
 #align fractional_ideal.coe_mk0 FractionalIdeal.coe_mk0
 
-theorem FractionalIdeal.canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type _) [Field K']
+theorem FractionalIdeal.canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type*) [Field K']
     [Algebra R K'] [IsFractionRing R K'] (I : (Ideal R)⁰) :
     FractionalIdeal.canonicalEquiv R⁰ K K' (FractionalIdeal.mk0 K I) = FractionalIdeal.mk0 K' I :=
   by simp only [FractionalIdeal.coe_mk0, FractionalIdeal.canonicalEquiv_coeIdeal]
 #align fractional_ideal.canonical_equiv_mk0 FractionalIdeal.canonicalEquiv_mk0
 
 @[simp]
-theorem FractionalIdeal.map_canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type _) [Field K']
+theorem FractionalIdeal.map_canonicalEquiv_mk0 [IsDedekindDomain R] (K' : Type*) [Field K']
     [Algebra R K'] [IsFractionRing R K'] (I : (Ideal R)⁰) :
     Units.map (↑(FractionalIdeal.canonicalEquiv R⁰ K K')) (FractionalIdeal.mk0 K I) =
       FractionalIdeal.mk0 K' I :=
perf: change to CommGroup instance on units (#6398)

Fixes a slowdown issue reported on Zulip. The first declaration in that example (the Basis example) takes 268578 to elaborate on master but only 11541 (an order of magnitude better) on this branch, and heartbeats no longer need to be bumped.

Diff
@@ -180,8 +180,6 @@ theorem ClassGroup.induction {P : ClassGroup R → Prop}
     exact h _
 #align class_group.induction ClassGroup.induction
 
--- Porting note: This definition needs a lot of heartbeats to complete even with some help
-set_option maxHeartbeats 600000 in
 /-- The definition of the class group does not depend on the choice of field of fractions. -/
 noncomputable def ClassGroup.equiv :
     ClassGroup R ≃* (FractionalIdeal R⁰ K)ˣ ⧸ (toPrincipalIdeal R K).range := by
@@ -210,8 +208,6 @@ noncomputable def ClassGroup.equiv :
     (Units.mapEquiv (FractionalIdeal.canonicalEquiv R⁰ (FractionRing R) K).toMulEquiv) this
 #align class_group.equiv ClassGroup.equiv
 
--- Porting note: This proof needs a lot of heartbeats to complete
-set_option maxHeartbeats 600000 in
 @[simp]
 theorem ClassGroup.equiv_mk (K' : Type _) [Field K'] [Algebra R K'] [IsFractionRing R K']
     (I : (FractionalIdeal R⁰ K)ˣ) :
chore: split ClassGroup.mk0_surjective (#6146)

Not only was this a huge declaration, it also remained unfolded throughout checking the proof, so things like defeq checking were extremely slow (total declaration elaboration time ~1 minute on my machine). Splitting it into a def + proofs makes everything much faster.

Total build time for this file on my machine went from ~140 seconds to ~80 seconds.

I came across this issue while trying to figure out why #6011 appeared to slow down building of ClassGroup.lean.

Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>

Diff
@@ -112,6 +112,13 @@ noncomputable def ClassGroup.mk : (FractionalIdeal R⁰ K)ˣ →* ClassGroup R :
     (Units.map (FractionalIdeal.canonicalEquiv R⁰ K (FractionRing R)))
 #align class_group.mk ClassGroup.mk
 
+-- Can't be `@[simp]` because it can't figure out the quotient relation.
+theorem ClassGroup.Quot_mk_eq_mk (I : (FractionalIdeal R⁰ (FractionRing R))ˣ) :
+    Quot.mk _ I = ClassGroup.mk I := by
+  rw [ClassGroup.mk, canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id,
+      MonoidHom.comp_apply, MonoidHom.id_apply, QuotientGroup.mk'_apply]
+  rfl
+
 theorem ClassGroup.mk_eq_mk {I J : (FractionalIdeal R⁰ <| FractionRing R)ˣ} :
     ClassGroup.mk I = ClassGroup.mk J ↔
       ∃ x : (FractionRing R)ˣ, I * toPrincipalIdeal R (FractionRing R) x = J := by
@@ -312,53 +319,77 @@ theorem ClassGroup.mk0_eq_mk0_iff [IsDedekindDomain R] {I J : (Ideal R)⁰} :
     · exact (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal _ hy').mpr h
 #align class_group.mk0_eq_mk0_iff ClassGroup.mk0_eq_mk0_iff
 
--- Porting note: This proof needs some extra heartbeats to complete
-set_option maxHeartbeats 300000 in
-theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
-    Function.Surjective (ClassGroup.mk0 : (Ideal R)⁰ → ClassGroup R) := by
-  rintro ⟨I⟩
-  obtain ⟨a, a_ne_zero', ha⟩ := I.1.2
+/-- Maps a nonzero fractional ideal to an integral representative in the class group. -/
+noncomputable def ClassGroup.integralRep
+    (I : FractionalIdeal R⁰ (FractionRing R)) :
+    Ideal R :=
+  let a := I.2.choose
+  { carrier := {x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1}
+    add_mem' := by
+      simp only [Set.mem_setOf_eq, RingHom.map_add, mul_add]
+      exact fun ha hb => Submodule.add_mem _ ha hb
+    zero_mem' := by
+      simp only [Set.mem_setOf_eq, RingHom.map_zero, mul_zero]
+      exact Submodule.zero_mem _
+    smul_mem' := by
+      intro c _ hb
+      simp only [smul_eq_mul, Set.mem_setOf_eq, RingHom.map_mul,
+        mul_left_comm ((algebraMap R (FractionRing R)) a)⁻¹]
+      rw [← Algebra.smul_def c]
+      exact Submodule.smul_mem _ c hb }
+
+theorem ClassGroup.integralRep_mem_nonZeroDivisors
+    {I} (hI : I ≠ 0) :
+    ClassGroup.integralRep I ∈ (Ideal R)⁰ := by
+  let a := I.2.choose
+  have a_ne_zero' := I.2.choose_spec.1
   have a_ne_zero := mem_nonZeroDivisors_iff_ne_zero.mp a_ne_zero'
   have fa_ne_zero : (algebraMap R (FractionRing R)) a ≠ 0 :=
     IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors a_ne_zero'
-  refine ⟨⟨⟨⟨⟨?_, ?_⟩, ?_⟩, ?_⟩, ?_⟩, ?_⟩
-  · exact {x | (algebraMap R _ a)⁻¹ * algebraMap R _ x ∈ I.1}
-  · simp only [Set.mem_setOf_eq, RingHom.map_add, mul_add]
-    exact fun ha hb => Submodule.add_mem _ ha hb
-  · simp only [Set.mem_setOf_eq, RingHom.map_zero, mul_zero]
-    exact Submodule.zero_mem _
-  · intro c _ hb
-    simp only [smul_eq_mul, Set.mem_setOf_eq, RingHom.map_mul,
-      mul_left_comm ((algebraMap R (FractionRing R)) a)⁻¹]
-    rw [← Algebra.smul_def c]
-    exact Submodule.smul_mem _ c hb
-  · rw [mem_nonZeroDivisors_iff_ne_zero, Submodule.zero_eq_bot, Submodule.ne_bot_iff]
-    obtain ⟨x, x_ne, x_mem⟩ := exists_ne_zero_mem_isInteger I.ne_zero
-    refine ⟨a*x, ?_, mul_ne_zero a_ne_zero x_ne⟩
-    change ((algebraMap R _) a)⁻¹ * (algebraMap R _) (a * x) ∈ I.1
-    rwa [RingHom.map_mul, ← mul_assoc, inv_mul_cancel fa_ne_zero, one_mul]
-  · symm
-    apply Quotient.sound
-    change @Setoid.r _
-      (QuotientGroup.leftRel (toPrincipalIdeal R (FractionRing R)).range) _ _
-    rw [QuotientGroup.leftRel_apply]
-    refine ⟨Units.mk0 (algebraMap R _ a) fa_ne_zero, ?_⟩
-    rw [_root_.eq_inv_mul_iff_mul_eq, eq_comm, mul_comm I]
-    apply Units.ext
-    simp only [FractionalIdeal.coe_mk0, FractionalIdeal.map_canonicalEquiv_mk0,
-      Units.val_mk0, coe_toPrincipalIdeal, Units.val_mul,
-      FractionalIdeal.eq_spanSingleton_mul]
-    constructor
-    · intro zJ' hzJ'
-      obtain ⟨zJ, hzJ, rfl⟩ := (mem_coeIdeal R⁰).mp hzJ'
-      refine ⟨_, hzJ, ?_⟩
-      rw [← mul_assoc, mul_inv_cancel fa_ne_zero, one_mul]
-    · intro zI' hzI'
-      obtain ⟨y, hy⟩ := ha zI' hzI'
-      rw [← Algebra.smul_def, mem_coeIdeal]
-      refine' ⟨y, _, hy⟩
-      show (algebraMap R _ a)⁻¹ * algebraMap R _ y ∈ (I : FractionalIdeal R⁰ (FractionRing R))
-      rwa [hy, Algebra.smul_def, ← mul_assoc, inv_mul_cancel fa_ne_zero, one_mul]
+  rw [mem_nonZeroDivisors_iff_ne_zero, Submodule.zero_eq_bot, Submodule.ne_bot_iff]
+  obtain ⟨x, x_ne, x_mem⟩ := exists_ne_zero_mem_isInteger hI
+  refine ⟨a*x, ?_, mul_ne_zero a_ne_zero x_ne⟩
+  change ((algebraMap R _) a)⁻¹ * (algebraMap R _) (a * x) ∈ I
+  rwa [RingHom.map_mul, ← mul_assoc, inv_mul_cancel fa_ne_zero, one_mul]
+
+theorem ClassGroup.mk0_integralRep [IsDedekindDomain R]
+    (I : (FractionalIdeal R⁰ (FractionRing R))ˣ) :
+    ClassGroup.mk0 ⟨ClassGroup.integralRep I, ClassGroup.integralRep_mem_nonZeroDivisors I.ne_zero⟩
+      = ClassGroup.mk I := by
+  let a := I.1.2.choose
+  have a_ne_zero' := I.1.2.choose_spec.1
+  have ha := I.1.2.choose_spec.2
+  have fa_ne_zero : (algebraMap R (FractionRing R)) a ≠ 0 :=
+    IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors a_ne_zero'
+  symm
+  apply Quotient.sound
+  change @Setoid.r _
+    (QuotientGroup.leftRel (toPrincipalIdeal R (FractionRing R)).range) _ _
+  rw [canonicalEquiv_self, RingEquiv.coe_monoidHom_refl, Units.map_id, MonoidHom.id_apply,
+      MonoidHom.id_apply, QuotientGroup.leftRel_apply]
+  refine ⟨Units.mk0 (algebraMap R _ a) fa_ne_zero, ?_⟩
+  rw [_root_.eq_inv_mul_iff_mul_eq, eq_comm, mul_comm I]
+  apply Units.ext
+  simp only [FractionalIdeal.coe_mk0, FractionalIdeal.map_canonicalEquiv_mk0,
+    Units.val_mk0, coe_toPrincipalIdeal, Units.val_mul,
+    FractionalIdeal.eq_spanSingleton_mul]
+  constructor
+  · intro zJ' hzJ'
+    obtain ⟨zJ, hzJ, rfl⟩ := (mem_coeIdeal R⁰).mp hzJ'
+    refine ⟨_, hzJ, ?_⟩
+    rw [← mul_assoc, mul_inv_cancel fa_ne_zero, one_mul]
+  · intro zI' hzI'
+    obtain ⟨y, hy⟩ := ha zI' hzI'
+    rw [← Algebra.smul_def, mem_coeIdeal]
+    refine' ⟨y, _, hy⟩
+    show (algebraMap R _ a)⁻¹ * algebraMap R _ y ∈ (I : FractionalIdeal R⁰ (FractionRing R))
+    rwa [hy, Algebra.smul_def, ← mul_assoc, inv_mul_cancel fa_ne_zero, one_mul]
+
+theorem ClassGroup.mk0_surjective [IsDedekindDomain R] :
+    Function.Surjective (ClassGroup.mk0 : (Ideal R)⁰ → ClassGroup R) := by
+  rintro ⟨I⟩
+  refine ⟨⟨ ClassGroup.integralRep I.1, ClassGroup.integralRep_mem_nonZeroDivisors I.ne_zero⟩, ?_⟩
+  rw [ClassGroup.mk0_integralRep, ClassGroup.Quot_mk_eq_mk]
 #align class_group.mk0_surjective ClassGroup.mk0_surjective
 
 theorem ClassGroup.mk_eq_one_iff {I : (FractionalIdeal R⁰ K)ˣ} :
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,15 +2,12 @@
 Copyright (c) 2021 Anne Baanen. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Anne Baanen
-
-! This file was ported from Lean 3 source module ring_theory.class_group
-! leanprover-community/mathlib commit 565eb991e264d0db702722b4bde52ee5173c9950
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.GroupTheory.QuotientGroup
 import Mathlib.RingTheory.DedekindDomain.Ideal
 
+#align_import ring_theory.class_group from "leanprover-community/mathlib"@"565eb991e264d0db702722b4bde52ee5173c9950"
+
 /-!
 # The ideal class group
 
chore: tidy various files (#5469)

Co-authored-by: Scott Morrison <scott@tqft.net>

Diff
@@ -19,7 +19,7 @@ inside its field of fractions.
 
 ## Main definitions
  - `toPrincipalIdeal` sends an invertible `x : K` to an invertible fractional ideal
- - `ClassGroup` is the quotient of invertible fractional ideals modulo `to_principal_ideal.range`
+ - `ClassGroup` is the quotient of invertible fractional ideals modulo `toPrincipalIdeal.range`
  - `ClassGroup.mk0` sends a nonzero integral ideal in a Dedekind domain to its class
 
 ## Main results
chore: tidy various files (#4997)
Diff
@@ -388,7 +388,7 @@ theorem ClassGroup.mk0_eq_one_iff [IsDedekindDomain R] {I : Ideal R} (hI : I ∈
 
 /-- The class group of principal ideal domain is finite (in fact a singleton).
 
-See `class_group.fintype_of_admissible` for a finiteness proof that works for rings of integers
+See `ClassGroup.fintypeOfAdmissibleOfFinite` for a finiteness proof that works for rings of integers
 of global fields.
 -/
 noncomputable instance [IsPrincipalIdealRing R] : Fintype (ClassGroup R) where
feat: port RingTheory.ClassGroup (#4732)

Some proofs are really slow and need a lot of heartbeats to complete (up to 600000).

Co-authored-by: Johan Commelin <johan@commelin.net>

Dependencies 11 + 695

696 files ported (98.4%)
296911 lines ported (98.2%)
Show graph

The unported dependencies are