l3lab/ntp-mathlib huggingface dataset:
/-- For a nonzero element `f` in an algebra `S` over a principal ideal domain `R` that is finite and
free as an `R`-module, the norm of `f` relative to `R` is associated to the product of the Smith
coefficients of the ideal generated by `f`. -/
theorem associated_norm_prod_smith [Fintype ι] (b : Basis ι R S) {f : S} (hf : f ≠ 0) :
    Associated (Algebra.norm R f) (∏ i, smithCoeffs b _ (span_singleton_eq_bot.not.2 hf) i) := by
  have hI := span_singleton_eq_bot.not.2 hf
  let b' := ringBasis b (span {f}) hI
  classical
  rw [← Matrix.det_diagonal, ← LinearMap.det_toLin b']
  let e :=
    (b'.equiv ((span {f}).selfBasis b hI) <| Equiv.refl _).trans
      ((LinearEquiv.coord S S f hf).restrictScalars R)
  refine (LinearMap.associated_det_of_eq_comp e _ _ ?_).symm
  dsimp only [LinearEquiv.trans_apply]
  simp_rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.comp_apply, ← LinearMap.ext_iff]
  refine b'.ext fun i => ?_
  simp_rw [LinearMap.comp_apply, LinearEquiv.coe_toLinearMap, Matrix.toLin_apply, Basis.repr_self,
    Finsupp.single_eq_pi_single, Matrix.diagonal_mulVec_single, Pi.single_apply, ite_smul,
    zero_smul, Finset.sum_ite_eq', mul_one, if_pos (Finset.mem_univ _), b'.equiv_apply]
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : CommRing F
inst✝³ : Algebra F R
inst✝² : Algebra F S
inst✝¹ : IsScalarTower F R S
inst✝ : Fintype ι
b : Basis ι R S
f : S
hf : f ≠ 0
hI : ¬span {f} = ⊥
b' : Basis ι R S := ringBasis b (span {f}) hI
e : S ≃ₗ[R] S :=
  Basis.equiv b' (selfBasis b (span {f}) hI) (Equiv.refl ι) ≪≫ₗ
    LinearEquiv.restrictScalars R (LinearEquiv.coord S S f hf)
i : ι
⊢ smithCoeffs b (span {f}) (_ : ¬span {f} = ⊥) i • (ringBasis b (span {f}) hI) i =
    (↑↑(Algebra.lmul R S) f)
      ((LinearEquiv.restrictScalars R (LinearEquiv.coord S S f hf)) ((selfBasis b (span {f}) hI) ((Equiv.refl ι) i)))

Next tactic:
change _ = f * _
/-- For a nonzero element `f` in an algebra `S` over a principal ideal domain `R` that is finite and
free as an `R`-module, the norm of `f` relative to `R` is associated to the product of the Smith
coefficients of the ideal generated by `f`. -/
theorem associated_norm_prod_smith [Fintype ι] (b : Basis ι R S) {f : S} (hf : f ≠ 0) :
    Associated (Algebra.norm R f) (∏ i, smithCoeffs b _ (span_singleton_eq_bot.not.2 hf) i) := by
  have hI := span_singleton_eq_bot.not.2 hf
  let b' := ringBasis b (span {f}) hI
  classical
  rw [← Matrix.det_diagonal, ← LinearMap.det_toLin b']
  let e :=
    (b'.equiv ((span {f}).selfBasis b hI) <| Equiv.refl _).trans
      ((LinearEquiv.coord S S f hf).restrictScalars R)
  refine (LinearMap.associated_det_of_eq_comp e _ _ ?_).symm
  dsimp only [LinearEquiv.trans_apply]
  simp_rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.comp_apply, ← LinearMap.ext_iff]
  refine b'.ext fun i => ?_
  simp_rw [LinearMap.comp_apply, LinearEquiv.coe_toLinearMap, Matrix.toLin_apply, Basis.repr_self,
    Finsupp.single_eq_pi_single, Matrix.diagonal_mulVec_single, Pi.single_apply, ite_smul,
    zero_smul, Finset.sum_ite_eq', mul_one, if_pos (Finset.mem_univ _), b'.equiv_apply]
  change _ = f * _
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : CommRing F
inst✝³ : Algebra F R
inst✝² : Algebra F S
inst✝¹ : IsScalarTower F R S
inst✝ : Fintype ι
b : Basis ι R S
f : S
hf : f ≠ 0
hI : ¬span {f} = ⊥
b' : Basis ι R S := ringBasis b (span {f}) hI
e : S ≃ₗ[R] S :=
  Basis.equiv b' (selfBasis b (span {f}) hI) (Equiv.refl ι) ≪≫ₗ
    LinearEquiv.restrictScalars R (LinearEquiv.coord S S f hf)
i : ι
⊢ smithCoeffs b (span {f}) (_ : ¬span {f} = ⊥) i • (ringBasis b (span {f}) hI) i =
    f * (LinearEquiv.restrictScalars R (LinearEquiv.coord S S f hf)) ((selfBasis b (span {f}) hI) ((Equiv.refl ι) i))

Next tactic:
erw [mul_comm, ← smul_eq_mul, LinearEquiv.restrictScalars_apply, LinearEquiv.coord_apply_smul,
    Ideal.selfBasis_def]
/-- For a nonzero element `f` in an algebra `S` over a principal ideal domain `R` that is finite and
free as an `R`-module, the norm of `f` relative to `R` is associated to the product of the Smith
coefficients of the ideal generated by `f`. -/
theorem associated_norm_prod_smith [Fintype ι] (b : Basis ι R S) {f : S} (hf : f ≠ 0) :
    Associated (Algebra.norm R f) (∏ i, smithCoeffs b _ (span_singleton_eq_bot.not.2 hf) i) := by
  have hI := span_singleton_eq_bot.not.2 hf
  let b' := ringBasis b (span {f}) hI
  classical
  rw [← Matrix.det_diagonal, ← LinearMap.det_toLin b']
  let e :=
    (b'.equiv ((span {f}).selfBasis b hI) <| Equiv.refl _).trans
      ((LinearEquiv.coord S S f hf).restrictScalars R)
  refine (LinearMap.associated_det_of_eq_comp e _ _ ?_).symm
  dsimp only [LinearEquiv.trans_apply]
  simp_rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.comp_apply, ← LinearMap.ext_iff]
  refine b'.ext fun i => ?_
  simp_rw [LinearMap.comp_apply, LinearEquiv.coe_toLinearMap, Matrix.toLin_apply, Basis.repr_self,
    Finsupp.single_eq_pi_single, Matrix.diagonal_mulVec_single, Pi.single_apply, ite_smul,
    zero_smul, Finset.sum_ite_eq', mul_one, if_pos (Finset.mem_univ _), b'.equiv_apply]
  change _ = f * _
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  erw [mul_comm, ← smul_eq_mul, LinearEquiv.restrictScalars_apply, LinearEquiv.coord_apply_smul,
    Ideal.selfBasis_def]
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : CommRing F
inst✝³ : Algebra F R
inst✝² : Algebra F S
inst✝¹ : IsScalarTower F R S
inst✝ : Fintype ι
b : Basis ι R S
f : S
hf : f ≠ 0
hI : ¬span {f} = ⊥
b' : Basis ι R S := ringBasis b (span {f}) hI
e : S ≃ₗ[R] S :=
  Basis.equiv b' (selfBasis b (span {f}) hI) (Equiv.refl ι) ≪≫ₗ
    LinearEquiv.restrictScalars R (LinearEquiv.coord S S f hf)
i : ι
⊢ smithCoeffs b (span {f}) (_ : ¬span {f} = ⊥) i • (ringBasis b (span {f}) hI) i =
    smithCoeffs b (span {f}) hI ((Equiv.refl ι) i) • (ringBasis b (span {f}) hI) ((Equiv.refl ι) i)

Next tactic:
rfl
instance (b : Basis ι F[X] S) {I : Ideal S} (hI : I ≠ ⊥) (i : ι) :
    FiniteDimensional F (F[X] ⧸ span ({I.smithCoeffs b hI i} : Set F[X])) := by
  -- Porting note: we need to do this proof in two stages otherwise it times out
  -- original proof: (AdjoinRoot.powerBasis <| I.smithCoeffs_ne_zero b hI i).FiniteDimensional
  -- The first tactic takes over 10 seconds, spending a lot of time in checking
  -- that instances on the quotient commute.  My guess is that we unfold
  -- operations to the `Quotient.lift` level and then end up comparing huge
  -- terms.  We should probably make most of the quotient operations
  -- irreducible so that they don't expose `Quotient.lift` accidentally.
  

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

Next tactic:
refine PowerBasis.finiteDimensional ?_
instance (b : Basis ι F[X] S) {I : Ideal S} (hI : I ≠ ⊥) (i : ι) :
    FiniteDimensional F (F[X] ⧸ span ({I.smithCoeffs b hI i} : Set F[X])) := by
  -- Porting note: we need to do this proof in two stages otherwise it times out
  -- original proof: (AdjoinRoot.powerBasis <| I.smithCoeffs_ne_zero b hI i).FiniteDimensional
  -- The first tactic takes over 10 seconds, spending a lot of time in checking
  -- that instances on the quotient commute.  My guess is that we unfold
  -- operations to the `Quotient.lift` level and then end up comparing huge
  -- terms.  We should probably make most of the quotient operations
  -- irreducible so that they don't expose `Quotient.lift` accidentally.
  refine PowerBasis.finiteDimensional ?_
  

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

Next tactic:
refine AdjoinRoot.powerBasis ?_
instance (b : Basis ι F[X] S) {I : Ideal S} (hI : I ≠ ⊥) (i : ι) :
    FiniteDimensional F (F[X] ⧸ span ({I.smithCoeffs b hI i} : Set F[X])) := by
  -- Porting note: we need to do this proof in two stages otherwise it times out
  -- original proof: (AdjoinRoot.powerBasis <| I.smithCoeffs_ne_zero b hI i).FiniteDimensional
  -- The first tactic takes over 10 seconds, spending a lot of time in checking
  -- that instances on the quotient commute.  My guess is that we unfold
  -- operations to the `Quotient.lift` level and then end up comparing huge
  -- terms.  We should probably make most of the quotient operations
  -- irreducible so that they don't expose `Quotient.lift` accidentally.
  refine PowerBasis.finiteDimensional ?_
  refine AdjoinRoot.powerBasis ?_
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : IsDomain R
inst✝⁶ : IsPrincipalIdealRing R
inst✝⁵ : CommRing S
inst✝⁴ : IsDomain S
inst✝³ : Algebra R S
F : Type u_4
inst✝² : Field F
inst✝¹ : Algebra F[X] S
inst✝ : Finite ι
b : Basis ι F[X] S
I : Ideal S
hI : I ≠ ⊥
i : ι
⊢ smithCoeffs b I hI i ≠ 0

Next tactic:
exact I.smithCoeffs_ne_zero b hI i
/-- For a nonzero element `f` in a `F[X]`-module `S`, the dimension of $S/\langle f \rangle$ as an
`F`-vector space is the degree of the norm of `f` relative to `F[X]`. -/
theorem finrank_quotient_span_eq_natDegree_norm [Algebra F S] [IsScalarTower F F[X] S]
    (b : Basis ι F[X] S) {f : S} (hf : f ≠ 0) :
    FiniteDimensional.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : Field F
inst✝³ : Algebra F[X] S
inst✝² : Finite ι
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F F[X] S
b : Basis ι F[X] S
f : S
hf : f ≠ 0
⊢ FiniteDimensional.finrank F (S ⧸ span {f}) = natDegree ((Algebra.norm F[X]) f)

Next tactic:
haveI := Fintype.ofFinite ι
/-- For a nonzero element `f` in a `F[X]`-module `S`, the dimension of $S/\langle f \rangle$ as an
`F`-vector space is the degree of the norm of `f` relative to `F[X]`. -/
theorem finrank_quotient_span_eq_natDegree_norm [Algebra F S] [IsScalarTower F F[X] S]
    (b : Basis ι F[X] S) {f : S} (hf : f ≠ 0) :
    FiniteDimensional.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by
  haveI := Fintype.ofFinite ι
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : Field F
inst✝³ : Algebra F[X] S
inst✝² : Finite ι
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F F[X] S
b : Basis ι F[X] S
f : S
hf : f ≠ 0
this : Fintype ι
⊢ FiniteDimensional.finrank F (S ⧸ span {f}) = natDegree ((Algebra.norm F[X]) f)

Next tactic:
have h := span_singleton_eq_bot.not.2 hf
/-- For a nonzero element `f` in a `F[X]`-module `S`, the dimension of $S/\langle f \rangle$ as an
`F`-vector space is the degree of the norm of `f` relative to `F[X]`. -/
theorem finrank_quotient_span_eq_natDegree_norm [Algebra F S] [IsScalarTower F F[X] S]
    (b : Basis ι F[X] S) {f : S} (hf : f ≠ 0) :
    FiniteDimensional.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by
  haveI := Fintype.ofFinite ι
  have h := span_singleton_eq_bot.not.2 hf
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : Field F
inst✝³ : Algebra F[X] S
inst✝² : Finite ι
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F F[X] S
b : Basis ι F[X] S
f : S
hf : f ≠ 0
this : Fintype ι
h : ¬span {f} = ⊥
⊢ FiniteDimensional.finrank F (S ⧸ span {f}) = natDegree ((Algebra.norm F[X]) f)

Next tactic:
rw [natDegree_eq_of_degree_eq
      (degree_eq_degree_of_associated <| associated_norm_prod_smith b hf)]
/-- For a nonzero element `f` in a `F[X]`-module `S`, the dimension of $S/\langle f \rangle$ as an
`F`-vector space is the degree of the norm of `f` relative to `F[X]`. -/
theorem finrank_quotient_span_eq_natDegree_norm [Algebra F S] [IsScalarTower F F[X] S]
    (b : Basis ι F[X] S) {f : S} (hf : f ≠ 0) :
    FiniteDimensional.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by
  haveI := Fintype.ofFinite ι
  have h := span_singleton_eq_bot.not.2 hf
  rw [natDegree_eq_of_degree_eq
      (degree_eq_degree_of_associated <| associated_norm_prod_smith b hf)]
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : Field F
inst✝³ : Algebra F[X] S
inst✝² : Finite ι
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F F[X] S
b : Basis ι F[X] S
f : S
hf : f ≠ 0
this : Fintype ι
h : ¬span {f} = ⊥
⊢ FiniteDimensional.finrank F (S ⧸ span {f}) = natDegree (∏ i : ι, smithCoeffs b (span {f}) (_ : ¬span {f} = ⊥) i)

Next tactic:
rw [natDegree_prod _ _ fun i _ => smithCoeffs_ne_zero b _ h i, finrank_quotient_eq_sum F h b]
/-- For a nonzero element `f` in a `F[X]`-module `S`, the dimension of $S/\langle f \rangle$ as an
`F`-vector space is the degree of the norm of `f` relative to `F[X]`. -/
theorem finrank_quotient_span_eq_natDegree_norm [Algebra F S] [IsScalarTower F F[X] S]
    (b : Basis ι F[X] S) {f : S} (hf : f ≠ 0) :
    FiniteDimensional.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by
  haveI := Fintype.ofFinite ι
  have h := span_singleton_eq_bot.not.2 hf
  rw [natDegree_eq_of_degree_eq
      (degree_eq_degree_of_associated <| associated_norm_prod_smith b hf)]
  rw [natDegree_prod _ _ fun i _ => smithCoeffs_ne_zero b _ h i, finrank_quotient_eq_sum F h b]
  -- finrank_quotient_eq_sum slow
  

Proof state:
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : Field F
inst✝³ : Algebra F[X] S
inst✝² : Finite ι
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F F[X] S
b : Basis ι F[X] S
f : S
hf : f ≠ 0
this : Fintype ι
h : ¬span {f} = ⊥
⊢ ∑ i : ι, FiniteDimensional.finrank F (F[X] ⧸ span {smithCoeffs b (span {f}) h i}) =
    ∑ i : ι, natDegree (smithCoeffs b (span {f}) h i)

Next tactic:
congr with i
/-- For a nonzero element `f` in a `F[X]`-module `S`, the dimension of $S/\langle f \rangle$ as an
`F`-vector space is the degree of the norm of `f` relative to `F[X]`. -/
theorem finrank_quotient_span_eq_natDegree_norm [Algebra F S] [IsScalarTower F F[X] S]
    (b : Basis ι F[X] S) {f : S} (hf : f ≠ 0) :
    FiniteDimensional.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by
  haveI := Fintype.ofFinite ι
  have h := span_singleton_eq_bot.not.2 hf
  rw [natDegree_eq_of_degree_eq
      (degree_eq_degree_of_associated <| associated_norm_prod_smith b hf)]
  rw [natDegree_prod _ _ fun i _ => smithCoeffs_ne_zero b _ h i, finrank_quotient_eq_sum F h b]
  -- finrank_quotient_eq_sum slow
  congr with i
  

Proof state:
case e_f.h
R : Type u_1
S : Type u_2
ι : Type u_3
inst✝¹⁰ : CommRing R
inst✝⁹ : IsDomain R
inst✝⁸ : IsPrincipalIdealRing R
inst✝⁷ : CommRing S
inst✝⁶ : IsDomain S
inst✝⁵ : Algebra R S
F : Type u_4
inst✝⁴ : Field F
inst✝³ : Algebra F[X] S
inst✝² : Finite ι
inst✝¹ : Algebra F S
inst✝ : IsScalarTower F F[X] S
b : Basis ι F[X] S
f : S
hf : f ≠ 0
this : Fintype ι
h : ¬span {f} = ⊥
i : ι
⊢ FiniteDimensional.finrank F (F[X] ⧸ span {smithCoeffs b (span {f}) h i}) = natDegree (smithCoeffs b (span {f}) h i)

Next tactic:
exact (AdjoinRoot.powerBasis <| smithCoeffs_ne_zero b _ h i).finrank
theorem ext_s {q₁ q₂ : Semiquot α} : q₁ = q₂ ↔ q₁.s = q₂.s := by
  

Proof state:
α : Type u_1
β : Type u_2
q₁ q₂ : Semiquot α
⊢ q₁ = q₂ ↔ q₁.s = q₂.s

Next tactic:
refine' ⟨congr_arg _, fun h => _⟩
theorem ext_s {q₁ q₂ : Semiquot α} : q₁ = q₂ ↔ q₁.s = q₂.s := by
  refine' ⟨congr_arg _, fun h => _⟩
  

Proof state:
α : Type u_1
β : Type u_2
q₁ q₂ : Semiquot α
h : q₁.s = q₂.s
⊢ q₁ = q₂

Next tactic:
cases' q₁ with _ v₁
theorem ext_s {q₁ q₂ : Semiquot α} : q₁ = q₂ ↔ q₁.s = q₂.s := by
  refine' ⟨congr_arg _, fun h => _⟩
  cases' q₁ with _ v₁; 

Proof state:
case mk'
α : Type u_1
β : Type u_2
q₂ : Semiquot α
s✝ : Set α
v₁ : Trunc ↑s✝
h : { s := s✝, val := v₁ }.s = q₂.s
⊢ { s := s✝, val := v₁ } = q₂

Next tactic:
cases' q₂ with _ v₂
theorem ext_s {q₁ q₂ : Semiquot α} : q₁ = q₂ ↔ q₁.s = q₂.s := by
  refine' ⟨congr_arg _, fun h => _⟩
  cases' q₁ with _ v₁; cases' q₂ with _ v₂; 

Proof state:
case mk'.mk'
α : Type u_1
β : Type u_2
s✝¹ : Set α
v₁ : Trunc ↑s✝¹
s✝ : Set α
v₂ : Trunc ↑s✝
h : { s := s✝¹, val := v₁ }.s = { s := s✝, val := v₂ }.s
⊢ { s := s✝¹, val := v₁ } = { s := s✝, val := v₂ }

Next tactic:
congr
theorem ext_s {q₁ q₂ : Semiquot α} : q₁ = q₂ ↔ q₁.s = q₂.s := by
  refine' ⟨congr_arg _, fun h => _⟩
  cases' q₁ with _ v₁; cases' q₂ with _ v₂; congr
  

Proof state:
case mk'.mk'.h.e_3
α : Type u_1
β : Type u_2
s✝¹ : Set α
v₁ : Trunc ↑s✝¹
s✝ : Set α
v₂ : Trunc ↑s✝
h : { s := s✝¹, val := v₁ }.s = { s := s✝, val := v₂ }.s
⊢ HEq v₁ v₂

Next tactic:
exact Subsingleton.helim (congrArg Trunc (congrArg Set.Elem h)) v₁ v₂
theorem blur_eq_blur' (q : Semiquot α) (s : Set α) (h : q.s ⊆ s) : blur s q = blur' q h := by
  

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
s : Set α
h : q.s ⊆ s
⊢ blur s q = blur' q h

Next tactic:
unfold blur
theorem blur_eq_blur' (q : Semiquot α) (s : Set α) (h : q.s ⊆ s) : blur s q = blur' q h := by
  unfold blur; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
s : Set α
h : q.s ⊆ s
⊢ blur' q (_ : q.s ⊆ s ∪ q.s) = blur' q h

Next tactic:
congr
theorem blur_eq_blur' (q : Semiquot α) (s : Set α) (h : q.s ⊆ s) : blur s q = blur' q h := by
  unfold blur; congr; 

Proof state:
case e_s
α : Type u_1
β : Type u_2
q : Semiquot α
s : Set α
h : q.s ⊆ s
⊢ s ∪ q.s = s

Next tactic:
exact Set.union_eq_self_of_subset_right h
theorem liftOn_ofMem (q : Semiquot α) (f : α → β)
    (h : ∀ a ∈ q, ∀ b ∈ q, f a = f b) (a : α) (aq : a ∈ q) : liftOn q f h = f a :=
  by 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
f : α → β
h : ∀ a ∈ q, ∀ b ∈ q, f a = f b
a : α
aq : a ∈ q
⊢ liftOn q f h = f a

Next tactic:
revert h
theorem liftOn_ofMem (q : Semiquot α) (f : α → β)
    (h : ∀ a ∈ q, ∀ b ∈ q, f a = f b) (a : α) (aq : a ∈ q) : liftOn q f h = f a :=
  by revert h; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
f : α → β
a : α
aq : a ∈ q
⊢ ∀ (h : ∀ a ∈ q, ∀ b ∈ q, f a = f b), liftOn q f h = f a

Next tactic:
rw [eq_mk_of_mem aq]
theorem liftOn_ofMem (q : Semiquot α) (f : α → β)
    (h : ∀ a ∈ q, ∀ b ∈ q, f a = f b) (a : α) (aq : a ∈ q) : liftOn q f h = f a :=
  by revert h; rw [eq_mk_of_mem aq]; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
f : α → β
a : α
aq : a ∈ q
⊢ ∀ (h : ∀ a_1 ∈ mk aq, ∀ b ∈ mk aq, f a_1 = f b), liftOn (mk aq) f h = f a

Next tactic:
intro
theorem liftOn_ofMem (q : Semiquot α) (f : α → β)
    (h : ∀ a ∈ q, ∀ b ∈ q, f a = f b) (a : α) (aq : a ∈ q) : liftOn q f h = f a :=
  by revert h; rw [eq_mk_of_mem aq]; intro; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
f : α → β
a : α
aq : a ∈ q
h✝ : ∀ a_1 ∈ mk aq, ∀ b ∈ mk aq, f a_1 = f b
⊢ liftOn (mk aq) f h✝ = f a

Next tactic:
rfl
@[simp]
theorem mem_bind (q : Semiquot α) (f : α → Semiquot β) (b : β) : b ∈ bind q f ↔ ∃ a ∈ q, b ∈ f a :=
  by 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
f : α → Semiquot β
b : β
⊢ b ∈ bind q f ↔ ∃ a ∈ q, b ∈ f a

Next tactic:
simp_rw [← exists_prop]
@[simp]
theorem mem_bind (q : Semiquot α) (f : α → Semiquot β) (b : β) : b ∈ bind q f ↔ ∃ a ∈ q, b ∈ f a :=
  by simp_rw [← exists_prop]; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
f : α → Semiquot β
b : β
⊢ b ∈ bind q f ↔ ∃ a, ∃ (_ : a ∈ q), b ∈ f a

Next tactic:
exact Set.mem_iUnion₂
instance : LawfulMonad Semiquot := LawfulMonad.mk'
  (pure_bind := fun {α β} x f => ext.2 <| by simp)
  (bind_assoc := fun {α β} γ s f g =>
    ext.2 <| by
    simp only [bind_def, mem_bind]
    exact fun c => ⟨fun ⟨b, ⟨a, as, bf⟩, cg⟩ => ⟨a, as, b, bf, cg⟩,
      fun ⟨a, as, b, bf, cg⟩ => ⟨b, ⟨a, as, bf⟩, cg⟩⟩)
  (id_map := fun {α} q => ext.2 <| by 

Proof state:
α✝ : Type u_1
β : Type u_2
α : Type ?u.6486
q : Semiquot α
⊢ ∀ (a : α), a ∈ id <$> q ↔ a ∈ q

Next tactic:
simp
instance : LawfulMonad Semiquot := LawfulMonad.mk'
  (pure_bind := fun {α β} x f => ext.2 <| by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
α β : Type ?u.6486
x : α
f : α → Semiquot β
⊢ ∀ (a : β), a ∈ pure x >>= f ↔ a ∈ f x

Next tactic:
simp
instance : LawfulMonad Semiquot := LawfulMonad.mk'
  (pure_bind := fun {α β} x f => ext.2 <| by simp)
  (bind_assoc := fun {α β} γ s f g =>
    ext.2 <| by
    

Proof state:
α✝ : Type u_1
β✝ : Type u_2
α β γ : Type ?u.6486
s : Semiquot α
f : α → Semiquot β
g : β → Semiquot γ
⊢ ∀ (a : γ), a ∈ s >>= f >>= g ↔ a ∈ s >>= fun x => f x >>= g

Next tactic:
simp only [bind_def, mem_bind]
instance : LawfulMonad Semiquot := LawfulMonad.mk'
  (pure_bind := fun {α β} x f => ext.2 <| by simp)
  (bind_assoc := fun {α β} γ s f g =>
    ext.2 <| by
    simp only [bind_def, mem_bind]
    

Proof state:
α✝ : Type u_1
β✝ : Type u_2
α β γ : Type ?u.6486
s : Semiquot α
f : α → Semiquot β
g : β → Semiquot γ
⊢ ∀ (a : γ), (∃ a_1, (∃ a ∈ s, a_1 ∈ f a) ∧ a ∈ g a_1) ↔ ∃ a_1 ∈ s, ∃ a_2 ∈ f a_1, a ∈ g a_2

Next tactic:
exact fun c => ⟨fun ⟨b, ⟨a, as, bf⟩, cg⟩ => ⟨a, as, b, bf, cg⟩,
      fun ⟨a, as, b, bf, cg⟩ => ⟨b, ⟨a, as, bf⟩, cg⟩⟩
instance : LawfulMonad Semiquot := LawfulMonad.mk'
  (pure_bind := fun {α β} x f => ext.2 <| by simp)
  (bind_assoc := fun {α β} γ s f g =>
    ext.2 <| by
    simp only [bind_def, mem_bind]
    exact fun c => ⟨fun ⟨b, ⟨a, as, bf⟩, cg⟩ => ⟨a, as, b, bf, cg⟩,
      fun ⟨a, as, b, bf, cg⟩ => ⟨b, ⟨a, as, bf⟩, cg⟩⟩)
  (id_map := fun {α} q => ext.2 <| by simp)
  (bind_pure_comp := fun {α β} f s => ext.2 <| by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
α β : Type ?u.6486
f : α → β
s : Semiquot α
⊢ ∀ (a : β),
    (a ∈ do
        let y ← s
        pure (f y)) ↔
      a ∈ f <$> s

Next tactic:
simp [eq_comm]
theorem get_mem {q : Semiquot α} (p) : get q p ∈ q := by
  

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
p : IsPure q
⊢ get q p ∈ q

Next tactic:
let ⟨a, h⟩ := exists_mem q
theorem get_mem {q : Semiquot α} (p) : get q p ∈ q := by
  let ⟨a, h⟩ := exists_mem q
  

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
p : IsPure q
a : α
h : a ∈ q
⊢ get q p ∈ q

Next tactic:
unfold get
theorem get_mem {q : Semiquot α} (p) : get q p ∈ q := by
  let ⟨a, h⟩ := exists_mem q
  unfold get; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
p : IsPure q
a : α
h : a ∈ q
⊢ liftOn q id p ∈ q

Next tactic:
rw [liftOn_ofMem q _ _ a h]
theorem get_mem {q : Semiquot α} (p) : get q p ∈ q := by
  let ⟨a, h⟩ := exists_mem q
  unfold get; rw [liftOn_ofMem q _ _ a h]; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
p : IsPure q
a : α
h : a ∈ q
⊢ id a ∈ q

Next tactic:
exact h
theorem eq_pure {q : Semiquot α} (p) : q = pure (get q p) :=
  ext.2 fun a => by 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
p : IsPure q
a : α
⊢ a ∈ q ↔ a ∈ pure (get q p)

Next tactic:
simp
theorem eq_pure {q : Semiquot α} (p) : q = pure (get q p) :=
  ext.2 fun a => by simp; 

Proof state:
α : Type u_1
β : Type u_2
q : Semiquot α
p : IsPure q
a : α
⊢ a ∈ q ↔ a = get q p

Next tactic:
exact ⟨fun h => p _ h _ (get_mem _), fun e => e.symm ▸ get_mem _⟩
@[simp]
theorem pure_isPure (a : α) : IsPure (pure a)
  | b, ab, c, ac => by
    

Proof state:
α : Type u_1
β : Type u_2
a b : α
ab : b ∈ pure a
c : α
ac : c ∈ pure a
⊢ b = c

Next tactic:
rw [mem_pure] at ab ac