l3lab/ntp-mathlib huggingface dataset:
/-- We can write the quotient of an ideal over a PID as a product of quotients by principal ideals.
-/
noncomputable def quotientEquivPiSpan (I : Ideal S) (b : Basis ι R S) (hI : I ≠ ⊥) :
    (S ⧸ I) ≃ₗ[R] ∀ i, R ⧸ span ({I.smithCoeffs b hI i} : Set R) := by
  haveI := Fintype.ofFinite ι
  -- Choose `e : S ≃ₗ I` and a basis `b'` for `S` that turns the map
  -- `f := ((Submodule.subtype I).restrictScalars R).comp e` into a diagonal matrix:
  -- there is an `a : ι → ℤ` such that `f (b' i) = a i • b' i`.
  let a := I.smithCoeffs b hI
  let b' := I.ringBasis b hI
  let ab := I.selfBasis b hI
  have ab_eq := I.selfBasis_def b hI
  have mem_I_iff : ∀ x, x ∈ I ↔ ∀ i, a i ∣ b'.repr x i := by
    intro x
    -- Porting note: these lines used to be `simp_rw [ab.mem_ideal_iff', ab_eq]`
    rw [ab.mem_ideal_iff']
    simp_rw [ab_eq]
    have : ∀ (c : ι → R) (i), b'.repr (∑ j : ι, c j • a j • b' j) i = a i * c i := by
      intro c i
      simp only [← MulAction.mul_smul, b'.repr_sum_self, mul_comm]
    constructor
    · rintro ⟨c, rfl⟩ i
      exact ⟨c i, this c i⟩
    · rintro ha
      choose c hc using ha
      exact ⟨c, b'.ext_elem fun i => Eq.trans (hc i) (this c i).symm⟩
  -- Now we map everything through the linear equiv `S ≃ₗ (ι → R)`,
  -- which maps `I` to `I' := Π i, a i ℤ`.
  let I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span ({a i} : Set R)
  have : Submodule.map (b'.equivFun : S →ₗ[R] ι → R) (I.restrictScalars R) = I' := by
    ext x
    simp only [Submodule.mem_map, Submodule.mem_pi, mem_span_singleton, Set.mem_univ,
      Submodule.restrictScalars_mem, mem_I_iff, smul_eq_mul, forall_true_left, LinearEquiv.coe_coe,
      Basis.equivFun_apply]
    constructor
    · rintro ⟨y, hy, rfl⟩ i
      exact hy i
    · rintro hdvd
      refine' ⟨∑ i, x i • b' i, fun i => _, _⟩ <;> rw [b'.repr_sum_self]
      · exact hdvd i
  refine' ((Submodule.Quotient.restrictScalarsEquiv R I).restrictScalars R).symm.trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · infer_instance
  · infer_instance
  refine' (Submodule.Quotient.equiv (I.restrictScalars R) I' b'.equivFun this).trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · 

Proof state:
case refine'_3.refine'_1
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁶ : CommRing R
inst✝⁵ : CommRing S
inst✝⁴ : Algebra R S
inst✝³ : IsDomain R
inst✝² : IsPrincipalIdealRing R
inst✝¹ : IsDomain S
inst✝ : Finite ι
I : Ideal S
b : Basis ι R S
hI : I ≠ ⊥
this✝ : Fintype ι
a : ι → R := smithCoeffs b I hI
b' : Basis ι R S := ringBasis b I hI
ab : Basis ι R ↥I := selfBasis b I hI
ab_eq : ∀ (i : ι), ↑((selfBasis b I hI) i) = smithCoeffs b I hI i • (ringBasis b I hI) i
mem_I_iff : ∀ (x : S), x ∈ I ↔ ∀ (i : ι), a i ∣ (b'.repr x) i
I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span {a i}
this : Submodule.map (↑(Basis.equivFun b')) (Submodule.restrictScalars R I) = I'
⊢ RingHomInvPair (RingHom.id R) (RingHom.id R)

Next tactic:
infer_instance
/-- We can write the quotient of an ideal over a PID as a product of quotients by principal ideals.
-/
noncomputable def quotientEquivPiSpan (I : Ideal S) (b : Basis ι R S) (hI : I ≠ ⊥) :
    (S ⧸ I) ≃ₗ[R] ∀ i, R ⧸ span ({I.smithCoeffs b hI i} : Set R) := by
  haveI := Fintype.ofFinite ι
  -- Choose `e : S ≃ₗ I` and a basis `b'` for `S` that turns the map
  -- `f := ((Submodule.subtype I).restrictScalars R).comp e` into a diagonal matrix:
  -- there is an `a : ι → ℤ` such that `f (b' i) = a i • b' i`.
  let a := I.smithCoeffs b hI
  let b' := I.ringBasis b hI
  let ab := I.selfBasis b hI
  have ab_eq := I.selfBasis_def b hI
  have mem_I_iff : ∀ x, x ∈ I ↔ ∀ i, a i ∣ b'.repr x i := by
    intro x
    -- Porting note: these lines used to be `simp_rw [ab.mem_ideal_iff', ab_eq]`
    rw [ab.mem_ideal_iff']
    simp_rw [ab_eq]
    have : ∀ (c : ι → R) (i), b'.repr (∑ j : ι, c j • a j • b' j) i = a i * c i := by
      intro c i
      simp only [← MulAction.mul_smul, b'.repr_sum_self, mul_comm]
    constructor
    · rintro ⟨c, rfl⟩ i
      exact ⟨c i, this c i⟩
    · rintro ha
      choose c hc using ha
      exact ⟨c, b'.ext_elem fun i => Eq.trans (hc i) (this c i).symm⟩
  -- Now we map everything through the linear equiv `S ≃ₗ (ι → R)`,
  -- which maps `I` to `I' := Π i, a i ℤ`.
  let I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span ({a i} : Set R)
  have : Submodule.map (b'.equivFun : S →ₗ[R] ι → R) (I.restrictScalars R) = I' := by
    ext x
    simp only [Submodule.mem_map, Submodule.mem_pi, mem_span_singleton, Set.mem_univ,
      Submodule.restrictScalars_mem, mem_I_iff, smul_eq_mul, forall_true_left, LinearEquiv.coe_coe,
      Basis.equivFun_apply]
    constructor
    · rintro ⟨y, hy, rfl⟩ i
      exact hy i
    · rintro hdvd
      refine' ⟨∑ i, x i • b' i, fun i => _, _⟩ <;> rw [b'.repr_sum_self]
      · exact hdvd i
  refine' ((Submodule.Quotient.restrictScalarsEquiv R I).restrictScalars R).symm.trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · infer_instance
  · infer_instance
  refine' (Submodule.Quotient.equiv (I.restrictScalars R) I' b'.equivFun this).trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · infer_instance
  · 

Proof state:
case refine'_3.refine'_2
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁶ : CommRing R
inst✝⁵ : CommRing S
inst✝⁴ : Algebra R S
inst✝³ : IsDomain R
inst✝² : IsPrincipalIdealRing R
inst✝¹ : IsDomain S
inst✝ : Finite ι
I : Ideal S
b : Basis ι R S
hI : I ≠ ⊥
this✝ : Fintype ι
a : ι → R := smithCoeffs b I hI
b' : Basis ι R S := ringBasis b I hI
ab : Basis ι R ↥I := selfBasis b I hI
ab_eq : ∀ (i : ι), ↑((selfBasis b I hI) i) = smithCoeffs b I hI i • (ringBasis b I hI) i
mem_I_iff : ∀ (x : S), x ∈ I ↔ ∀ (i : ι), a i ∣ (b'.repr x) i
I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span {a i}
this : Submodule.map (↑(Basis.equivFun b')) (Submodule.restrictScalars R I) = I'
⊢ RingHomInvPair (RingHom.id R) (RingHom.id R)

Next tactic:
infer_instance
/-- We can write the quotient of an ideal over a PID as a product of quotients by principal ideals.
-/
noncomputable def quotientEquivPiSpan (I : Ideal S) (b : Basis ι R S) (hI : I ≠ ⊥) :
    (S ⧸ I) ≃ₗ[R] ∀ i, R ⧸ span ({I.smithCoeffs b hI i} : Set R) := by
  haveI := Fintype.ofFinite ι
  -- Choose `e : S ≃ₗ I` and a basis `b'` for `S` that turns the map
  -- `f := ((Submodule.subtype I).restrictScalars R).comp e` into a diagonal matrix:
  -- there is an `a : ι → ℤ` such that `f (b' i) = a i • b' i`.
  let a := I.smithCoeffs b hI
  let b' := I.ringBasis b hI
  let ab := I.selfBasis b hI
  have ab_eq := I.selfBasis_def b hI
  have mem_I_iff : ∀ x, x ∈ I ↔ ∀ i, a i ∣ b'.repr x i := by
    intro x
    -- Porting note: these lines used to be `simp_rw [ab.mem_ideal_iff', ab_eq]`
    rw [ab.mem_ideal_iff']
    simp_rw [ab_eq]
    have : ∀ (c : ι → R) (i), b'.repr (∑ j : ι, c j • a j • b' j) i = a i * c i := by
      intro c i
      simp only [← MulAction.mul_smul, b'.repr_sum_self, mul_comm]
    constructor
    · rintro ⟨c, rfl⟩ i
      exact ⟨c i, this c i⟩
    · rintro ha
      choose c hc using ha
      exact ⟨c, b'.ext_elem fun i => Eq.trans (hc i) (this c i).symm⟩
  -- Now we map everything through the linear equiv `S ≃ₗ (ι → R)`,
  -- which maps `I` to `I' := Π i, a i ℤ`.
  let I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span ({a i} : Set R)
  have : Submodule.map (b'.equivFun : S →ₗ[R] ι → R) (I.restrictScalars R) = I' := by
    ext x
    simp only [Submodule.mem_map, Submodule.mem_pi, mem_span_singleton, Set.mem_univ,
      Submodule.restrictScalars_mem, mem_I_iff, smul_eq_mul, forall_true_left, LinearEquiv.coe_coe,
      Basis.equivFun_apply]
    constructor
    · rintro ⟨y, hy, rfl⟩ i
      exact hy i
    · rintro hdvd
      refine' ⟨∑ i, x i • b' i, fun i => _, _⟩ <;> rw [b'.repr_sum_self]
      · exact hdvd i
  refine' ((Submodule.Quotient.restrictScalarsEquiv R I).restrictScalars R).symm.trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · infer_instance
  · infer_instance
  refine' (Submodule.Quotient.equiv (I.restrictScalars R) I' b'.equivFun this).trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · infer_instance
  · infer_instance
  

Proof state:
case refine'_3.refine'_3
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁶ : CommRing R
inst✝⁵ : CommRing S
inst✝⁴ : Algebra R S
inst✝³ : IsDomain R
inst✝² : IsPrincipalIdealRing R
inst✝¹ : IsDomain S
inst✝ : Finite ι
I : Ideal S
b : Basis ι R S
hI : I ≠ ⊥
this✝ : Fintype ι
a : ι → R := smithCoeffs b I hI
b' : Basis ι R S := ringBasis b I hI
ab : Basis ι R ↥I := selfBasis b I hI
ab_eq : ∀ (i : ι), ↑((selfBasis b I hI) i) = smithCoeffs b I hI i • (ringBasis b I hI) i
mem_I_iff : ∀ (x : S), x ∈ I ↔ ∀ (i : ι), a i ∣ (b'.repr x) i
I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span {a i}
this : Submodule.map (↑(Basis.equivFun b')) (Submodule.restrictScalars R I) = I'
⊢ ((ι → R) ⧸ I') ≃ₗ[R] (i : ι) → R ⧸ span {smithCoeffs b I hI i}

Next tactic:
classical
    let this :=
      Submodule.quotientPi (show ∀ _, Submodule R R from fun i => span ({a i} : Set R))
    exact this
/-- We can write the quotient of an ideal over a PID as a product of quotients by principal ideals.
-/
noncomputable def quotientEquivPiSpan (I : Ideal S) (b : Basis ι R S) (hI : I ≠ ⊥) :
    (S ⧸ I) ≃ₗ[R] ∀ i, R ⧸ span ({I.smithCoeffs b hI i} : Set R) := by
  haveI := Fintype.ofFinite ι
  -- Choose `e : S ≃ₗ I` and a basis `b'` for `S` that turns the map
  -- `f := ((Submodule.subtype I).restrictScalars R).comp e` into a diagonal matrix:
  -- there is an `a : ι → ℤ` such that `f (b' i) = a i • b' i`.
  let a := I.smithCoeffs b hI
  let b' := I.ringBasis b hI
  let ab := I.selfBasis b hI
  have ab_eq := I.selfBasis_def b hI
  have mem_I_iff : ∀ x, x ∈ I ↔ ∀ i, a i ∣ b'.repr x i := by
    intro x
    -- Porting note: these lines used to be `simp_rw [ab.mem_ideal_iff', ab_eq]`
    rw [ab.mem_ideal_iff']
    simp_rw [ab_eq]
    have : ∀ (c : ι → R) (i), b'.repr (∑ j : ι, c j • a j • b' j) i = a i * c i := by
      intro c i
      simp only [← MulAction.mul_smul, b'.repr_sum_self, mul_comm]
    constructor
    · rintro ⟨c, rfl⟩ i
      exact ⟨c i, this c i⟩
    · rintro ha
      choose c hc using ha
      exact ⟨c, b'.ext_elem fun i => Eq.trans (hc i) (this c i).symm⟩
  -- Now we map everything through the linear equiv `S ≃ₗ (ι → R)`,
  -- which maps `I` to `I' := Π i, a i ℤ`.
  let I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span ({a i} : Set R)
  have : Submodule.map (b'.equivFun : S →ₗ[R] ι → R) (I.restrictScalars R) = I' := by
    ext x
    simp only [Submodule.mem_map, Submodule.mem_pi, mem_span_singleton, Set.mem_univ,
      Submodule.restrictScalars_mem, mem_I_iff, smul_eq_mul, forall_true_left, LinearEquiv.coe_coe,
      Basis.equivFun_apply]
    constructor
    · rintro ⟨y, hy, rfl⟩ i
      exact hy i
    · rintro hdvd
      refine' ⟨∑ i, x i • b' i, fun i => _, _⟩ <;> rw [b'.repr_sum_self]
      · exact hdvd i
  refine' ((Submodule.Quotient.restrictScalarsEquiv R I).restrictScalars R).symm.trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · infer_instance
  · infer_instance
  refine' (Submodule.Quotient.equiv (I.restrictScalars R) I' b'.equivFun this).trans
    (σ₁₂ := RingHom.id R) (σ₃₂ := RingHom.id R) _
  · infer_instance
  · infer_instance
  classical
    

Proof state:
case refine'_3.refine'_3
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁶ : CommRing R
inst✝⁵ : CommRing S
inst✝⁴ : Algebra R S
inst✝³ : IsDomain R
inst✝² : IsPrincipalIdealRing R
inst✝¹ : IsDomain S
inst✝ : Finite ι
I : Ideal S
b : Basis ι R S
hI : I ≠ ⊥
this✝ : Fintype ι
a : ι → R := smithCoeffs b I hI
b' : Basis ι R S := ringBasis b I hI
ab : Basis ι R ↥I := selfBasis b I hI
ab_eq : ∀ (i : ι), ↑((selfBasis b I hI) i) = smithCoeffs b I hI i • (ringBasis b I hI) i
mem_I_iff : ∀ (x : S), x ∈ I ↔ ∀ (i : ι), a i ∣ (b'.repr x) i
I' : Submodule R (ι → R) := Submodule.pi Set.univ fun i => span {a i}
this : Submodule.map (↑(Basis.equivFun b')) (Submodule.restrictScalars R I) = I'
⊢ ((ι → R) ⧸ I') ≃ₗ[R] (i : ι) → R ⧸ span {smithCoeffs b I hI i}

Next tactic:
let this :=
      Submodule.quotientPi (show ∀ _, Submodule R R from fun i => span ({a i} : Set R))
/-- A nonzero ideal over a free finite extension of `ℤ` has a finite quotient.

Can't be an instance because of the side condition `I ≠ ⊥`, and more importantly,
because the choice of `Fintype` instance is non-canonical.
-/
noncomputable def fintypeQuotientOfFreeOfNeBot [Module.Free ℤ S] [Module.Finite ℤ S]
    (I : Ideal S) (hI : I ≠ ⊥) : Fintype (S ⧸ I) := by
  

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : CommRing S
inst✝⁶ : Algebra R S
inst✝⁵ : IsDomain R
inst✝⁴ : IsPrincipalIdealRing R
inst✝³ : IsDomain S
inst✝² : Finite ι
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I : Ideal S
hI : I ≠ ⊥
⊢ Fintype (S ⧸ I)

Next tactic:
let b := Module.Free.chooseBasis ℤ S
/-- A nonzero ideal over a free finite extension of `ℤ` has a finite quotient.

Can't be an instance because of the side condition `I ≠ ⊥`, and more importantly,
because the choice of `Fintype` instance is non-canonical.
-/
noncomputable def fintypeQuotientOfFreeOfNeBot [Module.Free ℤ S] [Module.Finite ℤ S]
    (I : Ideal S) (hI : I ≠ ⊥) : Fintype (S ⧸ I) := by
  let b := Module.Free.chooseBasis ℤ S
  

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : CommRing S
inst✝⁶ : Algebra R S
inst✝⁵ : IsDomain R
inst✝⁴ : IsPrincipalIdealRing R
inst✝³ : IsDomain S
inst✝² : Finite ι
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I : Ideal S
hI : I ≠ ⊥
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
⊢ Fintype (S ⧸ I)

Next tactic:
let a := I.smithCoeffs b hI
/-- A nonzero ideal over a free finite extension of `ℤ` has a finite quotient.

Can't be an instance because of the side condition `I ≠ ⊥`, and more importantly,
because the choice of `Fintype` instance is non-canonical.
-/
noncomputable def fintypeQuotientOfFreeOfNeBot [Module.Free ℤ S] [Module.Finite ℤ S]
    (I : Ideal S) (hI : I ≠ ⊥) : Fintype (S ⧸ I) := by
  let b := Module.Free.chooseBasis ℤ S
  let a := I.smithCoeffs b hI
  

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : CommRing S
inst✝⁶ : Algebra R S
inst✝⁵ : IsDomain R
inst✝⁴ : IsPrincipalIdealRing R
inst✝³ : IsDomain S
inst✝² : Finite ι
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I : Ideal S
hI : I ≠ ⊥
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
a : Module.Free.ChooseBasisIndex ℤ S → ℤ := smithCoeffs b I hI
⊢ Fintype (S ⧸ I)

Next tactic:
let e := I.quotientEquivPiZMod b hI
/-- A nonzero ideal over a free finite extension of `ℤ` has a finite quotient.

Can't be an instance because of the side condition `I ≠ ⊥`, and more importantly,
because the choice of `Fintype` instance is non-canonical.
-/
noncomputable def fintypeQuotientOfFreeOfNeBot [Module.Free ℤ S] [Module.Finite ℤ S]
    (I : Ideal S) (hI : I ≠ ⊥) : Fintype (S ⧸ I) := by
  let b := Module.Free.chooseBasis ℤ S
  let a := I.smithCoeffs b hI
  let e := I.quotientEquivPiZMod b hI
  

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : CommRing S
inst✝⁶ : Algebra R S
inst✝⁵ : IsDomain R
inst✝⁴ : IsPrincipalIdealRing R
inst✝³ : IsDomain S
inst✝² : Finite ι
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I : Ideal S
hI : I ≠ ⊥
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
a : Module.Free.ChooseBasisIndex ℤ S → ℤ := smithCoeffs b I hI
e : S ⧸ I ≃+ ((i : Module.Free.ChooseBasisIndex ℤ S) → ZMod (Int.natAbs (smithCoeffs b I hI i))) :=
  quotientEquivPiZMod I b hI
⊢ Fintype (S ⧸ I)

Next tactic:
haveI : ∀ i, NeZero (a i).natAbs := fun i =>
    ⟨Int.natAbs_ne_zero.mpr (smithCoeffs_ne_zero b I hI i)⟩
/-- A nonzero ideal over a free finite extension of `ℤ` has a finite quotient.

Can't be an instance because of the side condition `I ≠ ⊥`, and more importantly,
because the choice of `Fintype` instance is non-canonical.
-/
noncomputable def fintypeQuotientOfFreeOfNeBot [Module.Free ℤ S] [Module.Finite ℤ S]
    (I : Ideal S) (hI : I ≠ ⊥) : Fintype (S ⧸ I) := by
  let b := Module.Free.chooseBasis ℤ S
  let a := I.smithCoeffs b hI
  let e := I.quotientEquivPiZMod b hI
  haveI : ∀ i, NeZero (a i).natAbs := fun i =>
    ⟨Int.natAbs_ne_zero.mpr (smithCoeffs_ne_zero b I hI i)⟩
  

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : CommRing S
inst✝⁶ : Algebra R S
inst✝⁵ : IsDomain R
inst✝⁴ : IsPrincipalIdealRing R
inst✝³ : IsDomain S
inst✝² : Finite ι
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I : Ideal S
hI : I ≠ ⊥
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
a : Module.Free.ChooseBasisIndex ℤ S → ℤ := smithCoeffs b I hI
e : S ⧸ I ≃+ ((i : Module.Free.ChooseBasisIndex ℤ S) → ZMod (Int.natAbs (smithCoeffs b I hI i))) :=
  quotientEquivPiZMod I b hI
this : ∀ (i : Module.Free.ChooseBasisIndex ℤ S), NeZero (Int.natAbs (a i))
⊢ Fintype (S ⧸ I)

Next tactic:
classical exact Fintype.ofEquiv (∀ i, ZMod (a i).natAbs) e.symm
/-- A nonzero ideal over a free finite extension of `ℤ` has a finite quotient.

Can't be an instance because of the side condition `I ≠ ⊥`, and more importantly,
because the choice of `Fintype` instance is non-canonical.
-/
noncomputable def fintypeQuotientOfFreeOfNeBot [Module.Free ℤ S] [Module.Finite ℤ S]
    (I : Ideal S) (hI : I ≠ ⊥) : Fintype (S ⧸ I) := by
  let b := Module.Free.chooseBasis ℤ S
  let a := I.smithCoeffs b hI
  let e := I.quotientEquivPiZMod b hI
  haveI : ∀ i, NeZero (a i).natAbs := fun i =>
    ⟨Int.natAbs_ne_zero.mpr (smithCoeffs_ne_zero b I hI i)⟩
  classical 

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : CommRing S
inst✝⁶ : Algebra R S
inst✝⁵ : IsDomain R
inst✝⁴ : IsPrincipalIdealRing R
inst✝³ : IsDomain S
inst✝² : Finite ι
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I : Ideal S
hI : I ≠ ⊥
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
a : Module.Free.ChooseBasisIndex ℤ S → ℤ := smithCoeffs b I hI
e : S ⧸ I ≃+ ((i : Module.Free.ChooseBasisIndex ℤ S) → ZMod (Int.natAbs (smithCoeffs b I hI i))) :=
  quotientEquivPiZMod I b hI
this : ∀ (i : Module.Free.ChooseBasisIndex ℤ S), NeZero (Int.natAbs (a i))
⊢ Fintype (S ⧸ I)

Next tactic:
exact Fintype.ofEquiv (∀ i, ZMod (a i).natAbs) e.symm
/-- Decompose `S⧸I` as a direct sum of cyclic `R`-modules
  (quotients by the ideals generated by Smith coefficients of `I`). -/
noncomputable def quotientEquivDirectSum :
    (S ⧸ I) ≃ₗ[F] ⨁ i, R ⧸ span ({I.smithCoeffs b hI i} : Set R) := by
  

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : CommRing S
inst✝⁸ : Algebra R S
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
inst✝⁵ : IsDomain S
inst✝⁴ : Finite ι
F : Type u_4
inst✝³ : CommRing F
inst✝² : Algebra F R
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F R S
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
⊢ (S ⧸ I) ≃ₗ[F] ⨁ (i : ι), R ⧸ span {smithCoeffs b I hI i}

Next tactic:
haveI := Fintype.ofFinite ι
/-- Decompose `S⧸I` as a direct sum of cyclic `R`-modules
  (quotients by the ideals generated by Smith coefficients of `I`). -/
noncomputable def quotientEquivDirectSum :
    (S ⧸ I) ≃ₗ[F] ⨁ i, R ⧸ span ({I.smithCoeffs b hI i} : Set R) := by
  haveI := Fintype.ofFinite ι
  -- porting note: manual construction of `CompatibleSMul` typeclass no longer needed
  

Proof state:
ι : Type u_1
R : Type u_2
S : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : CommRing S
inst✝⁸ : Algebra R S
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
inst✝⁵ : IsDomain S
inst✝⁴ : Finite ι
F : Type u_4
inst✝³ : CommRing F
inst✝² : Algebra F R
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F R S
b : Basis ι R S
I : Ideal S
hI : I ≠ ⊥
this : Fintype ι
⊢ (S ⧸ I) ≃ₗ[F] ⨁ (i : ι), R ⧸ span {smithCoeffs b I hI i}

Next tactic:
exact ((I.quotientEquivPiSpan b _).restrictScalars F).trans
    (DirectSum.linearEquivFunOnFintype _ _ _).symm
theorem finrank_quotient_eq_sum {ι} [Fintype ι] (b : Basis ι R S) [Nontrivial F]
    [∀ i, Module.Free F (R ⧸ span ({I.smithCoeffs b hI i} : Set R))]
    [∀ i, Module.Finite F (R ⧸ span ({I.smithCoeffs b hI i} : Set R))] :
    FiniteDimensional.finrank F (S ⧸ I) =
      ∑ i, FiniteDimensional.finrank F (R ⧸ span ({I.smithCoeffs b hI i} : Set R)) := by
  -- slow, and dot notation doesn't work
  

Proof state:
ι✝ : Type u_1
R : Type u_2
S : Type u_3
inst✝¹⁴ : CommRing R
inst✝¹³ : CommRing S
inst✝¹² : Algebra R S
inst✝¹¹ : IsDomain R
inst✝¹⁰ : IsPrincipalIdealRing R
inst✝⁹ : IsDomain S
inst✝⁸ : Finite ι✝
F : Type u_4
inst✝⁷ : CommRing F
inst✝⁶ : Algebra F R
inst✝⁵ : Algebra F S
inst✝⁴ : IsScalarTower F R S
b✝ : Basis ι✝ R S
I : Ideal S
hI : I ≠ ⊥
ι : Type u_5
inst✝³ : Fintype ι
b : Basis ι R S
inst✝² : Nontrivial F
inst✝¹ : ∀ (i : ι), Module.Free F (R ⧸ span {smithCoeffs b I hI i})
inst✝ : ∀ (i : ι), Module.Finite F (R ⧸ span {smithCoeffs b I hI i})
⊢ FiniteDimensional.finrank F (S ⧸ I) = ∑ i : ι, FiniteDimensional.finrank F (R ⧸ span {smithCoeffs b I hI i})

Next tactic:
rw [LinearEquiv.finrank_eq <| quotientEquivDirectSum F b hI, FiniteDimensional.finrank_directSum]
/-- If `m₁, m₂` are independent σ-algebras and `f` is `m₁`-measurable, then `𝔼[f | m₂] = 𝔼[f]`
almost everywhere. -/
theorem condexp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinite (μ.trim hle₂)]
    (hf : StronglyMeasurable[m₁] f) (hindp : Indep m₁ m₂ μ) : μ[f|m₂] =ᵐ[μ] fun _ => μ[f] := by
  

Proof state:
Ω : Type u_1
E : Type u_2
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace ℝ E
inst✝¹ : CompleteSpace E
m₁ m₂ m : MeasurableSpace Ω
μ : Measure Ω
f : Ω → E
hle₁ : m₁ ≤ m
hle₂ : m₂ ≤ m
inst✝ : SigmaFinite (Measure.trim μ hle₂)
hf : StronglyMeasurable f
hindp : Indep m₁ m₂
⊢ μ[f|m₂] =ᵐ[μ] fun x => ∫ (x : Ω), f x ∂μ

Next tactic:
by_cases hfint : Integrable f μ
/-- If `m₁, m₂` are independent σ-algebras and `f` is `m₁`-measurable, then `𝔼[f | m₂] = 𝔼[f]`
almost everywhere. -/
theorem condexp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinite (μ.trim hle₂)]
    (hf : StronglyMeasurable[m₁] f) (hindp : Indep m₁ m₂ μ) : μ[f|m₂] =ᵐ[μ] fun _ => μ[f] := by
  by_cases hfint : Integrable f μ
  

Proof state:
case pos
Ω : Type u_1
E : Type u_2
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace ℝ E
inst✝¹ : CompleteSpace E
m₁ m₂ m : MeasurableSpace Ω
μ : Measure Ω
f : Ω → E
hle₁ : m₁ ≤ m
hle₂ : m₂ ≤ m
inst✝ : SigmaFinite (Measure.trim μ hle₂)
hf : StronglyMeasurable f
hindp : Indep m₁ m₂
hfint : Integrable f
⊢ μ[f|m₂] =ᵐ[μ] fun x => ∫ (x : Ω), f x ∂μ
case neg
Ω : Type u_1
E : Type u_2
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace ℝ E
inst✝¹ : CompleteSpace E
m₁ m₂ m : MeasurableSpace Ω
μ : Measure Ω
f : Ω → E
hle₁ : m₁ ≤ m
hle₂ : m₂ ≤ m
inst✝ : SigmaFinite (Measure.trim μ hle₂)
hf : StronglyMeasurable f
hindp : Indep m₁ m₂
hfint : ¬Integrable f
⊢ μ[f|m₂] =ᵐ[μ] fun x => ∫ (x : Ω), f x ∂μ

Next tactic:
swap
/-- If `m₁, m₂` are independent σ-algebras and `f` is `m₁`-measurable, then `𝔼[f | m₂] = 𝔼[f]`
almost everywhere. -/
theorem condexp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinite (μ.trim hle₂)]
    (hf : StronglyMeasurable[m₁] f) (hindp : Indep m₁ m₂ μ) : μ[f|m₂] =ᵐ[μ] fun _ => μ[f] := by
  by_cases hfint : Integrable f μ
  swap; · 

Proof state:
case neg
Ω : Type u_1
E : Type u_2
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace ℝ E
inst✝¹ : CompleteSpace E
m₁ m₂ m : MeasurableSpace Ω
μ : Measure Ω
f : Ω → E
hle₁ : m₁ ≤ m
hle₂ : m₂ ≤ m
inst✝ : SigmaFinite (Measure.trim μ hle₂)
hf : StronglyMeasurable f
hindp : Indep m₁ m₂
hfint : ¬Integrable f
⊢ μ[f|m₂] =ᵐ[μ] fun x => ∫ (x : Ω), f x ∂μ

Next tactic:
rw [condexp_undef hfint, integral_undef hfint]
/-- If `m₁, m₂` are independent σ-algebras and `f` is `m₁`-measurable, then `𝔼[f | m₂] = 𝔼[f]`
almost everywhere. -/
theorem condexp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinite (μ.trim hle₂)]
    (hf : StronglyMeasurable[m₁] f) (hindp : Indep m₁ m₂ μ) : μ[f|m₂] =ᵐ[μ] fun _ => μ[f] := by
  by_cases hfint : Integrable f μ
  swap; · rw [condexp_undef hfint, integral_undef hfint]; 

Proof state:
case neg
Ω : Type u_1
E : Type u_2
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace ℝ E
inst✝¹ : CompleteSpace E
m₁ m₂ m : MeasurableSpace Ω
μ : Measure Ω
f : Ω → E
hle₁ : m₁ ≤ m
hle₂ : m₂ ≤ m
inst✝ : SigmaFinite (Measure.trim μ hle₂)
hf : StronglyMeasurable f
hindp : Indep m₁ m₂
hfint : ¬Integrable f
⊢ 0 =ᵐ[μ] fun x => 0

Next tactic:
rfl