/-
Copyright (c) 2020 Zhouhang Zhou. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Zhouhang Zhou, Yury Kudryashov

! This file was ported from Lean 3 source module measure_theory.integral.set_integral
! leanprover-community/mathlib commit 46b633fd842bef9469441c0209906f6dddd2b4f5
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.MeasureTheory.Integral.IntegrableOn
import Mathbin.MeasureTheory.Integral.Bochner
import Mathbin.MeasureTheory.Function.LocallyIntegrable
import Mathbin.Order.Filter.IndicatorFunction
import Mathbin.Topology.MetricSpace.ThickenedIndicator
import Mathbin.Topology.ContinuousFunction.Compact

/-!
# Set integral

In this file we prove some properties of `∫ x in s, f x ∂μ`. Recall that this notation
is defined as `∫ x, f x ∂(μ.restrict s)`. In `integral_indicator` we prove that for a measurable
function `f` and a measurable set `s` this definition coincides with another natural definition:
`∫ x, indicator s f x ∂μ = ∫ x in s, f x ∂μ`, where `indicator s f x` is equal to `f x` for `x ∈ s`
and is zero otherwise.

Since `∫ x in s, f x ∂μ` is a notation, one can rewrite or apply any theorem about `∫ x, f x ∂μ`
directly. In this file we prove some theorems about dependence of `∫ x in s, f x ∂μ` on `s`, e.g.
`integral_union`, `integral_empty`, `integral_univ`.

We use the property `integrable_on f s μ := integrable f (μ.restrict s)`, defined in
`measure_theory.integrable_on`. We also defined in that same file a predicate
`integrable_at_filter (f : α → E) (l : filter α) (μ : measure α)` saying that `f` is integrable at
some set `s ∈ l`.

