/-
Copyright (c) 2021 Sébastien Gouëzel. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sébastien Gouëzel, Heather Macbeth, Johannes Hölzl, Yury Kudryashov

! This file was ported from Lean 3 source module analysis.normed.group.infinite_sum
! leanprover-community/mathlib commit 69c6a5a12d8a2b159f20933e60115a4f2de62b58
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Algebra.BigOperators.Intervals
import Mathbin.Analysis.Normed.Group.Basic
import Mathbin.Topology.Instances.Nnreal

/-!
# Infinite sums in (semi)normed groups

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

In a complete (semi)normed group,

- `summable_iff_vanishing_norm`: a series `∑' i, f i` is summable if and only if for any `ε > 0`,
  there exists a finite set `s` such that the sum `∑ i in t, f i` over any finite set `t` disjoint
  with `s` has norm less than `ε`;

- `summable_of_norm_bounded`, `summable_of_norm_bounded_eventually`: if `‖f i‖` is bounded above by
  a summable series `∑' i, g i`, then `∑' i, f i` is summable as well; the same is true if the
  inequality hold only off some finite set.

- `tsum_of_norm_bounded`, `has_sum.norm_le_of_bounded`: if `‖f i‖ ≤ g i`, where `∑' i, g i` is a
  summable series, then `‖∑' i, f i‖ ≤ ∑' i, g i`.

## Tags

infinite series, absolute convergence, normed group
-/

open Classical BigOperators Topology NNReal

open Finset Filter Metric

variable {ι α E F : Type _} [SeminormedAddCommGroup E] [SeminormedAddCommGroup F]

/- warning: cauchy_seq_finset_iff_vanishing_norm -> cauchySeq_finset_iff_vanishing_norm is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E}, Iff (CauchySeq.{u2, u1} E (Finset.{u1} ι) (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1)) (Lattice.toSemilatticeSup.{u1} (Finset.{u1} ι) (Finset.lattice.{u1} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u1} ι a b)))) (fun (s : Finset.{u1} ι) => Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) s (fun (i : ι) => f i))) (forall (ε : Real), (GT.gt.{0} Real Real.hasLt ε (OfNat.ofNat.{0} Real 0 (OfNat.mk.{0} Real 0 (Zero.zero.{0} Real Real.hasZero)))) -> (Exists.{succ u1} (Finset.{u1} ι) (fun (s : Finset.{u1} ι) => forall (t : Finset.{u1} ι), (Disjoint.{u1} (Finset.{u1} ι) (Finset.partialOrder.{u1} ι) (Finset.orderBot.{u1} ι) t s) -> (LT.lt.{0} Real Real.hasLt (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) t (fun (i : ι) => f i))) ε))))
but is expected to have type
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E}, Iff (CauchySeq.{u2, u1} E (Finset.{u1} ι) (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1)) (Lattice.toSemilatticeSup.{u1} (Finset.{u1} ι) (Finset.instLatticeFinset.{u1} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u1} ι a b)))) (fun (s : Finset.{u1} ι) => Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) s (fun (i : ι) => f i))) (forall (ε : Real), (GT.gt.{0} Real Real.instLTReal ε (OfNat.ofNat.{0} Real 0 (Zero.toOfNat0.{0} Real Real.instZeroReal))) -> (Exists.{succ u1} (Finset.{u1} ι) (fun (s : Finset.{u1} ι) => forall (t : Finset.{u1} ι), (Disjoint.{u1} (Finset.{u1} ι) (Finset.partialOrder.{u1} ι) (Finset.instOrderBotFinsetToLEToPreorderPartialOrder.{u1} ι) t s) -> (LT.lt.{0} Real Real.instLTReal (Norm.norm.{u2} E (SeminormedAddCommGroup.toNorm.{u2} E _inst_1) (Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) t (fun (i : ι) => f i))) ε))))
Case conversion may be inaccurate. Consider using '#align cauchy_seq_finset_iff_vanishing_norm cauchySeq_finset_iff_vanishing_normₓ'. -/
theorem cauchySeq_finset_iff_vanishing_norm {f : ι → E} :
    (CauchySeq fun s : Finset ι => ∑ i in s, f i) ↔
      ∀ ε > (0 : ℝ), ∃ s : Finset ι, ∀ t, Disjoint t s → ‖∑ i in t, f i‖ < ε :=
  by
  rw [cauchySeq_finset_iff_vanishing, nhds_basis_ball.forall_iff]
  · simp only [ball_zero_eq, Set.mem_setOf_eq]
  · rintro s t hst ⟨s', hs'⟩
    exact ⟨s', fun t' ht' => hst <| hs' _ ht'⟩
#align cauchy_seq_finset_iff_vanishing_norm cauchySeq_finset_iff_vanishing_norm

/- warning: summable_iff_vanishing_norm -> summable_iff_vanishing_norm is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E}, Iff (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f) (forall (ε : Real), (GT.gt.{0} Real Real.hasLt ε (OfNat.ofNat.{0} Real 0 (OfNat.mk.{0} Real 0 (Zero.zero.{0} Real Real.hasZero)))) -> (Exists.{succ u1} (Finset.{u1} ι) (fun (s : Finset.{u1} ι) => forall (t : Finset.{u1} ι), (Disjoint.{u1} (Finset.{u1} ι) (Finset.partialOrder.{u1} ι) (Finset.orderBot.{u1} ι) t s) -> (LT.lt.{0} Real Real.hasLt (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) t (fun (i : ι) => f i))) ε))))
but is expected to have type
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E}, Iff (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f) (forall (ε : Real), (GT.gt.{0} Real Real.instLTReal ε (OfNat.ofNat.{0} Real 0 (Zero.toOfNat0.{0} Real Real.instZeroReal))) -> (Exists.{succ u1} (Finset.{u1} ι) (fun (s : Finset.{u1} ι) => forall (t : Finset.{u1} ι), (Disjoint.{u1} (Finset.{u1} ι) (Finset.partialOrder.{u1} ι) (Finset.instOrderBotFinsetToLEToPreorderPartialOrder.{u1} ι) t s) -> (LT.lt.{0} Real Real.instLTReal (Norm.norm.{u2} E (SeminormedAddCommGroup.toNorm.{u2} E _inst_1) (Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) t (fun (i : ι) => f i))) ε))))
Case conversion may be inaccurate. Consider using '#align summable_iff_vanishing_norm summable_iff_vanishing_normₓ'. -/
theorem summable_iff_vanishing_norm [CompleteSpace E] {f : ι → E} :
    Summable f ↔ ∀ ε > (0 : ℝ), ∃ s : Finset ι, ∀ t, Disjoint t s → ‖∑ i in t, f i‖ < ε := by
  rw [summable_iff_cauchySeq_finset, cauchySeq_finset_iff_vanishing_norm]
#align summable_iff_vanishing_norm summable_iff_vanishing_norm

/- warning: cauchy_seq_finset_of_norm_bounded_eventually -> cauchySeq_finset_of_norm_bounded_eventually is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E} {g : ι -> Real}, (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (Filter.Eventually.{u1} ι (fun (i : ι) => LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i)) (g i)) (Filter.cofinite.{u1} ι)) -> (CauchySeq.{u2, u1} E (Finset.{u1} ι) (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1)) (Lattice.toSemilatticeSup.{u1} (Finset.{u1} ι) (Finset.lattice.{u1} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u1} ι a b)))) (fun (s : Finset.{u1} ι) => Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) s (fun (i : ι) => f i)))
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : ι -> E} {g : ι -> Real}, (Summable.{0, u2} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (Filter.Eventually.{u2} ι (fun (i : ι) => LE.le.{0} Real Real.instLEReal (Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f i)) (g i)) (Filter.cofinite.{u2} ι)) -> (CauchySeq.{u1, u2} E (Finset.{u2} ι) (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1)) (Lattice.toSemilatticeSup.{u2} (Finset.{u2} ι) (Finset.instLatticeFinset.{u2} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u2} ι a b)))) (fun (s : Finset.{u2} ι) => Finset.sum.{u1, u2} E ι (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) s (fun (i : ι) => f i)))
Case conversion may be inaccurate. Consider using '#align cauchy_seq_finset_of_norm_bounded_eventually cauchySeq_finset_of_norm_bounded_eventuallyₓ'. -/
theorem cauchySeq_finset_of_norm_bounded_eventually {f : ι → E} {g : ι → ℝ} (hg : Summable g)
    (h : ∀ᶠ i in cofinite, ‖f i‖ ≤ g i) : CauchySeq fun s => ∑ i in s, f i :=
  by
  refine' cauchySeq_finset_iff_vanishing_norm.2 fun ε hε => _
  rcases summable_iff_vanishing_norm.1 hg ε hε with ⟨s, hs⟩
  refine' ⟨s ∪ h.to_finset, fun t ht => _⟩
  have : ∀ i ∈ t, ‖f i‖ ≤ g i := by
    intro i hi
    simp only [disjoint_left, mem_union, not_or, h.mem_to_finset, Set.mem_compl_iff,
      Classical.not_not] at ht
    exact (ht hi).2
  calc
    ‖∑ i in t, f i‖ ≤ ∑ i in t, g i := norm_sum_le_of_le _ this
    _ ≤ ‖∑ i in t, g i‖ := (le_abs_self _)
    _ < ε := hs _ (ht.mono_right le_sup_left)

#align cauchy_seq_finset_of_norm_bounded_eventually cauchySeq_finset_of_norm_bounded_eventually

/- warning: cauchy_seq_finset_of_norm_bounded -> cauchySeq_finset_of_norm_bounded is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E} (g : ι -> Real), (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (forall (i : ι), LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i)) (g i)) -> (CauchySeq.{u2, u1} E (Finset.{u1} ι) (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1)) (Lattice.toSemilatticeSup.{u1} (Finset.{u1} ι) (Finset.lattice.{u1} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u1} ι a b)))) (fun (s : Finset.{u1} ι) => Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) s (fun (i : ι) => f i)))
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : ι -> E} (g : ι -> Real), (Summable.{0, u2} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (forall (i : ι), LE.le.{0} Real Real.instLEReal (Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f i)) (g i)) -> (CauchySeq.{u1, u2} E (Finset.{u2} ι) (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1)) (Lattice.toSemilatticeSup.{u2} (Finset.{u2} ι) (Finset.instLatticeFinset.{u2} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u2} ι a b)))) (fun (s : Finset.{u2} ι) => Finset.sum.{u1, u2} E ι (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) s (fun (i : ι) => f i)))
Case conversion may be inaccurate. Consider using '#align cauchy_seq_finset_of_norm_bounded cauchySeq_finset_of_norm_boundedₓ'. -/
theorem cauchySeq_finset_of_norm_bounded {f : ι → E} (g : ι → ℝ) (hg : Summable g)
    (h : ∀ i, ‖f i‖ ≤ g i) : CauchySeq fun s : Finset ι => ∑ i in s, f i :=
  cauchySeq_finset_of_norm_bounded_eventually hg <| eventually_of_forall h
