l3lab/ntp-mathlib huggingface dataset:
/-- Shows that `Aₙ = bₙ * Aₙ₋₁ + aₙ * Aₙ₋₂`. -/
theorem numerators_recurrence {gp : Pair K} {ppredA predA : K}
    (succ_nth_s_eq : g.s.get? (n + 1) = some gp) (nth_num_eq : g.numerators n = ppredA)
    (succ_nth_num_eq : g.numerators (n + 1) = predA) :
    g.numerators (n + 2) = gp.b * predA + gp.a * ppredA := by
  obtain ⟨ppredConts, nth_conts_eq, ⟨rfl⟩⟩ : ∃ conts, g.continuants n = conts ∧ conts.a = ppredA
  exact exists_conts_a_of_num nth_num_eq
  obtain ⟨predConts, succ_nth_conts_eq, ⟨rfl⟩⟩ :
    ∃ conts, g.continuants (n + 1) = conts ∧ conts.a = predA
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
predA : K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
succ_nth_num_eq : numerators g (n + 1) = predA
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_num_eq : numerators g n = ppredConts.a
⊢ ∃ conts, continuants g (n + 1) = conts ∧ conts.a = predA
case intro.intro.refl.intro.intro.refl
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_num_eq : numerators g n = ppredConts.a
predConts : Pair K
succ_nth_conts_eq : continuants g (n + 1) = predConts
succ_nth_num_eq : numerators g (n + 1) = predConts.a
⊢ numerators g (n + 2) = gp.b * predConts.a + gp.a * ppredConts.a

Next tactic:
exact exists_conts_a_of_num succ_nth_num_eq
/-- Shows that `Aₙ = bₙ * Aₙ₋₁ + aₙ * Aₙ₋₂`. -/
theorem numerators_recurrence {gp : Pair K} {ppredA predA : K}
    (succ_nth_s_eq : g.s.get? (n + 1) = some gp) (nth_num_eq : g.numerators n = ppredA)
    (succ_nth_num_eq : g.numerators (n + 1) = predA) :
    g.numerators (n + 2) = gp.b * predA + gp.a * ppredA := by
  obtain ⟨ppredConts, nth_conts_eq, ⟨rfl⟩⟩ : ∃ conts, g.continuants n = conts ∧ conts.a = ppredA
  exact exists_conts_a_of_num nth_num_eq
  obtain ⟨predConts, succ_nth_conts_eq, ⟨rfl⟩⟩ :
    ∃ conts, g.continuants (n + 1) = conts ∧ conts.a = predA
  exact exists_conts_a_of_num succ_nth_num_eq
  

Proof state:
case intro.intro.refl.intro.intro.refl
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_num_eq : numerators g n = ppredConts.a
predConts : Pair K
succ_nth_conts_eq : continuants g (n + 1) = predConts
succ_nth_num_eq : numerators g (n + 1) = predConts.a
⊢ numerators g (n + 2) = gp.b * predConts.a + gp.a * ppredConts.a

Next tactic:
rw [num_eq_conts_a, continuants_recurrence succ_nth_s_eq nth_conts_eq succ_nth_conts_eq]
/-- Shows that `Bₙ = bₙ * Bₙ₋₁ + aₙ * Bₙ₋₂`. -/
theorem denominators_recurrence {gp : Pair K} {ppredB predB : K}
    (succ_nth_s_eq : g.s.get? (n + 1) = some gp) (nth_denom_eq : g.denominators n = ppredB)
    (succ_nth_denom_eq : g.denominators (n + 1) = predB) :
    g.denominators (n + 2) = gp.b * predB + gp.a * ppredB := by
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
ppredB predB : K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
nth_denom_eq : denominators g n = ppredB
succ_nth_denom_eq : denominators g (n + 1) = predB
⊢ denominators g (n + 2) = gp.b * predB + gp.a * ppredB

