l3lab/ntp-mathlib huggingface dataset:
/-- Any group is isomorphic to the units of itself adjoined with `0`. -/
def unitsWithZeroEquiv {α : Type*} [Group α] : (WithZero α)ˣ ≃* α where
  toFun a := unzero a.ne_zero
  invFun a := Units.mk0 a coe_ne_zero
  left_inv _ := Units.ext <| by simp only [coe_unzero, Units.mk0_val]
  right_inv _ := rfl
  map_mul' _ _ := coe_inj.mp <| by 

Proof state:
α : Type u_1
inst✝ : Group α
x✝¹ x✝ : (WithZero α)ˣ
⊢ ↑(Equiv.toFun
        { toFun := fun a => unzero (_ : ↑a ≠ 0), invFun := fun a => Units.mk0 ↑a (_ : ↑a ≠ 0),
          left_inv :=
            (_ : ∀ (x : (WithZero α)ˣ), (fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) ((fun a => unzero (_ : ↑a ≠ 0)) x) = x),
          right_inv :=
            (_ :
              ∀ (x : α),
                (fun a => unzero (_ : ↑a ≠ 0)) ((fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) x) =
                  (fun a => unzero (_ : ↑a ≠ 0)) ((fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) x)) }
        (x✝¹ * x✝)) =
    ↑(Equiv.toFun
          { toFun := fun a => unzero (_ : ↑a ≠ 0), invFun := fun a => Units.mk0 ↑a (_ : ↑a ≠ 0),
            left_inv :=
              (_ : ∀ (x : (WithZero α)ˣ), (fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) ((fun a => unzero (_ : ↑a ≠ 0)) x) = x),
            right_inv :=
              (_ :
                ∀ (x : α),
                  (fun a => unzero (_ : ↑a ≠ 0)) ((fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) x) =
                    (fun a => unzero (_ : ↑a ≠ 0)) ((fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) x)) }
          x✝¹ *
        Equiv.toFun
          { toFun := fun a => unzero (_ : ↑a ≠ 0), invFun := fun a => Units.mk0 ↑a (_ : ↑a ≠ 0),
            left_inv :=
              (_ : ∀ (x : (WithZero α)ˣ), (fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) ((fun a => unzero (_ : ↑a ≠ 0)) x) = x),
            right_inv :=
              (_ :
                ∀ (x : α),
                  (fun a => unzero (_ : ↑a ≠ 0)) ((fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) x) =
                    (fun a => unzero (_ : ↑a ≠ 0)) ((fun a => Units.mk0 ↑a (_ : ↑a ≠ 0)) x)) }
          x✝)

Next tactic:
simp only [Units.val_mul, coe_unzero, coe_mul]
lemma nat_sqrt_helper {x y r : ℕ} (hr : y * y + r = x) (hle : Nat.ble r (2 * y)) :
    Nat.sqrt x = y := by
  

Proof state:
x y r : ℕ
hr : y * y + r = x
hle : Nat.ble r (2 * y) = true
⊢ Nat.sqrt x = y

Next tactic:
rw [← hr, ← pow_two]
lemma nat_sqrt_helper {x y r : ℕ} (hr : y * y + r = x) (hle : Nat.ble r (2 * y)) :
    Nat.sqrt x = y := by
  rw [← hr, ← pow_two]
  

Proof state:
x y r : ℕ
hr : y * y + r = x
hle : Nat.ble r (2 * y) = true
⊢ Nat.sqrt (y ^ 2 + r) = y

Next tactic:
rw [two_mul] at hle
lemma nat_sqrt_helper {x y r : ℕ} (hr : y * y + r = x) (hle : Nat.ble r (2 * y)) :
    Nat.sqrt x = y := by
  rw [← hr, ← pow_two]
  rw [two_mul] at hle
  

Proof state:
x y r : ℕ
hr : y * y + r = x
hle : Nat.ble r (y + y) = true
⊢ Nat.sqrt (y ^ 2 + r) = y

Next tactic:
exact Nat.sqrt_add_eq' _ (Nat.le_of_ble_eq_true hle)
instance : AddCommGroup I.Cotangent := by 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ AddCommGroup (Cotangent I)

Next tactic:
delta Cotangent
instance : AddCommGroup I.Cotangent := by delta Cotangent; 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ AddCommGroup (↥I ⧸ I • ⊤)