#align cauchy_seq_finset_of_norm_bounded cauchySeq_finset_of_norm_bounded

/- warning: cauchy_seq_range_of_norm_bounded -> cauchySeq_range_of_norm_bounded is a dubious translation:
lean 3 declaration is
  forall {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : Nat -> E} (g : Nat -> Real), (CauchySeq.{0, 0} Real Nat (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace) (CanonicallyLinearOrderedAddMonoid.semilatticeSup.{0} Nat Nat.canonicallyLinearOrderedAddMonoid) (fun (n : Nat) => Finset.sum.{0, 0} Real Nat Real.addCommMonoid (Finset.range n) (fun (i : Nat) => g i))) -> (forall (i : Nat), LE.le.{0} Real Real.hasLe (Norm.norm.{u1} E (SeminormedAddCommGroup.toHasNorm.{u1} E _inst_1) (f i)) (g i)) -> (CauchySeq.{u1, 0} E Nat (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1)) (CanonicallyLinearOrderedAddMonoid.semilatticeSup.{0} Nat Nat.canonicallyLinearOrderedAddMonoid) (fun (n : Nat) => Finset.sum.{u1, 0} E Nat (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (Finset.range n) (fun (i : Nat) => f i)))
but is expected to have type
  forall {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : Nat -> E} (g : Nat -> Real), (CauchySeq.{0, 0} Real Nat (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace) (Lattice.toSemilatticeSup.{0} Nat Nat.instLatticeNat) (fun (n : Nat) => Finset.sum.{0, 0} Real Nat Real.instAddCommMonoidReal (Finset.range n) (fun (i : Nat) => g i))) -> (forall (i : Nat), LE.le.{0} Real Real.instLEReal (Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f i)) (g i)) -> (CauchySeq.{u1, 0} E Nat (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1)) (Lattice.toSemilatticeSup.{0} Nat Nat.instLatticeNat) (fun (n : Nat) => Finset.sum.{u1, 0} E Nat (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (Finset.range n) (fun (i : Nat) => f i)))
Case conversion may be inaccurate. Consider using '#align cauchy_seq_range_of_norm_bounded cauchySeq_range_of_norm_boundedₓ'. -/
/-- A version of the **direct comparison test** for conditionally convergent series.
See `cauchy_seq_finset_of_norm_bounded` for the same statement about absolutely convergent ones. -/
theorem cauchySeq_range_of_norm_bounded {f : ℕ → E} (g : ℕ → ℝ)
    (hg : CauchySeq fun n => ∑ i in range n, g i) (hf : ∀ i, ‖f i‖ ≤ g i) :
    CauchySeq fun n => ∑ i in range n, f i :=
  by
  refine' Metric.cauchySeq_iff'.2 fun ε hε => _
  refine' (Metric.cauchySeq_iff'.1 hg ε hε).imp fun N hg n hn => _
  specialize hg n hn
  rw [dist_eq_norm, ← sum_Ico_eq_sub _ hn] at hg⊢
  calc
    ‖∑ k in Ico N n, f k‖ ≤ ∑ k in _, ‖f k‖ := norm_sum_le _ _
    _ ≤ ∑ k in _, g k := (sum_le_sum fun x _ => hf x)
    _ ≤ ‖∑ k in _, g k‖ := (le_abs_self _)
    _ < ε := hg

#align cauchy_seq_range_of_norm_bounded cauchySeq_range_of_norm_bounded

/- warning: cauchy_seq_finset_of_summable_norm -> cauchySeq_finset_of_summable_norm is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E}, (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (a : ι) => Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f a))) -> (CauchySeq.{u2, u1} E (Finset.{u1} ι) (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1)) (Lattice.toSemilatticeSup.{u1} (Finset.{u1} ι) (Finset.lattice.{u1} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u1} ι a b)))) (fun (s : Finset.{u1} ι) => Finset.sum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) s (fun (a : ι) => f a)))
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : ι -> E}, (Summable.{0, u2} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (a : ι) => Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f a))) -> (CauchySeq.{u1, u2} E (Finset.{u2} ι) (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1)) (Lattice.toSemilatticeSup.{u2} (Finset.{u2} ι) (Finset.instLatticeFinset.{u2} ι (fun (a : ι) (b : ι) => Classical.propDecidable (Eq.{succ u2} ι a b)))) (fun (s : Finset.{u2} ι) => Finset.sum.{u1, u2} E ι (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) s (fun (a : ι) => f a)))
Case conversion may be inaccurate. Consider using '#align cauchy_seq_finset_of_summable_norm cauchySeq_finset_of_summable_normₓ'. -/
theorem cauchySeq_finset_of_summable_norm {f : ι → E} (hf : Summable fun a => ‖f a‖) :
    CauchySeq fun s : Finset ι => ∑ a in s, f a :=
  cauchySeq_finset_of_norm_bounded _ hf fun i => le_rfl
#align cauchy_seq_finset_of_summable_norm cauchySeq_finset_of_summable_norm

/- warning: has_sum_of_subseq_of_summable -> hasSum_of_subseq_of_summable is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : Type.{u2}} {E : Type.{u3}} [_inst_1 : SeminormedAddCommGroup.{u3} E] {f : ι -> E}, (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (a : ι) => Norm.norm.{u3} E (SeminormedAddCommGroup.toHasNorm.{u3} E _inst_1) (f a))) -> (forall {s : α -> (Finset.{u1} ι)} {p : Filter.{u2} α} [_inst_3 : Filter.NeBot.{u2} α p], (Filter.Tendsto.{u2, u1} α (Finset.{u1} ι) s p (Filter.atTop.{u1} (Finset.{u1} ι) (PartialOrder.toPreorder.{u1} (Finset.{u1} ι) (Finset.partialOrder.{u1} ι)))) -> (forall {a : E}, (Filter.Tendsto.{u2, u3} α E (fun (b : α) => Finset.sum.{u3, u1} E ι (AddCommGroup.toAddCommMonoid.{u3} E (SeminormedAddCommGroup.toAddCommGroup.{u3} E _inst_1)) (s b) (fun (i : ι) => f i)) p (nhds.{u3} E (UniformSpace.toTopologicalSpace.{u3} E (PseudoMetricSpace.toUniformSpace.{u3} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u3} E _inst_1))) a)) -> (HasSum.{u3, u1} E ι (AddCommGroup.toAddCommMonoid.{u3} E (SeminormedAddCommGroup.toAddCommGroup.{u3} E _inst_1)) (UniformSpace.toTopologicalSpace.{u3} E (PseudoMetricSpace.toUniformSpace.{u3} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u3} E _inst_1))) f a)))
but is expected to have type
  forall {ι : Type.{u3}} {α : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E}, (Summable.{0, u3} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (a : ι) => Norm.norm.{u2} E (SeminormedAddCommGroup.toNorm.{u2} E _inst_1) (f a))) -> (forall {s : α -> (Finset.{u3} ι)} {p : Filter.{u1} α} [_inst_3 : Filter.NeBot.{u1} α p], (Filter.Tendsto.{u1, u3} α (Finset.{u3} ι) s p (Filter.atTop.{u3} (Finset.{u3} ι) (PartialOrder.toPreorder.{u3} (Finset.{u3} ι) (Finset.partialOrder.{u3} ι)))) -> (forall {a : E}, (Filter.Tendsto.{u1, u2} α E (fun (b : α) => Finset.sum.{u2, u3} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (s b) (fun (i : ι) => f i)) p (nhds.{u2} E (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) a)) -> (HasSum.{u2, u3} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f a)))
Case conversion may be inaccurate. Consider using '#align has_sum_of_subseq_of_summable hasSum_of_subseq_of_summableₓ'. -/
/-- If a function `f` is summable in norm, and along some sequence of finsets exhausting the space
its sum is converging to a limit `a`, then this holds along all finsets, i.e., `f` is summable
with sum `a`. -/
theorem hasSum_of_subseq_of_summable {f : ι → E} (hf : Summable fun a => ‖f a‖) {s : α → Finset ι}
    {p : Filter α} [NeBot p] (hs : Tendsto s p atTop) {a : E}
    (ha : Tendsto (fun b => ∑ i in s b, f i) p (𝓝 a)) : HasSum f a :=
  tendsto_nhds_of_cauchySeq_of_subseq (cauchySeq_finset_of_summable_norm hf) hs ha
#align has_sum_of_subseq_of_summable hasSum_of_subseq_of_summable

#print hasSum_iff_tendsto_nat_of_summable_norm /-
theorem hasSum_iff_tendsto_nat_of_summable_norm {f : ℕ → E} {a : E} (hf : Summable fun i => ‖f i‖) :
    HasSum f a ↔ Tendsto (fun n : ℕ => ∑ i in range n, f i) atTop (𝓝 a) :=
  ⟨fun h => h.tendsto_sum_nat, fun h => hasSum_of_subseq_of_summable hf tendsto_finset_range h⟩
#align has_sum_iff_tendsto_nat_of_summable_norm hasSum_iff_tendsto_nat_of_summable_norm
-/