Next tactic:
obtain ⟨ppredConts, nth_conts_eq, ⟨rfl⟩⟩ : ∃ conts, g.continuants n = conts ∧ conts.b = ppredB
/-- Shows that `Bₙ = bₙ * Bₙ₋₁ + aₙ * Bₙ₋₂`. -/
theorem denominators_recurrence {gp : Pair K} {ppredB predB : K}
    (succ_nth_s_eq : g.s.get? (n + 1) = some gp) (nth_denom_eq : g.denominators n = ppredB)
    (succ_nth_denom_eq : g.denominators (n + 1) = predB) :
    g.denominators (n + 2) = gp.b * predB + gp.a * ppredB := by
  obtain ⟨ppredConts, nth_conts_eq, ⟨rfl⟩⟩ : ∃ conts, g.continuants n = conts ∧ conts.b = ppredB
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
ppredB predB : K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
nth_denom_eq : denominators g n = ppredB
succ_nth_denom_eq : denominators g (n + 1) = predB
⊢ ∃ conts, continuants g n = conts ∧ conts.b = ppredB
case intro.intro.refl
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
predB : K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
succ_nth_denom_eq : denominators g (n + 1) = predB
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_denom_eq : denominators g n = ppredConts.b
⊢ denominators g (n + 2) = gp.b * predB + gp.a * ppredConts.b

Next tactic:
exact exists_conts_b_of_denom nth_denom_eq
/-- Shows that `Bₙ = bₙ * Bₙ₋₁ + aₙ * Bₙ₋₂`. -/
theorem denominators_recurrence {gp : Pair K} {ppredB predB : K}
    (succ_nth_s_eq : g.s.get? (n + 1) = some gp) (nth_denom_eq : g.denominators n = ppredB)
    (succ_nth_denom_eq : g.denominators (n + 1) = predB) :
    g.denominators (n + 2) = gp.b * predB + gp.a * ppredB := by
  obtain ⟨ppredConts, nth_conts_eq, ⟨rfl⟩⟩ : ∃ conts, g.continuants n = conts ∧ conts.b = ppredB
  exact exists_conts_b_of_denom nth_denom_eq
  

Proof state:
case intro.intro.refl
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
predB : K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
succ_nth_denom_eq : denominators g (n + 1) = predB
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_denom_eq : denominators g n = ppredConts.b
⊢ denominators g (n + 2) = gp.b * predB + gp.a * ppredConts.b

Next tactic:
obtain ⟨predConts, succ_nth_conts_eq, ⟨rfl⟩⟩ :
    ∃ conts, g.continuants (n + 1) = conts ∧ conts.b = predB
/-- Shows that `Bₙ = bₙ * Bₙ₋₁ + aₙ * Bₙ₋₂`. -/
theorem denominators_recurrence {gp : Pair K} {ppredB predB : K}
    (succ_nth_s_eq : g.s.get? (n + 1) = some gp) (nth_denom_eq : g.denominators n = ppredB)
    (succ_nth_denom_eq : g.denominators (n + 1) = predB) :
    g.denominators (n + 2) = gp.b * predB + gp.a * ppredB := by
  obtain ⟨ppredConts, nth_conts_eq, ⟨rfl⟩⟩ : ∃ conts, g.continuants n = conts ∧ conts.b = ppredB
  exact exists_conts_b_of_denom nth_denom_eq
  obtain ⟨predConts, succ_nth_conts_eq, ⟨rfl⟩⟩ :
    ∃ conts, g.continuants (n + 1) = conts ∧ conts.b = predB
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
predB : K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
succ_nth_denom_eq : denominators g (n + 1) = predB
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_denom_eq : denominators g n = ppredConts.b
⊢ ∃ conts, continuants g (n + 1) = conts ∧ conts.b = predB
case intro.intro.refl.intro.intro.refl
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_denom_eq : denominators g n = ppredConts.b
predConts : Pair K
succ_nth_conts_eq : continuants g (n + 1) = predConts
succ_nth_denom_eq : denominators g (n + 1) = predConts.b
⊢ denominators g (n + 2) = gp.b * predConts.b + gp.a * ppredConts.b