Next tactic:
infer_instance
instance cotangentModule : Module (R ⧸ I) I.Cotangent := by 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ Module (R ⧸ I) (Cotangent I)

Next tactic:
delta Cotangent
instance cotangentModule : Module (R ⧸ I) I.Cotangent := by delta Cotangent; 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ Module (R ⧸ I) (↥I ⧸ I • ⊤)

Next tactic:
infer_instance
theorem map_toCotangent_ker : I.toCotangent.ker.map I.subtype = I ^ 2 := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ Submodule.map (Submodule.subtype I) (LinearMap.ker (toCotangent I)) = I ^ 2

Next tactic:
rw [Ideal.toCotangent, Submodule.ker_mkQ, pow_two, Submodule.map_smul'' I ⊤ (Submodule.subtype I),
    Algebra.id.smul_eq_mul, Submodule.map_subtype_top]
theorem mem_toCotangent_ker {x : I} : x ∈ LinearMap.ker I.toCotangent ↔ (x : R) ∈ I ^ 2 := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x : ↥I
⊢ x ∈ LinearMap.ker (toCotangent I) ↔ ↑x ∈ I ^ 2

Next tactic:
rw [← I.map_toCotangent_ker]
theorem mem_toCotangent_ker {x : I} : x ∈ LinearMap.ker I.toCotangent ↔ (x : R) ∈ I ^ 2 := by
  rw [← I.map_toCotangent_ker]
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x : ↥I
⊢ x ∈ LinearMap.ker (toCotangent I) ↔ ↑x ∈ Submodule.map (Submodule.subtype I) (LinearMap.ker (toCotangent I))

Next tactic:
simp
theorem toCotangent_eq {x y : I} : I.toCotangent x = I.toCotangent y ↔ (x - y : R) ∈ I ^ 2 := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x y : ↥I
⊢ (toCotangent I) x = (toCotangent I) y ↔ ↑x - ↑y ∈ I ^ 2

Next tactic:
rw [← sub_eq_zero]
theorem toCotangent_eq {x y : I} : I.toCotangent x = I.toCotangent y ↔ (x - y : R) ∈ I ^ 2 := by
  rw [← sub_eq_zero]
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x y : ↥I
⊢ (toCotangent I) x - (toCotangent I) y = 0 ↔ ↑x - ↑y ∈ I ^ 2

Next tactic:
exact I.mem_toCotangent_ker
theorem cotangent_subsingleton_iff : Subsingleton I.Cotangent ↔ IsIdempotentElem I := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ Subsingleton (Cotangent I) ↔ IsIdempotentElem I

Next tactic:
constructor
theorem cotangent_subsingleton_iff : Subsingleton I.Cotangent ↔ IsIdempotentElem I := by
  constructor
  · 

Proof state:
case mp
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ Subsingleton (Cotangent I) → IsIdempotentElem I

Next tactic:
intro H
theorem cotangent_subsingleton_iff : Subsingleton I.Cotangent ↔ IsIdempotentElem I := by
  constructor
  · intro H
    

Proof state:
case mp
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
H : Subsingleton (Cotangent I)
⊢ IsIdempotentElem I

Next tactic:
refine' (pow_two I).symm.trans (le_antisymm (Ideal.pow_le_self two_ne_zero) _)
theorem cotangent_subsingleton_iff : Subsingleton I.Cotangent ↔ IsIdempotentElem I := by
  constructor
  · intro H
    refine' (pow_two I).symm.trans (le_antisymm (Ideal.pow_le_self two_ne_zero) _)
    

Proof state:
case mp
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
H : Subsingleton (Cotangent I)
⊢ I ≤ I ^ 2

Next tactic:
exact fun x hx => (I.toCotangent_eq_zero ⟨x, hx⟩).mp (Subsingleton.elim _ _)
theorem cotangent_subsingleton_iff : Subsingleton I.Cotangent ↔ IsIdempotentElem I := by
  constructor
  · intro H
    refine' (pow_two I).symm.trans (le_antisymm (Ideal.pow_le_self two_ne_zero) _)
    exact fun x hx => (I.toCotangent_eq_zero ⟨x, hx⟩).mp (Subsingleton.elim _ _)
  · 

Proof state:
case mpr
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ IsIdempotentElem I → Subsingleton (Cotangent I)

Next tactic:
exact fun e =>
      ⟨fun x y =>
        Quotient.inductionOn₂' x y fun x y =>
          I.toCotangent_eq.mpr <| ((pow_two I).trans e).symm ▸ I.sub_mem x.prop y.prop⟩