/- warning: summable_of_norm_bounded -> summable_of_norm_bounded is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E} (g : ι -> Real), (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (forall (i : ι), LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i)) (g i)) -> (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f)
but is expected to have type
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E} (g : ι -> Real), (Summable.{0, u1} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (forall (i : ι), LE.le.{0} Real Real.instLEReal (Norm.norm.{u2} E (SeminormedAddCommGroup.toNorm.{u2} E _inst_1) (f i)) (g i)) -> (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f)
Case conversion may be inaccurate. Consider using '#align summable_of_norm_bounded summable_of_norm_boundedₓ'. -/
/-- The direct comparison test for series:  if the norm of `f` is bounded by a real function `g`
which is summable, then `f` is summable. -/
theorem summable_of_norm_bounded [CompleteSpace E] {f : ι → E} (g : ι → ℝ) (hg : Summable g)
    (h : ∀ i, ‖f i‖ ≤ g i) : Summable f :=
  by
  rw [summable_iff_cauchySeq_finset]
  exact cauchySeq_finset_of_norm_bounded g hg h
#align summable_of_norm_bounded summable_of_norm_bounded

/- warning: has_sum.norm_le_of_bounded -> HasSum.norm_le_of_bounded is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E} {g : ι -> Real} {a : E} {b : Real}, (HasSum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f a) -> (HasSum.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g b) -> (forall (i : ι), LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i)) (g i)) -> (LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) a) b)
but is expected to have type
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E} {g : ι -> Real} {a : E} {b : Real}, (HasSum.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f a) -> (HasSum.{0, u1} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g b) -> (forall (i : ι), LE.le.{0} Real Real.instLEReal (Norm.norm.{u2} E (SeminormedAddCommGroup.toNorm.{u2} E _inst_1) (f i)) (g i)) -> (LE.le.{0} Real Real.instLEReal (Norm.norm.{u2} E (SeminormedAddCommGroup.toNorm.{u2} E _inst_1) a) b)
Case conversion may be inaccurate. Consider using '#align has_sum.norm_le_of_bounded HasSum.norm_le_of_boundedₓ'. -/
theorem HasSum.norm_le_of_bounded {f : ι → E} {g : ι → ℝ} {a : E} {b : ℝ} (hf : HasSum f a)
    (hg : HasSum g b) (h : ∀ i, ‖f i‖ ≤ g i) : ‖a‖ ≤ b :=
  le_of_tendsto_of_tendsto' hf.norm hg fun s => norm_sum_le_of_le _ fun i hi => h i
#align has_sum.norm_le_of_bounded HasSum.norm_le_of_bounded

/- warning: tsum_of_norm_bounded -> tsum_of_norm_bounded is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E} {g : ι -> Real} {a : Real}, (HasSum.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g a) -> (forall (i : ι), LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i)) (g i)) -> (LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (tsum.{u2, u1} E (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) ι (fun (i : ι) => f i))) a)
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : ι -> E} {g : ι -> Real} {a : Real}, (HasSum.{0, u2} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g a) -> (forall (i : ι), LE.le.{0} Real Real.instLEReal (Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f i)) (g i)) -> (LE.le.{0} Real Real.instLEReal (Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (tsum.{u1, u2} E (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) ι (fun (i : ι) => f i))) a)
Case conversion may be inaccurate. Consider using '#align tsum_of_norm_bounded tsum_of_norm_boundedₓ'. -/
/-- Quantitative result associated to the direct comparison test for series:  If `∑' i, g i` is
summable, and for all `i`, `‖f i‖ ≤ g i`, then `‖∑' i, f i‖ ≤ ∑' i, g i`. Note that we do not
assume that `∑' i, f i` is summable, and it might not be the case if `α` is not a complete space. -/
theorem tsum_of_norm_bounded {f : ι → E} {g : ι → ℝ} {a : ℝ} (hg : HasSum g a)
    (h : ∀ i, ‖f i‖ ≤ g i) : ‖∑' i : ι, f i‖ ≤ a :=
  by
  by_cases hf : Summable f
  · exact hf.has_sum.norm_le_of_bounded hg h
  · rw [tsum_eq_zero_of_not_summable hf, norm_zero]
    exact ge_of_tendsto' hg fun s => sum_nonneg fun i hi => (norm_nonneg _).trans (h i)
#align tsum_of_norm_bounded tsum_of_norm_bounded

/- warning: norm_tsum_le_tsum_norm -> norm_tsum_le_tsum_norm is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E}, (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (i : ι) => Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i))) -> (LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (tsum.{u2, u1} E (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) ι (fun (i : ι) => f i))) (tsum.{0, u1} Real Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) ι (fun (i : ι) => Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i))))
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : ι -> E}, (Summable.{0, u2} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (i : ι) => Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f i))) -> (LE.le.{0} Real Real.instLEReal (Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (tsum.{u1, u2} E (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) ι (fun (i : ι) => f i))) (tsum.{0, u2} Real Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) ι (fun (i : ι) => Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f i))))
Case conversion may be inaccurate. Consider using '#align norm_tsum_le_tsum_norm norm_tsum_le_tsum_normₓ'. -/
/-- If `∑' i, ‖f i‖` is summable, then `‖∑' i, f i‖ ≤ (∑' i, ‖f i‖)`. Note that we do not assume
that `∑' i, f i` is summable, and it might not be the case if `α` is not a complete space. -/
theorem norm_tsum_le_tsum_norm {f : ι → E} (hf : Summable fun i => ‖f i‖) :
    ‖∑' i, f i‖ ≤ ∑' i, ‖f i‖ :=
  tsum_of_norm_bounded hf.HasSum fun i => le_rfl
#align norm_tsum_le_tsum_norm norm_tsum_le_tsum_norm

/- warning: tsum_of_nnnorm_bounded -> tsum_of_nnnorm_bounded is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E} {g : ι -> NNReal} {a : NNReal}, (HasSum.{0, u1} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)) NNReal.topologicalSpace g a) -> (forall (i : ι), LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (OrderedCancelAddCommMonoid.toPartialOrder.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)))) (NNNorm.nnnorm.{u2} E (SeminormedAddGroup.toNNNorm.{u2} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u2} E _inst_1)) (f i)) (g i)) -> (LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (OrderedCancelAddCommMonoid.toPartialOrder.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)))) (NNNorm.nnnorm.{u2} E (SeminormedAddGroup.toNNNorm.{u2} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u2} E _inst_1)) (tsum.{u2, u1} E (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) ι (fun (i : ι) => f i))) a)
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : ι -> E} {g : ι -> NNReal} {a : NNReal}, (HasSum.{0, u2} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal instNNRealStrictOrderedSemiring)) NNReal.instTopologicalSpaceNNReal g a) -> (forall (i : ι), LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (StrictOrderedSemiring.toPartialOrder.{0} NNReal instNNRealStrictOrderedSemiring))) (NNNorm.nnnorm.{u1} E (SeminormedAddGroup.toNNNorm.{u1} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u1} E _inst_1)) (f i)) (g i)) -> (LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (StrictOrderedSemiring.toPartialOrder.{0} NNReal instNNRealStrictOrderedSemiring))) (NNNorm.nnnorm.{u1} E (SeminormedAddGroup.toNNNorm.{u1} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u1} E _inst_1)) (tsum.{u1, u2} E (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) ι (fun (i : ι) => f i))) a)
Case conversion may be inaccurate. Consider using '#align tsum_of_nnnorm_bounded tsum_of_nnnorm_boundedₓ'. -/
/-- Quantitative result associated to the direct comparison test for series: If `∑' i, g i` is
summable, and for all `i`, `‖f i‖₊ ≤ g i`, then `‖∑' i, f i‖₊ ≤ ∑' i, g i`. Note that we
do not assume that `∑' i, f i` is summable, and it might not be the case if `α` is not a complete
space. -/
theorem tsum_of_nnnorm_bounded {f : ι → E} {g : ι → ℝ≥0} {a : ℝ≥0} (hg : HasSum g a)
    (h : ∀ i, ‖f i‖₊ ≤ g i) : ‖∑' i : ι, f i‖₊ ≤ a :=
  by
  simp only [← NNReal.coe_le_coe, ← NNReal.hasSum_coe, coe_nnnorm] at *
  exact tsum_of_norm_bounded hg h
#align tsum_of_nnnorm_bounded tsum_of_nnnorm_bounded

/- warning: nnnorm_tsum_le -> nnnorm_tsum_le is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] {f : ι -> E}, (Summable.{0, u1} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)) NNReal.topologicalSpace (fun (i : ι) => NNNorm.nnnorm.{u2} E (SeminormedAddGroup.toNNNorm.{u2} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u2} E _inst_1)) (f i))) -> (LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (OrderedCancelAddCommMonoid.toPartialOrder.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)))) (NNNorm.nnnorm.{u2} E (SeminormedAddGroup.toNNNorm.{u2} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u2} E _inst_1)) (tsum.{u2, u1} E (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) ι (fun (i : ι) => f i))) (tsum.{0, u1} NNReal (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)) NNReal.topologicalSpace ι (fun (i : ι) => NNNorm.nnnorm.{u2} E (SeminormedAddGroup.toNNNorm.{u2} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u2} E _inst_1)) (f i))))
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] {f : ι -> E}, (Summable.{0, u2} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal instNNRealStrictOrderedSemiring)) NNReal.instTopologicalSpaceNNReal (fun (i : ι) => NNNorm.nnnorm.{u1} E (SeminormedAddGroup.toNNNorm.{u1} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u1} E _inst_1)) (f i))) -> (LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (StrictOrderedSemiring.toPartialOrder.{0} NNReal instNNRealStrictOrderedSemiring))) (NNNorm.nnnorm.{u1} E (SeminormedAddGroup.toNNNorm.{u1} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u1} E _inst_1)) (tsum.{u1, u2} E (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) ι (fun (i : ι) => f i))) (tsum.{0, u2} NNReal (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal instNNRealStrictOrderedSemiring)) NNReal.instTopologicalSpaceNNReal ι (fun (i : ι) => NNNorm.nnnorm.{u1} E (SeminormedAddGroup.toNNNorm.{u1} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u1} E _inst_1)) (f i))))
Case conversion may be inaccurate. Consider using '#align nnnorm_tsum_le nnnorm_tsum_leₓ'. -/
/-- If `∑' i, ‖f i‖₊` is summable, then `‖∑' i, f i‖₊ ≤ ∑' i, ‖f i‖₊`. Note that
we do not assume that `∑' i, f i` is summable, and it might not be the case if `α` is not a complete
space. -/
theorem nnnorm_tsum_le {f : ι → E} (hf : Summable fun i => ‖f i‖₊) : ‖∑' i, f i‖₊ ≤ ∑' i, ‖f i‖₊ :=
  tsum_of_nnnorm_bounded hf.HasSum fun i => le_rfl
#align nnnorm_tsum_le nnnorm_tsum_le

variable [CompleteSpace E]