Next tactic:
exact exists_conts_b_of_denom succ_nth_denom_eq
/-- Shows that `Bₙ = bₙ * Bₙ₋₁ + aₙ * Bₙ₋₂`. -/
theorem denominators_recurrence {gp : Pair K} {ppredB predB : K}
    (succ_nth_s_eq : g.s.get? (n + 1) = some gp) (nth_denom_eq : g.denominators n = ppredB)
    (succ_nth_denom_eq : g.denominators (n + 1) = predB) :
    g.denominators (n + 2) = gp.b * predB + gp.a * ppredB := by
  obtain ⟨ppredConts, nth_conts_eq, ⟨rfl⟩⟩ : ∃ conts, g.continuants n = conts ∧ conts.b = ppredB
  exact exists_conts_b_of_denom nth_denom_eq
  obtain ⟨predConts, succ_nth_conts_eq, ⟨rfl⟩⟩ :
    ∃ conts, g.continuants (n + 1) = conts ∧ conts.b = predB
  exact exists_conts_b_of_denom succ_nth_denom_eq
  

Proof state:
case intro.intro.refl.intro.intro.refl
K : Type u_1
g : GeneralizedContinuedFraction K
n : ℕ
inst✝ : DivisionRing K
gp : Pair K
succ_nth_s_eq : Stream'.Seq.get? g.s (n + 1) = some gp
ppredConts : Pair K
nth_conts_eq : continuants g n = ppredConts
nth_denom_eq : denominators g n = ppredConts.b
predConts : Pair K
succ_nth_conts_eq : continuants g (n + 1) = predConts
succ_nth_denom_eq : denominators g (n + 1) = predConts.b
⊢ denominators g (n + 2) = gp.b * predConts.b + gp.a * ppredConts.b

Next tactic:
rw [denom_eq_conts_b, continuants_recurrence succ_nth_s_eq nth_conts_eq succ_nth_conts_eq]
theorem tendsto_div_exp_atTop (p : ℝ[X]) : Tendsto (fun x ↦ p.eval x / exp x) atTop (𝓝 0) := by
  

Proof state:
p : ℝ[X]
⊢ Tendsto (fun x => eval x p / rexp x) atTop (𝓝 0)

Next tactic:
induction p using Polynomial.induction_on' with
  | h_monomial n c => simpa [exp_neg, div_eq_mul_inv, mul_assoc]
    using tendsto_const_nhds.mul (tendsto_pow_mul_exp_neg_atTop_nhds_0 n)
  | h_add p q hp hq => simpa [add_div] using hp.add hq
theorem tendsto_div_exp_atTop (p : ℝ[X]) : Tendsto (fun x ↦ p.eval x / exp x) atTop (𝓝 0) := by
  induction p using Polynomial.induction_on' with
  

Proof state:
case h_monomial
n : ℕ
c : ℝ
⊢ Tendsto (fun x => eval x ((monomial n) c) / rexp x) atTop (𝓝 0)

Next tactic:
| h_monomial n c => simpa [exp_neg, div_eq_mul_inv, mul_assoc]
    using tendsto_const_nhds.mul (tendsto_pow_mul_exp_neg_atTop_nhds_0 n)
theorem tendsto_div_exp_atTop (p : ℝ[X]) : Tendsto (fun x ↦ p.eval x / exp x) atTop (𝓝 0) := by
  induction p using Polynomial.induction_on' with
  | h_monomial n c => 

Proof state:
case h_monomial
n : ℕ
c : ℝ
⊢ Tendsto (fun x => eval x ((monomial n) c) / rexp x) atTop (𝓝 0)

Next tactic:
simpa [exp_neg, div_eq_mul_inv, mul_assoc]
    using tendsto_const_nhds.mul (tendsto_pow_mul_exp_neg_atTop_nhds_0 n)