/-- The inclusion map `I ⧸ I ^ 2` to `R ⧸ I ^ 2`. -/
def cotangentToQuotientSquare : I.Cotangent →ₗ[R] R ⧸ I ^ 2 :=
  Submodule.mapQ (I • ⊤) (I ^ 2) I.subtype
    (by
      

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ I • ⊤ ≤ Submodule.comap (Submodule.subtype I) (I ^ 2)

Next tactic:
rw [← Submodule.map_le_iff_le_comap, Submodule.map_smul'', Submodule.map_top,
        Submodule.range_subtype, smul_eq_mul, pow_two]
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
⊢ cotangentIdeal I ^ 2 = ⊥

Next tactic:
rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
⊢ cotangentIdeal I • cotangentIdeal I ≤ ⊥

Next tactic:
intro x hx
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  intro x hx
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
x : R ⧸ I ^ 2
hx : x ∈ cotangentIdeal I • cotangentIdeal I
⊢ x ∈ ⊥

Next tactic:
refine Submodule.smul_induction_on hx ?_ ?_
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  intro x hx
  refine Submodule.smul_induction_on hx ?_ ?_
  · 

Proof state:
case refine_1
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
x : R ⧸ I ^ 2
hx : x ∈ cotangentIdeal I • cotangentIdeal I
⊢ ∀ r ∈ cotangentIdeal I, ∀ n ∈ cotangentIdeal I, r • n ∈ ⊥

Next tactic:
rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  intro x hx
  refine Submodule.smul_induction_on hx ?_ ?_
  · rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩; 

Proof state:
case refine_1.intro.intro.intro.intro
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
x✝ : R ⧸ I ^ 2
hx✝ : x✝ ∈ cotangentIdeal I • cotangentIdeal I
x : R
hx : x ∈ ↑I
y : R
hy : y ∈ ↑I
⊢ (RingHom.toSemilinearMap (Quotient.mk (I ^ 2))) x • (RingHom.toSemilinearMap (Quotient.mk (I ^ 2))) y ∈ ⊥

Next tactic:
apply (Submodule.Quotient.eq _).mpr _
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  intro x hx
  refine Submodule.smul_induction_on hx ?_ ?_
  · rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩; apply (Submodule.Quotient.eq _).mpr _
    

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
x✝ : R ⧸ I ^ 2
hx✝ : x✝ ∈ cotangentIdeal I • cotangentIdeal I
x : R
hx : x ∈ ↑I
y : R
hy : y ∈ ↑I
⊢ (fun x x_1 => x * x_1) x y - 0 ∈ I ^ 2

Next tactic:
rw [sub_zero, pow_two]
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  intro x hx
  refine Submodule.smul_induction_on hx ?_ ?_
  · rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩; apply (Submodule.Quotient.eq _).mpr _
    rw [sub_zero, pow_two]; 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
x✝ : R ⧸ I ^ 2
hx✝ : x✝ ∈ cotangentIdeal I • cotangentIdeal I
x : R
hx : x ∈ ↑I
y : R
hy : y ∈ ↑I
⊢ (fun x x_1 => x * x_1) x y ∈ I * I

Next tactic:
exact Ideal.mul_mem_mul hx hy
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  intro x hx
  refine Submodule.smul_induction_on hx ?_ ?_
  · rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩; apply (Submodule.Quotient.eq _).mpr _
    rw [sub_zero, pow_two]; exact Ideal.mul_mem_mul hx hy
  · 

Proof state:
case refine_2
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
x : R ⧸ I ^ 2
hx : x ∈ cotangentIdeal I • cotangentIdeal I
⊢ ∀ (x y : R ⧸ I ^ 2), x ∈ ⊥ → y ∈ ⊥ → x + y ∈ ⊥

Next tactic:
intro x y hx hy
theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by
  rw [eq_bot_iff, pow_two I.cotangentIdeal, ← smul_eq_mul]
  intro x hx
  refine Submodule.smul_induction_on hx ?_ ?_
  · rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩; apply (Submodule.Quotient.eq _).mpr _
    rw [sub_zero, pow_two]; exact Ideal.mul_mem_mul hx hy
  · intro x y hx hy; 

Proof state:
case refine_2
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I✝ I : Ideal R
x✝ : R ⧸ I ^ 2
hx✝ : x✝ ∈ cotangentIdeal I • cotangentIdeal I
x y : R ⧸ I ^ 2
hx : x ∈ ⊥
hy : y ∈ ⊥
⊢ x + y ∈ ⊥

Next tactic:
exact add_mem hx hy
theorem to_quotient_square_range :
    LinearMap.range I.cotangentToQuotientSquare = I.cotangentIdeal.restrictScalars R := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ LinearMap.range (cotangentToQuotientSquare I) = Submodule.restrictScalars R (cotangentIdeal I)

Next tactic:
trans LinearMap.range (I.cotangentToQuotientSquare.comp I.toCotangent)
theorem to_quotient_square_range :
    LinearMap.range I.cotangentToQuotientSquare = I.cotangentIdeal.restrictScalars R := by
  trans LinearMap.range (I.cotangentToQuotientSquare.comp I.toCotangent)
  · 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ LinearMap.range (cotangentToQuotientSquare I) = LinearMap.range (cotangentToQuotientSquare I ∘ₗ toCotangent I)

Next tactic:
rw [LinearMap.range_comp, I.toCotangent_range, Submodule.map_top]
theorem to_quotient_square_range :
    LinearMap.range I.cotangentToQuotientSquare = I.cotangentIdeal.restrictScalars R := by
  trans LinearMap.range (I.cotangentToQuotientSquare.comp I.toCotangent)
  · rw [LinearMap.range_comp, I.toCotangent_range, Submodule.map_top]
  · 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ LinearMap.range (cotangentToQuotientSquare I ∘ₗ toCotangent I) = Submodule.restrictScalars R (cotangentIdeal I)

Next tactic:
rw [to_quotient_square_comp_toCotangent, LinearMap.range_comp, I.range_subtype]
theorem to_quotient_square_range :
    LinearMap.range I.cotangentToQuotientSquare = I.cotangentIdeal.restrictScalars R := by
  trans LinearMap.range (I.cotangentToQuotientSquare.comp I.toCotangent)
  · rw [LinearMap.range_comp, I.toCotangent_range, Submodule.map_top]
  · rw [to_quotient_square_comp_toCotangent, LinearMap.range_comp, I.range_subtype]; 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ Submodule.map (Submodule.mkQ (I ^ 2)) I = Submodule.restrictScalars R (cotangentIdeal I)

Next tactic:
ext
theorem to_quotient_square_range :
    LinearMap.range I.cotangentToQuotientSquare = I.cotangentIdeal.restrictScalars R := by
  trans LinearMap.range (I.cotangentToQuotientSquare.comp I.toCotangent)
  · rw [LinearMap.range_comp, I.toCotangent_range, Submodule.map_top]
  · rw [to_quotient_square_comp_toCotangent, LinearMap.range_comp, I.range_subtype]; ext; 

Proof state:
case h
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x✝ : R ⧸ I ^ 2
⊢ x✝ ∈ Submodule.map (Submodule.mkQ (I ^ 2)) I ↔ x✝ ∈ Submodule.restrictScalars R (cotangentIdeal I)

Next tactic:
rfl
/-- The equivalence of the two definitions of `I / I ^ 2`, either as the quotient of `I` or the
ideal of `R / I ^ 2`. -/
noncomputable def cotangentEquivIdeal : I.Cotangent ≃ₗ[R] I.cotangentIdeal := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
⊢ Cotangent I ≃ₗ[R] ↥(cotangentIdeal I)

Next tactic:
refine
  { LinearMap.codRestrict (I.cotangentIdeal.restrictScalars R) I.cotangentToQuotientSquare
      fun x => by { rw [← to_quotient_square_range]; exact LinearMap.mem_range_self _ _ },
    Equiv.ofBijective _ ⟨?_, ?_⟩ with }
/-- The equivalence of the two definitions of `I / I ^ 2`, either as the quotient of `I` or the
ideal of `R / I ^ 2`. -/
noncomputable def cotangentEquivIdeal : I.Cotangent ≃ₗ[R] I.cotangentIdeal := by
  refine
  { LinearMap.codRestrict (I.cotangentIdeal.restrictScalars R) I.cotangentToQuotientSquare
      fun x => by 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x : Cotangent I
⊢ (cotangentToQuotientSquare I) x ∈ Submodule.restrictScalars R (cotangentIdeal I)

Next tactic:
{ rw [← to_quotient_square_range]; exact LinearMap.mem_range_self _ _ }
/-- The equivalence of the two definitions of `I / I ^ 2`, either as the quotient of `I` or the
ideal of `R / I ^ 2`. -/
noncomputable def cotangentEquivIdeal : I.Cotangent ≃ₗ[R] I.cotangentIdeal := by
  refine
  { LinearMap.codRestrict (I.cotangentIdeal.restrictScalars R) I.cotangentToQuotientSquare
      fun x => by { 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x : Cotangent I
⊢ (cotangentToQuotientSquare I) x ∈ Submodule.restrictScalars R (cotangentIdeal I)

Next tactic:
rw [← to_quotient_square_range]
/-- The equivalence of the two definitions of `I / I ^ 2`, either as the quotient of `I` or the
ideal of `R / I ^ 2`. -/
noncomputable def cotangentEquivIdeal : I.Cotangent ≃ₗ[R] I.cotangentIdeal := by
  refine
  { LinearMap.codRestrict (I.cotangentIdeal.restrictScalars R) I.cotangentToQuotientSquare
      fun x => by { rw [← to_quotient_square_range]; 

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
x : Cotangent I
⊢ (cotangentToQuotientSquare I) x ∈ LinearMap.range (cotangentToQuotientSquare I)

Next tactic:
exact LinearMap.mem_range_self _ _
/-- The equivalence of the two definitions of `I / I ^ 2`, either as the quotient of `I` or the
ideal of `R / I ^ 2`. -/
noncomputable def cotangentEquivIdeal : I.Cotangent ≃ₗ[R] I.cotangentIdeal := by
  refine
  { LinearMap.codRestrict (I.cotangentIdeal.restrictScalars R) I.cotangentToQuotientSquare
      fun x => by { rw [← to_quotient_square_range]; exact LinearMap.mem_range_self _ _ },
    Equiv.ofBijective _ ⟨?_, ?_⟩ with }
  · 

Proof state:
case refine_1
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
src✝ : Cotangent I →ₗ[R] ↥(Submodule.restrictScalars R (cotangentIdeal I)) :=
  LinearMap.codRestrict (Submodule.restrictScalars R (cotangentIdeal I)) (cotangentToQuotientSquare I)
    (_ : ∀ (x : Cotangent I), (cotangentToQuotientSquare I) x ∈ Submodule.restrictScalars R (cotangentIdeal I))
⊢ Function.Injective fun c =>
    { val := (cotangentToQuotientSquare I) c,
      property := (_ : (cotangentToQuotientSquare I) c ∈ Submodule.restrictScalars R (cotangentIdeal I)) }

Next tactic:
rintro x y e
/-- The equivalence of the two definitions of `I / I ^ 2`, either as the quotient of `I` or the
ideal of `R / I ^ 2`. -/
noncomputable def cotangentEquivIdeal : I.Cotangent ≃ₗ[R] I.cotangentIdeal := by
  refine
  { LinearMap.codRestrict (I.cotangentIdeal.restrictScalars R) I.cotangentToQuotientSquare
      fun x => by { rw [← to_quotient_square_range]; exact LinearMap.mem_range_self _ _ },
    Equiv.ofBijective _ ⟨?_, ?_⟩ with }
  · rintro x y e
    

Proof state:
case refine_1
R : Type u
S : Type v
S' : Type w
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
inst✝⁴ : Algebra S R
inst✝³ : CommSemiring S'
inst✝² : Algebra S' R
inst✝¹ : Algebra S S'
inst✝ : IsScalarTower S S' R
I : Ideal R
src✝ : Cotangent I →ₗ[R] ↥(Submodule.restrictScalars R (cotangentIdeal I)) :=
  LinearMap.codRestrict (Submodule.restrictScalars R (cotangentIdeal I)) (cotangentToQuotientSquare I)
    (_ : ∀ (x : Cotangent I), (cotangentToQuotientSquare I) x ∈ Submodule.restrictScalars R (cotangentIdeal I))
x y : Cotangent I
e :
  (fun c =>
        { val := (cotangentToQuotientSquare I) c,
          property := (_ : (cotangentToQuotientSquare I) c ∈ Submodule.restrictScalars R (cotangentIdeal I)) })
      x =
    (fun c =>
        { val := (cotangentToQuotientSquare I) c,
          property := (_ : (cotangentToQuotientSquare I) c ∈ Submodule.restrictScalars R (cotangentIdeal I)) })
      y
⊢ x = y

Next tactic:
replace e := congr_arg Subtype.val e