/- warning: summable_of_norm_bounded_eventually -> summable_of_norm_bounded_eventually is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E} (g : ι -> Real), (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (Filter.Eventually.{u1} ι (fun (i : ι) => LE.le.{0} Real Real.hasLe (Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f i)) (g i)) (Filter.cofinite.{u1} ι)) -> (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f)
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] [_inst_3 : CompleteSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))] {f : ι -> E} (g : ι -> Real), (Summable.{0, u2} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) g) -> (Filter.Eventually.{u2} ι (fun (i : ι) => LE.le.{0} Real Real.instLEReal (Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f i)) (g i)) (Filter.cofinite.{u2} ι)) -> (Summable.{u1, u2} E ι (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) f)
Case conversion may be inaccurate. Consider using '#align summable_of_norm_bounded_eventually summable_of_norm_bounded_eventuallyₓ'. -/
/-- Variant of the direct comparison test for series:  if the norm of `f` is eventually bounded by a
real function `g` which is summable, then `f` is summable. -/
theorem summable_of_norm_bounded_eventually {f : ι → E} (g : ι → ℝ) (hg : Summable g)
    (h : ∀ᶠ i in cofinite, ‖f i‖ ≤ g i) : Summable f :=
  summable_iff_cauchySeq_finset.2 <| cauchySeq_finset_of_norm_bounded_eventually hg h
#align summable_of_norm_bounded_eventually summable_of_norm_bounded_eventually

/- warning: summable_of_nnnorm_bounded -> summable_of_nnnorm_bounded is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E} (g : ι -> NNReal), (Summable.{0, u1} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)) NNReal.topologicalSpace g) -> (forall (i : ι), LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (OrderedCancelAddCommMonoid.toPartialOrder.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)))) (NNNorm.nnnorm.{u2} E (SeminormedAddGroup.toNNNorm.{u2} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u2} E _inst_1)) (f i)) (g i)) -> (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f)
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] [_inst_3 : CompleteSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))] {f : ι -> E} (g : ι -> NNReal), (Summable.{0, u2} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal instNNRealStrictOrderedSemiring)) NNReal.instTopologicalSpaceNNReal g) -> (forall (i : ι), LE.le.{0} NNReal (Preorder.toLE.{0} NNReal (PartialOrder.toPreorder.{0} NNReal (StrictOrderedSemiring.toPartialOrder.{0} NNReal instNNRealStrictOrderedSemiring))) (NNNorm.nnnorm.{u1} E (SeminormedAddGroup.toNNNorm.{u1} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u1} E _inst_1)) (f i)) (g i)) -> (Summable.{u1, u2} E ι (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) f)
Case conversion may be inaccurate. Consider using '#align summable_of_nnnorm_bounded summable_of_nnnorm_boundedₓ'. -/
theorem summable_of_nnnorm_bounded {f : ι → E} (g : ι → ℝ≥0) (hg : Summable g)
    (h : ∀ i, ‖f i‖₊ ≤ g i) : Summable f :=
  summable_of_norm_bounded (fun i => (g i : ℝ)) (NNReal.summable_coe.2 hg) fun i => by
    exact_mod_cast h i
#align summable_of_nnnorm_bounded summable_of_nnnorm_bounded

/- warning: summable_of_summable_norm -> summable_of_summable_norm is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E}, (Summable.{0, u1} Real ι Real.addCommMonoid (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (a : ι) => Norm.norm.{u2} E (SeminormedAddCommGroup.toHasNorm.{u2} E _inst_1) (f a))) -> (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f)
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] [_inst_3 : CompleteSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))] {f : ι -> E}, (Summable.{0, u2} Real ι Real.instAddCommMonoidReal (UniformSpace.toTopologicalSpace.{0} Real (PseudoMetricSpace.toUniformSpace.{0} Real Real.pseudoMetricSpace)) (fun (a : ι) => Norm.norm.{u1} E (SeminormedAddCommGroup.toNorm.{u1} E _inst_1) (f a))) -> (Summable.{u1, u2} E ι (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) f)
Case conversion may be inaccurate. Consider using '#align summable_of_summable_norm summable_of_summable_normₓ'. -/
theorem summable_of_summable_norm {f : ι → E} (hf : Summable fun a => ‖f a‖) : Summable f :=
  summable_of_norm_bounded _ hf fun i => le_rfl
#align summable_of_summable_norm summable_of_summable_norm

/- warning: summable_of_summable_nnnorm -> summable_of_summable_nnnorm is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {E : Type.{u2}} [_inst_1 : SeminormedAddCommGroup.{u2} E] [_inst_3 : CompleteSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))] {f : ι -> E}, (Summable.{0, u1} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal NNReal.strictOrderedSemiring)) NNReal.topologicalSpace (fun (a : ι) => NNNorm.nnnorm.{u2} E (SeminormedAddGroup.toNNNorm.{u2} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u2} E _inst_1)) (f a))) -> (Summable.{u2, u1} E ι (AddCommGroup.toAddCommMonoid.{u2} E (SeminormedAddCommGroup.toAddCommGroup.{u2} E _inst_1)) (UniformSpace.toTopologicalSpace.{u2} E (PseudoMetricSpace.toUniformSpace.{u2} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u2} E _inst_1))) f)
but is expected to have type
  forall {ι : Type.{u2}} {E : Type.{u1}} [_inst_1 : SeminormedAddCommGroup.{u1} E] [_inst_3 : CompleteSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))] {f : ι -> E}, (Summable.{0, u2} NNReal ι (OrderedCancelAddCommMonoid.toAddCommMonoid.{0} NNReal (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} NNReal instNNRealStrictOrderedSemiring)) NNReal.instTopologicalSpaceNNReal (fun (a : ι) => NNNorm.nnnorm.{u1} E (SeminormedAddGroup.toNNNorm.{u1} E (SeminormedAddCommGroup.toSeminormedAddGroup.{u1} E _inst_1)) (f a))) -> (Summable.{u1, u2} E ι (AddCommGroup.toAddCommMonoid.{u1} E (SeminormedAddCommGroup.toAddCommGroup.{u1} E _inst_1)) (UniformSpace.toTopologicalSpace.{u1} E (PseudoMetricSpace.toUniformSpace.{u1} E (SeminormedAddCommGroup.toPseudoMetricSpace.{u1} E _inst_1))) f)
Case conversion may be inaccurate. Consider using '#align summable_of_summable_nnnorm summable_of_summable_nnnormₓ'. -/
theorem summable_of_summable_nnnorm {f : ι → E} (hf : Summable fun a => ‖f a‖₊) : Summable f :=
  summable_of_nnnorm_bounded _ hf fun i => le_rfl
#align summable_of_summable_nnnorm summable_of_summable_nnnorm


/-
Copyright (c) 2020 Kevin Buzzard. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kevin Buzzard

! This file was ported from Lean 3 source module ring_theory.discrete_valuation_ring
! leanprover-community/mathlib commit b86c528d08a52a1fdb50d999232408e1c7e85d7d
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.RingTheory.PrincipalIdealDomain
import Mathbin.RingTheory.Ideal.LocalRing
import Mathbin.RingTheory.Multiplicity
import Mathbin.RingTheory.Valuation.Basic
import Mathbin.LinearAlgebra.AdicCompletion

/-!
# Discrete valuation rings

This file defines discrete valuation rings (DVRs) and develops a basic interface
for them.

## Important definitions

There are various definitions of a DVR in the literature; we define a DVR to be a local PID
which is not a field (the first definition in Wikipedia) and prove that this is equivalent
to being a PID with a unique non-zero prime ideal (the definition in Serre's
book "Local Fields").

Let R be an integral domain, assumed to be a principal ideal ring and a local ring.

* `discrete_valuation_ring R` : a predicate expressing that R is a DVR

### Definitions

* `add_val R : add_valuation R part_enat` : the additive valuation on a DVR.

## Implementation notes

It's a theorem that an element of a DVR is a uniformizer if and only if it's irreducible.
We do not hence define `uniformizer` at all, because we can use `irreducible` instead.

## Tags

discrete valuation ring
-/

open Classical

universe u

open Ideal LocalRing

/-- An integral domain is a *discrete valuation ring* (DVR) if it's a local PID which
  is not a field. -/
class DiscreteValuationRing (R : Type u) [CommRing R] [IsDomain R] extends IsPrincipalIdealRing R,
  LocalRing R : Prop where
  not_a_field' : maximalIdeal R ≠ ⊥
#align discrete_valuation_ring DiscreteValuationRing

namespace DiscreteValuationRing

variable (R : Type u) [CommRing R] [IsDomain R] [DiscreteValuationRing R]

theorem not_a_field : maximalIdeal R ≠ ⊥ :=
  not_a_field'
#align discrete_valuation_ring.not_a_field DiscreteValuationRing.not_a_field

/-- A discrete valuation ring `R` is not a field. -/
theorem not_isField : ¬IsField R :=
  LocalRing.isField_iff_maximalIdeal_eq.Not.mpr (not_a_field R)
#align discrete_valuation_ring.not_is_field DiscreteValuationRing.not_isField

variable {R}

open PrincipalIdealRing