Finally, we prove a version of the
[Fundamental theorem of calculus](https://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus)
for set integral, see `filter.tendsto.integral_sub_linear_is_o_ae` and its corollaries.
Namely, consider a measurably generated filter `l`, a measure `μ` finite at this filter, and
a function `f` that has a finite limit `c` at `l ⊓ μ.ae`. Then `∫ x in s, f x ∂μ = μ s • c + o(μ s)`
as `s` tends to `l.small_sets`, i.e. for any `ε>0` there exists `t ∈ l` such that
`‖∫ x in s, f x ∂μ - μ s • c‖ ≤ ε * μ s` whenever `s ⊆ t`. We also formulate a version of this
theorem for a locally finite measure `μ` and a function `f` continuous at a point `a`.

## Notation

We provide the following notations for expressing the integral of a function on a set :
* `∫ a in s, f a ∂μ` is `measure_theory.integral (μ.restrict s) f`
* `∫ a in s, f a` is `∫ a in s, f a ∂volume`

Note that the set notations are defined in the file `measure_theory/integral/bochner`,
but we reference them here because all theorems about set integrals are in this file.

-/

noncomputable section

open Set Filter TopologicalSpace MeasureTheory Function

open Classical Topology Interval BigOperators Filter ENNReal NNReal MeasureTheory

variable {α β E F : Type _} [MeasurableSpace α]

namespace MeasureTheory

section NormedAddCommGroup

variable [NormedAddCommGroup E] {f g : α → E} {s t : Set α} {μ ν : Measure α} {l l' : Filter α}

variable [CompleteSpace E] [NormedSpace ℝ E]

theorem set_integral_congr_ae₀ (hs : NullMeasurableSet s μ) (h : ∀ᵐ x ∂μ, x ∈ s → f x = g x) :
    (∫ x in s, f x ∂μ) = ∫ x in s, g x ∂μ :=
  integral_congr_ae ((ae_restrict_iff'₀ hs).2 h)
#align measure_theory.set_integral_congr_ae₀ MeasureTheory.set_integral_congr_ae₀

theorem set_integral_congr_ae (hs : MeasurableSet s) (h : ∀ᵐ x ∂μ, x ∈ s → f x = g x) :
    (∫ x in s, f x ∂μ) = ∫ x in s, g x ∂μ :=
  integral_congr_ae ((ae_restrict_iff' hs).2 h)
#align measure_theory.set_integral_congr_ae MeasureTheory.set_integral_congr_ae

theorem set_integral_congr₀ (hs : NullMeasurableSet s μ) (h : EqOn f g s) :
    (∫ x in s, f x ∂μ) = ∫ x in s, g x ∂μ :=
  set_integral_congr_ae₀ hs <| eventually_of_forall h
#align measure_theory.set_integral_congr₀ MeasureTheory.set_integral_congr₀

theorem set_integral_congr (hs : MeasurableSet s) (h : EqOn f g s) :
    (∫ x in s, f x ∂μ) = ∫ x in s, g x ∂μ :=
  set_integral_congr_ae hs <| eventually_of_forall h
#align measure_theory.set_integral_congr MeasureTheory.set_integral_congr

theorem set_integral_congr_set_ae (hst : s =ᵐ[μ] t) : (∫ x in s, f x ∂μ) = ∫ x in t, f x ∂μ := by
  rw [measure.restrict_congr_set hst]
#align measure_theory.set_integral_congr_set_ae MeasureTheory.set_integral_congr_set_ae

theorem integral_union_ae (hst : AeDisjoint μ s t) (ht : NullMeasurableSet t μ)
    (hfs : IntegrableOn f s μ) (hft : IntegrableOn f t μ) :
    (∫ x in s ∪ t, f x ∂μ) = (∫ x in s, f x ∂μ) + ∫ x in t, f x ∂μ := by
  simp only [integrable_on, measure.restrict_union₀ hst ht, integral_add_measure hfs hft]
#align measure_theory.integral_union_ae MeasureTheory.integral_union_ae

theorem integral_union (hst : Disjoint s t) (ht : MeasurableSet t) (hfs : IntegrableOn f s μ)
    (hft : IntegrableOn f t μ) : (∫ x in s ∪ t, f x ∂μ) = (∫ x in s, f x ∂μ) + ∫ x in t, f x ∂μ :=
  integral_union_ae hst.AeDisjoint ht.NullMeasurableSet hfs hft
#align measure_theory.integral_union MeasureTheory.integral_union

theorem integral_diff (ht : MeasurableSet t) (hfs : IntegrableOn f s μ) (hts : t ⊆ s) :
    (∫ x in s \ t, f x ∂μ) = (∫ x in s, f x ∂μ) - ∫ x in t, f x ∂μ :=
  by
  rw [eq_sub_iff_add_eq, ← integral_union, diff_union_of_subset hts]
  exacts[disjoint_sdiff_self_left, ht, hfs.mono_set (diff_subset _ _), hfs.mono_set hts]
#align measure_theory.integral_diff MeasureTheory.integral_diff

theorem integral_inter_add_diff₀ (ht : NullMeasurableSet t μ) (hfs : IntegrableOn f s μ) :
    ((∫ x in s ∩ t, f x ∂μ) + ∫ x in s \ t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  by
  rw [← measure.restrict_inter_add_diff₀ s ht, integral_add_measure]
  · exact integrable.mono_measure hfs (measure.restrict_mono (inter_subset_left _ _) le_rfl)
  · exact integrable.mono_measure hfs (measure.restrict_mono (diff_subset _ _) le_rfl)
#align measure_theory.integral_inter_add_diff₀ MeasureTheory.integral_inter_add_diff₀

theorem integral_inter_add_diff (ht : MeasurableSet t) (hfs : IntegrableOn f s μ) :
    ((∫ x in s ∩ t, f x ∂μ) + ∫ x in s \ t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  integral_inter_add_diff₀ ht.NullMeasurableSet hfs
#align measure_theory.integral_inter_add_diff MeasureTheory.integral_inter_add_diff

theorem integral_finset_bUnion {ι : Type _} (t : Finset ι) {s : ι → Set α}
    (hs : ∀ i ∈ t, MeasurableSet (s i)) (h's : Set.Pairwise (↑t) (Disjoint on s))
    (hf : ∀ i ∈ t, IntegrableOn f (s i) μ) :
    (∫ x in ⋃ i ∈ t, s i, f x ∂μ) = ∑ i in t, ∫ x in s i, f x ∂μ :=
  by
  induction' t using Finset.induction_on with a t hat IH hs h's
  · simp
  · simp only [Finset.coe_insert, Finset.forall_mem_insert, Set.pairwise_insert,
      Finset.set_bunionᵢ_insert] at hs hf h's⊢
    rw [integral_union _ _ hf.1 (integrable_on_finset_Union.2 hf.2)]
    · rw [Finset.sum_insert hat, IH hs.2 h's.1 hf.2]
    · simp only [disjoint_Union_right]
      exact fun i hi => (h's.2 i hi (ne_of_mem_of_not_mem hi hat).symm).1
    · exact Finset.measurableSet_bunionᵢ _ hs.2
#align measure_theory.integral_finset_bUnion MeasureTheory.integral_finset_bUnion

theorem integral_fintype_unionᵢ {ι : Type _} [Fintype ι] {s : ι → Set α}
    (hs : ∀ i, MeasurableSet (s i)) (h's : Pairwise (Disjoint on s))
    (hf : ∀ i, IntegrableOn f (s i) μ) : (∫ x in ⋃ i, s i, f x ∂μ) = ∑ i, ∫ x in s i, f x ∂μ :=
  by
  convert integral_finset_bUnion Finset.univ (fun i hi => hs i) _ fun i _ => hf i
  · simp
  · simp [pairwise_univ, h's]
#align measure_theory.integral_fintype_Union MeasureTheory.integral_fintype_unionᵢ

theorem integral_empty : (∫ x in ∅, f x ∂μ) = 0 := by
  rw [measure.restrict_empty, integral_zero_measure]
#align measure_theory.integral_empty MeasureTheory.integral_empty

theorem integral_univ : (∫ x in univ, f x ∂μ) = ∫ x, f x ∂μ := by rw [measure.restrict_univ]
#align measure_theory.integral_univ MeasureTheory.integral_univ

theorem integral_add_compl₀ (hs : NullMeasurableSet s μ) (hfi : Integrable f μ) :
    ((∫ x in s, f x ∂μ) + ∫ x in sᶜ, f x ∂μ) = ∫ x, f x ∂μ := by
  rw [←
    integral_union_ae (@disjoint_compl_right (Set α) _ _).AeDisjoint hs.compl hfi.integrable_on
      hfi.integrable_on,
    union_compl_self, integral_univ]
#align measure_theory.integral_add_compl₀ MeasureTheory.integral_add_compl₀

theorem integral_add_compl (hs : MeasurableSet s) (hfi : Integrable f μ) :
    ((∫ x in s, f x ∂μ) + ∫ x in sᶜ, f x ∂μ) = ∫ x, f x ∂μ :=
  integral_add_compl₀ hs.NullMeasurableSet hfi
#align measure_theory.integral_add_compl MeasureTheory.integral_add_compl

/-- For a function `f` and a measurable set `s`, the integral of `indicator s f`
over the whole space is equal to `∫ x in s, f x ∂μ` defined as `∫ x, f x ∂(μ.restrict s)`. -/
theorem integral_indicator (hs : MeasurableSet s) : (∫ x, indicator s f x ∂μ) = ∫ x in s, f x ∂μ :=
  by
  by_cases hfi : integrable_on f s μ; swap
  · rwa [integral_undef, integral_undef]
    rwa [integrable_indicator_iff hs]
  calc
    (∫ x, indicator s f x ∂μ) = (∫ x in s, indicator s f x ∂μ) + ∫ x in sᶜ, indicator s f x ∂μ :=
      (integral_add_compl hs (hfi.integrable_indicator hs)).symm
    _ = (∫ x in s, f x ∂μ) + ∫ x in sᶜ, 0 ∂μ :=
      (congr_arg₂ (· + ·) (integral_congr_ae (indicator_ae_eq_restrict hs))
        (integral_congr_ae (indicator_ae_eq_restrict_compl hs)))
    _ = ∫ x in s, f x ∂μ := by simp

#align measure_theory.integral_indicator MeasureTheory.integral_indicator

theorem set_integral_indicator (ht : MeasurableSet t) :
    (∫ x in s, t.indicator f x ∂μ) = ∫ x in s ∩ t, f x ∂μ := by
  rw [integral_indicator ht, measure.restrict_restrict ht, Set.inter_comm]
#align measure_theory.set_integral_indicator MeasureTheory.set_integral_indicator

theorem ofReal_set_integral_one_of_measure_ne_top {α : Type _} {m : MeasurableSpace α}
    {μ : Measure α} {s : Set α} (hs : μ s ≠ ∞) : ENNReal.ofReal (∫ x in s, (1 : ℝ) ∂μ) = μ s :=
  calc
    ENNReal.ofReal (∫ x in s, (1 : ℝ) ∂μ) = ENNReal.ofReal (∫ x in s, ‖(1 : ℝ)‖ ∂μ) := by
      simp only [norm_one]
    _ = ∫⁻ x in s, 1 ∂μ :=
      by
      rw [of_real_integral_norm_eq_lintegral_nnnorm (integrable_on_const.2 (Or.inr hs.lt_top))]
      simp only [nnnorm_one, ENNReal.coe_one]
    _ = μ s := set_lintegral_one _

#align measure_theory.of_real_set_integral_one_of_measure_ne_top MeasureTheory.ofReal_set_integral_one_of_measure_ne_top

theorem ofReal_set_integral_one {α : Type _} {m : MeasurableSpace α} (μ : Measure α)
    [IsFiniteMeasure μ] (s : Set α) : ENNReal.ofReal (∫ x in s, (1 : ℝ) ∂μ) = μ s :=
  ofReal_set_integral_one_of_measure_ne_top (measure_ne_top μ s)
#align measure_theory.of_real_set_integral_one MeasureTheory.ofReal_set_integral_one

theorem integral_piecewise [DecidablePred (· ∈ s)] (hs : MeasurableSet s) (hf : IntegrableOn f s μ)
    (hg : IntegrableOn g (sᶜ) μ) :
    (∫ x, s.piecewise f g x ∂μ) = (∫ x in s, f x ∂μ) + ∫ x in sᶜ, g x ∂μ := by
  rw [← Set.indicator_add_compl_eq_piecewise,
    integral_add' (hf.integrable_indicator hs) (hg.integrable_indicator hs.compl),
    integral_indicator hs, integral_indicator hs.compl]
#align measure_theory.integral_piecewise MeasureTheory.integral_piecewise

theorem tendsto_set_integral_of_monotone {ι : Type _} [Countable ι] [SemilatticeSup ι]
    {s : ι → Set α} (hsm : ∀ i, MeasurableSet (s i)) (h_mono : Monotone s)
    (hfi : IntegrableOn f (⋃ n, s n) μ) :
    Tendsto (fun i => ∫ a in s i, f a ∂μ) atTop (𝓝 (∫ a in ⋃ n, s n, f a ∂μ)) :=
  by
  have hfi' : (∫⁻ x in ⋃ n, s n, ‖f x‖₊ ∂μ) < ∞ := hfi.2
  set S := ⋃ i, s i
  have hSm : MeasurableSet S := MeasurableSet.unionᵢ hsm
  have hsub : ∀ {i}, s i ⊆ S := subset_Union s
  rw [← with_density_apply _ hSm] at hfi'
  set ν := μ.with_density fun x => ‖f x‖₊ with hν
  refine' metric.nhds_basis_closed_ball.tendsto_right_iff.2 fun ε ε0 => _
  lift ε to ℝ≥0 using ε0.le
  have : ∀ᶠ i in at_top, ν (s i) ∈ Icc (ν S - ε) (ν S + ε) :=
    tendsto_measure_Union h_mono (ENNReal.Icc_mem_nhds hfi'.ne (ENNReal.coe_pos.2 ε0).ne')
  refine' this.mono fun i hi => _
  rw [mem_closedBall_iff_norm', ← integral_diff (hsm i) hfi hsub, ← coe_nnnorm, NNReal.coe_le_coe, ←
    ENNReal.coe_le_coe]
  refine' (ennnorm_integral_le_lintegral_ennnorm _).trans _
  rw [← with_density_apply _ (hSm.diff (hsm _)), ← hν, measure_diff hsub (hsm _)]
  exacts[tsub_le_iff_tsub_le.mp hi.1,
    (hi.2.trans_lt <| ENNReal.add_lt_top.2 ⟨hfi', ENNReal.coe_lt_top⟩).Ne]
#align measure_theory.tendsto_set_integral_of_monotone MeasureTheory.tendsto_set_integral_of_monotone

theorem hasSum_integral_unionᵢ_ae {ι : Type _} [Countable ι] {s : ι → Set α}
    (hm : ∀ i, NullMeasurableSet (s i) μ) (hd : Pairwise (AeDisjoint μ on s))
    (hfi : IntegrableOn f (⋃ i, s i) μ) :
    HasSum (fun n => ∫ a in s n, f a ∂μ) (∫ a in ⋃ n, s n, f a ∂μ) :=
  by
  simp only [integrable_on, measure.restrict_Union_ae hd hm] at hfi⊢
  exact has_sum_integral_measure hfi
#align measure_theory.has_sum_integral_Union_ae MeasureTheory.hasSum_integral_unionᵢ_ae

theorem hasSum_integral_unionᵢ {ι : Type _} [Countable ι] {s : ι → Set α}
    (hm : ∀ i, MeasurableSet (s i)) (hd : Pairwise (Disjoint on s))
    (hfi : IntegrableOn f (⋃ i, s i) μ) :
    HasSum (fun n => ∫ a in s n, f a ∂μ) (∫ a in ⋃ n, s n, f a ∂μ) :=
  hasSum_integral_unionᵢ_ae (fun i => (hm i).NullMeasurableSet) (hd.mono fun i j h => h.AeDisjoint)
    hfi
#align measure_theory.has_sum_integral_Union MeasureTheory.hasSum_integral_unionᵢ

theorem integral_unionᵢ {ι : Type _} [Countable ι] {s : ι → Set α} (hm : ∀ i, MeasurableSet (s i))
    (hd : Pairwise (Disjoint on s)) (hfi : IntegrableOn f (⋃ i, s i) μ) :
    (∫ a in ⋃ n, s n, f a ∂μ) = ∑' n, ∫ a in s n, f a ∂μ :=
  (HasSum.tsum_eq (hasSum_integral_unionᵢ hm hd hfi)).symm
#align measure_theory.integral_Union MeasureTheory.integral_unionᵢ

theorem integral_unionᵢ_ae {ι : Type _} [Countable ι] {s : ι → Set α}
    (hm : ∀ i, NullMeasurableSet (s i) μ) (hd : Pairwise (AeDisjoint μ on s))
    (hfi : IntegrableOn f (⋃ i, s i) μ) : (∫ a in ⋃ n, s n, f a ∂μ) = ∑' n, ∫ a in s n, f a ∂μ :=
  (HasSum.tsum_eq (hasSum_integral_unionᵢ_ae hm hd hfi)).symm
#align measure_theory.integral_Union_ae MeasureTheory.integral_unionᵢ_ae

theorem set_integral_eq_zero_of_ae_eq_zero (ht_eq : ∀ᵐ x ∂μ, x ∈ t → f x = 0) :
    (∫ x in t, f x ∂μ) = 0 :=
  by
  by_cases hf : ae_strongly_measurable f (μ.restrict t)
  swap
  · rw [integral_undef]
    contrapose! hf
    exact hf.1
  have : (∫ x in t, hf.mk f x ∂μ) = 0 :=
    by
    refine' integral_eq_zero_of_ae _
    rw [eventually_eq,
      ae_restrict_iff (hf.strongly_measurable_mk.measurable_set_eq_fun strongly_measurable_zero)]
    filter_upwards [ae_imp_of_ae_restrict hf.ae_eq_mk, ht_eq]with x hx h'x h''x
    rw [← hx h''x]
    exact h'x h''x
  rw [← this]
  exact integral_congr_ae hf.ae_eq_mk
#align measure_theory.set_integral_eq_zero_of_ae_eq_zero MeasureTheory.set_integral_eq_zero_of_ae_eq_zero

theorem set_integral_eq_zero_of_forall_eq_zero (ht_eq : ∀ x ∈ t, f x = 0) :
    (∫ x in t, f x ∂μ) = 0 :=
  set_integral_eq_zero_of_ae_eq_zero (eventually_of_forall ht_eq)
#align measure_theory.set_integral_eq_zero_of_forall_eq_zero MeasureTheory.set_integral_eq_zero_of_forall_eq_zero

theorem integral_union_eq_left_of_ae_aux (ht_eq : ∀ᵐ x ∂μ.restrict t, f x = 0)
    (haux : StronglyMeasurable f) (H : IntegrableOn f (s ∪ t) μ) :
    (∫ x in s ∪ t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  by
  let k := f ⁻¹' {0}
  have hk : MeasurableSet k := by
    borelize E
    exact haux.measurable (measurable_set_singleton _)
  have h's : integrable_on f s μ := H.mono (subset_union_left _ _) le_rfl
  have A : ∀ u : Set α, (∫ x in u ∩ k, f x ∂μ) = 0 := fun u =>
    set_integral_eq_zero_of_forall_eq_zero fun x hx => hx.2
  rw [← integral_inter_add_diff hk h's, ← integral_inter_add_diff hk H, A, A, zero_add, zero_add,
    union_diff_distrib, union_comm]
  apply set_integral_congr_set_ae
  rw [union_ae_eq_right]
  apply measure_mono_null (diff_subset _ _)
  rw [measure_zero_iff_ae_nmem]
  filter_upwards [ae_imp_of_ae_restrict ht_eq]with x hx h'x using h'x.2 (hx h'x.1)
#align measure_theory.integral_union_eq_left_of_ae_aux MeasureTheory.integral_union_eq_left_of_ae_aux

theorem integral_union_eq_left_of_ae (ht_eq : ∀ᵐ x ∂μ.restrict t, f x = 0) :
    (∫ x in s ∪ t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  by
  have ht : integrable_on f t μ :=
    by
    apply integrable_on.congr_fun' integrable_on_zero
    symm
    exact ht_eq
  by_cases H : integrable_on f (s ∪ t) μ
  swap
  · rw [integral_undef H, integral_undef]
    simpa [integrable_on_union, ht] using H
  let f' := H.1.mk f
  calc
    (∫ x : α in s ∪ t, f x ∂μ) = ∫ x : α in s ∪ t, f' x ∂μ := integral_congr_ae H.1.ae_eq_mk
    _ = ∫ x in s, f' x ∂μ :=
      by
      apply integral_union_eq_left_of_ae_aux _ H.1.stronglyMeasurable_mk (H.congr_fun' H.1.ae_eq_mk)
      filter_upwards [ht_eq,
        ae_mono (measure.restrict_mono (subset_union_right s t) le_rfl) H.1.ae_eq_mk]with x hx h'x
      rw [← h'x, hx]
    _ = ∫ x in s, f x ∂μ :=
      integral_congr_ae
        (ae_mono (measure.restrict_mono (subset_union_left s t) le_rfl) H.1.ae_eq_mk.symm)

#align measure_theory.integral_union_eq_left_of_ae MeasureTheory.integral_union_eq_left_of_ae

theorem integral_union_eq_left_of_forall₀ {f : α → E} (ht : NullMeasurableSet t μ)
    (ht_eq : ∀ x ∈ t, f x = 0) : (∫ x in s ∪ t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  integral_union_eq_left_of_ae ((ae_restrict_iff'₀ ht).2 (eventually_of_forall ht_eq))
#align measure_theory.integral_union_eq_left_of_forall₀ MeasureTheory.integral_union_eq_left_of_forall₀

theorem integral_union_eq_left_of_forall {f : α → E} (ht : MeasurableSet t)
    (ht_eq : ∀ x ∈ t, f x = 0) : (∫ x in s ∪ t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  integral_union_eq_left_of_forall₀ ht.NullMeasurableSet ht_eq
#align measure_theory.integral_union_eq_left_of_forall MeasureTheory.integral_union_eq_left_of_forall

theorem set_integral_eq_of_subset_of_ae_diff_eq_zero_aux (hts : s ⊆ t)
    (h't : ∀ᵐ x ∂μ, x ∈ t \ s → f x = 0) (haux : StronglyMeasurable f)
    (h'aux : IntegrableOn f t μ) : (∫ x in t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  by
  let k := f ⁻¹' {0}
  have hk : MeasurableSet k := by
    borelize E
    exact haux.measurable (measurable_set_singleton _)
  calc
    (∫ x in t, f x ∂μ) = (∫ x in t ∩ k, f x ∂μ) + ∫ x in t \ k, f x ∂μ := by
      rw [integral_inter_add_diff hk h'aux]
    _ = ∫ x in t \ k, f x ∂μ :=
      by
      rw [set_integral_eq_zero_of_forall_eq_zero fun x hx => _, zero_add]
      exact hx.2
    _ = ∫ x in s \ k, f x ∂μ := by
      apply set_integral_congr_set_ae
      filter_upwards [h't]with x hx
      change (x ∈ t \ k) = (x ∈ s \ k)
      simp only [mem_preimage, mem_singleton_iff, eq_iff_iff, and_congr_left_iff, mem_diff]
      intro h'x
      by_cases xs : x ∈ s
      · simp only [xs, hts xs]
      · simp only [xs, iff_false_iff]
        intro xt
        exact h'x (hx ⟨xt, xs⟩)
    _ = (∫ x in s ∩ k, f x ∂μ) + ∫ x in s \ k, f x ∂μ :=
      by
      have : ∀ x ∈ s ∩ k, f x = 0 := fun x hx => hx.2
      rw [set_integral_eq_zero_of_forall_eq_zero this, zero_add]
    _ = ∫ x in s, f x ∂μ := by rw [integral_inter_add_diff hk (h'aux.mono hts le_rfl)]

#align measure_theory.set_integral_eq_of_subset_of_ae_diff_eq_zero_aux MeasureTheory.set_integral_eq_of_subset_of_ae_diff_eq_zero_aux

/-- If a function vanishes almost everywhere on `t \ s` with `s ⊆ t`, then its integrals on `s`
and `t` coincide if `t` is null-measurable. -/
theorem set_integral_eq_of_subset_of_ae_diff_eq_zero (ht : NullMeasurableSet t μ) (hts : s ⊆ t)
    (h't : ∀ᵐ x ∂μ, x ∈ t \ s → f x = 0) : (∫ x in t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  by
  by_cases h : integrable_on f t μ; swap
  · have : ¬integrable_on f s μ := fun H => h (H.ofAeDiffEqZero ht h't)
    rw [integral_undef h, integral_undef this]
  let f' := h.1.mk f
  calc
    (∫ x in t, f x ∂μ) = ∫ x in t, f' x ∂μ := integral_congr_ae h.1.ae_eq_mk
    _ = ∫ x in s, f' x ∂μ :=
      by
      apply
        set_integral_eq_of_subset_of_ae_diff_eq_zero_aux hts _ h.1.stronglyMeasurable_mk
          (h.congr h.1.ae_eq_mk)
      filter_upwards [h't, ae_imp_of_ae_restrict h.1.ae_eq_mk]with x hx h'x h''x
      rw [← h'x h''x.1, hx h''x]
    _ = ∫ x in s, f x ∂μ := by
      apply integral_congr_ae
      apply ae_restrict_of_ae_restrict_of_subset hts
      exact h.1.ae_eq_mk.symm

#align measure_theory.set_integral_eq_of_subset_of_ae_diff_eq_zero MeasureTheory.set_integral_eq_of_subset_of_ae_diff_eq_zero

/-- If a function vanishes on `t \ s` with `s ⊆ t`, then its integrals on `s`
and `t` coincide if `t` is measurable. -/
theorem set_integral_eq_of_subset_of_forall_diff_eq_zero (ht : MeasurableSet t) (hts : s ⊆ t)
    (h't : ∀ x ∈ t \ s, f x = 0) : (∫ x in t, f x ∂μ) = ∫ x in s, f x ∂μ :=
  set_integral_eq_of_subset_of_ae_diff_eq_zero ht.NullMeasurableSet hts
    (eventually_of_forall fun x hx => h't x hx)
#align measure_theory.set_integral_eq_of_subset_of_forall_diff_eq_zero MeasureTheory.set_integral_eq_of_subset_of_forall_diff_eq_zero

/-- If a function vanishes almost everywhere on `sᶜ`, then its integral on `s`
coincides with its integral on the whole space. -/
theorem set_integral_eq_integral_of_ae_compl_eq_zero (h : ∀ᵐ x ∂μ, x ∉ s → f x = 0) :
    (∫ x in s, f x ∂μ) = ∫ x, f x ∂μ :=
  by
  conv_rhs => rw [← integral_univ]
  symm
  apply set_integral_eq_of_subset_of_ae_diff_eq_zero null_measurable_set_univ (subset_univ _)
  filter_upwards [h]with x hx h'x using hx h'x.2
#align measure_theory.set_integral_eq_integral_of_ae_compl_eq_zero MeasureTheory.set_integral_eq_integral_of_ae_compl_eq_zero

/-- If a function vanishes on `sᶜ`, then its integral on `s` coincides with its integral on the
whole space. -/
theorem set_integral_eq_integral_of_forall_compl_eq_zero (h : ∀ x, x ∉ s → f x = 0) :
    (∫ x in s, f x ∂μ) = ∫ x, f x ∂μ :=
  set_integral_eq_integral_of_ae_compl_eq_zero (eventually_of_forall h)
#align measure_theory.set_integral_eq_integral_of_forall_compl_eq_zero MeasureTheory.set_integral_eq_integral_of_forall_compl_eq_zero

theorem set_integral_neg_eq_set_integral_nonpos [LinearOrder E] {f : α → E}
    (hf : AeStronglyMeasurable f μ) :
    (∫ x in { x | f x < 0 }, f x ∂μ) = ∫ x in { x | f x ≤ 0 }, f x ∂μ :=
  by
  have h_union : { x | f x ≤ 0 } = { x | f x < 0 } ∪ { x | f x = 0 } :=
    by
    ext
    simp_rw [Set.mem_union, Set.mem_setOf_eq]
    exact le_iff_lt_or_eq
  rw [h_union]
  have B : null_measurable_set { x | f x = 0 } μ :=
    hf.null_measurable_set_eq_fun ae_strongly_measurable_zero
  symm
  refine' integral_union_eq_left_of_ae _
  filter_upwards [ae_restrict_mem₀ B]with x hx using hx
#align measure_theory.set_integral_neg_eq_set_integral_nonpos MeasureTheory.set_integral_neg_eq_set_integral_nonpos

theorem integral_norm_eq_pos_sub_neg {f : α → ℝ} (hfi : Integrable f μ) :
    (∫ x, ‖f x‖ ∂μ) = (∫ x in { x | 0 ≤ f x }, f x ∂μ) - ∫ x in { x | f x ≤ 0 }, f x ∂μ :=
  have h_meas : NullMeasurableSet { x | 0 ≤ f x } μ :=
    aeStronglyMeasurableConst.nullMeasurableSetLe hfi.1
  calc
    (∫ x, ‖f x‖ ∂μ) = (∫ x in { x | 0 ≤ f x }, ‖f x‖ ∂μ) + ∫ x in { x | 0 ≤ f x }ᶜ, ‖f x‖ ∂μ := by
      rw [← integral_add_compl₀ h_meas hfi.norm]
    _ = (∫ x in { x | 0 ≤ f x }, f x ∂μ) + ∫ x in { x | 0 ≤ f x }ᶜ, ‖f x‖ ∂μ :=
      by
      congr 1
      refine' set_integral_congr₀ h_meas fun x hx => _
      dsimp only
      rw [Real.norm_eq_abs, abs_eq_self.mpr _]
      exact hx
    _ = (∫ x in { x | 0 ≤ f x }, f x ∂μ) - ∫ x in { x | 0 ≤ f x }ᶜ, f x ∂μ :=
      by
      congr 1
      rw [← integral_neg]
      refine' set_integral_congr₀ h_meas.compl fun x hx => _
      dsimp only
      rw [Real.norm_eq_abs, abs_eq_neg_self.mpr _]
      rw [Set.mem_compl_iff, Set.nmem_setOf_iff] at hx
      linarith
    _ = (∫ x in { x | 0 ≤ f x }, f x ∂μ) - ∫ x in { x | f x ≤ 0 }, f x ∂μ :=
      by
      rw [← set_integral_neg_eq_set_integral_nonpos hfi.1]
      congr
      ext1 x
      simp

#align measure_theory.integral_norm_eq_pos_sub_neg MeasureTheory.integral_norm_eq_pos_sub_neg

theorem set_integral_const (c : E) : (∫ x in s, c ∂μ) = (μ s).toReal • c := by
  rw [integral_const, measure.restrict_apply_univ]
#align measure_theory.set_integral_const MeasureTheory.set_integral_const

@[simp]
theorem integral_indicator_const (e : E) ⦃s : Set α⦄ (s_meas : MeasurableSet s) :
    (∫ a : α, s.indicator (fun x : α => e) a ∂μ) = (μ s).toReal • e := by
  rw [integral_indicator s_meas, ← set_integral_const]
#align measure_theory.integral_indicator_const MeasureTheory.integral_indicator_const

@[simp]
theorem integral_indicator_one ⦃s : Set α⦄ (hs : MeasurableSet s) :
    (∫ a, s.indicator 1 a ∂μ) = (μ s).toReal :=
  (integral_indicator_const 1 hs).trans ((smul_eq_mul _).trans (mul_one _))
#align measure_theory.integral_indicator_one MeasureTheory.integral_indicator_one

theorem set_integral_indicatorConstLp {p : ℝ≥0∞} (hs : MeasurableSet s) (ht : MeasurableSet t)
    (hμt : μ t ≠ ∞) (x : E) :
    (∫ a in s, indicatorConstLp p ht hμt x a ∂μ) = (μ (t ∩ s)).toReal • x :=
  calc
    (∫ a in s, indicatorConstLp p ht hμt x a ∂μ) = ∫ a in s, t.indicator (fun _ => x) a ∂μ := by
      rw [set_integral_congr_ae hs (indicator_const_Lp_coe_fn.mono fun x hx hxs => hx)]
    _ = (μ (t ∩ s)).toReal • x := by rw [integral_indicator_const _ ht, measure.restrict_apply ht]

#align measure_theory.set_integral_indicator_const_Lp MeasureTheory.set_integral_indicatorConstLp

theorem integral_indicatorConstLp {p : ℝ≥0∞} (ht : MeasurableSet t) (hμt : μ t ≠ ∞) (x : E) :
    (∫ a, indicatorConstLp p ht hμt x a ∂μ) = (μ t).toReal • x :=
  calc
    (∫ a, indicatorConstLp p ht hμt x a ∂μ) = ∫ a in univ, indicatorConstLp p ht hμt x a ∂μ := by
      rw [integral_univ]
    _ = (μ (t ∩ univ)).toReal • x := (set_integral_indicatorConstLp MeasurableSet.univ ht hμt x)
    _ = (μ t).toReal • x := by rw [inter_univ]

#align measure_theory.integral_indicator_const_Lp MeasureTheory.integral_indicatorConstLp

theorem set_integral_map {β} [MeasurableSpace β] {g : α → β} {f : β → E} {s : Set β}
    (hs : MeasurableSet s) (hf : AeStronglyMeasurable f (Measure.map g μ)) (hg : AeMeasurable g μ) :
    (∫ y in s, f y ∂Measure.map g μ) = ∫ x in g ⁻¹' s, f (g x) ∂μ :=
  by
  rw [measure.restrict_map_of_ae_measurable hg hs,
    integral_map (hg.mono_measure measure.restrict_le_self) (hf.mono_measure _)]
  exact measure.map_mono_of_ae_measurable measure.restrict_le_self hg
#align measure_theory.set_integral_map MeasureTheory.set_integral_map

theorem MeasurableEmbedding.set_integral_map {β} {_ : MeasurableSpace β} {f : α → β}
    (hf : MeasurableEmbedding f) (g : β → E) (s : Set β) :
    (∫ y in s, g y ∂Measure.map f μ) = ∫ x in f ⁻¹' s, g (f x) ∂μ := by
  rw [hf.restrict_map, hf.integral_map]
#align measurable_embedding.set_integral_map MeasurableEmbedding.set_integral_map

theorem ClosedEmbedding.set_integral_map [TopologicalSpace α] [BorelSpace α] {β} [MeasurableSpace β]
    [TopologicalSpace β] [BorelSpace β] {g : α → β} {f : β → E} (s : Set β)
    (hg : ClosedEmbedding g) : (∫ y in s, f y ∂Measure.map g μ) = ∫ x in g ⁻¹' s, f (g x) ∂μ :=
  hg.MeasurableEmbedding.set_integral_map _ _
#align closed_embedding.set_integral_map ClosedEmbedding.set_integral_map

theorem MeasurePreserving.set_integral_preimage_emb {β} {_ : MeasurableSpace β} {f : α → β} {ν}
    (h₁ : MeasurePreserving f μ ν) (h₂ : MeasurableEmbedding f) (g : β → E) (s : Set β) :
    (∫ x in f ⁻¹' s, g (f x) ∂μ) = ∫ y in s, g y ∂ν :=
  (h₁.restrictPreimageEmb h₂ s).integral_comp h₂ _
#align measure_theory.measure_preserving.set_integral_preimage_emb MeasureTheory.MeasurePreserving.set_integral_preimage_emb

theorem MeasurePreserving.set_integral_image_emb {β} {_ : MeasurableSpace β} {f : α → β} {ν}
    (h₁ : MeasurePreserving f μ ν) (h₂ : MeasurableEmbedding f) (g : β → E) (s : Set α) :
    (∫ y in f '' s, g y ∂ν) = ∫ x in s, g (f x) ∂μ :=
  Eq.symm <| (h₁.restrictImageEmb h₂ s).integral_comp h₂ _
#align measure_theory.measure_preserving.set_integral_image_emb MeasureTheory.MeasurePreserving.set_integral_image_emb

theorem set_integral_map_equiv {β} [MeasurableSpace β] (e : α ≃ᵐ β) (f : β → E) (s : Set β) :
    (∫ y in s, f y ∂Measure.map e μ) = ∫ x in e ⁻¹' s, f (e x) ∂μ :=
  e.MeasurableEmbedding.set_integral_map f s
#align measure_theory.set_integral_map_equiv MeasureTheory.set_integral_map_equiv

theorem norm_set_integral_le_of_norm_le_const_ae {C : ℝ} (hs : μ s < ∞)
    (hC : ∀ᵐ x ∂μ.restrict s, ‖f x‖ ≤ C) : ‖∫ x in s, f x ∂μ‖ ≤ C * (μ s).toReal :=
  by
  rw [← measure.restrict_apply_univ] at *
  haveI : is_finite_measure (μ.restrict s) := ⟨‹_›⟩
  exact norm_integral_le_of_norm_le_const hC
#align measure_theory.norm_set_integral_le_of_norm_le_const_ae MeasureTheory.norm_set_integral_le_of_norm_le_const_ae

theorem norm_set_integral_le_of_norm_le_const_ae' {C : ℝ} (hs : μ s < ∞)
    (hC : ∀ᵐ x ∂μ, x ∈ s → ‖f x‖ ≤ C) (hfm : AeStronglyMeasurable f (μ.restrict s)) :
    ‖∫ x in s, f x ∂μ‖ ≤ C * (μ s).toReal :=
  by
  apply norm_set_integral_le_of_norm_le_const_ae hs
  have A : ∀ᵐ x : α ∂μ, x ∈ s → ‖ae_strongly_measurable.mk f hfm x‖ ≤ C :=
    by
    filter_upwards [hC, hfm.ae_mem_imp_eq_mk]with _ h1 h2 h3
    rw [← h2 h3]
    exact h1 h3
  have B : MeasurableSet { x | ‖(hfm.mk f) x‖ ≤ C } :=
    hfm.strongly_measurable_mk.norm.measurable measurableSet_Iic
  filter_upwards [hfm.ae_eq_mk, (ae_restrict_iff B).2 A]with _ h1 _
  rwa [h1]
#align measure_theory.norm_set_integral_le_of_norm_le_const_ae' MeasureTheory.norm_set_integral_le_of_norm_le_const_ae'

theorem norm_set_integral_le_of_norm_le_const_ae'' {C : ℝ} (hs : μ s < ∞) (hsm : MeasurableSet s)
    (hC : ∀ᵐ x ∂μ, x ∈ s → ‖f x‖ ≤ C) : ‖∫ x in s, f x ∂μ‖ ≤ C * (μ s).toReal :=
  norm_set_integral_le_of_norm_le_const_ae hs <| by
    rwa [ae_restrict_eq hsm, eventually_inf_principal]
#align measure_theory.norm_set_integral_le_of_norm_le_const_ae'' MeasureTheory.norm_set_integral_le_of_norm_le_const_ae''

theorem norm_set_integral_le_of_norm_le_const {C : ℝ} (hs : μ s < ∞) (hC : ∀ x ∈ s, ‖f x‖ ≤ C)
    (hfm : AeStronglyMeasurable f (μ.restrict s)) : ‖∫ x in s, f x ∂μ‖ ≤ C * (μ s).toReal :=
  norm_set_integral_le_of_norm_le_const_ae' hs (eventually_of_forall hC) hfm
#align measure_theory.norm_set_integral_le_of_norm_le_const MeasureTheory.norm_set_integral_le_of_norm_le_const

theorem norm_set_integral_le_of_norm_le_const' {C : ℝ} (hs : μ s < ∞) (hsm : MeasurableSet s)
    (hC : ∀ x ∈ s, ‖f x‖ ≤ C) : ‖∫ x in s, f x ∂μ‖ ≤ C * (μ s).toReal :=
  norm_set_integral_le_of_norm_le_const_ae'' hs hsm <| eventually_of_forall hC
#align measure_theory.norm_set_integral_le_of_norm_le_const' MeasureTheory.norm_set_integral_le_of_norm_le_const'

theorem set_integral_eq_zero_iff_of_nonneg_ae {f : α → ℝ} (hf : 0 ≤ᵐ[μ.restrict s] f)
    (hfi : IntegrableOn f s μ) : (∫ x in s, f x ∂μ) = 0 ↔ f =ᵐ[μ.restrict s] 0 :=
  integral_eq_zero_iff_of_nonneg_ae hf hfi
#align measure_theory.set_integral_eq_zero_iff_of_nonneg_ae MeasureTheory.set_integral_eq_zero_iff_of_nonneg_ae

theorem set_integral_pos_iff_support_of_nonneg_ae {f : α → ℝ} (hf : 0 ≤ᵐ[μ.restrict s] f)
    (hfi : IntegrableOn f s μ) : (0 < ∫ x in s, f x ∂μ) ↔ 0 < μ (support f ∩ s) :=
  by
  rw [integral_pos_iff_support_of_nonneg_ae hf hfi, measure.restrict_apply₀]
  rw [support_eq_preimage]
  exact hfi.ae_strongly_measurable.ae_measurable.null_measurable (measurable_set_singleton 0).compl
#align measure_theory.set_integral_pos_iff_support_of_nonneg_ae MeasureTheory.set_integral_pos_iff_support_of_nonneg_ae

theorem set_integral_gt_gt {R : ℝ} {f : α → ℝ} (hR : 0 ≤ R) (hfm : Measurable f)
    (hfint : IntegrableOn f { x | ↑R < f x } μ) (hμ : μ { x | ↑R < f x } ≠ 0) :
    (μ { x | ↑R < f x }).toReal * R < ∫ x in { x | ↑R < f x }, f x ∂μ :=
  by
  have : integrable_on (fun x => R) { x | ↑R < f x } μ :=
    by
    refine' ⟨ae_strongly_measurable_const, lt_of_le_of_lt _ hfint.2⟩
    refine'
      set_lintegral_mono (Measurable.nnnorm _).coe_nNReal_eNNReal hfm.nnnorm.coe_nnreal_ennreal
        fun x hx => _
    · exact measurable_const
    · simp only [ENNReal.coe_le_coe, Real.nnnorm_of_nonneg hR,
        Real.nnnorm_of_nonneg (hR.trans <| le_of_lt hx), Subtype.mk_le_mk]
      exact le_of_lt hx
  rw [← sub_pos, ← smul_eq_mul, ← set_integral_const, ← integral_sub hfint this,
    set_integral_pos_iff_support_of_nonneg_ae]
  · rw [← zero_lt_iff] at hμ
    rwa [Set.inter_eq_self_of_subset_right]
    exact fun x hx => Ne.symm (ne_of_lt <| sub_pos.2 hx)
  · change ∀ᵐ x ∂μ.restrict _, _
    rw [ae_restrict_iff]
    · exact eventually_of_forall fun x hx => sub_nonneg.2 <| le_of_lt hx
    · exact measurableSet_le measurable_zero (hfm.sub measurable_const)
  · exact integrable.sub hfint this
#align measure_theory.set_integral_gt_gt MeasureTheory.set_integral_gt_gt

theorem set_integral_trim {α} {m m0 : MeasurableSpace α} {μ : Measure α} (hm : m ≤ m0) {f : α → E}
    (hf_meas : strongly_measurable[m] f) {s : Set α} (hs : measurable_set[m] s) :
    (∫ x in s, f x ∂μ) = ∫ x in s, f x ∂μ.trim hm := by
  rwa [integral_trim hm hf_meas, restrict_trim hm μ]
#align measure_theory.set_integral_trim MeasureTheory.set_integral_trim

theorem integral_Icc_eq_integral_Ioc' [PartialOrder α] {f : α → E} {a b : α} (ha : μ {a} = 0) :
    (∫ t in Icc a b, f t ∂μ) = ∫ t in Ioc a b, f t ∂μ :=
  set_integral_congr_set_ae (Ioc_ae_eq_Icc' ha).symm
#align measure_theory.integral_Icc_eq_integral_Ioc' MeasureTheory.integral_Icc_eq_integral_Ioc'

theorem integral_Ioc_eq_integral_Ioo' [PartialOrder α] {f : α → E} {a b : α} (hb : μ {b} = 0) :
    (∫ t in Ioc a b, f t ∂μ) = ∫ t in Ioo a b, f t ∂μ :=
  set_integral_congr_set_ae (Ioo_ae_eq_Ioc' hb).symm
#align measure_theory.integral_Ioc_eq_integral_Ioo' MeasureTheory.integral_Ioc_eq_integral_Ioo'

theorem integral_Icc_eq_integral_Ioc [PartialOrder α] {f : α → E} {a b : α} [HasNoAtoms μ] :
    (∫ t in Icc a b, f t ∂μ) = ∫ t in Ioc a b, f t ∂μ :=
  integral_Icc_eq_integral_Ioc' <| measure_singleton a
#align measure_theory.integral_Icc_eq_integral_Ioc MeasureTheory.integral_Icc_eq_integral_Ioc

theorem integral_Ioc_eq_integral_Ioo [PartialOrder α] {f : α → E} {a b : α} [HasNoAtoms μ] :
    (∫ t in Ioc a b, f t ∂μ) = ∫ t in Ioo a b, f t ∂μ :=
  integral_Ioc_eq_integral_Ioo' <| measure_singleton b
#align measure_theory.integral_Ioc_eq_integral_Ioo MeasureTheory.integral_Ioc_eq_integral_Ioo

end NormedAddCommGroup

section Mono

variable {μ : Measure α} {f g : α → ℝ} {s t : Set α} (hf : IntegrableOn f s μ)
  (hg : IntegrableOn g s μ)

theorem set_integral_mono_ae_restrict (h : f ≤ᵐ[μ.restrict s] g) :
    (∫ a in s, f a ∂μ) ≤ ∫ a in s, g a ∂μ :=
  integral_mono_ae hf hg h
#align measure_theory.set_integral_mono_ae_restrict MeasureTheory.set_integral_mono_ae_restrict

theorem set_integral_mono_ae (h : f ≤ᵐ[μ] g) : (∫ a in s, f a ∂μ) ≤ ∫ a in s, g a ∂μ :=
  set_integral_mono_ae_restrict hf hg (ae_restrict_of_ae h)
#align measure_theory.set_integral_mono_ae MeasureTheory.set_integral_mono_ae

theorem set_integral_mono_on (hs : MeasurableSet s) (h : ∀ x ∈ s, f x ≤ g x) :
    (∫ a in s, f a ∂μ) ≤ ∫ a in s, g a ∂μ :=
  set_integral_mono_ae_restrict hf hg
    (by simp [hs, eventually_le, eventually_inf_principal, ae_of_all _ h])
#align measure_theory.set_integral_mono_on MeasureTheory.set_integral_mono_on

include hf hg

-- why do I need this include, but we don't need it in other lemmas?
theorem set_integral_mono_on_ae (hs : MeasurableSet s) (h : ∀ᵐ x ∂μ, x ∈ s → f x ≤ g x) :
    (∫ a in s, f a ∂μ) ≤ ∫ a in s, g a ∂μ :=
  by
  refine' set_integral_mono_ae_restrict hf hg _
  rwa [eventually_le, ae_restrict_iff' hs]
#align measure_theory.set_integral_mono_on_ae MeasureTheory.set_integral_mono_on_ae

omit hf hg

theorem set_integral_mono (h : f ≤ g) : (∫ a in s, f a ∂μ) ≤ ∫ a in s, g a ∂μ :=
  integral_mono hf hg h
#align measure_theory.set_integral_mono MeasureTheory.set_integral_mono

theorem set_integral_mono_set (hfi : IntegrableOn f t μ) (hf : 0 ≤ᵐ[μ.restrict t] f)
    (hst : s ≤ᵐ[μ] t) : (∫ x in s, f x ∂μ) ≤ ∫ x in t, f x ∂μ :=
  integral_mono_measure (Measure.restrict_mono_ae hst) hf hfi
#align measure_theory.set_integral_mono_set MeasureTheory.set_integral_mono_set

theorem set_integral_ge_of_const_le {c : ℝ} (hs : MeasurableSet s) (hμs : μ s ≠ ∞)
    (hf : ∀ x ∈ s, c ≤ f x) (hfint : IntegrableOn (fun x : α => f x) s μ) :
    c * (μ s).toReal ≤ ∫ x in s, f x ∂μ :=
  by
  rw [mul_comm, ← smul_eq_mul, ← set_integral_const c]
  exact set_integral_mono_on (integrable_on_const.2 (Or.inr hμs.lt_top)) hfint hs hf
#align measure_theory.set_integral_ge_of_const_le MeasureTheory.set_integral_ge_of_const_le

end Mono

section Nonneg

variable {μ : Measure α} {f : α → ℝ} {s : Set α}

theorem set_integral_nonneg_of_ae_restrict (hf : 0 ≤ᵐ[μ.restrict s] f) : 0 ≤ ∫ a in s, f a ∂μ :=
  integral_nonneg_of_ae hf
#align measure_theory.set_integral_nonneg_of_ae_restrict MeasureTheory.set_integral_nonneg_of_ae_restrict

theorem set_integral_nonneg_of_ae (hf : 0 ≤ᵐ[μ] f) : 0 ≤ ∫ a in s, f a ∂μ :=
  set_integral_nonneg_of_ae_restrict (ae_restrict_of_ae hf)
#align measure_theory.set_integral_nonneg_of_ae MeasureTheory.set_integral_nonneg_of_ae

theorem set_integral_nonneg (hs : MeasurableSet s) (hf : ∀ a, a ∈ s → 0 ≤ f a) :
    0 ≤ ∫ a in s, f a ∂μ :=
  set_integral_nonneg_of_ae_restrict ((ae_restrict_iff' hs).mpr (ae_of_all μ hf))
#align measure_theory.set_integral_nonneg MeasureTheory.set_integral_nonneg

theorem set_integral_nonneg_ae (hs : MeasurableSet s) (hf : ∀ᵐ a ∂μ, a ∈ s → 0 ≤ f a) :
    0 ≤ ∫ a in s, f a ∂μ :=
  set_integral_nonneg_of_ae_restrict <| by rwa [eventually_le, ae_restrict_iff' hs]
#align measure_theory.set_integral_nonneg_ae MeasureTheory.set_integral_nonneg_ae

theorem set_integral_le_nonneg {s : Set α} (hs : MeasurableSet s) (hf : StronglyMeasurable f)
    (hfi : Integrable f μ) : (∫ x in s, f x ∂μ) ≤ ∫ x in { y | 0 ≤ f y }, f x ∂μ :=
  by
  rw [← integral_indicator hs, ←
    integral_indicator (strongly_measurable_const.measurable_set_le hf)]
  exact
    integral_mono (hfi.indicator hs)
      (hfi.indicator (strongly_measurable_const.measurable_set_le hf))
      (indicator_le_indicator_nonneg s f)
#align measure_theory.set_integral_le_nonneg MeasureTheory.set_integral_le_nonneg

theorem set_integral_nonpos_of_ae_restrict (hf : f ≤ᵐ[μ.restrict s] 0) : (∫ a in s, f a ∂μ) ≤ 0 :=
  integral_nonpos_of_ae hf
#align measure_theory.set_integral_nonpos_of_ae_restrict MeasureTheory.set_integral_nonpos_of_ae_restrict

theorem set_integral_nonpos_of_ae (hf : f ≤ᵐ[μ] 0) : (∫ a in s, f a ∂μ) ≤ 0 :=
  set_integral_nonpos_of_ae_restrict (ae_restrict_of_ae hf)
#align measure_theory.set_integral_nonpos_of_ae MeasureTheory.set_integral_nonpos_of_ae

theorem set_integral_nonpos (hs : MeasurableSet s) (hf : ∀ a, a ∈ s → f a ≤ 0) :
    (∫ a in s, f a ∂μ) ≤ 0 :=
  set_integral_nonpos_of_ae_restrict ((ae_restrict_iff' hs).mpr (ae_of_all μ hf))
#align measure_theory.set_integral_nonpos MeasureTheory.set_integral_nonpos

theorem set_integral_nonpos_ae (hs : MeasurableSet s) (hf : ∀ᵐ a ∂μ, a ∈ s → f a ≤ 0) :
    (∫ a in s, f a ∂μ) ≤ 0 :=
  set_integral_nonpos_of_ae_restrict <| by rwa [eventually_le, ae_restrict_iff' hs]
#align measure_theory.set_integral_nonpos_ae MeasureTheory.set_integral_nonpos_ae

theorem set_integral_nonpos_le {s : Set α} (hs : MeasurableSet s) (hf : StronglyMeasurable f)
    (hfi : Integrable f μ) : (∫ x in { y | f y ≤ 0 }, f x ∂μ) ≤ ∫ x in s, f x ∂μ :=
  by
  rw [← integral_indicator hs, ←
    integral_indicator (hf.measurable_set_le strongly_measurable_const)]
  exact
    integral_mono (hfi.indicator (hf.measurable_set_le strongly_measurable_const))
      (hfi.indicator hs) (indicator_nonpos_le_indicator s f)
#align measure_theory.set_integral_nonpos_le MeasureTheory.set_integral_nonpos_le

end Nonneg

section IntegrableUnion

variable {μ : Measure α} [NormedAddCommGroup E] [Countable β]

theorem integrableOnUnionOfSummableIntegralNorm {f : α → E} {s : β → Set α}
    (hs : ∀ b : β, MeasurableSet (s b)) (hi : ∀ b : β, IntegrableOn f (s b) μ)
    (h : Summable fun b : β => ∫ a : α in s b, ‖f a‖ ∂μ) : IntegrableOn f (unionᵢ s) μ :=
  by
  refine' ⟨ae_strongly_measurable.Union fun i => (hi i).1, (lintegral_Union_le _ _).trans_lt _⟩
  have B := fun b : β => lintegral_coe_eq_integral (fun a : α => ‖f a‖₊) (hi b).norm
  rw [tsum_congr B]
  have S' :
    Summable fun b : β =>
      (⟨∫ a : α in s b, ‖f a‖₊ ∂μ, set_integral_nonneg (hs b) fun a ha => NNReal.coe_nonneg _⟩ :
        NNReal) :=
    by
    rw [← NNReal.summable_coe]
    exact h
  have S'' := ENNReal.tsum_coe_eq S'.has_sum
  simp_rw [ENNReal.coe_nnreal_eq, NNReal.coe_mk, coe_nnnorm] at S''
  convert ENNReal.ofReal_lt_top
#align measure_theory.integrable_on_Union_of_summable_integral_norm MeasureTheory.integrableOnUnionOfSummableIntegralNorm

variable [TopologicalSpace α] [BorelSpace α] [MetrizableSpace α] [IsLocallyFiniteMeasure μ]

/-- If `s` is a countable family of compact sets, `f` is a continuous function, and the sequence
`‖f.restrict (s i)‖ * μ (s i)` is summable, then `f` is integrable on the union of the `s i`. -/
theorem integrableOnUnionOfSummableNormRestrict {f : C(α, E)} {s : β → Compacts α}
    (hf : Summable fun i : β => ‖f.restrict (s i)‖ * ENNReal.toReal (μ <| s i)) :
    IntegrableOn f (⋃ i : β, s i) μ :=
  by
  refine'
    integrable_on_Union_of_summable_integral_norm (fun i => (s i).IsCompact.IsClosed.MeasurableSet)
      (fun i => (map_continuous f).ContinuousOn.integrableOnCompact (s i).IsCompact)
      (summable_of_nonneg_of_le (fun ι => integral_nonneg fun x => norm_nonneg _) (fun i => _) hf)
  rw [← (Real.norm_of_nonneg (integral_nonneg fun a => norm_nonneg _) : ‖_‖ = ∫ x in s i, ‖f x‖ ∂μ)]
  exact
    norm_set_integral_le_of_norm_le_const' (s i).IsCompact.measure_lt_top
      (s i).IsCompact.IsClosed.MeasurableSet fun x hx =>
      (norm_norm (f x)).symm ▸ (f.restrict ↑(s i)).norm_coe_le_norm ⟨x, hx⟩
#align measure_theory.integrable_on_Union_of_summable_norm_restrict MeasureTheory.integrableOnUnionOfSummableNormRestrict

/-- If `s` is a countable family of compact sets covering `α`, `f` is a continuous function, and
the sequence `‖f.restrict (s i)‖ * μ (s i)` is summable, then `f` is integrable. -/
theorem integrableOfSummableNormRestrict {f : C(α, E)} {s : β → Compacts α}
    (hf : Summable fun i : β => ‖f.restrict (s i)‖ * ENNReal.toReal (μ <| s i))
    (hs : (⋃ i : β, ↑(s i)) = (univ : Set α)) : Integrable f μ := by
  simpa only [hs, integrable_on_univ] using integrable_on_Union_of_summable_norm_restrict hf
#align measure_theory.integrable_of_summable_norm_restrict MeasureTheory.integrableOfSummableNormRestrict

end IntegrableUnion

section TendstoMono

variable {μ : Measure α} [NormedAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] {s : ℕ → Set α}
  {f : α → E}

/- ./././Mathport/Syntax/Translate/Tactic/Builtin.lean:72:38: in filter_upwards #[[], ["with", ident a], ["using", expr le_trans (h_anti.tendsto_indicator _ _ _) (pure_le_nhds _)]]: ./././Mathport/Syntax/Translate/Basic.lean:349:22: unsupported: parse error @ arg 0: next failed, no more args -/
theorem Antitone.tendsto_set_integral (hsm : ∀ i, MeasurableSet (s i)) (h_anti : Antitone s)
    (hfi : IntegrableOn f (s 0) μ) :
    Tendsto (fun i => ∫ a in s i, f a ∂μ) atTop (𝓝 (∫ a in ⋂ n, s n, f a ∂μ)) :=
  by
  let bound : α → ℝ := indicator (s 0) fun a => ‖f a‖
  have h_int_eq : (fun i => ∫ a in s i, f a ∂μ) = fun i => ∫ a, (s i).indicator f a ∂μ :=
    funext fun i => (integral_indicator (hsm i)).symm
  rw [h_int_eq]
  rw [← integral_indicator (MeasurableSet.interᵢ hsm)]
  refine' tendsto_integral_of_dominated_convergence bound _ _ _ _
  · intro n
    rw [aeStronglyMeasurable_indicator_iff (hsm n)]
    exact (integrable_on.mono_set hfi (h_anti (zero_le n))).1
  · rw [integrable_indicator_iff (hsm 0)]
    exact hfi.norm
  · simp_rw [norm_indicator_eq_indicator_norm]
    refine' fun n => eventually_of_forall fun x => _
    exact indicator_le_indicator_of_subset (h_anti (zero_le n)) (fun a => norm_nonneg _) _
  ·
    trace
      "./././Mathport/Syntax/Translate/Tactic/Builtin.lean:72:38: in filter_upwards #[[], [\"with\", ident a], [\"using\", expr le_trans (h_anti.tendsto_indicator _ _ _) (pure_le_nhds _)]]: ./././Mathport/Syntax/Translate/Basic.lean:349:22: unsupported: parse error @ arg 0: next failed, no more args"
#align antitone.tendsto_set_integral Antitone.tendsto_set_integral

end TendstoMono

/-! ### Continuity of the set integral

We prove that for any set `s`, the function `λ f : α →₁[μ] E, ∫ x in s, f x ∂μ` is continuous. -/

section ContinuousSetIntegral

variable [NormedAddCommGroup E] {𝕜 : Type _} [NormedField 𝕜] [NormedAddCommGroup F]
  [NormedSpace 𝕜 F] {p : ℝ≥0∞} {μ : Measure α}

/-- For `f : Lp E p μ`, we can define an element of `Lp E p (μ.restrict s)` by
`(Lp.mem_ℒp f).restrict s).to_Lp f`. This map is additive. -/
theorem lp_toLp_restrict_add (f g : lp E p μ) (s : Set α) :
    ((lp.memℒp (f + g)).restrict s).toLp ⇑(f + g) =
      ((lp.memℒp f).restrict s).toLp f + ((lp.memℒp g).restrict s).toLp g :=
  by
  ext1
  refine' (ae_restrict_of_ae (Lp.coe_fn_add f g)).mp _
  refine'
    (Lp.coe_fn_add (mem_ℒp.to_Lp f ((Lp.mem_ℒp f).restrict s))
          (mem_ℒp.to_Lp g ((Lp.mem_ℒp g).restrict s))).mp
      _
  refine' (mem_ℒp.coe_fn_to_Lp ((Lp.mem_ℒp f).restrict s)).mp _
  refine' (mem_ℒp.coe_fn_to_Lp ((Lp.mem_ℒp g).restrict s)).mp _
  refine' (mem_ℒp.coe_fn_to_Lp ((Lp.mem_ℒp (f + g)).restrict s)).mono fun x hx1 hx2 hx3 hx4 hx5 => _
  rw [hx4, hx1, Pi.add_apply, hx2, hx3, hx5, Pi.add_apply]
#align measure_theory.Lp_to_Lp_restrict_add MeasureTheory.lp_toLp_restrict_add

/-- For `f : Lp E p μ`, we can define an element of `Lp E p (μ.restrict s)` by
`(Lp.mem_ℒp f).restrict s).to_Lp f`. This map commutes with scalar multiplication. -/
theorem lp_toLp_restrict_smul (c : 𝕜) (f : lp F p μ) (s : Set α) :
    ((lp.memℒp (c • f)).restrict s).toLp ⇑(c • f) = c • ((lp.memℒp f).restrict s).toLp f :=
  by
  ext1
  refine' (ae_restrict_of_ae (Lp.coe_fn_smul c f)).mp _
  refine' (mem_ℒp.coe_fn_to_Lp ((Lp.mem_ℒp f).restrict s)).mp _
  refine' (mem_ℒp.coe_fn_to_Lp ((Lp.mem_ℒp (c • f)).restrict s)).mp _
  refine'
    (Lp.coe_fn_smul c (mem_ℒp.to_Lp f ((Lp.mem_ℒp f).restrict s))).mono fun x hx1 hx2 hx3 hx4 => _
  rw [hx2, hx1, Pi.smul_apply, hx3, hx4, Pi.smul_apply]
#align measure_theory.Lp_to_Lp_restrict_smul MeasureTheory.lp_toLp_restrict_smul

/-- For `f : Lp E p μ`, we can define an element of `Lp E p (μ.restrict s)` by
`(Lp.mem_ℒp f).restrict s).to_Lp f`. This map is non-expansive. -/
theorem norm_lp_toLp_restrict_le (s : Set α) (f : lp E p μ) :
    ‖((lp.memℒp f).restrict s).toLp f‖ ≤ ‖f‖ :=
  by
  rw [Lp.norm_def, Lp.norm_def, ENNReal.toReal_le_toReal (Lp.snorm_ne_top _) (Lp.snorm_ne_top _)]
  refine' (le_of_eq _).trans (snorm_mono_measure _ measure.restrict_le_self)
  · exact s
  exact snorm_congr_ae (mem_ℒp.coe_fn_to_Lp _)
#align measure_theory.norm_Lp_to_Lp_restrict_le MeasureTheory.norm_lp_toLp_restrict_le

variable (α F 𝕜)

/-- Continuous linear map sending a function of `Lp F p μ` to the same function in
`Lp F p (μ.restrict s)`. -/
def lpToLpRestrictClm (μ : Measure α) (p : ℝ≥0∞) [hp : Fact (1 ≤ p)] (s : Set α) :
    lp F p μ →L[𝕜] lp F p (μ.restrict s) :=
  @LinearMap.mkContinuous 𝕜 𝕜 (lp F p μ) (lp F p (μ.restrict s)) _ _ _ _ _ _ (RingHom.id 𝕜)
    ⟨fun f => Memℒp.toLp f ((lp.memℒp f).restrict s), fun f g => lp_toLp_restrict_add f g s,
      fun c f => lp_toLp_restrict_smul c f s⟩
    1
    (by
      intro f
      rw [one_mul]
      exact norm_Lp_to_Lp_restrict_le s f)
#align measure_theory.Lp_to_Lp_restrict_clm MeasureTheory.lpToLpRestrictClm

variable {α F 𝕜}

variable (𝕜)

theorem lpToLpRestrictClm_coeFn [hp : Fact (1 ≤ p)] (s : Set α) (f : lp F p μ) :
    lpToLpRestrictClm α F 𝕜 μ p s f =ᵐ[μ.restrict s] f :=
  Memℒp.coeFn_toLp ((lp.memℒp f).restrict s)
#align measure_theory.Lp_to_Lp_restrict_clm_coe_fn MeasureTheory.lpToLpRestrictClm_coeFn

variable {𝕜}

@[continuity]
theorem continuous_set_integral [NormedSpace ℝ E] [CompleteSpace E] (s : Set α) :
    Continuous fun f : α →₁[μ] E => ∫ x in s, f x ∂μ :=
  by
  haveI : Fact ((1 : ℝ≥0∞) ≤ 1) := ⟨le_rfl⟩
  have h_comp :
    (fun f : α →₁[μ] E => ∫ x in s, f x ∂μ) =
      integral (μ.restrict s) ∘ fun f => Lp_to_Lp_restrict_clm α E ℝ μ 1 s f :=
    by
    ext1 f
    rw [Function.comp_apply, integral_congr_ae (Lp_to_Lp_restrict_clm_coe_fn ℝ s f)]
  rw [h_comp]
  exact continuous_integral.comp (Lp_to_Lp_restrict_clm α E ℝ μ 1 s).Continuous
#align measure_theory.continuous_set_integral MeasureTheory.continuous_set_integral

end ContinuousSetIntegral

end MeasureTheory

open MeasureTheory Asymptotics Metric

variable {ι : Type _} [NormedAddCommGroup E]

/-- Fundamental theorem of calculus for set integrals: if `μ` is a measure that is finite at a
filter `l` and `f` is a measurable function that has a finite limit `b` at `l ⊓ μ.ae`, then `∫ x in
s i, f x ∂μ = μ (s i) • b + o(μ (s i))` at a filter `li` provided that `s i` tends to `l.small_sets`
along `li`. Since `μ (s i)` is an `ℝ≥0∞` number, we use `(μ (s i)).to_real` in the actual statement.

Often there is a good formula for `(μ (s i)).to_real`, so the formalization can take an optional
argument `m` with this formula and a proof `of `(λ i, (μ (s i)).to_real) =ᶠ[li] m`. Without these
arguments, `m i = (μ (s i)).to_real` is used in the output. -/
theorem Filter.Tendsto.integral_sub_linear_isOCat_ae [NormedSpace ℝ E] [CompleteSpace E]
    {μ : Measure α} {l : Filter α} [l.IsMeasurablyGenerated] {f : α → E} {b : E}
    (h : Tendsto f (l ⊓ μ.ae) (𝓝 b)) (hfm : StronglyMeasurableAtFilter f l μ)
    (hμ : μ.FiniteAtFilter l) {s : ι → Set α} {li : Filter ι} (hs : Tendsto s li l.smallSets)
    (m : ι → ℝ := fun i => (μ (s i)).toReal)
    (hsμ : (fun i => (μ (s i)).toReal) =ᶠ[li] m := by rfl) :
    (fun i => (∫ x in s i, f x ∂μ) - m i • b) =o[li] m :=
  by
  suffices : (fun s => (∫ x in s, f x ∂μ) - (μ s).toReal • b) =o[l.small_sets] fun s => (μ s).toReal
  exact (this.comp_tendsto hs).congr' (hsμ.mono fun a ha => ha ▸ rfl) hsμ
  refine' is_o_iff.2 fun ε ε₀ => _
  have : ∀ᶠ s in l.small_sets, ∀ᶠ x in μ.ae, x ∈ s → f x ∈ closed_ball b ε :=
    eventually_small_sets_eventually.2 (h.eventually <| closed_ball_mem_nhds _ ε₀)
  filter_upwards [hμ.eventually, (hμ.integrable_at_filter_of_tendsto_ae hfm h).Eventually,
    hfm.eventually, this]
  simp only [mem_closed_ball, dist_eq_norm]
  intro s hμs h_integrable hfm h_norm
  rw [← set_integral_const, ← integral_sub h_integrable (integrable_on_const.2 <| Or.inr hμs),
    Real.norm_eq_abs, abs_of_nonneg ENNReal.toReal_nonneg]
  exact norm_set_integral_le_of_norm_le_const_ae' hμs h_norm (hfm.sub ae_strongly_measurable_const)
#align filter.tendsto.integral_sub_linear_is_o_ae Filter.Tendsto.integral_sub_linear_isOCat_ae

/-- Fundamental theorem of calculus for set integrals, `nhds_within` version: if `μ` is a locally
finite measure and `f` is an almost everywhere measurable function that is continuous at a point `a`
within a measurable set `t`, then `∫ x in s i, f x ∂μ = μ (s i) • f a + o(μ (s i))` at a filter `li`
provided that `s i` tends to `(𝓝[t] a).small_sets` along `li`.  Since `μ (s i)` is an `ℝ≥0∞`
number, we use `(μ (s i)).to_real` in the actual statement.

Often there is a good formula for `(μ (s i)).to_real`, so the formalization can take an optional
argument `m` with this formula and a proof `of `(λ i, (μ (s i)).to_real) =ᶠ[li] m`. Without these
arguments, `m i = (μ (s i)).to_real` is used in the output. -/
theorem ContinuousWithinAt.integral_sub_linear_isOCat_ae [TopologicalSpace α]
    [OpensMeasurableSpace α] [NormedSpace ℝ E] [CompleteSpace E] {μ : Measure α}
    [IsLocallyFiniteMeasure μ] {a : α} {t : Set α} {f : α → E} (ha : ContinuousWithinAt f t a)
    (ht : MeasurableSet t) (hfm : StronglyMeasurableAtFilter f (𝓝[t] a) μ) {s : ι → Set α}
    {li : Filter ι} (hs : Tendsto s li (𝓝[t] a).smallSets) (m : ι → ℝ := fun i => (μ (s i)).toReal)
    (hsμ : (fun i => (μ (s i)).toReal) =ᶠ[li] m := by rfl) :
    (fun i => (∫ x in s i, f x ∂μ) - m i • f a) =o[li] m :=
  haveI : (𝓝[t] a).IsMeasurablyGenerated := ht.nhds_within_is_measurably_generated _
  (ha.mono_left inf_le_left).integral_sub_linear_isOCat_ae hfm (μ.finite_at_nhds_within a t) hs m
    hsμ
#align continuous_within_at.integral_sub_linear_is_o_ae ContinuousWithinAt.integral_sub_linear_isOCat_ae

/-- Fundamental theorem of calculus for set integrals, `nhds` version: if `μ` is a locally finite
measure and `f` is an almost everywhere measurable function that is continuous at a point `a`, then
`∫ x in s i, f x ∂μ = μ (s i) • f a + o(μ (s i))` at `li` provided that `s` tends to
`(𝓝 a).small_sets` along `li.  Since `μ (s i)` is an `ℝ≥0∞` number, we use `(μ (s i)).to_real` in
the actual statement.

Often there is a good formula for `(μ (s i)).to_real`, so the formalization can take an optional
argument `m` with this formula and a proof `of `(λ i, (μ (s i)).to_real) =ᶠ[li] m`. Without these
arguments, `m i = (μ (s i)).to_real` is used in the output. -/
theorem ContinuousAt.integral_sub_linear_isOCat_ae [TopologicalSpace α] [OpensMeasurableSpace α]
    [NormedSpace ℝ E] [CompleteSpace E] {μ : Measure α} [IsLocallyFiniteMeasure μ] {a : α}
    {f : α → E} (ha : ContinuousAt f a) (hfm : StronglyMeasurableAtFilter f (𝓝 a) μ) {s : ι → Set α}
    {li : Filter ι} (hs : Tendsto s li (𝓝 a).smallSets) (m : ι → ℝ := fun i => (μ (s i)).toReal)
    (hsμ : (fun i => (μ (s i)).toReal) =ᶠ[li] m := by rfl) :
    (fun i => (∫ x in s i, f x ∂μ) - m i • f a) =o[li] m :=
  (ha.mono_left inf_le_left).integral_sub_linear_isOCat_ae hfm (μ.finiteAtNhds a) hs m hsμ
#align continuous_at.integral_sub_linear_is_o_ae ContinuousAt.integral_sub_linear_isOCat_ae

/-- Fundamental theorem of calculus for set integrals, `nhds_within` version: if `μ` is a locally
finite measure, `f` is continuous on a measurable set `t`, and `a ∈ t`, then `∫ x in (s i), f x ∂μ =
μ (s i) • f a + o(μ (s i))` at `li` provided that `s i` tends to `(𝓝[t] a).small_sets` along `li`.
Since `μ (s i)` is an `ℝ≥0∞` number, we use `(μ (s i)).to_real` in the actual statement.

Often there is a good formula for `(μ (s i)).to_real`, so the formalization can take an optional
argument `m` with this formula and a proof `of `(λ i, (μ (s i)).to_real) =ᶠ[li] m`. Without these
arguments, `m i = (μ (s i)).to_real` is used in the output. -/
theorem ContinuousOn.integral_sub_linear_isOCat_ae [TopologicalSpace α] [OpensMeasurableSpace α]
    [NormedSpace ℝ E] [CompleteSpace E] [SecondCountableTopologyEither α E] {μ : Measure α}
    [IsLocallyFiniteMeasure μ] {a : α} {t : Set α} {f : α → E} (hft : ContinuousOn f t) (ha : a ∈ t)
    (ht : MeasurableSet t) {s : ι → Set α} {li : Filter ι} (hs : Tendsto s li (𝓝[t] a).smallSets)
    (m : ι → ℝ := fun i => (μ (s i)).toReal)
    (hsμ : (fun i => (μ (s i)).toReal) =ᶠ[li] m := by rfl) :
    (fun i => (∫ x in s i, f x ∂μ) - m i • f a) =o[li] m :=
  (hft a ha).integral_sub_linear_isOCat_ae ht ⟨t, self_mem_nhdsWithin, hft.AeStronglyMeasurable ht⟩
    hs m hsμ
#align continuous_on.integral_sub_linear_is_o_ae ContinuousOn.integral_sub_linear_isOCat_ae

section

/-! ### Continuous linear maps composed with integration

The goal of this section is to prove that integration commutes with continuous linear maps.
This holds for simple functions. The general result follows from the continuity of all involved
operations on the space `L¹`. Note that composition by a continuous linear map on `L¹` is not just
the composition, as we are dealing with classes of functions, but it has already been defined
as `continuous_linear_map.comp_Lp`. We take advantage of this construction here.
-/

open ComplexConjugate

variable {μ : Measure α} {𝕜 : Type _} [IsROrC 𝕜] [NormedSpace 𝕜 E] [NormedAddCommGroup F]
  [NormedSpace 𝕜 F] {p : ENNReal}

namespace ContinuousLinearMap

variable [CompleteSpace F] [NormedSpace ℝ F]

theorem integral_compLp (L : E →L[𝕜] F) (φ : lp E p μ) :
    (∫ a, (L.compLp φ) a ∂μ) = ∫ a, L (φ a) ∂μ :=
  integral_congr_ae <| coeFn_compLp _ _
#align continuous_linear_map.integral_comp_Lp ContinuousLinearMap.integral_compLp

theorem set_integral_compLp (L : E →L[𝕜] F) (φ : lp E p μ) {s : Set α} (hs : MeasurableSet s) :
    (∫ a in s, (L.compLp φ) a ∂μ) = ∫ a in s, L (φ a) ∂μ :=
  set_integral_congr_ae hs ((L.coeFn_compLp φ).mono fun x hx hx2 => hx)
#align continuous_linear_map.set_integral_comp_Lp ContinuousLinearMap.set_integral_compLp

theorem continuous_integral_comp_L1 (L : E →L[𝕜] F) :
    Continuous fun φ : α →₁[μ] E => ∫ a : α, L (φ a) ∂μ :=
  by
  rw [← funext L.integral_comp_Lp]
  exact continuous_integral.comp (L.comp_LpL 1 μ).Continuous
#align continuous_linear_map.continuous_integral_comp_L1 ContinuousLinearMap.continuous_integral_comp_L1

variable [CompleteSpace E] [NormedSpace ℝ E]

theorem integral_comp_comm (L : E →L[𝕜] F) {φ : α → E} (φ_int : Integrable φ μ) :
    (∫ a, L (φ a) ∂μ) = L (∫ a, φ a ∂μ) :=
  by
  apply integrable.induction fun φ => (∫ a, L (φ a) ∂μ) = L (∫ a, φ a ∂μ)
  · intro e s s_meas s_finite
    rw [integral_indicator_const e s_meas, ← @smul_one_smul E ℝ 𝕜 _ _ _ _ _ (μ s).toReal e,
      ContinuousLinearMap.map_smul, @smul_one_smul F ℝ 𝕜 _ _ _ _ _ (μ s).toReal (L e), ←
      integral_indicator_const (L e) s_meas]
    congr 1 with a
    rw [Set.indicator_comp_of_zero L.map_zero]
  · intro f g H f_int g_int hf hg
    simp [L.map_add, integral_add f_int g_int,
      integral_add (L.integrable_comp f_int) (L.integrable_comp g_int), hf, hg]
  · exact isClosed_eq L.continuous_integral_comp_L1 (L.continuous.comp continuous_integral)
  · intro f g hfg f_int hf
    convert hf using 1 <;> clear hf
    · exact integral_congr_ae (hfg.fun_comp L).symm
    · rw [integral_congr_ae hfg.symm]
  all_goals assumption
#align continuous_linear_map.integral_comp_comm ContinuousLinearMap.integral_comp_comm

theorem integral_apply {H : Type _} [NormedAddCommGroup H] [NormedSpace 𝕜 H] {φ : α → H →L[𝕜] E}
    (φ_int : Integrable φ μ) (v : H) : (∫ a, φ a ∂μ) v = ∫ a, φ a v ∂μ :=
  ((ContinuousLinearMap.apply 𝕜 E v).integral_comp_comm φ_int).symm
#align continuous_linear_map.integral_apply ContinuousLinearMap.integral_apply

theorem integral_comp_comm' (L : E →L[𝕜] F) {K} (hL : AntilipschitzWith K L) (φ : α → E) :
    (∫ a, L (φ a) ∂μ) = L (∫ a, φ a ∂μ) :=
  by
  by_cases h : integrable φ μ
  · exact integral_comp_comm L h
  have : ¬integrable (L ∘ φ) μ := by
    rwa [lipschitz_with.integrable_comp_iff_of_antilipschitz L.lipschitz hL L.map_zero]
  simp [integral_undef, h, this]
#align continuous_linear_map.integral_comp_comm' ContinuousLinearMap.integral_comp_comm'

theorem integral_comp_L1_comm (L : E →L[𝕜] F) (φ : α →₁[μ] E) :
    (∫ a, L (φ a) ∂μ) = L (∫ a, φ a ∂μ) :=
  L.integral_comp_comm (L1.integrableCoeFn φ)
#align continuous_linear_map.integral_comp_L1_comm ContinuousLinearMap.integral_comp_L1_comm

end ContinuousLinearMap

namespace LinearIsometry

variable [CompleteSpace F] [NormedSpace ℝ F] [CompleteSpace E] [NormedSpace ℝ E]

theorem integral_comp_comm (L : E →ₗᵢ[𝕜] F) (φ : α → E) : (∫ a, L (φ a) ∂μ) = L (∫ a, φ a ∂μ) :=
  L.toContinuousLinearMap.integral_comp_comm' L.antilipschitz _
#align linear_isometry.integral_comp_comm LinearIsometry.integral_comp_comm

end LinearIsometry

namespace ContinuousLinearEquiv

variable [CompleteSpace F] [NormedSpace ℝ F] [CompleteSpace E] [NormedSpace ℝ E]

theorem integral_comp_comm (L : E ≃L[𝕜] F) (φ : α → E) : (∫ a, L (φ a) ∂μ) = L (∫ a, φ a ∂μ) :=
  L.toContinuousLinearMap.integral_comp_comm' L.antilipschitz _
#align continuous_linear_equiv.integral_comp_comm ContinuousLinearEquiv.integral_comp_comm

end ContinuousLinearEquiv

variable [CompleteSpace E] [NormedSpace ℝ E] [CompleteSpace F] [NormedSpace ℝ F]

@[norm_cast]
theorem integral_of_real {f : α → ℝ} : (∫ a, (f a : 𝕜) ∂μ) = ↑(∫ a, f a ∂μ) :=
  (@IsROrC.ofRealLi 𝕜 _).integral_comp_comm f
#align integral_of_real integral_of_real

theorem integral_re {f : α → 𝕜} (hf : Integrable f μ) :
    (∫ a, IsROrC.re (f a) ∂μ) = IsROrC.re (∫ a, f a ∂μ) :=
  (@IsROrC.reClm 𝕜 _).integral_comp_comm hf
#align integral_re integral_re

theorem integral_im {f : α → 𝕜} (hf : Integrable f μ) :
    (∫ a, IsROrC.im (f a) ∂μ) = IsROrC.im (∫ a, f a ∂μ) :=
  (@IsROrC.imClm 𝕜 _).integral_comp_comm hf
#align integral_im integral_im

theorem integral_conj {f : α → 𝕜} : (∫ a, conj (f a) ∂μ) = conj (∫ a, f a ∂μ) :=
  (@IsROrC.conjLie 𝕜 _).toLinearIsometry.integral_comp_comm f
#align integral_conj integral_conj

theorem integral_coe_re_add_coe_im {f : α → 𝕜} (hf : Integrable f μ) :
    (∫ x, (IsROrC.re (f x) : 𝕜) ∂μ) + (∫ x, IsROrC.im (f x) ∂μ) * IsROrC.i = ∫ x, f x ∂μ :=
  by
  rw [mul_comm, ← smul_eq_mul, ← integral_smul, ← integral_add]
  · congr
    ext1 x
    rw [smul_eq_mul, mul_comm, IsROrC.re_add_im]
  · exact hf.re.of_real
  · exact hf.im.of_real.smul IsROrC.i
#align integral_coe_re_add_coe_im integral_coe_re_add_coe_im

theorem integral_re_add_im {f : α → 𝕜} (hf : Integrable f μ) :
    ((∫ x, IsROrC.re (f x) ∂μ : ℝ) : 𝕜) + (∫ x, IsROrC.im (f x) ∂μ : ℝ) * IsROrC.i = ∫ x, f x ∂μ :=
  by rw [← integral_of_real, ← integral_of_real, integral_coe_re_add_coe_im hf]
#align integral_re_add_im integral_re_add_im

theorem set_integral_re_add_im {f : α → 𝕜} {i : Set α} (hf : IntegrableOn f i μ) :
    ((∫ x in i, IsROrC.re (f x) ∂μ : ℝ) : 𝕜) + (∫ x in i, IsROrC.im (f x) ∂μ : ℝ) * IsROrC.i =
      ∫ x in i, f x ∂μ :=
  integral_re_add_im hf
#align set_integral_re_add_im set_integral_re_add_im

theorem fst_integral {f : α → E × F} (hf : Integrable f μ) : (∫ x, f x ∂μ).1 = ∫ x, (f x).1 ∂μ :=
  ((ContinuousLinearMap.fst ℝ E F).integral_comp_comm hf).symm
#align fst_integral fst_integral

theorem snd_integral {f : α → E × F} (hf : Integrable f μ) : (∫ x, f x ∂μ).2 = ∫ x, (f x).2 ∂μ :=
  ((ContinuousLinearMap.snd ℝ E F).integral_comp_comm hf).symm
#align snd_integral snd_integral

theorem integral_pair {f : α → E} {g : α → F} (hf : Integrable f μ) (hg : Integrable g μ) :
    (∫ x, (f x, g x) ∂μ) = (∫ x, f x ∂μ, ∫ x, g x ∂μ) :=
  have := hf.prod_mk hg
  Prod.ext (fst_integral this) (snd_integral this)
#align integral_pair integral_pair

theorem integral_smul_const {𝕜 : Type _} [IsROrC 𝕜] [NormedSpace 𝕜 E] (f : α → 𝕜) (c : E) :
    (∫ x, f x • c ∂μ) = (∫ x, f x ∂μ) • c :=
  by
  by_cases hf : integrable f μ
  · exact ((1 : 𝕜 →L[𝕜] 𝕜).smul_right c).integral_comp_comm hf
  · by_cases hc : c = 0
    · simp only [hc, integral_zero, smul_zero]
    rw [integral_undef hf, integral_undef, zero_smul]
    simp_rw [integrable_smul_const hc, hf, not_false_iff]
#align integral_smul_const integral_smul_const

section Inner

variable {E' : Type _}

variable [NormedAddCommGroup E'] [InnerProductSpace 𝕜 E']

variable [CompleteSpace E'] [NormedSpace ℝ E']

-- mathport name: «expr⟪ , ⟫»
local notation "⟪" x ", " y "⟫" => @inner 𝕜 E' _ x y

theorem integral_inner {f : α → E'} (hf : Integrable f μ) (c : E') :
    (∫ x, ⟪c, f x⟫ ∂μ) = ⟪c, ∫ x, f x ∂μ⟫ :=
  ((innerSL 𝕜 c).restrictScalars ℝ).integral_comp_comm hf
#align integral_inner integral_inner

variable (𝕜)

-- mathport name: inner_with_explicit
-- variable binder update doesn't work for lemmas which refer to `𝕜` only via the notation
local notation "⟪" x ", " y "⟫" => @inner 𝕜 E' _ x y

theorem integral_eq_zero_of_forall_integral_inner_eq_zero (f : α → E') (hf : Integrable f μ)
    (hf_int : ∀ c : E', (∫ x, ⟪c, f x⟫ ∂μ) = 0) : (∫ x, f x ∂μ) = 0 :=
  by
  specialize hf_int (∫ x, f x ∂μ)
  rwa [integral_inner hf, inner_self_eq_zero] at hf_int
#align integral_eq_zero_of_forall_integral_inner_eq_zero integral_eq_zero_of_forall_integral_inner_eq_zero

end Inner

theorem integral_withDensity_eq_integral_smul {f : α → ℝ≥0} (f_meas : Measurable f) (g : α → E) :
    (∫ a, g a ∂μ.withDensity fun x => f x) = ∫ a, f a • g a ∂μ :=
  by
  by_cases hg : integrable g (μ.with_density fun x => f x); swap
  · rw [integral_undef hg, integral_undef]
    rwa [← integrable_with_density_iff_integrable_smul f_meas] <;> infer_instance
  refine' integrable.induction _ _ _ _ _ hg
  · intro c s s_meas hs
    rw [integral_indicator s_meas]
    simp_rw [← indicator_smul_apply, integral_indicator s_meas]
    simp only [s_meas, integral_const, measure.restrict_apply', univ_inter, with_density_apply]
    rw [lintegral_coe_eq_integral, ENNReal.toReal_ofReal, ← integral_smul_const]
    · rfl
    · exact integral_nonneg fun x => NNReal.coe_nonneg _
    · refine' ⟨f_meas.coe_nnreal_real.AeMeasurable.AeStronglyMeasurable, _⟩
      rw [with_density_apply _ s_meas] at hs
      rw [has_finite_integral]
      convert hs
      ext1 x
      simp only [NNReal.nnnorm_eq]
  · intro u u' h_disj u_int u'_int h h'
    change
      (∫ a : α, u a + u' a ∂μ.with_density fun x : α => ↑(f x)) = ∫ a : α, f a • (u a + u' a) ∂μ
    simp_rw [smul_add]
    rw [integral_add u_int u'_int, h, h', integral_add]
    · exact (integrable_with_density_iff_integrable_smul f_meas).1 u_int
    · exact (integrable_with_density_iff_integrable_smul f_meas).1 u'_int
  · have C1 :
      Continuous fun u : Lp E 1 (μ.with_density fun x => f x) =>
        ∫ x, u x ∂μ.with_density fun x => f x :=
      continuous_integral
    have C2 : Continuous fun u : Lp E 1 (μ.with_density fun x => f x) => ∫ x, f x • u x ∂μ :=
      by
      have : Continuous ((fun u : Lp E 1 μ => ∫ x, u x ∂μ) ∘ with_density_smul_li μ f_meas) :=
        continuous_integral.comp (with_density_smul_li μ f_meas).Continuous
      convert this
      ext1 u
      simp only [Function.comp_apply, with_density_smul_li_apply]
      exact integral_congr_ae (mem_ℒ1_smul_of_L1_with_density f_meas u).coeFn_toLp.symm
    exact isClosed_eq C1 C2
  · intro u v huv u_int hu
    rw [← integral_congr_ae huv, hu]
    apply integral_congr_ae
    filter_upwards [(ae_with_density_iff f_meas.coe_nnreal_ennreal).1 huv]with x hx
    rcases eq_or_ne (f x) 0 with (h'x | h'x)
    · simp only [h'x, zero_smul]
    · rw [hx _]
      simpa only [Ne.def, ENNReal.coe_eq_zero] using h'x
#align integral_with_density_eq_integral_smul integral_withDensity_eq_integral_smul

theorem integral_withDensity_eq_integral_smul₀ {f : α → ℝ≥0} (hf : AeMeasurable f μ) (g : α → E) :
    (∫ a, g a ∂μ.withDensity fun x => f x) = ∫ a, f a • g a ∂μ :=
  by
  let f' := hf.mk _
  calc
    (∫ a, g a ∂μ.with_density fun x => f x) = ∫ a, g a ∂μ.with_density fun x => f' x :=
      by
      congr 1
      apply with_density_congr_ae
      filter_upwards [hf.ae_eq_mk]with x hx
      rw [hx]
    _ = ∫ a, f' a • g a ∂μ := (integral_withDensity_eq_integral_smul hf.measurable_mk _)
    _ = ∫ a, f a • g a ∂μ := by
      apply integral_congr_ae
      filter_upwards [hf.ae_eq_mk]with x hx
      rw [hx]

#align integral_with_density_eq_integral_smul₀ integral_withDensity_eq_integral_smul₀

theorem set_integral_withDensity_eq_set_integral_smul {f : α → ℝ≥0} (f_meas : Measurable f)
    (g : α → E) {s : Set α} (hs : MeasurableSet s) :
    (∫ a in s, g a ∂μ.withDensity fun x => f x) = ∫ a in s, f a • g a ∂μ := by
  rw [restrict_with_density hs, integral_withDensity_eq_integral_smul f_meas]
#align set_integral_with_density_eq_set_integral_smul set_integral_withDensity_eq_set_integral_smul

theorem set_integral_withDensity_eq_set_integral_smul₀ {f : α → ℝ≥0} {s : Set α}
    (hf : AeMeasurable f (μ.restrict s)) (g : α → E) (hs : MeasurableSet s) :
    (∫ a in s, g a ∂μ.withDensity fun x => f x) = ∫ a in s, f a • g a ∂μ := by
  rw [restrict_with_density hs, integral_withDensity_eq_integral_smul₀ hf]
#align set_integral_with_density_eq_set_integral_smul₀ set_integral_withDensity_eq_set_integral_smul₀

end

section thickenedIndicator

variable [PseudoEMetricSpace α]

theorem measure_le_lintegral_thickenedIndicatorAux (μ : Measure α) {E : Set α}
    (E_mble : MeasurableSet E) (δ : ℝ) : μ E ≤ ∫⁻ a, (thickenedIndicatorAux δ E a : ℝ≥0∞) ∂μ :=
  by
  convert_to lintegral μ (E.indicator fun _ => (1 : ℝ≥0∞)) ≤ lintegral μ (thickenedIndicatorAux δ E)
  · rw [lintegral_indicator _ E_mble]
    simp only [lintegral_one, measure.restrict_apply, MeasurableSet.univ, univ_inter]
  · apply lintegral_mono
    apply indicator_le_thickenedIndicatorAux
#align measure_le_lintegral_thickened_indicator_aux measure_le_lintegral_thickenedIndicatorAux

theorem measure_le_lintegral_thickenedIndicator (μ : Measure α) {E : Set α}
    (E_mble : MeasurableSet E) {δ : ℝ} (δ_pos : 0 < δ) :
    μ E ≤ ∫⁻ a, (thickenedIndicator δ_pos E a : ℝ≥0∞) ∂μ :=
  by
  convert measure_le_lintegral_thickenedIndicatorAux μ E_mble δ
  dsimp
  simp only [thickened_indicator_aux_lt_top.ne, ENNReal.coe_toNNReal, Ne.def, not_false_iff]
#align measure_le_lintegral_thickened_indicator measure_le_lintegral_thickenedIndicator

end thickenedIndicator

section BilinearMap

namespace MeasureTheory

variable {f : β → ℝ} {m m0 : MeasurableSpace β} {μ : Measure β}

theorem Integrable.simpleFuncMul (g : SimpleFunc β ℝ) (hf : Integrable f μ) :
    Integrable (g * f) μ :=
  by
  refine'
    simple_func.induction (fun c s hs => _)
      (fun g₁ g₂ h_disj h_int₁ h_int₂ =>
        (h_int₁.add h_int₂).congr (by rw [simple_func.coe_add, add_mul]))
      g
  simp only [simple_func.const_zero, simple_func.coe_piecewise, simple_func.coe_const,
    simple_func.coe_zero, Set.piecewise_eq_indicator]
  have : Set.indicator s (Function.const β c) * f = s.indicator (c • f) :=
    by
    ext1 x
    by_cases hx : x ∈ s
    · simp only [hx, Pi.mul_apply, Set.indicator_of_mem, Pi.smul_apply, Algebra.id.smul_eq_mul]
    · simp only [hx, Pi.mul_apply, Set.indicator_of_not_mem, not_false_iff, MulZeroClass.zero_mul]
  rw [this, integrable_indicator_iff hs]
  exact (hf.smul c).IntegrableOn
#align measure_theory.integrable.simple_func_mul MeasureTheory.Integrable.simpleFuncMul

theorem Integrable.simpleFuncMul' (hm : m ≤ m0) (g : @SimpleFunc β m ℝ) (hf : Integrable f μ) :
    Integrable (g * f) μ :=
  by
  rw [← simple_func.coe_to_larger_space_eq hm g]
  exact hf.simple_func_mul (g.to_larger_space hm)
#align measure_theory.integrable.simple_func_mul' MeasureTheory.Integrable.simpleFuncMul'

end MeasureTheory

end BilinearMap


/-
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

! This file was ported from Lean 3 source module measure_theory.covering.vitali_family
! leanprover-community/mathlib commit f2ce6086713c78a7f880485f7917ea547a215982
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.MeasureTheory.Measure.MeasureSpace

/-!
# Vitali families

On a metric space `X` with a measure `μ`, consider for each `x : X` a family of measurable sets with
nonempty interiors, called `sets_at x`. This family is a Vitali family if it satisfies the following
property: consider a (possibly non-measurable) set `s`, and for any `x` in `s` a
subfamily `f x` of `sets_at x` containing sets of arbitrarily small diameter. Then one can extract
a disjoint subfamily covering almost all `s`.

Vitali families are provided by covering theorems such as the Besicovitch covering theorem or the
Vitali covering theorem. They make it possible to formulate general versions of theorems on
differentiations of measure that apply in both contexts.

This file gives the basic definition of Vitali families. More interesting developments of this
notion are deferred to other files:
* constructions of specific Vitali families are provided by the Besicovitch covering theorem, in
`besicovitch.vitali_family`, and by the Vitali covering theorem, in `vitali.vitali_family`.
* The main theorem on differentiation of measures along a Vitali family is proved in
`vitali_family.ae_tendsto_rn_deriv`.

## Main definitions

* `vitali_family μ` is a structure made, for each `x : X`, of a family of sets around `x`, such that
one can extract an almost everywhere disjoint covering from any subfamily containing sets of
arbitrarily small diameters.

Let `v` be such a Vitali family.
* `v.fine_subfamily_on` describes the subfamilies of `v` from which one can extract almost
everywhere disjoint coverings. This property, called
`v.fine_subfamily_on.exists_disjoint_covering_ae`, is essentially a restatement of the definition
of a Vitali family. We also provide an API to use efficiently such a disjoint covering.
* `v.filter_at x` is a filter on sets of `X`, such that convergence with respect to this filter
means convergence when sets in the Vitali family shrink towards `x`.

## References

* [Herbert Federer, Geometric Measure Theory, Chapter 2.8][Federer1996] (Vitali families are called
Vitali relations there)
-/

open MeasureTheory Metric Set Filter TopologicalSpace MeasureTheory.Measure

open Filter MeasureTheory Topology

variable {α : Type _} [MetricSpace α]

/-- On a metric space `X` with a measure `μ`, consider for each `x : X` a family of measurable sets
with nonempty interiors, called `sets_at x`. This family is a Vitali family if it satisfies the
following property: consider a (possibly non-measurable) set `s`, and for any `x` in `s` a
subfamily `f x` of `sets_at x` containing sets of arbitrarily small diameter. Then one can extract
a disjoint subfamily covering almost all `s`.

Vitali families are provided by covering theorems such as the Besicovitch covering theorem or the
Vitali covering theorem. They make it possible to formulate general versions of theorems on
differentiations of measure that apply in both contexts.
-/
@[nolint has_nonempty_instance]
structure VitaliFamily {m : MeasurableSpace α} (μ : Measure α) where
  setsAt : ∀ x : α, Set (Set α)
  MeasurableSet' : ∀ x : α, ∀ a : Set α, a ∈ sets_at x → MeasurableSet a
  nonempty_interior : ∀ x : α, ∀ y : Set α, y ∈ sets_at x → (interior y).Nonempty
  Nontrivial : ∀ (x : α), ∀ ε > (0 : ℝ), ∃ y ∈ sets_at x, y ⊆ closedBall x ε
  covering :
    ∀ (s : Set α) (f : ∀ x : α, Set (Set α)),
      (∀ x ∈ s, f x ⊆ sets_at x) →
        (∀ x ∈ s, ∀ ε > (0 : ℝ), ∃ a ∈ f x, a ⊆ closedBall x ε) →
          ∃ t : Set (α × Set α),
            (∀ p : α × Set α, p ∈ t → p.1 ∈ s) ∧
              (t.PairwiseDisjoint fun p => p.2) ∧
                (∀ p : α × Set α, p ∈ t → p.2 ∈ f p.1) ∧
                  μ (s \ ⋃ (p : α × Set α) (hp : p ∈ t), p.2) = 0
#align vitali_family VitaliFamily

namespace VitaliFamily

variable {m0 : MeasurableSpace α} {μ : Measure α}

include μ

/-- A Vitali family for a measure `μ` is also a Vitali family for any measure absolutely continuous
with respect to `μ`. -/
def mono (v : VitaliFamily μ) (ν : Measure α) (hν : ν ≪ μ) : VitaliFamily ν
    where
  setsAt := v.setsAt
  MeasurableSet' := v.MeasurableSet'
  nonempty_interior := v.nonempty_interior
  Nontrivial := v.Nontrivial
  covering s f h h' :=
    by
    rcases v.covering s f h h' with ⟨t, ts, disj, mem_f, hμ⟩
    exact ⟨t, ts, disj, mem_f, hν hμ⟩
#align vitali_family.mono VitaliFamily.mono

/-- Given a Vitali family `v` for a measure `μ`, a family `f` is a fine subfamily on a set `s` if
every point `x` in `s` belongs to arbitrarily small sets in `v.sets_at x ∩ f x`. This is precisely
the subfamilies for which the Vitali family definition ensures that one can extract a disjoint
covering of almost all `s`. -/
def FineSubfamilyOn (v : VitaliFamily μ) (f : α → Set (Set α)) (s : Set α) : Prop :=
  ∀ x ∈ s, ∀ ε > 0, ∃ a ∈ v.setsAt x ∩ f x, a ⊆ closedBall x ε
#align vitali_family.fine_subfamily_on VitaliFamily.FineSubfamilyOn

namespace FineSubfamilyOn

variable {v : VitaliFamily μ} {f : α → Set (Set α)} {s : Set α} (h : v.FineSubfamilyOn f s)

include h

theorem exists_disjoint_covering_ae :
    ∃ t : Set (α × Set α),
      (∀ p : α × Set α, p ∈ t → p.1 ∈ s) ∧
        (t.PairwiseDisjoint fun p => p.2) ∧
          (∀ p : α × Set α, p ∈ t → p.2 ∈ v.setsAt p.1 ∩ f p.1) ∧
            μ (s \ ⋃ (p : α × Set α) (hp : p ∈ t), p.2) = 0 :=
  v.covering s (fun x => v.setsAt x ∩ f x) (fun x hx => inter_subset_left _ _) h
#align vitali_family.fine_subfamily_on.exists_disjoint_covering_ae VitaliFamily.FineSubfamilyOn.exists_disjoint_covering_ae

/-- Given `h : v.fine_subfamily_on f s`, then `h.index` is a set parametrizing a disjoint
covering of almost every `s`. -/
protected def index : Set (α × Set α) :=
  h.exists_disjoint_covering_ae.some
#align vitali_family.fine_subfamily_on.index VitaliFamily.FineSubfamilyOn.index

/-- Given `h : v.fine_subfamily_on f s`, then `h.covering p` is a set in the family,
for `p ∈ h.index`, such that these sets form a disjoint covering of almost every `s`. -/
@[nolint unused_arguments]
protected def covering : α × Set α → Set α := fun p => p.2
#align vitali_family.fine_subfamily_on.covering VitaliFamily.FineSubfamilyOn.covering

theorem index_subset : ∀ p : α × Set α, p ∈ h.index → p.1 ∈ s :=
  h.exists_disjoint_covering_ae.choose_spec.1
#align vitali_family.fine_subfamily_on.index_subset VitaliFamily.FineSubfamilyOn.index_subset

theorem covering_disjoint : h.index.PairwiseDisjoint h.covering :=
  h.exists_disjoint_covering_ae.choose_spec.2.1
#align vitali_family.fine_subfamily_on.covering_disjoint VitaliFamily.FineSubfamilyOn.covering_disjoint

theorem covering_disjoint_subtype : Pairwise (Disjoint on fun x : h.index => h.covering x) :=
  (pairwise_subtype_iff_pairwise_set _ _).2 h.covering_disjoint
#align vitali_family.fine_subfamily_on.covering_disjoint_subtype VitaliFamily.FineSubfamilyOn.covering_disjoint_subtype

theorem covering_mem {p : α × Set α} (hp : p ∈ h.index) : h.covering p ∈ f p.1 :=
  (h.exists_disjoint_covering_ae.choose_spec.2.2.1 p hp).2
#align vitali_family.fine_subfamily_on.covering_mem VitaliFamily.FineSubfamilyOn.covering_mem

theorem covering_mem_family {p : α × Set α} (hp : p ∈ h.index) : h.covering p ∈ v.setsAt p.1 :=
  (h.exists_disjoint_covering_ae.choose_spec.2.2.1 p hp).1
#align vitali_family.fine_subfamily_on.covering_mem_family VitaliFamily.FineSubfamilyOn.covering_mem_family

theorem measure_diff_bUnion : μ (s \ ⋃ p ∈ h.index, h.covering p) = 0 :=
  h.exists_disjoint_covering_ae.choose_spec.2.2.2
#align vitali_family.fine_subfamily_on.measure_diff_bUnion VitaliFamily.FineSubfamilyOn.measure_diff_bUnion

theorem index_countable [SecondCountableTopology α] : h.index.Countable :=
  h.covering_disjoint.countable_of_nonempty_interior fun x hx =>
    v.nonempty_interior _ _ (h.covering_mem_family hx)
#align vitali_family.fine_subfamily_on.index_countable VitaliFamily.FineSubfamilyOn.index_countable

protected theorem measurableSet_u {p : α × Set α} (hp : p ∈ h.index) :
    MeasurableSet (h.covering p) :=
  v.MeasurableSet' p.1 _ (h.covering_mem_family hp)
#align vitali_family.fine_subfamily_on.measurable_set_u VitaliFamily.FineSubfamilyOn.measurableSet_u

theorem measure_le_tsum_of_absolutelyContinuous [SecondCountableTopology α] {ρ : Measure α}
    (hρ : ρ ≪ μ) : ρ s ≤ ∑' p : h.index, ρ (h.covering p) :=
  calc
    ρ s ≤ ρ ((s \ ⋃ p ∈ h.index, h.covering p) ∪ ⋃ p ∈ h.index, h.covering p) :=
      measure_mono (by simp only [subset_union_left, diff_union_self])
    _ ≤ ρ (s \ ⋃ p ∈ h.index, h.covering p) + ρ (⋃ p ∈ h.index, h.covering p) :=
      (measure_union_le _ _)
    _ = ∑' p : h.index, ρ (h.covering p) := by
      rw [hρ h.measure_diff_bUnion,
        measure_bUnion h.index_countable h.covering_disjoint fun x hx => h.measurable_set_u hx,
        zero_add]

#align vitali_family.fine_subfamily_on.measure_le_tsum_of_absolutely_continuous VitaliFamily.FineSubfamilyOn.measure_le_tsum_of_absolutelyContinuous

theorem measure_le_tsum [SecondCountableTopology α] : μ s ≤ ∑' x : h.index, μ (h.covering x) :=
  h.measure_le_tsum_of_absolutelyContinuous Measure.AbsolutelyContinuous.rfl
#align vitali_family.fine_subfamily_on.measure_le_tsum VitaliFamily.FineSubfamilyOn.measure_le_tsum

end FineSubfamilyOn

/-- One can enlarge a Vitali family by adding to the sets `f x` at `x` all sets which are not
contained in a `δ`-neighborhood on `x`. This does not change the local filter at a point, but it
can be convenient to get a nicer global behavior. -/
def enlarge (v : VitaliFamily μ) (δ : ℝ) (δpos : 0 < δ) : VitaliFamily μ
    where
  setsAt x := v.setsAt x ∪ { a | MeasurableSet a ∧ (interior a).Nonempty ∧ ¬a ⊆ closedBall x δ }
  MeasurableSet' x a ha := by
    cases ha
    exacts[v.measurable_set' _ _ ha, ha.1]
  nonempty_interior x a ha := by
    cases ha
    exacts[v.nonempty_interior _ _ ha, ha.2.1]
  Nontrivial := by
    intro x ε εpos
    rcases v.nontrivial x ε εpos with ⟨a, ha, h'a⟩
    exact ⟨a, mem_union_left _ ha, h'a⟩
  covering := by
    intro s f fset ffine
    let g : α → Set (Set α) := fun x => f x ∩ v.sets_at x
    have : ∀ x ∈ s, ∀ ε : ℝ, ε > 0 → ∃ (a : Set α)(H : a ∈ g x), a ⊆ closed_ball x ε :=
      by
      intro x hx ε εpos
      obtain ⟨a, af, ha⟩ : ∃ a ∈ f x, a ⊆ closed_ball x (min ε δ)
      exact ffine x hx (min ε δ) (lt_min εpos δpos)
      rcases fset x hx af with (h'a | h'a)
      · exact ⟨a, ⟨af, h'a⟩, ha.trans (closed_ball_subset_closed_ball (min_le_left _ _))⟩
      · refine' False.elim (h'a.2.2 _)
        exact ha.trans (closed_ball_subset_closed_ball (min_le_right _ _))
    rcases v.covering s g (fun x hx => inter_subset_right _ _) this with ⟨t, ts, tdisj, tg, μt⟩
    exact ⟨t, ts, tdisj, fun p hp => (tg p hp).1, μt⟩
#align vitali_family.enlarge VitaliFamily.enlarge

variable (v : VitaliFamily μ)

include v

/-- Given a vitali family `v`, then `v.filter_at x` is the filter on `set α` made of those families
that contain all sets of `v.sets_at x` of a sufficiently small diameter. This filter makes it
possible to express limiting behavior when sets in `v.sets_at x` shrink to `x`. -/
def filterAt (x : α) : Filter (Set α) :=
  ⨅ ε ∈ Ioi (0 : ℝ), 𝓟 ({ a ∈ v.setsAt x | a ⊆ closedBall x ε })
#align vitali_family.filter_at VitaliFamily.filterAt

theorem mem_filterAt_iff {x : α} {s : Set (Set α)} :
    s ∈ v.filterAt x ↔ ∃ ε > (0 : ℝ), ∀ a ∈ v.setsAt x, a ⊆ closedBall x ε → a ∈ s :=
  by
  simp only [filter_at, exists_prop, gt_iff_lt]
  rw [mem_binfi_of_directed]
  · simp only [subset_def, and_imp, exists_prop, mem_sep_iff, mem_Ioi, mem_principal]
  · simp only [DirectedOn, exists_prop, ge_iff_le, le_principal_iff, mem_Ioi, Order.Preimage,
      mem_principal]
    intro x hx y hy
    refine'
      ⟨min x y, lt_min hx hy, fun a ha =>
        ⟨ha.1, ha.2.trans (closed_ball_subset_closed_ball (min_le_left _ _))⟩, fun a ha =>
        ⟨ha.1, ha.2.trans (closed_ball_subset_closed_ball (min_le_right _ _))⟩⟩
  · exact ⟨(1 : ℝ), mem_Ioi.2 zero_lt_one⟩
#align vitali_family.mem_filter_at_iff VitaliFamily.mem_filterAt_iff

instance filterAt_neBot (x : α) : (v.filterAt x).ne_bot :=
  by
  simp only [ne_bot_iff, ← empty_mem_iff_bot, mem_filter_at_iff, not_exists, exists_prop,
    mem_empty_iff_false, and_true_iff, gt_iff_lt, not_and, Ne.def, not_false_iff, not_forall]
  intro ε εpos
  obtain ⟨w, w_sets, hw⟩ : ∃ w ∈ v.sets_at x, w ⊆ closed_ball x ε := v.nontrivial x ε εpos
  exact ⟨w, w_sets, hw⟩
#align vitali_family.filter_at_ne_bot VitaliFamily.filterAt_neBot

theorem eventually_filterAt_iff {x : α} {P : Set α → Prop} :
    (∀ᶠ a in v.filterAt x, P a) ↔ ∃ ε > (0 : ℝ), ∀ a ∈ v.setsAt x, a ⊆ closedBall x ε → P a :=
  v.mem_filterAt_iff
#align vitali_family.eventually_filter_at_iff VitaliFamily.eventually_filterAt_iff

theorem eventually_filterAt_mem_sets (x : α) : ∀ᶠ a in v.filterAt x, a ∈ v.setsAt x :=
  by
  simp (config := { contextual := true }) only [eventually_filter_at_iff, exists_prop, and_true_iff,
    gt_iff_lt, imp_true_iff]
  exact ⟨1, zero_lt_one⟩
#align vitali_family.eventually_filter_at_mem_sets VitaliFamily.eventually_filterAt_mem_sets

theorem eventually_filterAt_subset_closedBall (x : α) {ε : ℝ} (hε : 0 < ε) :
    ∀ᶠ a : Set α in v.filterAt x, a ⊆ closedBall x ε :=
  by
  simp only [v.eventually_filter_at_iff]
  exact ⟨ε, hε, fun a ha ha' => ha'⟩
#align vitali_family.eventually_filter_at_subset_closed_ball VitaliFamily.eventually_filterAt_subset_closedBall

theorem tendsto_filterAt_iff {ι : Type _} {l : Filter ι} {f : ι → Set α} {x : α} :
    Tendsto f l (v.filterAt x) ↔
      (∀ᶠ i in l, f i ∈ v.setsAt x) ∧ ∀ ε > (0 : ℝ), ∀ᶠ i in l, f i ⊆ closedBall x ε :=
  by
  refine'
    ⟨fun H =>
      ⟨H.Eventually <| v.eventually_filter_at_mem_sets x, fun ε hε =>
        H.Eventually <| v.eventually_filter_at_subset_closed_ball x hε⟩,
      fun H s hs => (_ : ∀ᶠ i in l, f i ∈ s)⟩
  obtain ⟨ε, εpos, hε⟩ := v.mem_filter_at_iff.mp hs
  filter_upwards [H.1, H.2 ε εpos]with i hi hiε using hε _ hi hiε
#align vitali_family.tendsto_filter_at_iff VitaliFamily.tendsto_filterAt_iff

theorem eventually_filterAt_measurableSet (x : α) : ∀ᶠ a in v.filterAt x, MeasurableSet a := by
  filter_upwards [v.eventually_filter_at_mem_sets x]with _ ha using v.measurable_set' _ _ ha
#align vitali_family.eventually_filter_at_measurable_set VitaliFamily.eventually_filterAt_measurableSet

theorem frequently_filterAt_iff {x : α} {P : Set α → Prop} :
    (∃ᶠ a in v.filterAt x, P a) ↔ ∀ ε > (0 : ℝ), ∃ a ∈ v.setsAt x, a ⊆ closedBall x ε ∧ P a := by
  simp only [Filter.Frequently, eventually_filter_at_iff, not_exists, exists_prop, not_and,
    Classical.not_not, not_forall]
#align vitali_family.frequently_filter_at_iff VitaliFamily.frequently_filterAt_iff

theorem eventually_filterAt_subset_of_nhds {x : α} {o : Set α} (hx : o ∈ 𝓝 x) :
    ∀ᶠ a in v.filterAt x, a ⊆ o := by
  rw [eventually_filter_at_iff]
  rcases Metric.mem_nhds_iff.1 hx with ⟨ε, εpos, hε⟩
  exact
    ⟨ε / 2, half_pos εpos, fun a av ha =>
      ha.trans ((closed_ball_subset_ball (half_lt_self εpos)).trans hε)⟩
#align vitali_family.eventually_filter_at_subset_of_nhds VitaliFamily.eventually_filterAt_subset_of_nhds

theorem fineSubfamilyOnOfFrequently (v : VitaliFamily μ) (f : α → Set (Set α)) (s : Set α)
    (h : ∀ x ∈ s, ∃ᶠ a in v.filterAt x, a ∈ f x) : v.FineSubfamilyOn f s :=
  by
  intro x hx ε εpos
  obtain ⟨a, av, ha, af⟩ : ∃ (a : Set α)(H : a ∈ v.sets_at x), a ⊆ closed_ball x ε ∧ a ∈ f x :=
    v.frequently_filter_at_iff.1 (h x hx) ε εpos
  exact ⟨a, ⟨av, af⟩, ha⟩
#align vitali_family.fine_subfamily_on_of_frequently VitaliFamily.fineSubfamilyOnOfFrequently

end VitaliFamily


/-
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 9a59dcb7a2d06bf55da57b9030169219980660cd
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Algebra.BigOperators.Intervals
import Mathlib.Analysis.Normed.Group.Basic
import Mathlib.Topology.Instances.NNReal

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

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`, `HasSum.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]

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

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

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.toFinset, fun t ht => _⟩
  have : ∀ i ∈ t, ‖f i‖ ≤ g i := by
    intro i hi
    simp only [disjoint_left, mem_union, not_or, h.mem_toFinset, 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

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

/-- A version of the **direct comparison test** for conditionally convergent series.
See `cauchySeq_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

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

/-- 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

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

/-- 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

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

/-- 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.hasSum.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

/-- 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

/-- 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

/-- 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]

/-- 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

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

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

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