theorem tendsto_div_exp_atTop (p : ℝ[X]) : Tendsto (fun x ↦ p.eval x / exp x) atTop (𝓝 0) := by
  induction p using Polynomial.induction_on' with
  | h_monomial n c => simpa [exp_neg, div_eq_mul_inv, mul_assoc]
    using tendsto_const_nhds.mul (tendsto_pow_mul_exp_neg_atTop_nhds_0 n)
  

Proof state:
case h_add
p q : ℝ[X]
hp : Tendsto (fun x => eval x p / rexp x) atTop (𝓝 0)
hq : Tendsto (fun x => eval x q / rexp x) atTop (𝓝 0)
⊢ Tendsto (fun x => eval x (p + q) / rexp x) atTop (𝓝 0)

Next tactic:
| h_add p q hp hq => simpa [add_div] using hp.add hq
theorem tendsto_div_exp_atTop (p : ℝ[X]) : Tendsto (fun x ↦ p.eval x / exp x) atTop (𝓝 0) := by
  induction p using Polynomial.induction_on' with
  | h_monomial n c => simpa [exp_neg, div_eq_mul_inv, mul_assoc]
    using tendsto_const_nhds.mul (tendsto_pow_mul_exp_neg_atTop_nhds_0 n)
  | h_add p q hp hq => 

Proof state:
case h_add
p q : ℝ[X]
hp : Tendsto (fun x => eval x p / rexp x) atTop (𝓝 0)
hq : Tendsto (fun x => eval x q / rexp x) atTop (𝓝 0)
⊢ Tendsto (fun x => eval x (p + q) / rexp x) atTop (𝓝 0)

