-- Mathlib/RingTheory/Ideal/Quotient/Nilpotent.lean
theorem IsNilpotent.isUnit_quotient_mk_iff {R : Type*} [CommRing R] {I : Ideal R}
    (hI : IsNilpotent I) {x : R} : IsUnit (Ideal.Quotient.mk I x) ↔ IsUnit x

Proof state:
R : Type u_2
inst✝ : CommRing R
I : Ideal R
hI : IsNilpotent I
x : R
⊢ IsUnit ((Ideal.Quotient.mk I) x) ↔ IsUnit x

Tactic:
refine ⟨?_, fun h => h.map <| Ideal.Quotient.mk I⟩

Result:
R : Type u_2
inst✝ : CommRing R
I : Ideal R
hI : IsNilpotent I
x : R
⊢ IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x

Proof state:
case h₁.intro
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
this✝¹ : x * y - 1 ∈ I
this✝ : (x * y - 1) ^ 2 = 0
this : x * (y * (2 - x * y)) = 1
⊢ IsUnit x

Tactic:
exact isUnit_of_mul_eq_one _ _ this

Result:
no goals

Proof state:
case h₁
R : Type u_2
inst✝ : CommRing R
⊢ ∀ ⦃S : Type u_2⦄ [inst : CommRing S] (I : Ideal S), I ^ 2 = ⊥ → ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x

Tactic:
introv e H

Result:
case h₁
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
⊢ IsUnit x

Proof state:
case h₂.a
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I J : Ideal S
e : I ≤ J
h₁ : ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x
h₂ : ∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x
x : S
h₃ : IsUnit ((Ideal.Quotient.mk J) x)
⊢ IsUnit ((Ideal.Quotient.mk I) x)

Tactic:
apply h₂

Result:
case h₂.a.a
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I J : Ideal S
e : I ≤ J
h₁ : ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x
h₂ : ∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x
x : S
h₃ : IsUnit ((Ideal.Quotient.mk J) x)
⊢ IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) ((Ideal.Quotient.mk I) x))

Proof state:
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
this✝ : x * y - 1 ∈ I
this : (x * y - 1) ^ 2 = 0
⊢ x * (y * (2 - x * y)) = 1

Tactic:
rw [eq_comm, ← sub_eq_zero, ← this]

Result:
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
this✝ : x * y - 1 ∈ I
this : (x * y - 1) ^ 2 = 0
⊢ 1 - x * (y * (2 - x * y)) = (x * y - 1) ^ 2

Proof state:
case h₂
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I J : Ideal S
e : I ≤ J
h₁ : ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x
h₂ : ∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x
x : S
h₃ : IsUnit ((Ideal.Quotient.mk J) x)
⊢ IsUnit x

Tactic:
apply h₁

Result:
case h₂.a
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I J : Ideal S
e : I ≤ J
h₁ : ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x
h₂ : ∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x
x : S
h₃ : IsUnit ((Ideal.Quotient.mk J) x)
⊢ IsUnit ((Ideal.Quotient.mk I) x)

Proof state:
case h₂
R : Type u_2
inst✝ : CommRing R
⊢ ∀ ⦃S : Type u_2⦄ [inst : CommRing S] (I J : Ideal S),
    I ≤ J →
      (∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x) →
        (∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x) →
          ∀ {x : S}, IsUnit ((Ideal.Quotient.mk J) x) → IsUnit x

Tactic:
introv e h₁ h₂ h₃

Result:
case h₂
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I J : Ideal S
e : I ≤ J
h₁ : ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x
h₂ : ∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x
x : S
h₃ : IsUnit ((Ideal.Quotient.mk J) x)
⊢ IsUnit x

Proof state:
case h₂.a.a
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I J : Ideal S
e : I ≤ J
h₁ : ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x
h₂ : ∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x
x : S
h₃ : IsUnit ((Ideal.Quotient.mk J) x)
⊢ IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) ((Ideal.Quotient.mk I) x))

Tactic:
exact
  h₃.map
    ((DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr e))).symm.toRingHom

Result:
no goals

Proof state:
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
this : x * y - 1 ∈ I
⊢ (x * y - 1) ^ 2 ∈ I ^ 2

Tactic:
exact Ideal.pow_mem_pow this _

Result:
no goals

Proof state:
case h₁.intro
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
this✝ : x * y - 1 ∈ I
this : (x * y - 1) ^ 2 = 0
⊢ IsUnit x

Tactic:
have : x * (y * (2 - x * y)) = 1 := by
  rw [eq_comm, ← sub_eq_zero, ← this]
  ring

Result:
case h₁.intro
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
this✝¹ : x * y - 1 ∈ I
this✝ : (x * y - 1) ^ 2 = 0
this : x * (y * (2 - x * y)) = 1
⊢ IsUnit x

Proof state:
case h₁.intro
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
⊢ IsUnit x

Tactic:
have : Ideal.Quotient.mk I (x * y) = Ideal.Quotient.mk I 1 := by
  rw [map_one, _root_.map_mul, hy, IsUnit.mul_val_inv]

Result:
case h₁.intro
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
this : (Ideal.Quotient.mk I) (x * y) = (Ideal.Quotient.mk I) 1
⊢ IsUnit x

Proof state:
R : Type u_2
inst✝ : CommRing R
I : Ideal R
hI : IsNilpotent I
⊢ ∀ {x : R}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x

Tactic:
apply Ideal.IsNilpotent.induction_on (S := R) I hI <;> clear hI I

Result:
case h₁
R : Type u_2
inst✝ : CommRing R
⊢ ∀ ⦃S : Type u_2⦄ [inst : CommRing S] (I : Ideal S), I ^ 2 = ⊥ → ∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x

case h₂
R : Type u_2
inst✝ : CommRing R
⊢ ∀ ⦃S : Type u_2⦄ [inst : CommRing S] (I J : Ideal S),
    I ≤ J →
      (∀ {x : S}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x) →
        (∀ {x : S ⧸ I}, IsUnit ((Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) x) → IsUnit x) →
          ∀ {x : S}, IsUnit ((Ideal.Quotient.mk J) x) → IsUnit x

Proof state:
R : Type u_2
inst✝ : CommRing R
I : Ideal R
hI : IsNilpotent I
x : R
⊢ IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x

Tactic:
revert x

Result:
R : Type u_2
inst✝ : CommRing R
I : Ideal R
hI : IsNilpotent I
⊢ ∀ {x : R}, IsUnit ((Ideal.Quotient.mk I) x) → IsUnit x

Proof state:
R : Type u_2
inst✝¹ : CommRing R
S : Type u_2
inst✝ : CommRing S
I : Ideal S
e : I ^ 2 = ⊥
x : S
H : IsUnit ((Ideal.Quotient.mk I) x)
y : S
hy : (Ideal.Quotient.mk I) y = ↑H.unit⁻¹
⊢ (Ideal.Quotient.mk I) (x * y) = (Ideal.Quotient.mk I) 1

Tactic:
rw [map_one, _root_.map_mul, hy, IsUnit.mul_val_inv]

Result:
no goals