l3lab/ntp-mathlib huggingface dataset:
instance : PerfectRing (PerfectClosure K p) p where
  bijective_frobenius := by
    let f : PerfectClosure K p → PerfectClosure K p := fun e ↦
      liftOn e (fun x => mk K p (x.1 + 1, x.2)) fun x y H =>
      match x, y, H with
      | _, _, R.intro n x => Quot.sound (R.intro _ _)
    have hl : LeftInverse f (frobenius (PerfectClosure K p) p) := fun e ↦
      induction_on e fun ⟨n, x⟩ => by
        simp only [liftOn_mk, frobenius_mk]
        exact (Quot.sound <| R.intro _ _).symm
    have hr : RightInverse f (frobenius (PerfectClosure K p) p) := fun e ↦
      induction_on e fun ⟨n, x⟩ => by
        

Proof state:
K : Type u
inst✝² : Field K
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP K p
f : PerfectClosure K p → PerfectClosure K p :=
  fun e =>
    liftOn e (fun x => mk K p (x.1 + 1, x.2))
      (_ : ∀ (x y : ℕ × K), R K p x y → (fun x => mk K p (x.1 + 1, x.2)) x = (fun x => mk K p (x.1 + 1, x.2)) y)
hl : LeftInverse f ⇑(frobenius (PerfectClosure K p) p)
e : PerfectClosure K p
x✝ : ℕ × K
n : ℕ
x : K
⊢ (frobenius (PerfectClosure K p) p) (f (mk K p (n, x))) = mk K p (n, x)

Next tactic:
simp only [liftOn_mk, frobenius_mk]
instance : PerfectRing (PerfectClosure K p) p where
  bijective_frobenius := by
    let f : PerfectClosure K p → PerfectClosure K p := fun e ↦
      liftOn e (fun x => mk K p (x.1 + 1, x.2)) fun x y H =>
      match x, y, H with
      | _, _, R.intro n x => Quot.sound (R.intro _ _)
    have hl : LeftInverse f (frobenius (PerfectClosure K p) p) := fun e ↦
      induction_on e fun ⟨n, x⟩ => by
        simp only [liftOn_mk, frobenius_mk]
        exact (Quot.sound <| R.intro _ _).symm
    have hr : RightInverse f (frobenius (PerfectClosure K p) p) := fun e ↦
      induction_on e fun ⟨n, x⟩ => by
        simp only [liftOn_mk, frobenius_mk]
        

Proof state:
K : Type u
inst✝² : Field K
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP K p
f : PerfectClosure K p → PerfectClosure K p :=
  fun e =>
    liftOn e (fun x => mk K p (x.1 + 1, x.2))
      (_ : ∀ (x y : ℕ × K), R K p x y → (fun x => mk K p (x.1 + 1, x.2)) x = (fun x => mk K p (x.1 + 1, x.2)) y)
hl : LeftInverse f ⇑(frobenius (PerfectClosure K p) p)
e : PerfectClosure K p
x✝ : ℕ × K
n : ℕ
x : K
⊢ mk K p (n + 1, x ^ p) = mk K p (n, x)

Next tactic:
exact (Quot.sound <| R.intro _ _).symm
instance : PerfectRing (PerfectClosure K p) p where
  bijective_frobenius := by
    let f : PerfectClosure K p → PerfectClosure K p := fun e ↦
      liftOn e (fun x => mk K p (x.1 + 1, x.2)) fun x y H =>
      match x, y, H with
      | _, _, R.intro n x => Quot.sound (R.intro _ _)
    have hl : LeftInverse f (frobenius (PerfectClosure K p) p) := fun e ↦
      induction_on e fun ⟨n, x⟩ => by
        simp only [liftOn_mk, frobenius_mk]
        exact (Quot.sound <| R.intro _ _).symm
    have hr : RightInverse f (frobenius (PerfectClosure K p) p) := fun e ↦
      induction_on e fun ⟨n, x⟩ => by
        simp only [liftOn_mk, frobenius_mk]
        exact (Quot.sound <| R.intro _ _).symm
    

Proof state:
K : Type u
inst✝² : Field K
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP K p
f : PerfectClosure K p → PerfectClosure K p :=
  fun e =>
    liftOn e (fun x => mk K p (x.1 + 1, x.2))
      (_ : ∀ (x y : ℕ × K), R K p x y → (fun x => mk K p (x.1 + 1, x.2)) x = (fun x => mk K p (x.1 + 1, x.2)) y)