Next tactic:
simpa [add_div] using hp.add hq
/-- In the category of modules, every monomorphism is normal. -/
def normalMono (hf : Mono f) : NormalMono f where
  Z := of R (N ⧸ LinearMap.range f)
  g := f.range.mkQ
  w := LinearMap.range_mkQ_comp _
  isLimit :=
    /- The following [invalid Lean code](https://github.com/leanprover-community/lean/issues/341)
        might help you understand what's going on here:
        ```
        calc
        M   ≃ₗ[R] f.ker.quotient  : (submodule.quot_equiv_of_eq_bot _ (ker_eq_bot_of_mono _)).symm
        ... ≃ₗ[R] f.range         : linear_map.quot_ker_equiv_range f
        ... ≃ₗ[R] r.range.mkq.ker : linear_equiv.of_eq _ _ (submodule.ker_mkq _).symm
        ```
      -/
        IsKernel.isoKernel _ _ (kernelIsLimit _)
          (LinearEquiv.toModuleIso'
            ((Submodule.quotEquivOfEqBot _ (ker_eq_bot_of_mono _)).symm ≪≫ₗ
              (LinearMap.quotKerEquivRange f ≪≫ₗ
              LinearEquiv.ofEq _ _ (Submodule.ker_mkQ _).symm))) <| by 

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
hf : Mono f
⊢ (LinearEquiv.toModuleIso'
          (LinearEquiv.symm (Submodule.quotEquivOfEqBot (LinearMap.ker f) (_ : LinearMap.ker f = ⊥)) ≪≫ₗ
            (LinearMap.quotKerEquivRange f ≪≫ₗ
              LinearEquiv.ofEq (LinearMap.range f) (LinearMap.ker (Submodule.mkQ (LinearMap.range f)))
                (_ : LinearMap.range f = LinearMap.ker (Submodule.mkQ (LinearMap.range f)))))).hom ≫
      Fork.ι (kernelCone (Submodule.mkQ (LinearMap.range f))) =
    f

Next tactic:
ext
/-- In the category of modules, every monomorphism is normal. -/
def normalMono (hf : Mono f) : NormalMono f where
  Z := of R (N ⧸ LinearMap.range f)
  g := f.range.mkQ
  w := LinearMap.range_mkQ_comp _
  isLimit :=
    /- The following [invalid Lean code](https://github.com/leanprover-community/lean/issues/341)
        might help you understand what's going on here:
        ```
        calc
        M   ≃ₗ[R] f.ker.quotient  : (submodule.quot_equiv_of_eq_bot _ (ker_eq_bot_of_mono _)).symm
        ... ≃ₗ[R] f.range         : linear_map.quot_ker_equiv_range f
        ... ≃ₗ[R] r.range.mkq.ker : linear_equiv.of_eq _ _ (submodule.ker_mkq _).symm
        ```
      -/
        IsKernel.isoKernel _ _ (kernelIsLimit _)
          (LinearEquiv.toModuleIso'
            ((Submodule.quotEquivOfEqBot _ (ker_eq_bot_of_mono _)).symm ≪≫ₗ
              (LinearMap.quotKerEquivRange f ≪≫ₗ
              LinearEquiv.ofEq _ _ (Submodule.ker_mkQ _).symm))) <| by ext; 

Proof state:
case h
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
hf : Mono f
x✝ : ↑M
⊢ ((LinearEquiv.toModuleIso'
            (LinearEquiv.symm (Submodule.quotEquivOfEqBot (LinearMap.ker f) (_ : LinearMap.ker f = ⊥)) ≪≫ₗ
              (LinearMap.quotKerEquivRange f ≪≫ₗ
                LinearEquiv.ofEq (LinearMap.range f) (LinearMap.ker (Submodule.mkQ (LinearMap.range f)))
                  (_ : LinearMap.range f = LinearMap.ker (Submodule.mkQ (LinearMap.range f)))))).hom ≫
        Fork.ι (kernelCone (Submodule.mkQ (LinearMap.range f))))
      x✝ =
    f x✝

Next tactic:
rfl
/-- In the category of modules, every epimorphism is normal. -/
def normalEpi (hf : Epi f) : NormalEpi f where
  W := of R (LinearMap.ker f)
  g := (LinearMap.ker f).subtype
  w := LinearMap.comp_ker_subtype _
  isColimit :=
    /- The following invalid Lean code might help you understand what's going on here:
        ```
        calc f.ker.subtype.range.quotient
            ≃ₗ[R] f.ker.quotient : submodule.quot_equiv_of_eq _ _ (submodule.range_subtype _)
        ... ≃ₗ[R] f.range        : linear_map.quot_ker_equiv_range f
        ... ≃ₗ[R] N              : linear_equiv.of_top _ (range_eq_top_of_epi _)
        ```
      -/
        IsCokernel.cokernelIso _ _ (cokernelIsColimit _)
          (LinearEquiv.toModuleIso'
            (Submodule.quotEquivOfEq _ _ (Submodule.range_subtype _) ≪≫ₗ
                LinearMap.quotKerEquivRange f ≪≫ₗ
              LinearEquiv.ofTop _ (range_eq_top_of_epi _))) <| by 

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
hf : Epi f
⊢ Cofork.π (cokernelCocone (Submodule.subtype (LinearMap.ker f))) ≫
      (LinearEquiv.toModuleIso'
          (Submodule.quotEquivOfEq (LinearMap.range (Submodule.subtype (LinearMap.ker f))) (LinearMap.ker f)
                (_ : LinearMap.range (Submodule.subtype (LinearMap.ker f)) = LinearMap.ker f) ≪≫ₗ
              LinearMap.quotKerEquivRange f ≪≫ₗ
            LinearEquiv.ofTop (LinearMap.range f) (_ : LinearMap.range f = ⊤))).hom =
    f

Next tactic:
ext
/-- In the category of modules, every epimorphism is normal. -/
def normalEpi (hf : Epi f) : NormalEpi f where
  W := of R (LinearMap.ker f)
  g := (LinearMap.ker f).subtype
  w := LinearMap.comp_ker_subtype _
  isColimit :=
    /- The following invalid Lean code might help you understand what's going on here:
        ```
        calc f.ker.subtype.range.quotient
            ≃ₗ[R] f.ker.quotient : submodule.quot_equiv_of_eq _ _ (submodule.range_subtype _)
        ... ≃ₗ[R] f.range        : linear_map.quot_ker_equiv_range f
        ... ≃ₗ[R] N              : linear_equiv.of_top _ (range_eq_top_of_epi _)
        ```
      -/
        IsCokernel.cokernelIso _ _ (cokernelIsColimit _)
          (LinearEquiv.toModuleIso'
            (Submodule.quotEquivOfEq _ _ (Submodule.range_subtype _) ≪≫ₗ
                LinearMap.quotKerEquivRange f ≪≫ₗ
              LinearEquiv.ofTop _ (range_eq_top_of_epi _))) <| by ext; 

Proof state:
case h
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
hf : Epi f
x✝ : ↑((parallelPair (Submodule.subtype (LinearMap.ker f)) 0).obj WalkingParallelPair.one)
⊢ (Cofork.π (cokernelCocone (Submodule.subtype (LinearMap.ker f))) ≫
        (LinearEquiv.toModuleIso'
            (Submodule.quotEquivOfEq (LinearMap.range (Submodule.subtype (LinearMap.ker f))) (LinearMap.ker f)
                  (_ : LinearMap.range (Submodule.subtype (LinearMap.ker f)) = LinearMap.ker f) ≪≫ₗ
                LinearMap.quotKerEquivRange f ≪≫ₗ
              LinearEquiv.ofTop (LinearMap.range f) (_ : LinearMap.range f = ⊤))).hom)
      x✝ =
    f x✝

Next tactic:
rfl
theorem exact_iff : Exact f g ↔ LinearMap.range f = LinearMap.ker g := by
  

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
O : ModuleCat R
g : N ⟶ O
⊢ Exact f g ↔ range f = ker g

Next tactic:
rw [abelian.exact_iff' f g (kernelIsLimit _) (cokernelIsColimit _)]
theorem exact_iff : Exact f g ↔ LinearMap.range f = LinearMap.ker g := by
  rw [abelian.exact_iff' f g (kernelIsLimit _) (cokernelIsColimit _)]
  

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
O : ModuleCat R
g : N ⟶ O
⊢ f ≫ g = 0 ∧ Fork.ι (kernelCone g) ≫ Cofork.π (cokernelCocone f) = 0 ↔ range f = ker g

Next tactic:
exact
    ⟨fun h => le_antisymm (range_le_ker_iff.2 h.1) (ker_le_range_iff.2 h.2), fun h =>
      ⟨range_le_ker_iff.1 <| le_of_eq h, ker_le_range_iff.1 <| le_of_eq h.symm⟩⟩
@[simp]
theorem Multiset.coe_eq {x y : m} : (x : α) = (y : α) ↔ x.1 = y.1 := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m : Multiset α
x y : ToType m
⊢ x.fst = y.fst ↔ x.fst = y.fst

Next tactic:
cases x
@[simp]
theorem Multiset.coe_eq {x y : m} : (x : α) = (y : α) ↔ x.1 = y.1 := by
  cases x
  

Proof state:
case mk
α : Type u_1
inst✝ : DecidableEq α
m : Multiset α
y : ToType m
fst✝ : α
snd✝ : Fin (count fst✝ m)
⊢ { fst := fst✝, snd := snd✝ }.fst = y.fst ↔ { fst := fst✝, snd := snd✝ }.fst = y.fst

Next tactic:
cases y
@[simp]
theorem Multiset.coe_eq {x y : m} : (x : α) = (y : α) ↔ x.1 = y.1 := by
  cases x
  cases y
  

Proof state:
case mk.mk
α : Type u_1
inst✝ : DecidableEq α
m : Multiset α
fst✝¹ : α
snd✝¹ : Fin (count fst✝¹ m)
fst✝ : α
snd✝ : Fin (count fst✝ m)
⊢ { fst := fst✝¹, snd := snd✝¹ }.fst = { fst := fst✝, snd := snd✝ }.fst ↔
    { fst := fst✝¹, snd := snd✝¹ }.fst = { fst := fst✝, snd := snd✝ }.fst

Next tactic:
rfl
instance : Fintype { p : α × ℕ | p.2 < m.count p.1 } :=
  Fintype.ofFinset
    (m.toFinset.biUnion fun x ↦ (Finset.range (m.count x)).map ⟨Prod.mk x, Prod.mk.inj_left x⟩)
    (by
      

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m : Multiset α
⊢ ∀ (x : α × ℕ),
    (x ∈
        Finset.biUnion (Multiset.toFinset m) fun x =>
          Finset.map { toFun := Prod.mk x, inj' := (_ : Function.Injective (Prod.mk x)) }
            (Finset.range (Multiset.count x m))) ↔
      x ∈ {p | p.2 < Multiset.count p.1 m}

Next tactic:
rintro ⟨x, i⟩
instance : Fintype { p : α × ℕ | p.2 < m.count p.1 } :=
  Fintype.ofFinset
    (m.toFinset.biUnion fun x ↦ (Finset.range (m.count x)).map ⟨Prod.mk x, Prod.mk.inj_left x⟩)
    (by
      rintro ⟨x, i⟩
      

Proof state:
case mk
α : Type u_1
inst✝ : DecidableEq α
m : Multiset α
x : α
i : ℕ
⊢ ((x, i) ∈
      Finset.biUnion (Multiset.toFinset m) fun x =>
        Finset.map { toFun := Prod.mk x, inj' := (_ : Function.Injective (Prod.mk x)) }
          (Finset.range (Multiset.count x m))) ↔
    (x, i) ∈ {p | p.2 < Multiset.count p.1 m}

Next tactic:
simp only [Finset.mem_biUnion, Multiset.mem_toFinset, Finset.mem_map, Finset.mem_range,
        Function.Embedding.coeFn_mk, Prod.mk.inj_iff, Set.mem_setOf_eq]
instance : Fintype { p : α × ℕ | p.2 < m.count p.1 } :=
  Fintype.ofFinset
    (m.toFinset.biUnion fun x ↦ (Finset.range (m.count x)).map ⟨Prod.mk x, Prod.mk.inj_left x⟩)
    (by
      rintro ⟨x, i⟩
      simp only [Finset.mem_biUnion, Multiset.mem_toFinset, Finset.mem_map, Finset.mem_range,
        Function.Embedding.coeFn_mk, Prod.mk.inj_iff, Set.mem_setOf_eq]
      

Proof state:
case mk
α : Type u_1
inst✝ : DecidableEq α
m : Multiset α
x : α
i : ℕ
⊢ (∃ a ∈ m, ∃ a_1 < Multiset.count a m, a = x ∧ a_1 = i) ↔ i < Multiset.count x m

Next tactic:
simp only [← and_assoc, exists_eq_right, and_iff_right_iff_imp]
instance : Fintype { p : α × ℕ | p.2 < m.count p.1 } :=
  Fintype.ofFinset
    (m.toFinset.biUnion fun x ↦ (Finset.range (m.count x)).map ⟨Prod.mk x, Prod.mk.inj_left x⟩)
    (by
      rintro ⟨x, i⟩
      simp only [Finset.mem_biUnion, Multiset.mem_toFinset, Finset.mem_map, Finset.mem_range,
        Function.Embedding.coeFn_mk, Prod.mk.inj_iff, Set.mem_setOf_eq]
      simp only [← and_assoc, exists_eq_right, and_iff_right_iff_imp]
      

Proof state:
case mk
α : Type u_1
inst✝ : DecidableEq α
m : Multiset α
x : α
i : ℕ
⊢ i < Multiset.count x m → x ∈ m

Next tactic:
exact fun h ↦ Multiset.count_pos.mp (pos_of_gt h)
@[mono]
theorem Multiset.toEnumFinset_mono {m₁ m₂ : Multiset α} (h : m₁ ≤ m₂) :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
h : m₁ ≤ m₂
⊢ toEnumFinset m₁ ⊆ toEnumFinset m₂

Next tactic:
intro p
@[mono]
theorem Multiset.toEnumFinset_mono {m₁ m₂ : Multiset α} (h : m₁ ≤ m₂) :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset := by
  intro p
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
h : m₁ ≤ m₂
p : α × ℕ
⊢ p ∈ toEnumFinset m₁ → p ∈ toEnumFinset m₂

Next tactic:
simp only [Multiset.mem_toEnumFinset]
@[mono]
theorem Multiset.toEnumFinset_mono {m₁ m₂ : Multiset α} (h : m₁ ≤ m₂) :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset := by
  intro p
  simp only [Multiset.mem_toEnumFinset]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
h : m₁ ≤ m₂
p : α × ℕ
⊢ p.2 < count p.1 m₁ → p.2 < count p.1 m₂

Next tactic:
exact gt_of_ge_of_gt (Multiset.le_iff_count.mp h p.1)
@[simp]
theorem Multiset.toEnumFinset_subset_iff {m₁ m₂ : Multiset α} :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset ↔ m₁ ≤ m₂ := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
⊢ toEnumFinset m₁ ⊆ toEnumFinset m₂ ↔ m₁ ≤ m₂

Next tactic:
refine' ⟨fun h ↦ _, Multiset.toEnumFinset_mono⟩
@[simp]
theorem Multiset.toEnumFinset_subset_iff {m₁ m₂ : Multiset α} :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset ↔ m₁ ≤ m₂ := by
  refine' ⟨fun h ↦ _, Multiset.toEnumFinset_mono⟩
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
h : toEnumFinset m₁ ⊆ toEnumFinset m₂
⊢ m₁ ≤ m₂

Next tactic:
rw [Multiset.le_iff_count]
@[simp]
theorem Multiset.toEnumFinset_subset_iff {m₁ m₂ : Multiset α} :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset ↔ m₁ ≤ m₂ := by
  refine' ⟨fun h ↦ _, Multiset.toEnumFinset_mono⟩
  rw [Multiset.le_iff_count]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
h : toEnumFinset m₁ ⊆ toEnumFinset m₂
⊢ ∀ (a : α), count a m₁ ≤ count a m₂

Next tactic:
intro x
@[simp]
theorem Multiset.toEnumFinset_subset_iff {m₁ m₂ : Multiset α} :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset ↔ m₁ ≤ m₂ := by
  refine' ⟨fun h ↦ _, Multiset.toEnumFinset_mono⟩
  rw [Multiset.le_iff_count]
  intro x
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
h : toEnumFinset m₁ ⊆ toEnumFinset m₂
x : α
⊢ count x m₁ ≤ count x m₂

Next tactic:
by_cases hx : x ∈ m₁
@[simp]
theorem Multiset.toEnumFinset_subset_iff {m₁ m₂ : Multiset α} :
    m₁.toEnumFinset ⊆ m₂.toEnumFinset ↔ m₁ ≤ m₂ := by
  refine' ⟨fun h ↦ _, Multiset.toEnumFinset_mono⟩
  rw [Multiset.le_iff_count]
  intro x
  by_cases hx : x ∈ m₁
  · 

Proof state:
case pos
α : Type u_1
inst✝ : DecidableEq α
m m₁ m₂ : Multiset α
h : toEnumFinset m₁ ⊆ toEnumFinset m₂
x : α
hx : x ∈ m₁
⊢ count x m₁ ≤ count x m₂

Next tactic:
apply Nat.le_of_pred_lt