theorem irreducible_of_span_eq_maximalIdeal {R : Type _} [CommRing R] [LocalRing R] [IsDomain R]
    (ϖ : R) (hϖ : ϖ ≠ 0) (h : maximalIdeal R = Ideal.span {ϖ}) : Irreducible ϖ :=
  by
  have h2 : ¬IsUnit ϖ := show ϖ ∈ maximal_ideal R from h.symm ▸ Submodule.mem_span_singleton_self ϖ
  refine' ⟨h2, _⟩
  intro a b hab
  by_contra' h
  obtain ⟨ha : a ∈ maximal_ideal R, hb : b ∈ maximal_ideal R⟩ := h
  rw [h, mem_span_singleton'] at ha hb
  rcases ha with ⟨a, rfl⟩
  rcases hb with ⟨b, rfl⟩
  rw [show a * ϖ * (b * ϖ) = ϖ * (ϖ * (a * b)) by ring] at hab
  apply hϖ
  apply eq_zero_of_mul_eq_self_right _ hab.symm
  exact fun hh => h2 (isUnit_of_dvd_one ϖ ⟨_, hh.symm⟩)
#align discrete_valuation_ring.irreducible_of_span_eq_maximal_ideal DiscreteValuationRing.irreducible_of_span_eq_maximalIdeal

/-- An element of a DVR is irreducible iff it is a uniformizer, that is, generates the
  maximal ideal of R -/
theorem irreducible_iff_uniformizer (ϖ : R) : Irreducible ϖ ↔ maximalIdeal R = Ideal.span {ϖ} :=
  ⟨fun hϖ => (eq_maximalIdeal (isMaximal_of_irreducible hϖ)).symm, fun h =>
    irreducible_of_span_eq_maximalIdeal ϖ
      (fun e => not_a_field R <| by rwa [h, span_singleton_eq_bot]) h⟩
#align discrete_valuation_ring.irreducible_iff_uniformizer DiscreteValuationRing.irreducible_iff_uniformizer

theorem Irreducible.maximalIdeal_eq {ϖ : R} (h : Irreducible ϖ) : maximalIdeal R = Ideal.span {ϖ} :=
  (irreducible_iff_uniformizer _).mp h
#align irreducible.maximal_ideal_eq Irreducible.maximalIdeal_eq

variable (R)

/-- Uniformisers exist in a DVR -/
theorem exists_irreducible : ∃ ϖ : R, Irreducible ϖ :=
  by
  simp_rw [irreducible_iff_uniformizer]
  exact (IsPrincipalIdealRing.principal <| maximal_ideal R).principal
#align discrete_valuation_ring.exists_irreducible DiscreteValuationRing.exists_irreducible

/-- Uniformisers exist in a DVR -/
theorem exists_prime : ∃ ϖ : R, Prime ϖ :=
  (exists_irreducible R).imp fun _ => PrincipalIdealRing.irreducible_iff_prime.1
#align discrete_valuation_ring.exists_prime DiscreteValuationRing.exists_prime

/-- an integral domain is a DVR iff it's a PID with a unique non-zero prime ideal -/
theorem iff_pid_with_one_nonzero_prime (R : Type u) [CommRing R] [IsDomain R] :
    DiscreteValuationRing R ↔ IsPrincipalIdealRing R ∧ ∃! P : Ideal R, P ≠ ⊥ ∧ IsPrime P :=
  by
  constructor
  · intro RDVR
    rcases id RDVR with ⟨Rlocal⟩
    constructor
    assumption
    skip
    use LocalRing.maximalIdeal R
    constructor
    constructor
    · assumption
    · infer_instance
    · rintro Q ⟨hQ1, hQ2⟩
      obtain ⟨q, rfl⟩ := (IsPrincipalIdealRing.principal Q).1
      have hq : q ≠ 0 := by
        rintro rfl
        apply hQ1
        simp
      erw [span_singleton_prime hq] at hQ2
      replace hQ2 := hQ2.irreducible
      rw [irreducible_iff_uniformizer] at hQ2
      exact hQ2.symm
  · rintro ⟨RPID, Punique⟩
    haveI : LocalRing R := LocalRing.of_unique_nonzero_prime Punique
    refine' { not_a_field' := _ }
    rcases Punique with ⟨P, ⟨hP1, hP2⟩, hP3⟩
    have hPM : P ≤ maximal_ideal R := le_maximal_ideal hP2.1
    intro h
    rw [h, le_bot_iff] at hPM
    exact hP1 hPM
#align discrete_valuation_ring.iff_pid_with_one_nonzero_prime DiscreteValuationRing.iff_pid_with_one_nonzero_prime

theorem associated_of_irreducible {a b : R} (ha : Irreducible a) (hb : Irreducible b) :
    Associated a b := by
  rw [irreducible_iff_uniformizer] at ha hb
  rw [← span_singleton_eq_span_singleton, ← ha, hb]
#align discrete_valuation_ring.associated_of_irreducible DiscreteValuationRing.associated_of_irreducible

end DiscreteValuationRing

namespace DiscreteValuationRing

variable (R : Type _)

/-- Alternative characterisation of discrete valuation rings. -/
def HasUnitMulPowIrreducibleFactorization [CommRing R] : Prop :=
  ∃ p : R, Irreducible p ∧ ∀ {x : R}, x ≠ 0 → ∃ n : ℕ, Associated (p ^ n) x
#align discrete_valuation_ring.has_unit_mul_pow_irreducible_factorization DiscreteValuationRing.HasUnitMulPowIrreducibleFactorization

namespace HasUnitMulPowIrreducibleFactorization

variable {R} [CommRing R] (hR : HasUnitMulPowIrreducibleFactorization R)

include hR

theorem unique_irreducible ⦃p q : R⦄ (hp : Irreducible p) (hq : Irreducible q) : Associated p q :=
  by
  rcases hR with ⟨ϖ, hϖ, hR⟩
  suffices ∀ {p : R} (hp : Irreducible p), Associated p ϖ by
    apply Associated.trans (this hp) (this hq).symm
  clear hp hq p q
  intro p hp
  obtain ⟨n, hn⟩ := hR hp.ne_zero
  have : Irreducible (ϖ ^ n) := hn.symm.irreducible hp
  rcases lt_trichotomy n 1 with (H | rfl | H)
  · obtain rfl : n = 0 := by
      clear hn this
      revert H n
      exact by decide
    simpa only [not_irreducible_one, pow_zero] using this
  · simpa only [pow_one] using hn.symm
  · obtain ⟨n, rfl⟩ : ∃ k, n = 1 + k + 1 := Nat.exists_eq_add_of_lt H
    rw [pow_succ] at this
    rcases this.is_unit_or_is_unit rfl with (H0 | H0)
    · exact (hϖ.not_unit H0).elim
    · rw [add_comm, pow_succ] at H0
      exact (hϖ.not_unit (isUnit_of_mul_isUnit_left H0)).elim
#align discrete_valuation_ring.has_unit_mul_pow_irreducible_factorization.unique_irreducible DiscreteValuationRing.HasUnitMulPowIrreducibleFactorization.unique_irreducible

variable [IsDomain R]

/-- An integral domain in which there is an irreducible element `p`
such that every nonzero element is associated to a power of `p` is a unique factorization domain.
See `discrete_valuation_ring.of_has_unit_mul_pow_irreducible_factorization`. -/
theorem to_uniqueFactorizationMonoid : UniqueFactorizationMonoid R :=
  let p := Classical.choose hR
  let spec := Classical.choose_spec hR
  UniqueFactorizationMonoid.of_exists_prime_factors fun x hx =>
    by
    use Multiset.replicate (Classical.choose (spec.2 hx)) p
    constructor
    · intro q hq
      have hpq := Multiset.eq_of_mem_replicate hq
      rw [hpq]
      refine' ⟨spec.1.NeZero, spec.1.not_unit, _⟩
      intro a b h
      by_cases ha : a = 0
      · rw [ha]
        simp only [true_or_iff, dvd_zero]
      obtain ⟨m, u, rfl⟩ := spec.2 ha
      rw [mul_assoc, mul_left_comm, IsUnit.dvd_mul_left _ _ _ (Units.isUnit _)] at h
      rw [IsUnit.dvd_mul_right (Units.isUnit _)]
      by_cases hm : m = 0
      · simp only [hm, one_mul, pow_zero] at h⊢
        right
        exact h
      left
      obtain ⟨m, rfl⟩ := Nat.exists_eq_succ_of_ne_zero hm
      rw [pow_succ]
      apply dvd_mul_of_dvd_left dvd_rfl _
    · rw [Multiset.prod_replicate]
      exact Classical.choose_spec (spec.2 hx)
#align discrete_valuation_ring.has_unit_mul_pow_irreducible_factorization.to_unique_factorization_monoid DiscreteValuationRing.HasUnitMulPowIrreducibleFactorization.to_uniqueFactorizationMonoid

omit hR

theorem of_ufd_of_unique_irreducible [UniqueFactorizationMonoid R] (h₁ : ∃ p : R, Irreducible p)
    (h₂ : ∀ ⦃p q : R⦄, Irreducible p → Irreducible q → Associated p q) :
    HasUnitMulPowIrreducibleFactorization R :=
  by
  obtain ⟨p, hp⟩ := h₁
  refine' ⟨p, hp, _⟩
  intro x hx
  cases' WfDvdMonoid.exists_factors x hx with fx hfx
  refine' ⟨fx.card, _⟩
  have H := hfx.2
  rw [← Associates.mk_eq_mk_iff_associated] at H⊢
  rw [← H, ← Associates.prod_mk, Associates.mk_pow, ← Multiset.prod_replicate]
  congr 1
  symm
  rw [Multiset.eq_replicate]
  simp only [true_and_iff, and_imp, Multiset.card_map, eq_self_iff_true, Multiset.mem_map,
    exists_imp]
  rintro _ q hq rfl
  rw [Associates.mk_eq_mk_iff_associated]
  apply h₂ (hfx.1 _ hq) hp
#align discrete_valuation_ring.has_unit_mul_pow_irreducible_factorization.of_ufd_of_unique_irreducible DiscreteValuationRing.HasUnitMulPowIrreducibleFactorization.of_ufd_of_unique_irreducible

end HasUnitMulPowIrreducibleFactorization

theorem aux_pid_of_ufd_of_unique_irreducible (R : Type u) [CommRing R] [IsDomain R]
    [UniqueFactorizationMonoid R] (h₁ : ∃ p : R, Irreducible p)
    (h₂ : ∀ ⦃p q : R⦄, Irreducible p → Irreducible q → Associated p q) : IsPrincipalIdealRing R :=
  by
  constructor
  intro I
  by_cases I0 : I = ⊥
  · rw [I0]
    use 0
    simp only [Set.singleton_zero, Submodule.span_zero]
  obtain ⟨x, hxI, hx0⟩ : ∃ x ∈ I, x ≠ (0 : R) := I.ne_bot_iff.mp I0
  obtain ⟨p, hp, H⟩ := has_unit_mul_pow_irreducible_factorization.of_ufd_of_unique_irreducible h₁ h₂
  have ex : ∃ n : ℕ, p ^ n ∈ I := by
    obtain ⟨n, u, rfl⟩ := H hx0
    refine' ⟨n, _⟩
    simpa only [Units.mul_inv_cancel_right] using I.mul_mem_right (↑u⁻¹) hxI
  constructor
  use p ^ Nat.find ex
  show I = Ideal.span _
  apply le_antisymm
  · intro r hr
    by_cases hr0 : r = 0
    · simp only [hr0, Submodule.zero_mem]
    obtain ⟨n, u, rfl⟩ := H hr0
    simp only [mem_span_singleton, Units.isUnit, IsUnit.dvd_mul_right]
    apply pow_dvd_pow
    apply Nat.find_min'
    simpa only [Units.mul_inv_cancel_right] using I.mul_mem_right (↑u⁻¹) hr
  · erw [Submodule.span_singleton_le_iff_mem]
    exact Nat.find_spec ex
#align discrete_valuation_ring.aux_pid_of_ufd_of_unique_irreducible DiscreteValuationRing.aux_pid_of_ufd_of_unique_irreducible