hl : LeftInverse f ⇑(frobenius (PerfectClosure K p) p)
hr : Function.RightInverse f ⇑(frobenius (PerfectClosure K p) p)
⊢ Bijective ⇑(frobenius (PerfectClosure K p) p)

Next tactic:
exact bijective_iff_has_inverse.mpr ⟨f, hl, hr⟩
@[simp]
theorem iterate_frobenius_mk (n : ℕ) (x : K) :
    (frobenius (PerfectClosure K p) p)^[n] (mk K p ⟨n, x⟩) = of K p x := by
  

Proof state:
K : Type u
inst✝² : Field K
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP K p
n : ℕ
x : K
⊢ (⇑(frobenius (PerfectClosure K p) p))^[n] (mk K p (n, x)) = (of K p) x

Next tactic:
induction' n with n ih
@[simp]
theorem iterate_frobenius_mk (n : ℕ) (x : K) :
    (frobenius (PerfectClosure K p) p)^[n] (mk K p ⟨n, x⟩) = of K p x := by
  induction' n with n ih; 

Proof state:
case zero
K : Type u
inst✝² : Field K
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP K p
x : K
⊢ (⇑(frobenius (PerfectClosure K p) p))^[Nat.zero] (mk K p (Nat.zero, x)) = (of K p) x
case succ
K : Type u
inst✝² : Field K
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP K p
x : K
n : ℕ
ih : (⇑(frobenius (PerfectClosure K p) p))^[n] (mk K p (n, x)) = (of K p) x
⊢ (⇑(frobenius (PerfectClosure K p) p))^[Nat.succ n] (mk K p (Nat.succ n, x)) = (of K p) x

Next tactic:
rfl
@[simp]
theorem iterate_frobenius_mk (n : ℕ) (x : K) :
    (frobenius (PerfectClosure K p) p)^[n] (mk K p ⟨n, x⟩) = of K p x := by
  induction' n with n ih; rfl
  

Proof state:
case succ
K : Type u
inst✝² : Field K
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP K p
x : K
n : ℕ
ih : (⇑(frobenius (PerfectClosure K p) p))^[n] (mk K p (n, x)) = (of K p) x
⊢ (⇑(frobenius (PerfectClosure K p) p))^[Nat.succ n] (mk K p (Nat.succ n, x)) = (of K p) x

Next tactic:
rw [iterate_succ_apply, ← ih, frobenius_mk, mk_succ_pow]
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        

Proof state:
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
⊢ PerfectClosure K p → L

Next tactic:
refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        

Proof state:
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
e : PerfectClosure K p
⊢ ∀ (x y : ℕ × K),
    R K p x y →
      (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) x =
        (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) y

Next tactic:
rintro - - ⟨n, x⟩
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        

Proof state:
case intro
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
e : PerfectClosure K p
n : ℕ
x : K
⊢ (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) (n, x) =
    (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) (n + 1, (frobenius K p) x)

Next tactic:
simp [f.map_frobenius]
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        

Proof state:
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
⊢ ∀ (x y : PerfectClosure K p),
    OneHom.toFun
        {
          toFun := fun e =>
            liftOn e (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2))
              (_ :
                ∀ (x y : ℕ × K),
                  R K p x y →
                    (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) x =
                      (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) y),
          map_one' := (_ : f 1 = 1) }
        (x * y) =
      OneHom.toFun
          {
            toFun := fun e =>
              liftOn e (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2))
                (_ :
                  ∀ (x y : ℕ × K),
                    R K p x y →
                      (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) x =
                        (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) y),
            map_one' := (_ : f 1 = 1) }
          x *
        OneHom.toFun
          {
            toFun := fun e =>
              liftOn e (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2))
                (_ :
                  ∀ (x y : ℕ × K),
                    R K p x y →
                      (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) x =
                        (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) y),
            map_one' := (_ : f 1 = 1) }
          y

Next tactic:
rintro ⟨n, x⟩ ⟨m, y⟩
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        

Proof state:
case mk.mk.mk.mk
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
x✝ : PerfectClosure K p
n : ℕ
x : K
y✝ : PerfectClosure K p
m : ℕ
y : K
⊢ OneHom.toFun
      {
        toFun := fun e =>
          liftOn e (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2))
            (_ :
              ∀ (x y : ℕ × K),
                R K p x y →
                  (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) x =
                    (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) y),
        map_one' := (_ : f 1 = 1) }
      (Quot.mk (R K p) (n, x) * Quot.mk (R K p) (m, y)) =
    OneHom.toFun
        {
          toFun := fun e =>
            liftOn e (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2))
              (_ :
                ∀ (x y : ℕ × K),
                  R K p x y →
                    (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) x =
                      (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) y),
          map_one' := (_ : f 1 = 1) }
        (Quot.mk (R K p) (n, x)) *
      OneHom.toFun
        {
          toFun := fun e =>
            liftOn e (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2))
              (_ :
                ∀ (x y : ℕ × K),
                  R K p x y →
                    (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) x =
                      (fun x => (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[x.1] (f x.2)) y),
          map_one' := (_ : f 1 = 1) }
        (Quot.mk (R K p) (m, y))

Next tactic:
simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_mul_mk, map_mul,
          iterate_map_mul]
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_mul_mk, map_mul,
          iterate_map_mul]
        

