l3lab/ntp-mathlib huggingface dataset:
/-- `MonoOver.image : Over X ⥤ MonoOver X` is left adjoint to
`MonoOver.forget : MonoOver X ⥤ Over X`
-/
def imageForgetAdj : image ⊣ forget X :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun f g =>
        { toFun := fun k => by
            apply Over.homMk (factorThruImage f.hom ≫ k.left) _
            change (factorThruImage f.hom ≫ k.left) ≫ _ = f.hom
            rw [assoc, Over.w k]
            apply image.fac
          invFun := fun k => by
            refine' Over.homMk _ _
            refine'
              image.lift
                { I := g.obj.left
                  m := g.arrow
                  e := k.left
                  fac := Over.w k }
            apply image.lift_fac
          left_inv := fun k => Subsingleton.elim _ _
          right_inv := fun k => by
            ext1
            change factorThruImage _ ≫ image.lift _ = _
            

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X Y Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasImages C
f : Over X
g : MonoOver X
k : f ⟶ (forget X).obj g
⊢ factorThruImage f.hom ≫ image.lift (MonoFactorisation.mk g.obj.left (arrow g) k.left) = k.left

Next tactic:
rw [← cancel_mono g.arrow, assoc, image.lift_fac, image.fac f.hom]
/-- `MonoOver.image : Over X ⥤ MonoOver X` is left adjoint to
`MonoOver.forget : MonoOver X ⥤ Over X`
-/
def imageForgetAdj : image ⊣ forget X :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun f g =>
        { toFun := fun k => by
            apply Over.homMk (factorThruImage f.hom ≫ k.left) _
            change (factorThruImage f.hom ≫ k.left) ≫ _ = f.hom
            rw [assoc, Over.w k]
            apply image.fac
          invFun := fun k => by
            refine' Over.homMk _ _
            refine'
              image.lift
                { I := g.obj.left
                  m := g.arrow
                  e := k.left
                  fac := Over.w k }
            apply image.lift_fac
          left_inv := fun k => Subsingleton.elim _ _
          right_inv := fun k => by
            ext1
            change factorThruImage _ ≫ image.lift _ = _
            rw [← cancel_mono g.arrow, assoc, image.lift_fac, image.fac f.hom]
            

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
X Y Z : C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
inst✝ : HasImages C
f : Over X
g : MonoOver X
k : f ⟶ (forget X).obj g
⊢ f.hom = k.left ≫ arrow g

Next tactic:
exact (Over.w k).symm
/-- When `f : X ⟶ Y` is a monomorphism, `exists f` agrees with `map f`.
-/
def existsIsoMap (f : X ⟶ Y) [Mono f] : «exists» f ≅ map f :=
  NatIso.ofComponents (by
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
X Y Z : C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasImages C
f : X ⟶ Y
inst✝ : Mono f
⊢ (X_1 : MonoOver X) → (exists f).obj X_1 ≅ (map f).obj X_1

Next tactic:
intro Z
/-- When `f : X ⟶ Y` is a monomorphism, `exists f` agrees with `map f`.
-/
def existsIsoMap (f : X ⟶ Y) [Mono f] : «exists» f ≅ map f :=
  NatIso.ofComponents (by
    intro Z
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
X Y Z✝ : C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasImages C
f : X ⟶ Y
inst✝ : Mono f
Z : MonoOver X
⊢ (exists f).obj Z ≅ (map f).obj Z

Next tactic:
suffices (forget _).obj ((«exists» f).obj Z) ≅ (forget _).obj ((map f).obj Z) by
      apply (forget _).preimageIso this
/-- When `f : X ⟶ Y` is a monomorphism, `exists f` agrees with `map f`.
-/
def existsIsoMap (f : X ⟶ Y) [Mono f] : «exists» f ≅ map f :=
  NatIso.ofComponents (by
    intro Z
    suffices (forget _).obj ((«exists» f).obj Z) ≅ (forget _).obj ((map f).obj Z) by
      

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
X Y Z✝ : C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasImages C
f : X ⟶ Y
inst✝ : Mono f
Z : MonoOver X
this : (forget Y).obj ((exists f).obj Z) ≅ (forget Y).obj ((map f).obj Z)
⊢ (exists f).obj Z ≅ (map f).obj Z

Next tactic:
apply (forget _).preimageIso this
/-- When `f : X ⟶ Y` is a monomorphism, `exists f` agrees with `map f`.
-/
def existsIsoMap (f : X ⟶ Y) [Mono f] : «exists» f ≅ map f :=
  NatIso.ofComponents (by
    intro Z
    suffices (forget _).obj ((«exists» f).obj Z) ≅ (forget _).obj ((map f).obj Z) by
      apply (forget _).preimageIso this
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
X Y Z✝ : C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasImages C
f : X ⟶ Y
inst✝ : Mono f
Z : MonoOver X
⊢ (forget Y).obj ((exists f).obj Z) ≅ (forget Y).obj ((map f).obj Z)

Next tactic:
apply Over.isoMk _ _
/-- When `f : X ⟶ Y` is a monomorphism, `exists f` agrees with `map f`.
-/
def existsIsoMap (f : X ⟶ Y) [Mono f] : «exists» f ≅ map f :=
  NatIso.ofComponents (by
    intro Z
    suffices (forget _).obj ((«exists» f).obj Z) ≅ (forget _).obj ((map f).obj Z) by
      apply (forget _).preimageIso this
    apply Over.isoMk _ _
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
X Y Z✝ : C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasImages C
f : X ⟶ Y
inst✝ : Mono f
Z : MonoOver X
⊢ ((forget Y).obj ((exists f).obj Z)).left ≅ ((forget Y).obj ((map f).obj Z)).left
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
X Y Z✝ : C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasImages C
f : X ⟶ Y
inst✝ : Mono f
Z : MonoOver X
⊢ ?m.258988.hom ≫ ((forget Y).obj ((map f).obj Z)).hom = ((forget Y).obj ((exists f).obj Z)).hom

Next tactic:
apply imageMonoIsoSource (Z.arrow ≫ f)
/-- When `f : X ⟶ Y` is a monomorphism, `exists f` agrees with `map f`.
-/
def existsIsoMap (f : X ⟶ Y) [Mono f] : «exists» f ≅ map f :=
  NatIso.ofComponents (by
    intro Z
    suffices (forget _).obj ((«exists» f).obj Z) ≅ (forget _).obj ((map f).obj Z) by
      apply (forget _).preimageIso this
    apply Over.isoMk _ _
    apply imageMonoIsoSource (Z.arrow ≫ f)
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
X Y Z✝ : C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
inst✝¹ : HasImages C
f : X ⟶ Y
inst✝ : Mono f
Z : MonoOver X
⊢ (imageMonoIsoSource (arrow Z ≫ f)).hom ≫ ((forget Y).obj ((map f).obj Z)).hom =
    ((forget Y).obj ((exists f).obj Z)).hom

Next tactic:
apply imageMonoIsoSource_hom_self
theorem ext_iff {x y : TruncatedWittVector p n R} : x = y ↔ ∀ i, x.coeff i = y.coeff i :=
  ⟨fun h i => by 

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
x y : TruncatedWittVector p n R
h : x = y
i : Fin n
⊢ coeff i x = coeff i y

Next tactic:
rw [h]
@[simp]
theorem mk_coeff (x : TruncatedWittVector p n R) : (mk p fun i => x.coeff i) = x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
x : TruncatedWittVector p n R
⊢ (mk p fun i => coeff i x) = x

Next tactic:
ext i
@[simp]
theorem mk_coeff (x : TruncatedWittVector p n R) : (mk p fun i => x.coeff i) = x := by
  ext i; 

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
x : TruncatedWittVector p n R
i : Fin n
⊢ coeff i (mk p fun i => coeff i x) = coeff i x

Next tactic:
rw [coeff_mk]
@[simp]
theorem coeff_out (x : TruncatedWittVector p n R) (i : Fin n) : x.out.coeff i = x.coeff i := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : TruncatedWittVector p n R
i : Fin n
⊢ WittVector.coeff (out x) ↑i = coeff i x

Next tactic:
rw [out]
@[simp]
theorem coeff_out (x : TruncatedWittVector p n R) (i : Fin n) : x.out.coeff i = x.coeff i := by
  rw [out]; 

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : TruncatedWittVector p n R
i : Fin n
⊢ WittVector.coeff { coeff := fun i => if h : i < n then coeff { val := i, isLt := h } x else 0 } ↑i = coeff i x

Next tactic:
dsimp only
@[simp]
theorem coeff_out (x : TruncatedWittVector p n R) (i : Fin n) : x.out.coeff i = x.coeff i := by
  rw [out]; dsimp only; 

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : TruncatedWittVector p n R
i : Fin n
⊢ (if h : ↑i < n then coeff { val := ↑i, isLt := h } x else 0) = coeff i x

Next tactic:
rw [dif_pos i.is_lt, Fin.eta]
theorem out_injective : Injective (@out p n R _) := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
⊢ Injective out

Next tactic:
intro x y h
theorem out_injective : Injective (@out p n R _) := by
  intro x y h
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x y : TruncatedWittVector p n R
h : out x = out y
⊢ x = y

Next tactic:
ext i
theorem out_injective : Injective (@out p n R _) := by
  intro x y h
  ext i
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x y : TruncatedWittVector p n R
h : out x = out y
i : Fin n
⊢ coeff i x = coeff i y

Next tactic:
rw [WittVector.ext_iff] at h
theorem out_injective : Injective (@out p n R _) := by
  intro x y h
  ext i
  rw [WittVector.ext_iff] at h
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x y : TruncatedWittVector p n R
h : ∀ (n_1 : ℕ), WittVector.coeff (out x) n_1 = WittVector.coeff (out y) n_1
i : Fin n
⊢ coeff i x = coeff i y

Next tactic:
simpa only [coeff_out] using h ↑i
@[simp]
theorem coeff_truncateFun (x : 𝕎 R) (i : Fin n) : (truncateFun n x).coeff i = x.coeff i := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
x : 𝕎 R
i : Fin n
⊢ TruncatedWittVector.coeff i (truncateFun n x) = coeff x ↑i

Next tactic:
rw [truncateFun, TruncatedWittVector.coeff_mk]
@[simp]
theorem out_truncateFun (x : 𝕎 R) : (truncateFun n x).out = init n x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
⊢ TruncatedWittVector.out (truncateFun n x) = init n x

Next tactic:
ext i
@[simp]
theorem out_truncateFun (x : 𝕎 R) : (truncateFun n x).out = init n x := by
  ext i
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
i : ℕ
⊢ coeff (TruncatedWittVector.out (truncateFun n x)) i = coeff (init n x) i

Next tactic:
dsimp [TruncatedWittVector.out, init, select, coeff_mk]
@[simp]
theorem out_truncateFun (x : 𝕎 R) : (truncateFun n x).out = init n x := by
  ext i
  dsimp [TruncatedWittVector.out, init, select, coeff_mk]
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
i : ℕ
⊢ (if h : i < n then TruncatedWittVector.coeff { val := i, isLt := h } (truncateFun n x) else 0) =
    if i < n then coeff x i else 0

Next tactic:
split_ifs with hi
@[simp]
theorem out_truncateFun (x : 𝕎 R) : (truncateFun n x).out = init n x := by
  ext i
  dsimp [TruncatedWittVector.out, init, select, coeff_mk]
  split_ifs with hi; 

Proof state:
case pos
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
i : ℕ
hi : i < n
⊢ TruncatedWittVector.coeff { val := i, isLt := hi } (truncateFun n x) = coeff x i
case neg p : ℕ hp : Fact (Nat.Prime p) n : ℕ R : Type u_1 inst✝ : CommRing R x : 𝕎 R i : ℕ hi : ¬i < n ⊢ 0 = 0

Next tactic:
swap
@[simp]
theorem out_truncateFun (x : 𝕎 R) : (truncateFun n x).out = init n x := by
  ext i
  dsimp [TruncatedWittVector.out, init, select, coeff_mk]
  split_ifs with hi; swap; · 

Proof state:
case neg
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
i : ℕ
hi : ¬i < n
⊢ 0 = 0

Next tactic:
rfl
@[simp]
theorem out_truncateFun (x : 𝕎 R) : (truncateFun n x).out = init n x := by
  ext i
  dsimp [TruncatedWittVector.out, init, select, coeff_mk]
  split_ifs with hi; swap; · rfl
  

Proof state:
case pos
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
i : ℕ
hi : i < n
⊢ TruncatedWittVector.coeff { val := i, isLt := hi } (truncateFun n x) = coeff x i

Next tactic:
rw [coeff_truncateFun, Fin.val_mk]
@[simp]
theorem truncateFun_out (x : TruncatedWittVector p n R) : x.out.truncateFun n = x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : TruncatedWittVector p n R
⊢ WittVector.truncateFun n (out x) = x

Next tactic:
simp only [WittVector.truncateFun, coeff_out, mk_coeff]
@[simp]
theorem coeff_zero (i : Fin n) : (0 : TruncatedWittVector p n R).coeff i = 0 := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
i : Fin n
⊢ coeff i 0 = 0

Next tactic:
show coeff i (truncateFun _ 0 : TruncatedWittVector p n R) = 0
@[simp]
theorem coeff_zero (i : Fin n) : (0 : TruncatedWittVector p n R).coeff i = 0 := by
  show coeff i (truncateFun _ 0 : TruncatedWittVector p n R) = 0
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
i : Fin n
⊢ coeff i (truncateFun n 0) = 0

Next tactic:
rw [coeff_truncateFun, WittVector.zero_coeff]
@[simp]
theorem truncateFun_add (x y : 𝕎 R) :
    truncateFun n (x + y) = truncateFun n x + truncateFun n y := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x y : 𝕎 R
⊢ truncateFun n (x + y) = truncateFun n x + truncateFun n y

Next tactic:
witt_truncateFun_tac
@[simp]
theorem truncateFun_mul (x y : 𝕎 R) :
    truncateFun n (x * y) = truncateFun n x * truncateFun n y := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x y : 𝕎 R
⊢ truncateFun n (x * y) = truncateFun n x * truncateFun n y

Next tactic:
witt_truncateFun_tac
theorem truncateFun_neg (x : 𝕎 R) : truncateFun n (-x) = -truncateFun n x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
⊢ truncateFun n (-x) = -truncateFun n x

Next tactic:
witt_truncateFun_tac
theorem truncateFun_sub (x y : 𝕎 R) :
    truncateFun n (x - y) = truncateFun n x - truncateFun n y := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x y : 𝕎 R
⊢ truncateFun n (x - y) = truncateFun n x - truncateFun n y

Next tactic:
witt_truncateFun_tac
theorem truncateFun_nsmul (x : 𝕎 R) (m : ℕ) : truncateFun n (m • x) = m • truncateFun n x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
m : ℕ
⊢ truncateFun n (m • x) = m • truncateFun n x

Next tactic:
witt_truncateFun_tac
theorem truncateFun_zsmul (x : 𝕎 R) (m : ℤ) : truncateFun n (m • x) = m • truncateFun n x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
m : ℤ
⊢ truncateFun n (m • x) = m • truncateFun n x

Next tactic:
witt_truncateFun_tac
theorem truncateFun_pow (x : 𝕎 R) (m : ℕ) : truncateFun n (x ^ m) = truncateFun n x ^ m := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
m : ℕ
⊢ truncateFun n (x ^ m) = truncateFun n x ^ m

Next tactic:
witt_truncateFun_tac
theorem mem_ker_truncate (x : 𝕎 R) :
    x ∈ RingHom.ker (@truncate p _ n R _) ↔ ∀ i < n, x.coeff i = 0 := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
⊢ x ∈ RingHom.ker (truncate n) ↔ ∀ i < n, coeff x i = 0

Next tactic:
simp only [RingHom.mem_ker, truncate, truncateFun, RingHom.coe_mk, TruncatedWittVector.ext_iff,
    TruncatedWittVector.coeff_mk, coeff_zero]
theorem mem_ker_truncate (x : 𝕎 R) :
    x ∈ RingHom.ker (@truncate p _ n R _) ↔ ∀ i < n, x.coeff i = 0 := by
  simp only [RingHom.mem_ker, truncate, truncateFun, RingHom.coe_mk, TruncatedWittVector.ext_iff,
    TruncatedWittVector.coeff_mk, coeff_zero]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
⊢ (∀ (i : Fin n),
      TruncatedWittVector.coeff i
          ({ toOneHom := { toFun := truncateFun n, map_one' := (_ : truncateFun n 1 = 1) },
              map_mul' := (_ : ∀ (x y : 𝕎 R), truncateFun n (x * y) = truncateFun n x * truncateFun n y) }
            x) =
        0) ↔
    ∀ i < n, coeff x i = 0

Next tactic:
exact Fin.forall_iff
@[simp]
theorem truncate_mk' (f : ℕ → R) :
    truncate n (@mk' p _ f) = TruncatedWittVector.mk _ fun k => f k := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
f : ℕ → R
⊢ (truncate n) { coeff := f } = TruncatedWittVector.mk p fun k => f ↑k

Next tactic:
ext i
@[simp]
theorem truncate_mk' (f : ℕ → R) :
    truncate n (@mk' p _ f) = TruncatedWittVector.mk _ fun k => f k := by
  ext i
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
f : ℕ → R
i : Fin n
⊢ TruncatedWittVector.coeff i ((truncate n) { coeff := f }) =
    TruncatedWittVector.coeff i (TruncatedWittVector.mk p fun k => f ↑k)

Next tactic:
simp only [coeff_truncate, TruncatedWittVector.coeff_mk]
/-- A ring homomorphism that truncates a truncated Witt vector of length `m` to
a truncated Witt vector of length `n`, for `n ≤ m`.
-/
def truncate {m : ℕ} (hm : n ≤ m) : TruncatedWittVector p m R →+* TruncatedWittVector p n R :=
  RingHom.liftOfRightInverse (WittVector.truncate m) out truncateFun_out
    ⟨WittVector.truncate n, by
      

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
⊢ RingHom.ker (WittVector.truncate m) ≤ RingHom.ker (WittVector.truncate n)

Next tactic:
intro x
/-- A ring homomorphism that truncates a truncated Witt vector of length `m` to
a truncated Witt vector of length `n`, for `n ≤ m`.
-/
def truncate {m : ℕ} (hm : n ≤ m) : TruncatedWittVector p m R →+* TruncatedWittVector p n R :=
  RingHom.liftOfRightInverse (WittVector.truncate m) out truncateFun_out
    ⟨WittVector.truncate n, by
      intro x
      

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
x : 𝕎 R
⊢ x ∈ RingHom.ker (WittVector.truncate m) → x ∈ RingHom.ker (WittVector.truncate n)

Next tactic:
simp only [WittVector.mem_ker_truncate]
/-- A ring homomorphism that truncates a truncated Witt vector of length `m` to
a truncated Witt vector of length `n`, for `n ≤ m`.
-/
def truncate {m : ℕ} (hm : n ≤ m) : TruncatedWittVector p m R →+* TruncatedWittVector p n R :=
  RingHom.liftOfRightInverse (WittVector.truncate m) out truncateFun_out
    ⟨WittVector.truncate n, by
      intro x
      simp only [WittVector.mem_ker_truncate]
      

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
x : 𝕎 R
⊢ (∀ i < m, WittVector.coeff x i = 0) → ∀ i < n, WittVector.coeff x i = 0

Next tactic:
intro h i hi
/-- A ring homomorphism that truncates a truncated Witt vector of length `m` to
a truncated Witt vector of length `n`, for `n ≤ m`.
-/
def truncate {m : ℕ} (hm : n ≤ m) : TruncatedWittVector p m R →+* TruncatedWittVector p n R :=
  RingHom.liftOfRightInverse (WittVector.truncate m) out truncateFun_out
    ⟨WittVector.truncate n, by
      intro x
      simp only [WittVector.mem_ker_truncate]
      intro h i hi
      

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
x : 𝕎 R
h : ∀ i < m, WittVector.coeff x i = 0
i : ℕ
hi : i < n
⊢ WittVector.coeff x i = 0

Next tactic:
exact h i (lt_of_lt_of_le hi hm)
@[simp]
theorem truncate_truncate {n₁ n₂ n₃ : ℕ} (h1 : n₁ ≤ n₂) (h2 : n₂ ≤ n₃)
    (x : TruncatedWittVector p n₃ R) :
    (truncate h1) (truncate h2 x) = truncate (h1.trans h2) x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
n₁ n₂ n₃ : ℕ
h1 : n₁ ≤ n₂
h2 : n₂ ≤ n₃
x : TruncatedWittVector p n₃ R
⊢ (truncate h1) ((truncate h2) x) = (truncate (_ : n₁ ≤ n₃)) x

Next tactic:
obtain ⟨x, rfl⟩ := @WittVector.truncate_surjective p _ n₃ R _ x
@[simp]
theorem truncate_truncate {n₁ n₂ n₃ : ℕ} (h1 : n₁ ≤ n₂) (h2 : n₂ ≤ n₃)
    (x : TruncatedWittVector p n₃ R) :
    (truncate h1) (truncate h2 x) = truncate (h1.trans h2) x := by
  obtain ⟨x, rfl⟩ := @WittVector.truncate_surjective p _ n₃ R _ x
  

Proof state:
case intro
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
n₁ n₂ n₃ : ℕ
h1 : n₁ ≤ n₂
h2 : n₂ ≤ n₃
x : 𝕎 R
⊢ (truncate h1) ((truncate h2) ((WittVector.truncate n₃) x)) = (truncate (_ : n₁ ≤ n₃)) ((WittVector.truncate n₃) x)

Next tactic:
simp only [truncate_wittVector_truncate]
@[simp]
theorem truncate_comp {n₁ n₂ n₃ : ℕ} (h1 : n₁ ≤ n₂) (h2 : n₂ ≤ n₃) :
    (@truncate p _ _ R _ _ h1).comp (truncate h2) = truncate (h1.trans h2) := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
n₁ n₂ n₃ : ℕ
h1 : n₁ ≤ n₂
h2 : n₂ ≤ n₃
⊢ RingHom.comp (truncate h1) (truncate h2) = truncate (_ : n₁ ≤ n₃)

Next tactic:
ext1 x
@[simp]
theorem truncate_comp {n₁ n₂ n₃ : ℕ} (h1 : n₁ ≤ n₂) (h2 : n₂ ≤ n₃) :
    (@truncate p _ _ R _ _ h1).comp (truncate h2) = truncate (h1.trans h2) := by
  ext1 x; 

Proof state:
case a
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
n₁ n₂ n₃ : ℕ
h1 : n₁ ≤ n₂
h2 : n₂ ≤ n₃
x : TruncatedWittVector p n₃ R
⊢ (RingHom.comp (truncate h1) (truncate h2)) x = (truncate (_ : n₁ ≤ n₃)) x

Next tactic:
simp only [truncate_truncate, Function.comp_apply, RingHom.coe_comp]
theorem truncate_surjective {m : ℕ} (hm : n ≤ m) : Surjective (@truncate p _ _ R _ _ hm) := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
⊢ Surjective ⇑(truncate hm)

Next tactic:
intro x
theorem truncate_surjective {m : ℕ} (hm : n ≤ m) : Surjective (@truncate p _ _ R _ _ hm) := by
  intro x
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
x : TruncatedWittVector p n R
⊢ ∃ a, (truncate hm) a = x

Next tactic:
obtain ⟨x, rfl⟩ := @WittVector.truncate_surjective p _ _ R _ x
theorem truncate_surjective {m : ℕ} (hm : n ≤ m) : Surjective (@truncate p _ _ R _ _ hm) := by
  intro x
  obtain ⟨x, rfl⟩ := @WittVector.truncate_surjective p _ _ R _ x
  

Proof state:
case intro
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
x : 𝕎 R
⊢ ∃ a, (truncate hm) a = (WittVector.truncate n) x

Next tactic:
exact ⟨WittVector.truncate _ x, truncate_wittVector_truncate _ _⟩
@[simp]
theorem coeff_truncate {m : ℕ} (hm : n ≤ m) (i : Fin n) (x : TruncatedWittVector p m R) :
    (truncate hm x).coeff i = x.coeff (Fin.castLE hm i) := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
i : Fin n
x : TruncatedWittVector p m R
⊢ coeff i ((truncate hm) x) = coeff (Fin.castLE hm i) x

Next tactic:
obtain ⟨y, rfl⟩ := @WittVector.truncate_surjective p _ _ _ _ x
@[simp]
theorem coeff_truncate {m : ℕ} (hm : n ≤ m) (i : Fin n) (x : TruncatedWittVector p m R) :
    (truncate hm x).coeff i = x.coeff (Fin.castLE hm i) := by
  obtain ⟨y, rfl⟩ := @WittVector.truncate_surjective p _ _ _ _ x
  

Proof state:
case intro
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
i : Fin n
y : 𝕎 R
⊢ coeff i ((truncate hm) ((WittVector.truncate m) y)) = coeff (Fin.castLE hm i) ((WittVector.truncate m) y)

Next tactic:
simp only [truncate_wittVector_truncate, WittVector.coeff_truncate, Fin.coe_castLE]
theorem card {R : Type*} [Fintype R] :
    Fintype.card (TruncatedWittVector p n R) = Fintype.card R ^ n := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R✝ : Type u_1
inst✝¹ : CommRing R✝
R : Type u_2
inst✝ : Fintype R
⊢ Fintype.card (TruncatedWittVector p n R) = Fintype.card R ^ n

Next tactic:
simp only [TruncatedWittVector, Fintype.card_fin, Fintype.card_fun]
theorem iInf_ker_truncate : ⨅ i : ℕ, RingHom.ker (@WittVector.truncate p _ i R _) = ⊥ := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
⊢ ⨅ i, RingHom.ker (WittVector.truncate i) = ⊥

Next tactic:
rw [Submodule.eq_bot_iff]
theorem iInf_ker_truncate : ⨅ i : ℕ, RingHom.ker (@WittVector.truncate p _ i R _) = ⊥ := by
  rw [Submodule.eq_bot_iff]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
⊢ ∀ x ∈ ⨅ i, RingHom.ker (WittVector.truncate i), x = 0

Next tactic:
intro x hx
theorem iInf_ker_truncate : ⨅ i : ℕ, RingHom.ker (@WittVector.truncate p _ i R _) = ⊥ := by
  rw [Submodule.eq_bot_iff]
  intro x hx
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
hx : x ∈ ⨅ i, RingHom.ker (WittVector.truncate i)
⊢ x = 0

Next tactic:
ext
theorem iInf_ker_truncate : ⨅ i : ℕ, RingHom.ker (@WittVector.truncate p _ i R _) = ⊥ := by
  rw [Submodule.eq_bot_iff]
  intro x hx
  ext
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
x : 𝕎 R
hx : x ∈ ⨅ i, RingHom.ker (WittVector.truncate i)
n✝ : ℕ
⊢ WittVector.coeff x n✝ = WittVector.coeff 0 n✝

Next tactic:
simp only [WittVector.mem_ker_truncate, Ideal.mem_iInf, WittVector.zero_coeff] at hx ⊢