/-- A unique factorization domain with at least one irreducible element
in which all irreducible elements are associated
is a discrete valuation ring.
-/
theorem of_ufd_of_unique_irreducible {R : Type u} [CommRing R] [IsDomain R]
    [UniqueFactorizationMonoid R] (h₁ : ∃ p : R, Irreducible p)
    (h₂ : ∀ ⦃p q : R⦄, Irreducible p → Irreducible q → Associated p q) : DiscreteValuationRing R :=
  by
  rw [iff_pid_with_one_nonzero_prime]
  haveI PID : IsPrincipalIdealRing R := aux_pid_of_ufd_of_unique_irreducible R h₁ h₂
  obtain ⟨p, hp⟩ := h₁
  refine' ⟨PID, ⟨Ideal.span {p}, ⟨_, _⟩, _⟩⟩
  · rw [Submodule.ne_bot_iff]
    refine' ⟨p, ideal.mem_span_singleton.mpr (dvd_refl p), hp.ne_zero⟩
  · rwa [Ideal.span_singleton_prime hp.ne_zero, ← UniqueFactorizationMonoid.irreducible_iff_prime]
  · intro I
    rw [← Submodule.IsPrincipal.span_singleton_generator I]
    rintro ⟨I0, hI⟩
    apply span_singleton_eq_span_singleton.mpr
    apply h₂ _ hp
    erw [Ne.def, span_singleton_eq_bot] at I0
    rwa [UniqueFactorizationMonoid.irreducible_iff_prime, ← Ideal.span_singleton_prime I0]
    infer_instance
#align discrete_valuation_ring.of_ufd_of_unique_irreducible DiscreteValuationRing.of_ufd_of_unique_irreducible

/-- An integral domain in which there is an irreducible element `p`
such that every nonzero element is associated to a power of `p`
is a discrete valuation ring.
-/
theorem of_hasUnitMulPowIrreducibleFactorization {R : Type u} [CommRing R] [IsDomain R]
    (hR : HasUnitMulPowIrreducibleFactorization R) : DiscreteValuationRing R :=
  by
  letI : UniqueFactorizationMonoid R := hR.to_unique_factorization_monoid
  apply of_ufd_of_unique_irreducible _ hR.unique_irreducible
  obtain ⟨p, hp, H⟩ := hR
  exact ⟨p, hp⟩
#align discrete_valuation_ring.of_has_unit_mul_pow_irreducible_factorization DiscreteValuationRing.of_hasUnitMulPowIrreducibleFactorization

section

variable [CommRing R] [IsDomain R] [DiscreteValuationRing R]

variable {R}

theorem associated_pow_irreducible {x : R} (hx : x ≠ 0) {ϖ : R} (hirr : Irreducible ϖ) :
    ∃ n : ℕ, Associated x (ϖ ^ n) :=
  by
  have : WfDvdMonoid R := IsNoetherianRing.wfDvdMonoid
  cases' WfDvdMonoid.exists_factors x hx with fx hfx
  use fx.card
  have H := hfx.2
  rw [← Associates.mk_eq_mk_iff_associated] at H⊢
  rw [← H, ← Associates.prod_mk, Associates.mk_pow, ← Multiset.prod_replicate]
  congr 1
  rw [Multiset.eq_replicate]
  simp only [true_and_iff, and_imp, Multiset.card_map, eq_self_iff_true, Multiset.mem_map,
    exists_imp]
  rintro _ _ _ rfl
  rw [Associates.mk_eq_mk_iff_associated]
  refine' associated_of_irreducible _ _ hirr
  apply hfx.1
  assumption
#align discrete_valuation_ring.associated_pow_irreducible DiscreteValuationRing.associated_pow_irreducible

theorem eq_unit_mul_pow_irreducible {x : R} (hx : x ≠ 0) {ϖ : R} (hirr : Irreducible ϖ) :
    ∃ (n : ℕ)(u : Rˣ), x = u * ϖ ^ n :=
  by
  obtain ⟨n, hn⟩ := associated_pow_irreducible hx hirr
  obtain ⟨u, rfl⟩ := hn.symm
  use n, u
  apply mul_comm
#align discrete_valuation_ring.eq_unit_mul_pow_irreducible DiscreteValuationRing.eq_unit_mul_pow_irreducible

open Submodule.IsPrincipal

theorem ideal_eq_span_pow_irreducible {s : Ideal R} (hs : s ≠ ⊥) {ϖ : R} (hirr : Irreducible ϖ) :
    ∃ n : ℕ, s = Ideal.span {ϖ ^ n} :=
  by
  have gen_ne_zero : generator s ≠ 0 :=
    by
    rw [Ne.def, ← eq_bot_iff_generator_eq_zero]
    assumption
  rcases associated_pow_irreducible gen_ne_zero hirr with ⟨n, u, hnu⟩
  use n
  have : span _ = _ := span_singleton_generator s
  rw [← this, ← hnu, span_singleton_eq_span_singleton]
  use u
#align discrete_valuation_ring.ideal_eq_span_pow_irreducible DiscreteValuationRing.ideal_eq_span_pow_irreducible

theorem unit_mul_pow_congr_pow {p q : R} (hp : Irreducible p) (hq : Irreducible q) (u v : Rˣ)
    (m n : ℕ) (h : ↑u * p ^ m = v * q ^ n) : m = n :=
  by
  have key : Associated (Multiset.replicate m p).Prod (Multiset.replicate n q).Prod :=
    by
    rw [Multiset.prod_replicate, Multiset.prod_replicate, Associated]
    refine' ⟨u * v⁻¹, _⟩
    simp only [Units.val_mul]
    rw [mul_left_comm, ← mul_assoc, h, mul_right_comm, Units.mul_inv, one_mul]
  have := Multiset.card_eq_card_of_rel (UniqueFactorizationMonoid.factors_unique _ _ key)
  · simpa only [Multiset.card_replicate]
  all_goals
    intro x hx
    obtain rfl := Multiset.eq_of_mem_replicate hx
    assumption
#align discrete_valuation_ring.unit_mul_pow_congr_pow DiscreteValuationRing.unit_mul_pow_congr_pow

theorem unit_mul_pow_congr_unit {ϖ : R} (hirr : Irreducible ϖ) (u v : Rˣ) (m n : ℕ)
    (h : ↑u * ϖ ^ m = v * ϖ ^ n) : u = v :=
  by
  obtain rfl : m = n := unit_mul_pow_congr_pow hirr hirr u v m n h
  rw [← sub_eq_zero] at h
  rw [← sub_mul, mul_eq_zero] at h
  cases h
  · rw [sub_eq_zero] at h
    exact_mod_cast h
  · apply (hirr.ne_zero (pow_eq_zero h)).elim
#align discrete_valuation_ring.unit_mul_pow_congr_unit DiscreteValuationRing.unit_mul_pow_congr_unit

/-!
## The additive valuation on a DVR
-/

open multiplicity

/-- The `part_enat`-valued additive valuation on a DVR -/
noncomputable def addVal (R : Type u) [CommRing R] [IsDomain R] [DiscreteValuationRing R] :
    AddValuation R PartENat :=
  AddValuation (Classical.choose_spec (exists_prime R))
#align discrete_valuation_ring.add_val DiscreteValuationRing.addVal

theorem addVal_def (r : R) (u : Rˣ) {ϖ : R} (hϖ : Irreducible ϖ) (n : ℕ) (hr : r = u * ϖ ^ n) :
    addVal R r = n := by
  rw [add_val, add_valuation_apply, hr,
    eq_of_associated_left
      (associated_of_irreducible R hϖ (Classical.choose_spec (exists_prime R)).Irreducible),
    eq_of_associated_right (Associated.symm ⟨u, mul_comm _ _⟩),
    multiplicity_pow_self_of_prime (PrincipalIdealRing.irreducible_iff_prime.1 hϖ)]
#align discrete_valuation_ring.add_val_def DiscreteValuationRing.addVal_def

theorem addVal_def' (u : Rˣ) {ϖ : R} (hϖ : Irreducible ϖ) (n : ℕ) :
    addVal R ((u : R) * ϖ ^ n) = n :=
  addVal_def _ u hϖ n rfl
#align discrete_valuation_ring.add_val_def' DiscreteValuationRing.addVal_def'

@[simp]
theorem addVal_zero : addVal R 0 = ⊤ :=
  (addVal R).map_zero
#align discrete_valuation_ring.add_val_zero DiscreteValuationRing.addVal_zero

@[simp]
theorem addVal_one : addVal R 1 = 0 :=
  (addVal R).map_one
#align discrete_valuation_ring.add_val_one DiscreteValuationRing.addVal_one

@[simp]
theorem addVal_uniformizer {ϖ : R} (hϖ : Irreducible ϖ) : addVal R ϖ = 1 := by
  simpa only [one_mul, eq_self_iff_true, Units.val_one, pow_one, forall_true_left,
    Nat.cast_one] using add_val_def ϖ 1 hϖ 1
#align discrete_valuation_ring.add_val_uniformizer DiscreteValuationRing.addVal_uniformizer

@[simp]
theorem addVal_mul {a b : R} : addVal R (a * b) = addVal R a + addVal R b :=
  (addVal R).map_mul _ _
#align discrete_valuation_ring.add_val_mul DiscreteValuationRing.addVal_mul

theorem addVal_pow (a : R) (n : ℕ) : addVal R (a ^ n) = n • addVal R a :=
  (addVal R).map_pow _ _
#align discrete_valuation_ring.add_val_pow DiscreteValuationRing.addVal_pow

theorem Irreducible.addVal_pow {ϖ : R} (h : Irreducible ϖ) (n : ℕ) : addVal R (ϖ ^ n) = n := by
  rw [add_val_pow, add_val_uniformizer h, nsmul_one]
#align irreducible.add_val_pow Irreducible.addVal_pow