Proof state:
case mk.mk.mk.mk
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
x✝ : PerfectClosure K p
n : ℕ
x : K
y✝ : PerfectClosure K p
m : ℕ
y : K
⊢ (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[m] (f x)) *
      (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[n] (f y)) =
    (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (f x) * (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[m] (f y)

Next tactic:
have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_mul_mk, map_mul,
          iterate_map_mul]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        

Proof state:
case mk.mk.mk.mk
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
x✝ : PerfectClosure K p
n : ℕ
x : K
y✝ : PerfectClosure K p
m : ℕ
y : K
this : ∀ (n : ℕ), LeftInverse (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (fun x => (frobenius L p) x)^[n]
⊢ (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[m] (f x)) *
      (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[n] (f y)) =
    (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (f x) * (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[m] (f y)

Next tactic:
rw [iterate_add_apply, this _ _, add_comm, iterate_add_apply, this _ _]
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_mul_mk, map_mul,
          iterate_map_mul]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        rw [iterate_add_apply, this _ _, add_comm, iterate_add_apply, this _ _]
      map_add' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_add_mk, map_add,
          iterate_map_add]
        

Proof state:
case mk.mk.mk.mk
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
x✝ : PerfectClosure K p
n : ℕ
x : K
y✝ : PerfectClosure K p
m : ℕ
y : K
⊢ (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[m] (f x)) +
      (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[n] (f y)) =
    (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (f x) + (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[m] (f y)

Next tactic:
have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_mul_mk, map_mul,
          iterate_map_mul]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        rw [iterate_add_apply, this _ _, add_comm, iterate_add_apply, this _ _]
      map_add' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_add_mk, map_add,
          iterate_map_add]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        

Proof state:
case mk.mk.mk.mk
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : K →+* L
x✝ : PerfectClosure K p
n : ℕ
x : K
y✝ : PerfectClosure K p
m : ℕ
y : K
this : ∀ (n : ℕ), LeftInverse (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (fun x => (frobenius L p) x)^[n]
⊢ (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[m] (f x)) +
      (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n + m] ((⇑(frobenius L p))^[n] (f y)) =
    (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (f x) + (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[m] (f y)

Next tactic:
rw [iterate_add_apply, this _ _, add_comm n, iterate_add_apply, this _ _]
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_mul_mk, map_mul,
          iterate_map_mul]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        rw [iterate_add_apply, this _ _, add_comm, iterate_add_apply, this _ _]
      map_add' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_add_mk, map_add,
          iterate_map_add]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        rw [iterate_add_apply, this _ _, add_comm n, iterate_add_apply, this _ _] }
  invFun f := f.comp (of K p)
  left_inv f := by ext x; rfl
  right_inv f := by
    ext ⟨n, x⟩
    simp only [quot_mk_eq_mk, RingHom.comp_apply, RingHom.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk,
      liftOn_mk]
    

Proof state:
case a.mk.mk
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : PerfectClosure K p →+* L
x✝ : PerfectClosure K p
n : ℕ
x : K
⊢ (⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (f ((of K p) x)) = f (mk K p (n, x))

Next tactic:
apply (injective_frobenius L p).iterate n
/-- Given a field `K` of characteristic `p` and a perfect ring `L` of the same characteristic,
any homomorphism `K →+* L` can be lifted to `PerfectClosure K p`. -/
noncomputable def lift (L : Type v) [CommSemiring L] [CharP L p] [PerfectRing L p] :
    (K →+* L) ≃ (PerfectClosure K p →+* L) where
  toFun f :=
    { toFun := by
        refine' fun e => liftOn e (fun x => (frobeniusEquiv L p).symm^[x.1] (f x.2)) _
        rintro - - ⟨n, x⟩
        simp [f.map_frobenius]
      map_one' := f.map_one
      map_zero' := f.map_zero
      map_mul' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_mul_mk, map_mul,
          iterate_map_mul]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        rw [iterate_add_apply, this _ _, add_comm, iterate_add_apply, this _ _]
      map_add' := by
        rintro ⟨n, x⟩ ⟨m, y⟩
        simp only [quot_mk_eq_mk, liftOn_mk, f.map_iterate_frobenius, mk_add_mk, map_add,
          iterate_map_add]
        have := LeftInverse.iterate (frobeniusEquiv_symm_apply_frobenius L p)
        rw [iterate_add_apply, this _ _, add_comm n, iterate_add_apply, this _ _] }
  invFun f := f.comp (of K p)
  left_inv f := by ext x; rfl
  right_inv f := by
    ext ⟨n, x⟩
    simp only [quot_mk_eq_mk, RingHom.comp_apply, RingHom.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk,
      liftOn_mk]
    apply (injective_frobenius L p).iterate n
    

Proof state:
case a.mk.mk.a
K : Type u
inst✝⁵ : Field K
p : ℕ
inst✝⁴ : Fact (Nat.Prime p)
inst✝³ : CharP K p
L : Type v
inst✝² : CommSemiring L
inst✝¹ : CharP L p
inst✝ : PerfectRing L p
f : PerfectClosure K p →+* L
x✝ : PerfectClosure K p
n : ℕ
x : K
⊢ (⇑(frobenius L p))^[n] ((⇑(RingEquiv.symm (frobeniusEquiv L p)))^[n] (f ((of K p) x))) =
    (⇑(frobenius L p))^[n] (f (mk K p (n, x)))

Next tactic:
rw [← f.map_iterate_frobenius, iterate_frobenius_mk,
      RightInverse.iterate (frobenius_apply_frobeniusEquiv_symm L p) n]
theorem mk.inj_left {α β : Type*} (a : α) : Function.Injective (Prod.mk a : β → α × β) := by
  

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
α : Type u_5
β : Type u_6
a : α
⊢ Function.Injective (mk a)

Next tactic:
intro b₁ b₂ h
theorem mk.inj_left {α β : Type*} (a : α) : Function.Injective (Prod.mk a : β → α × β) := by
  intro b₁ b₂ h
  

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
α : Type u_5
β : Type u_6
a : α
b₁ b₂ : β
h : (a, b₁) = (a, b₂)
⊢ b₁ = b₂

Next tactic:
simpa only [true_and, Prod.mk.inj_iff, eq_self_iff_true] using h
theorem mk.inj_right {α β : Type*} (b : β) :
    Function.Injective (fun a ↦ Prod.mk a b : α → α × β) := by
  

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
α : Type u_5
β : Type u_6
b : β
⊢ Function.Injective fun a => (a, b)

Next tactic:
intro b₁ b₂ h
theorem mk.inj_right {α β : Type*} (b : β) :
    Function.Injective (fun a ↦ Prod.mk a b : α → α × β) := by
  intro b₁ b₂ h
  

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
δ : Type u_4
α : Type u_5
β : Type u_6
b : β
b₁ b₂ : α
h : (fun a => (a, b)) b₁ = (fun a => (a, b)) b₂
⊢ b₁ = b₂

Next tactic:
simpa only [and_true, eq_self_iff_true, mk.inj_iff] using h
theorem ext_iff {p q : α × β} : p = q ↔ p.1 = q.1 ∧ p.2 = q.2 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
p q : α × β
⊢ p = q ↔ p.fst = q.fst ∧ p.snd = q.snd

Next tactic:
rw [mk.inj_iff]
theorem eq_iff_fst_eq_snd_eq : ∀ {p q : α × β}, p = q ↔ p.1 = q.1 ∧ p.2 = q.2
  | ⟨p₁, p₂⟩, ⟨q₁, q₂⟩ => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
p₁ : α
p₂ : β
q₁ : α
q₂ : β
⊢ (p₁, p₂) = (q₁, q₂) ↔ (p₁, p₂).fst = (q₁, q₂).fst ∧ (p₁, p₂).snd = (q₁, q₂).snd

Next tactic:
simp
theorem fst_eq_iff : ∀ {p : α × β} {x : α}, p.1 = x ↔ p = (x, p.2)
  | ⟨a, b⟩, x => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
a : α
b : β
x : α
⊢ (a, b).fst = x ↔ (a, b) = (x, (a, b).snd)

Next tactic:
simp
theorem snd_eq_iff : ∀ {p : α × β} {x : β}, p.2 = x ↔ p = (p.1, x)
  | ⟨a, b⟩, x => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
a : α
b x : β
⊢ (a, b).snd = x ↔ (a, b) = ((a, b).fst, x)

Next tactic:
simp