theorem addVal_eq_top_iff {a : R} : addVal R a = ⊤ ↔ a = 0 :=
  by
  have hi := (Classical.choose_spec (exists_prime R)).Irreducible
  constructor
  · contrapose
    intro h
    obtain ⟨n, ha⟩ := associated_pow_irreducible h hi
    obtain ⟨u, rfl⟩ := ha.symm
    rw [mul_comm, add_val_def' u hi n]
    exact PartENat.natCast_ne_top _
  · rintro rfl
    exact add_val_zero
#align discrete_valuation_ring.add_val_eq_top_iff DiscreteValuationRing.addVal_eq_top_iff

theorem addVal_le_iff_dvd {a b : R} : addVal R a ≤ addVal R b ↔ a ∣ b :=
  by
  have hp := Classical.choose_spec (exists_prime R)
  constructor <;> intro h
  · by_cases ha0 : a = 0
    · rw [ha0, add_val_zero, top_le_iff, add_val_eq_top_iff] at h
      rw [h]
      apply dvd_zero
    obtain ⟨n, ha⟩ := associated_pow_irreducible ha0 hp.irreducible
    rw [add_val, add_valuation_apply, add_valuation_apply, multiplicity_le_multiplicity_iff] at h
    exact ha.dvd.trans (h n ha.symm.dvd)
  · rw [add_val, add_valuation_apply, add_valuation_apply]
    exact multiplicity_le_multiplicity_of_dvd_right h
#align discrete_valuation_ring.add_val_le_iff_dvd DiscreteValuationRing.addVal_le_iff_dvd

theorem addVal_add {a b : R} : min (addVal R a) (addVal R b) ≤ addVal R (a + b) :=
  (addVal R).map_add _ _
#align discrete_valuation_ring.add_val_add DiscreteValuationRing.addVal_add

end

instance (R : Type _) [CommRing R] [IsDomain R] [DiscreteValuationRing R] :
    IsHausdorff (maximalIdeal R) R
    where haus' x hx := by
    obtain ⟨ϖ, hϖ⟩ := exists_irreducible R
    simp only [← Ideal.one_eq_top, smul_eq_mul, mul_one, SModEq.zero, hϖ.maximal_ideal_eq,
      Ideal.span_singleton_pow, Ideal.mem_span_singleton, ← add_val_le_iff_dvd, hϖ.add_val_pow] at
      hx
    rwa [← add_val_eq_top_iff, PartENat.eq_top_iff_forall_le]

end DiscreteValuationRing


/-
Copyright (c) 2021 Oliver Nash. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Oliver Nash

! This file was ported from Lean 3 source module algebra.lie.non_unital_non_assoc_algebra
! leanprover-community/mathlib commit f47581155c818e6361af4e4fda60d27d020c226b
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Algebra.Hom.NonUnitalAlg
import Mathbin.Algebra.Lie.Basic

/-!
# Lie algebras as non-unital, non-associative algebras

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

The definition of Lie algebras uses the `has_bracket` typeclass for multiplication whereas we have a
separate `has_mul` typeclass used for general algebras.

It is useful to have a special typeclass for Lie algebras because:
 * it enables us to use the traditional notation `⁅x, y⁆` for the Lie multiplication,
 * associative algebras carry a natural Lie algebra structure via the ring commutator and so we need
   them to carry both `has_mul` and `has_bracket` simultaneously,
 * more generally, Poisson algebras (not yet defined) need both typeclasses.

However there are times when it is convenient to be able to regard a Lie algebra as a general
algebra and we provide some basic definitions for doing so here.

## Main definitions

  * `commutator_ring` turns a Lie ring into a `non_unital_non_assoc_semiring` by turning its
    `has_bracket` (denoted `⁅, ⁆`) into a `has_mul` (denoted `*`).
  * `lie_hom.to_non_unital_alg_hom`

## Tags

lie algebra, non-unital, non-associative
-/

universe u v w

variable (R : Type u) (L : Type v) [CommRing R] [LieRing L] [LieAlgebra R L]

#print CommutatorRing /-
/-- Type synonym for turning a `lie_ring` into a `non_unital_non_assoc_semiring`.

A `lie_ring` can be regarded as a `non_unital_non_assoc_semiring` by turning its
`has_bracket` (denoted `⁅, ⁆`) into a `has_mul` (denoted `*`). -/
def CommutatorRing (L : Type v) : Type v :=
  L
#align commutator_ring CommutatorRing
-/

/-- A `lie_ring` can be regarded as a `non_unital_non_assoc_semiring` by turning its
`has_bracket` (denoted `⁅, ⁆`) into a `has_mul` (denoted `*`). -/
instance : NonUnitalNonAssocSemiring (CommutatorRing L) :=
  show NonUnitalNonAssocSemiring L from
    {
      (inferInstance : AddCommMonoid
          L) with
      mul := Bracket.bracket
      left_distrib := lie_add
      right_distrib := add_lie
      zero_mul := zero_lie
      mul_zero := lie_zero }

namespace LieAlgebra

instance (L : Type v) [Nonempty L] : Nonempty (CommutatorRing L) :=
  ‹Nonempty L›

instance (L : Type v) [Inhabited L] : Inhabited (CommutatorRing L) :=
  ‹Inhabited L›

instance : LieRing (CommutatorRing L) :=
  show LieRing L by infer_instance

instance : LieAlgebra R (CommutatorRing L) :=
  show LieAlgebra R L by infer_instance

/- warning: lie_algebra.is_scalar_tower -> LieAlgebra.isScalarTower is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) (L : Type.{u2}) [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2], IsScalarTower.{u1, u2, u2} R (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (SMulZeroClass.toHasSmul.{u1, u2} R (CommutatorRing.{u2} L) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (SMulWithZero.toSmulZeroClass.{u1, u2} R (CommutatorRing.{u2} L) (MulZeroClass.toHasZero.{u1} R (MulZeroOneClass.toMulZeroClass.{u1} R (MonoidWithZero.toMulZeroOneClass.{u1} R (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)))))) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (MulActionWithZero.toSMulWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1))) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (Module.toMulActionWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2))) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2) (LieAlgebra.CommutatorRing.lieAlgebra.{u1, u2} R L _inst_1 _inst_2 _inst_3)))))) (Mul.toSMul.{u2} (CommutatorRing.{u2} L) (Distrib.toHasMul.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toDistrib.{u2} (CommutatorRing.{u2} L) (CommutatorRing.nonUnitalNonAssocSemiring.{u2} L _inst_2)))) (SMulZeroClass.toHasSmul.{u1, u2} R (CommutatorRing.{u2} L) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (SMulWithZero.toSmulZeroClass.{u1, u2} R (CommutatorRing.{u2} L) (MulZeroClass.toHasZero.{u1} R (MulZeroOneClass.toMulZeroClass.{u1} R (MonoidWithZero.toMulZeroOneClass.{u1} R (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)))))) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (MulActionWithZero.toSMulWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1))) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (Module.toMulActionWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2))) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2) (LieAlgebra.CommutatorRing.lieAlgebra.{u1, u2} R L _inst_1 _inst_2 _inst_3))))))
but is expected to have type
  forall (R : Type.{u1}) (L : Type.{u2}) [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2], IsScalarTower.{u1, u2, u2} R (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (SMulZeroClass.toSMul.{u1, u2} R (CommutatorRing.{u2} L) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (SMulWithZero.toSMulZeroClass.{u1, u2} R (CommutatorRing.{u2} L) (CommMonoidWithZero.toZero.{u1} R (CommSemiring.toCommMonoidWithZero.{u1} R (CommRing.toCommSemiring.{u1} R _inst_1))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (MulActionWithZero.toSMulWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (Module.toMulActionWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2)) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.instLieRingCommutatorRing.{u2} L _inst_2) (LieAlgebra.instLieAlgebraCommutatorRingInstLieRingCommutatorRing.{u1, u2} R L _inst_1 _inst_2 _inst_3)))))) (SMulZeroClass.toSMul.{u2, u2} (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (SMulWithZero.toSMulZeroClass.{u2, u2} (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (MulZeroClass.toSMulWithZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))))) (SMulZeroClass.toSMul.{u1, u2} R (CommutatorRing.{u2} L) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (SMulWithZero.toSMulZeroClass.{u1, u2} R (CommutatorRing.{u2} L) (CommMonoidWithZero.toZero.{u1} R (CommSemiring.toCommMonoidWithZero.{u1} R (CommRing.toCommSemiring.{u1} R _inst_1))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (MulActionWithZero.toSMulWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (Module.toMulActionWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2)) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.instLieRingCommutatorRing.{u2} L _inst_2) (LieAlgebra.instLieAlgebraCommutatorRingInstLieRingCommutatorRing.{u1, u2} R L _inst_1 _inst_2 _inst_3))))))
Case conversion may be inaccurate. Consider using '#align lie_algebra.is_scalar_tower LieAlgebra.isScalarTowerₓ'. -/
/-- Regarding the `lie_ring` of a `lie_algebra` as a `non_unital_non_assoc_semiring`, we can
reinterpret the `smul_lie` law as an `is_scalar_tower`. -/
instance isScalarTower : IsScalarTower R (CommutatorRing L) (CommutatorRing L) :=
  ⟨smul_lie⟩
#align lie_algebra.is_scalar_tower LieAlgebra.isScalarTower

/- warning: lie_algebra.smul_comm_class -> LieAlgebra.sMulCommClass is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) (L : Type.{u2}) [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2], SMulCommClass.{u1, u2, u2} R (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (SMulZeroClass.toHasSmul.{u1, u2} R (CommutatorRing.{u2} L) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (SMulWithZero.toSmulZeroClass.{u1, u2} R (CommutatorRing.{u2} L) (MulZeroClass.toHasZero.{u1} R (MulZeroOneClass.toMulZeroClass.{u1} R (MonoidWithZero.toMulZeroOneClass.{u1} R (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)))))) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (MulActionWithZero.toSMulWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1))) (AddZeroClass.toHasZero.{u2} (CommutatorRing.{u2} L) (AddMonoid.toAddZeroClass.{u2} (CommutatorRing.{u2} L) (AddCommMonoid.toAddMonoid.{u2} (CommutatorRing.{u2} L) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2)))))) (Module.toMulActionWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2))) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2) (LieAlgebra.CommutatorRing.lieAlgebra.{u1, u2} R L _inst_1 _inst_2 _inst_3)))))) (Mul.toSMul.{u2} (CommutatorRing.{u2} L) (Distrib.toHasMul.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toDistrib.{u2} (CommutatorRing.{u2} L) (CommutatorRing.nonUnitalNonAssocSemiring.{u2} L _inst_2))))
but is expected to have type
  forall (R : Type.{u1}) (L : Type.{u2}) [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2], SMulCommClass.{u1, u2, u2} R (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (SMulZeroClass.toSMul.{u1, u2} R (CommutatorRing.{u2} L) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (SMulWithZero.toSMulZeroClass.{u1, u2} R (CommutatorRing.{u2} L) (CommMonoidWithZero.toZero.{u1} R (CommSemiring.toCommMonoidWithZero.{u1} R (CommRing.toCommSemiring.{u1} R _inst_1))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (MulActionWithZero.toSMulWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (Module.toMulActionWithZero.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2)) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.instLieRingCommutatorRing.{u2} L _inst_2) (LieAlgebra.instLieAlgebraCommutatorRingInstLieRingCommutatorRing.{u1, u2} R L _inst_1 _inst_2 _inst_3)))))) (SMulZeroClass.toSMul.{u2, u2} (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (SMulWithZero.toSMulZeroClass.{u2, u2} (CommutatorRing.{u2} L) (CommutatorRing.{u2} L) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (MulZeroClass.toZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2))) (MulZeroClass.toSMulWithZero.{u2} (CommutatorRing.{u2} L) (NonUnitalNonAssocSemiring.toMulZeroClass.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2)))))
Case conversion may be inaccurate. Consider using '#align lie_algebra.smul_comm_class LieAlgebra.sMulCommClassₓ'. -/
/-- Regarding the `lie_ring` of a `lie_algebra` as a `non_unital_non_assoc_semiring`, we can
reinterpret the `lie_smul` law as an `smul_comm_class`. -/
instance sMulCommClass : SMulCommClass R (CommutatorRing L) (CommutatorRing L) :=
  ⟨fun t x y => (lie_smul t x y).symm⟩
#align lie_algebra.smul_comm_class LieAlgebra.sMulCommClass

end LieAlgebra

namespace LieHom

variable {R L} {L₂ : Type w} [LieRing L₂] [LieAlgebra R L₂]

/- warning: lie_hom.to_non_unital_alg_hom -> LieHom.toNonUnitalAlgHom is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} {L : Type.{u2}} [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2] {L₂ : Type.{u3}} [_inst_4 : LieRing.{u3} L₂] [_inst_5 : LieAlgebra.{u1, u3} R L₂ _inst_1 _inst_4], (LieHom.{u1, u2, u3} R L L₂ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5) -> (NonUnitalAlgHom.{u1, u2, u3} R (CommutatorRing.{u2} L) (CommutatorRing.{u3} L₂) (Ring.toMonoid.{u1} R (CommRing.toRing.{u1} R _inst_1)) (CommutatorRing.nonUnitalNonAssocSemiring.{u2} L _inst_2) (Module.toDistribMulAction.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2))) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2) (LieAlgebra.CommutatorRing.lieAlgebra.{u1, u2} R L _inst_1 _inst_2 _inst_3))) (CommutatorRing.nonUnitalNonAssocSemiring.{u3} L₂ _inst_4) (Module.toDistribMulAction.{u1, u3} R (CommutatorRing.{u3} L₂) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (AddCommGroup.toAddCommMonoid.{u3} (CommutatorRing.{u3} L₂) (LieRing.toAddCommGroup.{u3} (CommutatorRing.{u3} L₂) (LieAlgebra.CommutatorRing.lieRing.{u3} L₂ _inst_4))) (LieAlgebra.toModule.{u1, u3} R (CommutatorRing.{u3} L₂) _inst_1 (LieAlgebra.CommutatorRing.lieRing.{u3} L₂ _inst_4) (LieAlgebra.CommutatorRing.lieAlgebra.{u1, u3} R L₂ _inst_1 _inst_4 _inst_5))))
but is expected to have type
  forall {R : Type.{u1}} {L : Type.{u2}} [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2] {L₂ : Type.{u3}} [_inst_4 : LieRing.{u3} L₂] [_inst_5 : LieAlgebra.{u1, u3} R L₂ _inst_1 _inst_4], (LieHom.{u1, u2, u3} R L L₂ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5) -> (NonUnitalAlgHom.{u1, u2, u3} R (CommutatorRing.{u2} L) (CommutatorRing.{u3} L₂) (MonoidWithZero.toMonoid.{u1} R (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)))) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2) (Module.toDistribMulAction.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2)) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.instLieRingCommutatorRing.{u2} L _inst_2) (LieAlgebra.instLieAlgebraCommutatorRingInstLieRingCommutatorRing.{u1, u2} R L _inst_1 _inst_2 _inst_3))) (instNonUnitalNonAssocSemiringCommutatorRing.{u3} L₂ _inst_4) (Module.toDistribMulAction.{u1, u3} R (CommutatorRing.{u3} L₂) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u3} (CommutatorRing.{u3} L₂) (instNonUnitalNonAssocSemiringCommutatorRing.{u3} L₂ _inst_4)) (LieAlgebra.toModule.{u1, u3} R (CommutatorRing.{u3} L₂) _inst_1 (LieAlgebra.instLieRingCommutatorRing.{u3} L₂ _inst_4) (LieAlgebra.instLieAlgebraCommutatorRingInstLieRingCommutatorRing.{u1, u3} R L₂ _inst_1 _inst_4 _inst_5))))
Case conversion may be inaccurate. Consider using '#align lie_hom.to_non_unital_alg_hom LieHom.toNonUnitalAlgHomₓ'. -/
/-- Regarding the `lie_ring` of a `lie_algebra` as a `non_unital_non_assoc_semiring`, we can
regard a `lie_hom` as a `non_unital_alg_hom`. -/
@[simps]
def toNonUnitalAlgHom (f : L →ₗ⁅R⁆ L₂) : CommutatorRing L →ₙₐ[R] CommutatorRing L₂ :=
  { f with
    toFun := f
    map_zero' := f.map_zero
    map_mul' := f.map_lie }
#align lie_hom.to_non_unital_alg_hom LieHom.toNonUnitalAlgHom

/- warning: lie_hom.to_non_unital_alg_hom_injective -> LieHom.toNonUnitalAlgHom_injective is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} {L : Type.{u2}} [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2] {L₂ : Type.{u3}} [_inst_4 : LieRing.{u3} L₂] [_inst_5 : LieAlgebra.{u1, u3} R L₂ _inst_1 _inst_4], Function.Injective.{max (succ u2) (succ u3), max (succ u2) (succ u3)} (LieHom.{u1, u2, u3} R L L₂ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5) (NonUnitalAlgHom.{u1, u2, u3} R (CommutatorRing.{u2} L) (CommutatorRing.{u3} L₂) (Ring.toMonoid.{u1} R (CommRing.toRing.{u1} R _inst_1)) (CommutatorRing.nonUnitalNonAssocSemiring.{u2} L _inst_2) (Module.toDistribMulAction.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (AddCommGroup.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (LieRing.toAddCommGroup.{u2} (CommutatorRing.{u2} L) (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2))) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.CommutatorRing.lieRing.{u2} L _inst_2) (LieAlgebra.CommutatorRing.lieAlgebra.{u1, u2} R L _inst_1 _inst_2 _inst_3))) (CommutatorRing.nonUnitalNonAssocSemiring.{u3} L₂ _inst_4) (Module.toDistribMulAction.{u1, u3} R (CommutatorRing.{u3} L₂) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (AddCommGroup.toAddCommMonoid.{u3} (CommutatorRing.{u3} L₂) (LieRing.toAddCommGroup.{u3} (CommutatorRing.{u3} L₂) (LieAlgebra.CommutatorRing.lieRing.{u3} L₂ _inst_4))) (LieAlgebra.toModule.{u1, u3} R (CommutatorRing.{u3} L₂) _inst_1 (LieAlgebra.CommutatorRing.lieRing.{u3} L₂ _inst_4) (LieAlgebra.CommutatorRing.lieAlgebra.{u1, u3} R L₂ _inst_1 _inst_4 _inst_5)))) (LieHom.toNonUnitalAlgHom.{u1, u2, u3} R L _inst_1 _inst_2 _inst_3 L₂ _inst_4 _inst_5)
but is expected to have type
  forall {R : Type.{u1}} {L : Type.{u2}} [_inst_1 : CommRing.{u1} R] [_inst_2 : LieRing.{u2} L] [_inst_3 : LieAlgebra.{u1, u2} R L _inst_1 _inst_2] {L₂ : Type.{u3}} [_inst_4 : LieRing.{u3} L₂] [_inst_5 : LieAlgebra.{u1, u3} R L₂ _inst_1 _inst_4], Function.Injective.{max (succ u2) (succ u3), max (succ u2) (succ u3)} (LieHom.{u1, u2, u3} R L L₂ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5) (NonUnitalAlgHom.{u1, u2, u3} R (CommutatorRing.{u2} L) (CommutatorRing.{u3} L₂) (MonoidWithZero.toMonoid.{u1} R (Semiring.toMonoidWithZero.{u1} R (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)))) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2) (Module.toDistribMulAction.{u1, u2} R (CommutatorRing.{u2} L) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u2} (CommutatorRing.{u2} L) (instNonUnitalNonAssocSemiringCommutatorRing.{u2} L _inst_2)) (LieAlgebra.toModule.{u1, u2} R (CommutatorRing.{u2} L) _inst_1 (LieAlgebra.instLieRingCommutatorRing.{u2} L _inst_2) (LieAlgebra.instLieAlgebraCommutatorRingInstLieRingCommutatorRing.{u1, u2} R L _inst_1 _inst_2 _inst_3))) (instNonUnitalNonAssocSemiringCommutatorRing.{u3} L₂ _inst_4) (Module.toDistribMulAction.{u1, u3} R (CommutatorRing.{u3} L₂) (Ring.toSemiring.{u1} R (CommRing.toRing.{u1} R _inst_1)) (NonUnitalNonAssocSemiring.toAddCommMonoid.{u3} (CommutatorRing.{u3} L₂) (instNonUnitalNonAssocSemiringCommutatorRing.{u3} L₂ _inst_4)) (LieAlgebra.toModule.{u1, u3} R (CommutatorRing.{u3} L₂) _inst_1 (LieAlgebra.instLieRingCommutatorRing.{u3} L₂ _inst_4) (LieAlgebra.instLieAlgebraCommutatorRingInstLieRingCommutatorRing.{u1, u3} R L₂ _inst_1 _inst_4 _inst_5)))) (LieHom.toNonUnitalAlgHom.{u1, u2, u3} R L _inst_1 _inst_2 _inst_3 L₂ _inst_4 _inst_5)
Case conversion may be inaccurate. Consider using '#align lie_hom.to_non_unital_alg_hom_injective LieHom.toNonUnitalAlgHom_injectiveₓ'. -/
theorem toNonUnitalAlgHom_injective :
    Function.Injective (toNonUnitalAlgHom : _ → CommutatorRing L →ₙₐ[R] CommutatorRing L₂) :=
  fun f g h => ext <| NonUnitalAlgHom.congr_fun h
#align lie_hom.to_non_unital_alg_hom_injective LieHom.toNonUnitalAlgHom_injective

end LieHom