/-
Homework #7. Proper subset.
-/

/-
We have studied the subset relation on
sets. A set x is said to be a subset of
y if ∀ e, e ∈ x → e in y.

By contrast, we say that x is a *proper*
subset of y if x is a subset of y and
there is some f in y that is not in x.
Here's a formal definition of this binary
relation on sets.
-/

def proper_subset :
  ∀ { α : Type },
    set α → set α → Prop :=
  λ α x y, forall (e : α),
    (e ∈ x → e ∈ y) ∧ (∃ f, f ∈ y ∧ f ∉ x)

/-
Your homework, should you choose to
complete it (in preparation for the
postponed quiz), is to use "example"
to assert and prove the proposition
that { 1, 3 } is a proper subset of
the odd numbers.
-/

/-
We now introduce some new concepts
to help you through this proof. The
first has to do with the direction
of rewriting, the second explains
what the cases tactic actually does
and shows how it can then be used to
do false elimination on hypotheses
that assert incorrect equalities. We
will also remind you about how to
deal with an assumed proof of the
form, e ∈ ∅, which is obviously a
contradiction.
-/

/--/
First, a note on the rewrite tactic.

If e : x = y is an assumed proof of
x = y, then the tactic, "rewrite e"
rewrites each occurence of x in the
goal with y. Click through the proof
of the following trivial proposition
to see the idea in action.
-/

example :
  ∀ a b c : ℕ, a = b → b = c → a = c
:=
begin
intros a b c,
assume ab bc,
rewrite ab,
rw bc, -- shorthand
-- rw does "apply rfl" for us automatically
end

/-
If you want the rewriting to go in
the other direction, use "rw ←e"
-/

example :
  ∀ a b c : ℕ, a = b → b = c → a = c
:=
begin
intros a b c,
assume ab bc,
rewrite ←bc,
rw ←ab,
end

/-
Second, let's talk more about cases.

Whenever we have any data value, even
if its a proof, it must have been built
by one of the constructors defined for
that type of data.

With natural numbers, for example, a
given ℕ must be either 0 (constructed
by nat.zero) or 1 + a smaller natural
number (built by applying nat.succ to
the next smaller ℕ).

So if we have some value, n : ℕ,
even though we don't know what its
value is, we do know there are only
two ways it could be been produced.
So, if we want to prove something
about n, it suffices to show it is
true no matter which constructor
was used to "build" n. Case analysis
(and the cases tactic) replaces an
assumed value in the context with
each of the constructors that could
have been used to build it. Click
through the following proof to see
how this plays out, not when we
apply cases to a disjunction, but
to a natural number.
-/

example : ∀ n : ℕ, true :=
begin
assume n,
cases n,  -- whoa, that's cool
trivial,
trivial,
end

/-
The same idea holds for values that
are proofs. Suppose we have a proof
of, say, a disjunction, P ∨ Q. There
are only two ways that proof could
have been built: by or.inl or or.inr.
So when we use cases on a proof of a
disjunction, even though we don't
know exactly how it was proved, if
we can prove our goal for each of
the two ways in which it *could* have
been built, then we've proved our
goal in either case, as there are no
other ways in which we could have had
the value in the first place.
-/

example : ∀ P Q : Prop, P ∨ Q → true :=
begin
intros P Q,
assume h,
cases h, -- whoa, now I get it!
trivial,
trivial
end

/-
Okay, so here's the cool thing. If you
end up with an assumption, such as 2 = 3,
in your context, which is to say a wrong
proof of an equality, you can do case
analysis on it. We've already seen that
there is only one way to construct a proof
of an equality, using eq.refl applied to one
value. So if you have assumed a proof
of 2 = 3, when you do case analysis on
it, Lean will see that there are *no*
constructors that could have been used
to construct that proof. You thus have
zero cases to prove and you're done! It
is almost magic. But it's not. Having no
cases to prove is just false elimination
under a different guise.
-/

example : 4 = 5 → 0 = 1 :=
begin
assume four_equals_five,
cases four_equals_five, --whoa!
end

/-
Third if you have an assumption of
the form, h : e ∈ ∅, remember you
can use have f : false := h. That
gets you what you need to be done.

Oh, and don't forget that e ∉ x is
the same as ¬ (e ∈ x), and that of
course is just (e ∈ x) → false. Or,
just try cases!

And here are a few final hints.

(1) Remember that a set in Lean is
really represented as a membership
predicate.

(1A) When a set, such as { 1 , 3 },
viewed as a membership predicate,
is applied to a value, it reduces
to a proposition, here in the form
of a disjunction. So of you end up
with something like e ∈ { 1, 3 } as
an  assumption, treat it as a proof
of a disjunction.

(1B) If you end up with a goal of
the form of a membership proposition,
such as the following, for example,

α ∈ {n : ℕ | ∃ (m : ℕ), n = m }

think of it as the application of
the predicate/function defined by
the set, taking argument, n, to α.
The overall expression reduces to
∃ (m : ℕ), α = m. You need to see
this to know what inference rule
to use to prove such a goal.
-/

example :
proper_subset
  { 1, 3 }
  { n | ∃ m, n = 2 * m + 1 }
:=
begin
unfold proper_subset,
intro e,

split,

-- subset
assume h,
cases h,
show ∃ m, e = 2 * m + 1,
apply exists.intro 1, assumption,

cases h,
apply exists.intro 0, assumption,

cases h,

/-
have f : false, from h,
contradiction,
-/
-- proper
apply exists.intro 5,
split,
show ∃ m, 5 = 2 * m + 1,
apply exists.intro 2, apply rfl,

intro h,
change 5 = 3 ∨ 5 = 1 ∨ false at h,
cases h,
cases h,
cases h,
cases h,
cases h,
end


/-
Copyright (c) 2020 Devon Tuma. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Devon Tuma
-/
import ring_theory.ideal.quotient
import ring_theory.polynomial.quotient

/-!
# Jacobson radical

The Jacobson radical of a ring `R` is defined to be the intersection of all maximal ideals of `R`.
This is similar to how the nilradical is equal to the intersection of all prime ideals of `R`.

We can extend the idea of the nilradical to ideals of `R`,
by letting the radical of an ideal `I` be the intersection of prime ideals containing `I`.
Under this extension, the original nilradical is the radical of the zero ideal `⊥`.
Here we define the Jacobson radical of an ideal `I` in a similar way,
as the intersection of maximal ideals containing `I`.

## Main definitions

Let `R` be a commutative ring, and `I` be an ideal of `R`

* `jacobson I` is the jacobson radical, i.e. the infimum of all maximal ideals containing I.

* `is_local I` is the proposition that the jacobson radical of `I` is itself a maximal ideal

## Main statements

* `mem_jacobson_iff` gives a characterization of members of the jacobson of I

* `is_local_of_is_maximal_radical`: if the radical of I is maximal then so is the jacobson radical

## Tags

Jacobson, Jacobson radical, Local Ideal

-/

universes u v

namespace ideal
variables {R : Type u} {S : Type v}
open_locale polynomial

section jacobson

section ring
variables [ring R] [ring S] {I : ideal R}

/-- The Jacobson radical of `I` is the infimum of all maximal (left) ideals containing `I`. -/
def jacobson (I : ideal R) : ideal R :=
Inf {J : ideal R | I ≤ J ∧ is_maximal J}

lemma le_jacobson : I ≤ jacobson I :=
λ x hx, mem_Inf.mpr (λ J hJ, hJ.left hx)

@[simp] lemma jacobson_idem : jacobson (jacobson I) = jacobson I :=
le_antisymm (Inf_le_Inf (λ J hJ, ⟨Inf_le hJ, hJ.2⟩)) le_jacobson

@[simp] lemma jacobson_top : jacobson (⊤ : ideal R) = ⊤ :=
eq_top_iff.2 le_jacobson

@[simp] theorem jacobson_eq_top_iff : jacobson I = ⊤ ↔ I = ⊤ :=
⟨λ H, classical.by_contradiction $ λ hi, let ⟨M, hm, him⟩ := exists_le_maximal I hi in
  lt_top_iff_ne_top.1
    (lt_of_le_of_lt (show jacobson I ≤ M, from Inf_le ⟨him, hm⟩) $
      lt_top_iff_ne_top.2 hm.ne_top) H,
λ H, eq_top_iff.2 $ le_Inf $ λ J ⟨hij, hj⟩, H ▸ hij⟩

lemma jacobson_eq_bot : jacobson I = ⊥ → I = ⊥ :=
λ h, eq_bot_iff.mpr (h ▸ le_jacobson)

lemma jacobson_eq_self_of_is_maximal [H : is_maximal I] : I.jacobson = I :=
le_antisymm (Inf_le ⟨le_of_eq rfl, H⟩) le_jacobson

@[priority 100]
instance jacobson.is_maximal [H : is_maximal I] : is_maximal (jacobson I) :=
⟨⟨λ htop, H.1.1 (jacobson_eq_top_iff.1 htop),
  λ J hJ, H.1.2 _ (lt_of_le_of_lt le_jacobson hJ)⟩⟩

theorem mem_jacobson_iff {x : R} : x ∈ jacobson I ↔ ∀ y, ∃ z, z * y * x + z - 1 ∈ I :=
⟨λ hx y, classical.by_cases
  (assume hxy : I ⊔ span {y * x + 1} = ⊤,
    let ⟨p, hpi, q, hq, hpq⟩ := submodule.mem_sup.1 ((eq_top_iff_one _).1 hxy) in
    let ⟨r, hr⟩ := mem_span_singleton'.1 hq in
    ⟨r, by rw [mul_assoc, ←mul_add_one, hr, ← hpq, ← neg_sub, add_sub_cancel]; exact I.neg_mem hpi⟩)
  (assume hxy : I ⊔ span {y * x + 1} ≠ ⊤,
    let ⟨M, hm1, hm2⟩ := exists_le_maximal _ hxy in
    suffices x ∉ M, from (this $ mem_Inf.1 hx ⟨le_trans le_sup_left hm2, hm1⟩).elim,
    λ hxm, hm1.1.1 $ (eq_top_iff_one _).2 $ add_sub_cancel' (y * x) 1 ▸ M.sub_mem
      (le_sup_right.trans hm2 $ subset_span rfl)
      (M.mul_mem_left _ hxm)),
λ hx, mem_Inf.2 $ λ M ⟨him, hm⟩, classical.by_contradiction $ λ hxm,
  let ⟨y, i, hi, df⟩ := hm.exists_inv hxm, ⟨z, hz⟩ := hx (-y) in
  hm.1.1 $ (eq_top_iff_one _).2 $ sub_sub_cancel (z * -y * x + z) 1 ▸ M.sub_mem
    (by { rw [mul_assoc, ←mul_add_one, neg_mul, ← (sub_eq_iff_eq_add.mpr df.symm), neg_sub,
            sub_add_cancel],
          exact M.mul_mem_left _ hi }) (him hz)⟩

lemma exists_mul_sub_mem_of_sub_one_mem_jacobson {I : ideal R} (r : R)
  (h : r - 1 ∈ jacobson I) : ∃ s, s * r - 1 ∈ I :=
begin
  cases mem_jacobson_iff.1 h 1 with s hs,
  use s,
  simpa [mul_sub] using hs
end

/-- An ideal equals its Jacobson radical iff it is the intersection of a set of maximal ideals.
Allowing the set to include ⊤ is equivalent, and is included only to simplify some proofs. -/
theorem eq_jacobson_iff_Inf_maximal :
  I.jacobson = I ↔ ∃ M : set (ideal R), (∀ J ∈ M, is_maximal J ∨ J = ⊤) ∧ I = Inf M :=
begin
  use λ hI, ⟨{J : ideal R | I ≤ J ∧ J.is_maximal}, ⟨λ _ hJ, or.inl hJ.right, hI.symm⟩⟩,
  rintros ⟨M, hM, hInf⟩,
  refine le_antisymm (λ x hx, _) le_jacobson,
  rw [hInf, mem_Inf],
  intros I hI,
  cases hM I hI with is_max is_top,
  { exact (mem_Inf.1 hx) ⟨le_Inf_iff.1 (le_of_eq hInf) I hI, is_max⟩ },
  { exact is_top.symm ▸ submodule.mem_top }
end

theorem eq_jacobson_iff_Inf_maximal' :
  I.jacobson = I ↔ ∃ M : set (ideal R), (∀ (J ∈ M) (K : ideal R), J < K → K = ⊤) ∧ I = Inf M :=
eq_jacobson_iff_Inf_maximal.trans
  ⟨λ h, let ⟨M, hM⟩ := h in ⟨M, ⟨λ J hJ K hK, or.rec_on (hM.1 J hJ) (λ h, h.1.2 K hK)
    (λ h, eq_top_iff.2 (le_of_lt (h ▸ hK))), hM.2⟩⟩,
  λ h, let ⟨M, hM⟩ := h in ⟨M, ⟨λ J hJ, or.rec_on (classical.em (J = ⊤)) (λ h, or.inr h)
    (λ h, or.inl ⟨⟨h, hM.1 J hJ⟩⟩), hM.2⟩⟩⟩

/-- An ideal `I` equals its Jacobson radical if and only if every element outside `I`
also lies outside of a maximal ideal containing `I`. -/
lemma eq_jacobson_iff_not_mem :
  I.jacobson = I ↔ ∀ x ∉ I, ∃ M : ideal R, (I ≤ M ∧ M.is_maximal) ∧ x ∉ M :=
begin
  split,
  { intros h x hx,
    erw [← h, mem_Inf] at hx,
    push_neg at hx,
    exact hx },
  { refine λ h, le_antisymm (λ x hx, _) le_jacobson,
    contrapose hx,
    erw mem_Inf,
    push_neg,
    exact h x hx }
end

theorem map_jacobson_of_surjective {f : R →+* S} (hf : function.surjective f) :
  ring_hom.ker f ≤ I → map f (I.jacobson) = (map f I).jacobson :=
begin
  intro h,
  unfold ideal.jacobson,
  have : ∀ J ∈ {J : ideal R | I ≤ J ∧ J.is_maximal}, f.ker ≤ J := λ J hJ, le_trans h hJ.left,
  refine trans (map_Inf hf this) (le_antisymm _ _),
  { refine Inf_le_Inf (λ J hJ, ⟨comap f J, ⟨⟨le_comap_of_map_le hJ.1, _⟩,
    map_comap_of_surjective f hf J⟩⟩),
    haveI : J.is_maximal := hJ.right,
    exact comap_is_maximal_of_surjective f hf },
  { refine Inf_le_Inf_of_subset_insert_top (λ j hj, hj.rec_on (λ J hJ, _)),
    rw ← hJ.2,
    cases map_eq_top_or_is_maximal_of_surjective f hf hJ.left.right with htop hmax,
    { exact htop.symm ▸ set.mem_insert ⊤ _ },
    { exact set.mem_insert_of_mem ⊤ ⟨map_mono hJ.1.1, hmax⟩ } },
end

lemma map_jacobson_of_bijective {f : R →+* S} (hf : function.bijective f) :
  map f (I.jacobson) = (map f I).jacobson :=
map_jacobson_of_surjective hf.right
  (le_trans (le_of_eq (f.injective_iff_ker_eq_bot.1 hf.left)) bot_le)

lemma comap_jacobson {f : R →+* S} {K : ideal S} :
  comap f (K.jacobson) = Inf (comap f '' {J : ideal S | K ≤ J ∧ J.is_maximal}) :=
trans (comap_Inf' f _) (Inf_eq_infi).symm

theorem comap_jacobson_of_surjective {f : R →+* S} (hf : function.surjective f) {K : ideal S} :
  comap f (K.jacobson) = (comap f K).jacobson :=
begin
  unfold ideal.jacobson,
  refine le_antisymm _ _,
  { refine le_trans (comap_mono (le_of_eq (trans top_inf_eq.symm Inf_insert.symm))) _,
    rw [comap_Inf', Inf_eq_infi],
    refine infi_le_infi_of_subset (λ J hJ, _),
    have : comap f (map f J) = J := trans (comap_map_of_surjective f hf J)
      (le_antisymm (sup_le_iff.2 ⟨le_of_eq rfl, le_trans (comap_mono bot_le) hJ.left⟩) le_sup_left),
    cases map_eq_top_or_is_maximal_of_surjective _ hf hJ.right with htop hmax,
    { refine ⟨⊤, ⟨set.mem_insert ⊤ _, htop ▸ this⟩⟩ },
    { refine ⟨map f J, ⟨set.mem_insert_of_mem _
        ⟨le_map_of_comap_le_of_surjective f hf hJ.1, hmax⟩, this⟩⟩ } },
  { rw comap_Inf,
    refine le_infi_iff.2 (λ J, (le_infi_iff.2 (λ hJ, _))),
    haveI : J.is_maximal := hJ.right,
    refine Inf_le ⟨comap_mono hJ.left, comap_is_maximal_of_surjective _ hf⟩ }
end

@[mono] lemma jacobson_mono {I J : ideal R} : I ≤ J → I.jacobson ≤ J.jacobson :=
begin
  intros h x hx,
  erw mem_Inf at ⊢ hx,
  exact λ K ⟨hK, hK_max⟩, hx ⟨trans h hK, hK_max⟩
end

end ring

section comm_ring
variables [comm_ring R] [comm_ring S] {I : ideal R}

lemma radical_le_jacobson : radical I ≤ jacobson I :=
le_Inf (λ J hJ, (radical_eq_Inf I).symm ▸ Inf_le ⟨hJ.left, is_maximal.is_prime hJ.right⟩)

lemma is_radical_of_eq_jacobson (h : jacobson I = I) : I.is_radical :=
radical_le_jacobson.trans h.le

lemma is_unit_of_sub_one_mem_jacobson_bot (r : R)
  (h : r - 1 ∈ jacobson (⊥ : ideal R)) : is_unit r :=
begin
  cases exists_mul_sub_mem_of_sub_one_mem_jacobson r h with s hs,
  rw [mem_bot, sub_eq_zero, mul_comm] at hs,
  exact is_unit_of_mul_eq_one _ _ hs
end

lemma mem_jacobson_bot {x : R} : x ∈ jacobson (⊥ : ideal R) ↔ ∀ y, is_unit (x * y + 1) :=
⟨λ hx y, let ⟨z, hz⟩ := (mem_jacobson_iff.1 hx) y in
  is_unit_iff_exists_inv.2 ⟨z, by rwa [add_mul, one_mul, ← sub_eq_zero, mul_right_comm,
    mul_comm _ z, mul_right_comm]⟩,
λ h, mem_jacobson_iff.mpr (λ y, (let ⟨b, hb⟩ := is_unit_iff_exists_inv.1 (h y) in
  ⟨b, (submodule.mem_bot R).2 (hb ▸ (by ring))⟩))⟩

/-- An ideal `I` of `R` is equal to its Jacobson radical if and only if
the Jacobson radical of the quotient ring `R/I` is the zero ideal -/
theorem jacobson_eq_iff_jacobson_quotient_eq_bot :
  I.jacobson = I ↔ jacobson (⊥ : ideal (R ⧸ I)) = ⊥ :=
begin
  have hf : function.surjective (quotient.mk I) := submodule.quotient.mk_surjective I,
  split,
  { intro h,
    replace h := congr_arg (map (quotient.mk I)) h,
    rw map_jacobson_of_surjective hf (le_of_eq mk_ker) at h,
    simpa using h },
  { intro h,
    replace h := congr_arg (comap (quotient.mk I)) h,
    rw [comap_jacobson_of_surjective hf, ← (quotient.mk I).ker_eq_comap_bot] at h,
    simpa using h }
end

/-- The standard radical and Jacobson radical of an ideal `I` of `R` are equal if and only if
the nilradical and Jacobson radical of the quotient ring `R/I` coincide -/
theorem radical_eq_jacobson_iff_radical_quotient_eq_jacobson_bot :
  I.radical = I.jacobson ↔ radical (⊥ : ideal (R ⧸ I)) = jacobson ⊥ :=
begin
  have hf : function.surjective (quotient.mk I) := submodule.quotient.mk_surjective I,
  split,
  { intro h,
    have := congr_arg (map (quotient.mk I)) h,
    rw [map_radical_of_surjective hf (le_of_eq mk_ker),
      map_jacobson_of_surjective hf (le_of_eq mk_ker)] at this,
    simpa using this },
  { intro h,
    have := congr_arg (comap (quotient.mk I)) h,
    rw [comap_radical, comap_jacobson_of_surjective hf, ← (quotient.mk I).ker_eq_comap_bot] at this,
    simpa using this }
end

lemma jacobson_radical_eq_jacobson :
  I.radical.jacobson = I.jacobson :=
le_antisymm (le_trans (le_of_eq (congr_arg jacobson (radical_eq_Inf I)))
  (Inf_le_Inf (λ J hJ, ⟨Inf_le ⟨hJ.1, hJ.2.is_prime⟩, hJ.2⟩))) (jacobson_mono le_radical)

end comm_ring

end jacobson

section polynomial
open polynomial

variables [comm_ring R]

lemma jacobson_bot_polynomial_le_Inf_map_maximal :
  jacobson (⊥ : ideal R[X]) ≤ Inf (map (C : R →+* R[X]) '' {J : ideal R | J.is_maximal}) :=
begin
  refine le_Inf (λ J, exists_imp_distrib.2 (λ j hj, _)),
  haveI : j.is_maximal := hj.1,
  refine trans (jacobson_mono bot_le) (le_of_eq _ : J.jacobson ≤ J),
  suffices : (⊥ : ideal (polynomial (R ⧸ j))).jacobson = ⊥,
  { rw [← hj.2, jacobson_eq_iff_jacobson_quotient_eq_bot],
    replace this :=
    congr_arg (map (polynomial_quotient_equiv_quotient_polynomial j).to_ring_hom) this,
    rwa [map_jacobson_of_bijective _, map_bot] at this,
    exact (ring_equiv.bijective (polynomial_quotient_equiv_quotient_polynomial j)) },
  refine eq_bot_iff.2 (λ f hf, _),
  simpa [(λ hX, by simpa using congr_arg (λ f, coeff f 1) hX : (X : (R ⧸ j)[X]) ≠ 0)]
    using eq_C_of_degree_eq_zero (degree_eq_zero_of_is_unit ((mem_jacobson_bot.1 hf) X)),
end

lemma jacobson_bot_polynomial_of_jacobson_bot (h : jacobson (⊥ : ideal R) = ⊥) :
  jacobson (⊥ : ideal R[X]) = ⊥ :=
begin
  refine eq_bot_iff.2 (le_trans jacobson_bot_polynomial_le_Inf_map_maximal _),
  refine (λ f hf, ((submodule.mem_bot _).2 (polynomial.ext (λ n, trans _ (coeff_zero n).symm)))),
  suffices : f.coeff n ∈ ideal.jacobson ⊥, by rwa [h, submodule.mem_bot] at this,
  exact mem_Inf.2 (λ j hj, (mem_map_C_iff.1 ((mem_Inf.1 hf) ⟨j, ⟨hj.2, rfl⟩⟩)) n),
end

end polynomial

section is_local

variables [comm_ring R]

/-- An ideal `I` is local iff its Jacobson radical is maximal. -/
class is_local (I : ideal R) : Prop := (out : is_maximal (jacobson I))

theorem is_local_iff {I : ideal R} : is_local I ↔ is_maximal (jacobson I) :=
⟨λ h, h.1, λ h, ⟨h⟩⟩

theorem is_local_of_is_maximal_radical {I : ideal R} (hi : is_maximal (radical I)) : is_local I :=
⟨have radical I = jacobson I,
from le_antisymm (le_Inf $ λ M ⟨him, hm⟩, hm.is_prime.radical_le_iff.2 him)
  (Inf_le ⟨le_radical, hi⟩),
show is_maximal (jacobson I), from this ▸ hi⟩

theorem is_local.le_jacobson {I J : ideal R} (hi : is_local I) (hij : I ≤ J) (hj : J ≠ ⊤) :
  J ≤ jacobson I :=
let ⟨M, hm, hjm⟩ := exists_le_maximal J hj in
le_trans hjm $ le_of_eq $ eq.symm $ hi.1.eq_of_le hm.1.1 $ Inf_le ⟨le_trans hij hjm, hm⟩

theorem is_local.mem_jacobson_or_exists_inv {I : ideal R} (hi : is_local I) (x : R) :
  x ∈ jacobson I ∨ ∃ y, y * x - 1 ∈ I :=
classical.by_cases
  (assume h : I ⊔ span {x} = ⊤,
    let ⟨p, hpi, q, hq, hpq⟩ := submodule.mem_sup.1 ((eq_top_iff_one _).1 h) in
    let ⟨r, hr⟩ := mem_span_singleton.1 hq in
    or.inr ⟨r, by rw [← hpq, mul_comm, ← hr, ← neg_sub, add_sub_cancel]; exact I.neg_mem hpi⟩)
  (assume h : I ⊔ span {x} ≠ ⊤,
    or.inl $ le_trans le_sup_right (hi.le_jacobson le_sup_left h) $ mem_span_singleton.2 $
      dvd_refl x)

end is_local

theorem is_primary_of_is_maximal_radical [comm_ring R] {I : ideal R} (hi : is_maximal (radical I)) :
  is_primary I :=
have radical I = jacobson I,
from le_antisymm (le_Inf $ λ M ⟨him, hm⟩, hm.is_prime.radical_le_iff.2 him)
  (Inf_le ⟨le_radical, hi⟩),
⟨ne_top_of_lt $ lt_of_le_of_lt le_radical (lt_top_iff_ne_top.2 hi.1.1),
λ x y hxy, ((is_local_of_is_maximal_radical hi).mem_jacobson_or_exists_inv y).symm.imp
  (λ ⟨z, hz⟩, by rw [← mul_one x, ← sub_sub_cancel (z * y) 1, mul_sub, mul_left_comm]; exact
    I.sub_mem (I.mul_mem_left _ hxy) (I.mul_mem_left _ hz))
  (this ▸ id)⟩

end ideal


/-
Copyright (c) 2014 Parikshit Khanna. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro
-/
import data.list.big_operators.basic

/-!
# Counting in lists

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

This file proves basic properties of `list.countp` and `list.count`, which count the number of
elements of a list satisfying a predicate and equal to a given element respectively. Their
definitions can be found in [`data.list.defs`](./defs).
-/

open nat

variables {α β : Type*} {l l₁ l₂ : list α}

namespace list

section countp
variables (p q : α → Prop) [decidable_pred p] [decidable_pred q]

@[simp] lemma countp_nil : countp p [] = 0 := rfl

@[simp] lemma countp_cons_of_pos {a : α} (l) (pa : p a) : countp p (a::l) = countp p l + 1 :=
if_pos pa

@[simp] lemma countp_cons_of_neg {a : α} (l) (pa : ¬ p a) : countp p (a::l) = countp p l :=
if_neg pa

lemma countp_cons (a : α) (l) : countp p (a :: l) = countp p l + ite (p a) 1 0 :=
by { by_cases h : p a; simp [h] }

lemma length_eq_countp_add_countp (l) : length l = countp p l + countp (λ a, ¬p a) l :=
by induction l with x h ih; [refl, by_cases p x];
  [simp only [countp_cons_of_pos _ _ h, countp_cons_of_neg (λ a, ¬p a) _ (decidable.not_not.2 h),
    ih, length],
   simp only [countp_cons_of_pos (λ a, ¬p a) _ h, countp_cons_of_neg _ _ h, ih, length]]; ac_refl

lemma countp_eq_length_filter (l) : countp p l = length (filter p l) :=
by induction l with x l ih; [refl, by_cases (p x)];
  [simp only [filter_cons_of_pos _ h, countp, ih, if_pos h],
   simp only [countp_cons_of_neg _ _ h, ih, filter_cons_of_neg _ h]]; refl

lemma countp_le_length : countp p l ≤ l.length :=
by simpa only [countp_eq_length_filter] using length_filter_le _ _

@[simp] lemma countp_append (l₁ l₂) : countp p (l₁ ++ l₂) = countp p l₁ + countp p l₂ :=
by simp only [countp_eq_length_filter, filter_append, length_append]

lemma countp_join : ∀ l : list (list α), countp p l.join = (l.map (countp p)).sum
| [] := rfl
| (a :: l) := by rw [join, countp_append, map_cons, sum_cons, countp_join]

lemma countp_pos {l} : 0 < countp p l ↔ ∃ a ∈ l, p a :=
by simp only [countp_eq_length_filter, length_pos_iff_exists_mem, mem_filter, exists_prop]

@[simp] theorem countp_eq_zero {l} : countp p l = 0 ↔ ∀ a ∈ l, ¬ p a :=
by { rw [← not_iff_not, ← ne.def, ← pos_iff_ne_zero, countp_pos], simp }

@[simp] lemma countp_eq_length {l} : countp p l = l.length ↔ ∀ a ∈ l, p a :=
by rw [countp_eq_length_filter, filter_length_eq_length]

lemma length_filter_lt_length_iff_exists (l) : length (filter p l) < length l ↔ ∃ x ∈ l, ¬p x :=
by rw [length_eq_countp_add_countp p l, ← countp_pos, countp_eq_length_filter, lt_add_iff_pos_right]

lemma sublist.countp_le (s : l₁ <+ l₂) : countp p l₁ ≤ countp p l₂ :=
by simpa only [countp_eq_length_filter] using length_le_of_sublist (s.filter p)

@[simp] lemma countp_filter (l : list α) : countp p (filter q l) = countp (λ a, p a ∧ q a) l :=
by simp only [countp_eq_length_filter, filter_filter]

@[simp] lemma countp_true : l.countp (λ _, true) = l.length := by simp

@[simp] lemma countp_false : l.countp (λ _, false) = 0 := by simp

@[simp] lemma countp_map (p : β → Prop) [decidable_pred p] (f : α → β) :
  ∀ l, countp p (map f l) = countp (p ∘ f) l
| [] := rfl
| (a::l) := by rw [map_cons, countp_cons, countp_cons, countp_map]

variables {p q}

lemma countp_mono_left (h : ∀ x ∈ l, p x → q x) : countp p l ≤ countp q l :=
begin
  induction l with a l ihl, { refl },
  rw [forall_mem_cons] at h, cases h with ha hl,
  rw [countp_cons, countp_cons],
  refine add_le_add (ihl hl) _,
  split_ifs; try { simp only [le_rfl, zero_le] },
  exact absurd (ha ‹_›) ‹_›
end

lemma countp_congr (h : ∀ x ∈ l, p x ↔ q x) : countp p l = countp q l :=
le_antisymm (countp_mono_left $ λ x hx, (h x hx).1) (countp_mono_left $ λ x hx, (h x hx).2)

end countp

/-! ### count -/

section count
variables [decidable_eq α]

@[simp] lemma count_nil (a : α) : count a [] = 0 := rfl

lemma count_cons (a b : α) (l : list α) :
  count a (b :: l) = if a = b then succ (count a l) else count a l := rfl

lemma count_cons' (a b : α) (l : list α) :
  count a (b :: l) = count a l + (if a = b then 1 else 0) :=
begin rw count_cons, split_ifs; refl end

@[simp] lemma count_cons_self (a : α) (l : list α) : count a (a::l) = count a l + 1 := if_pos rfl

@[simp, priority 990]
lemma count_cons_of_ne {a b : α} (h : a ≠ b) (l : list α) : count a (b::l) = count a l := if_neg h

lemma count_tail : Π (l : list α) (a : α) (h : 0 < l.length),
  l.tail.count a = l.count a - ite (a = list.nth_le l 0 h) 1 0
| (_ :: _) a h := by { rw [count_cons], split_ifs; simp }

lemma count_le_length (a : α) (l : list α) : count a l ≤ l.length :=
countp_le_length _

lemma sublist.count_le (h : l₁ <+ l₂) (a : α) : count a l₁ ≤ count a l₂ := h.countp_le _

lemma count_le_count_cons (a b : α) (l : list α) : count a l ≤ count a (b :: l) :=
(sublist_cons _ _).count_le _

lemma count_singleton (a : α) : count a [a] = 1 := if_pos rfl

lemma count_singleton' (a b : α) : count a [b] = ite (a = b) 1 0 := rfl

@[simp] lemma count_append (a : α) : ∀ l₁ l₂, count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
countp_append _

lemma count_join (l : list (list α)) (a : α) : l.join.count a = (l.map (count a)).sum :=
countp_join _ _

lemma count_concat (a : α) (l : list α) : count a (concat l a) = succ (count a l) :=
by simp [-add_comm]

@[simp] lemma count_pos {a : α} {l : list α} : 0 < count a l ↔ a ∈ l :=
by simp only [count, countp_pos, exists_prop, exists_eq_right']

@[simp] lemma one_le_count_iff_mem {a : α} {l : list α} : 1 ≤ count a l ↔ a ∈ l :=
count_pos

@[simp, priority 980]
lemma count_eq_zero_of_not_mem {a : α} {l : list α} (h : a ∉ l) : count a l = 0 :=
decidable.by_contradiction $ λ h', h $ count_pos.1 (nat.pos_of_ne_zero h')

lemma not_mem_of_count_eq_zero {a : α} {l : list α} (h : count a l = 0) : a ∉ l :=
λ h', (count_pos.2 h').ne' h

@[simp] lemma count_eq_zero {a : α} {l} : count a l = 0 ↔ a ∉ l :=
⟨not_mem_of_count_eq_zero, count_eq_zero_of_not_mem⟩

@[simp] lemma count_eq_length {a : α} {l} : count a l = l.length ↔ ∀ b ∈ l, a = b :=
countp_eq_length _

@[simp] lemma count_replicate_self (a : α) (n : ℕ) : count a (replicate n a) = n :=
by rw [count, countp_eq_length_filter, filter_eq_self.2, length_replicate];
   exact λ b m, (eq_of_mem_replicate m).symm

lemma count_replicate (a b : α) (n : ℕ) : count a (replicate n b) = if a = b then n else 0 :=
begin
  split_ifs with h,
  exacts [h ▸ count_replicate_self _ _, count_eq_zero_of_not_mem $ mt eq_of_mem_replicate h]
end

theorem filter_eq (l : list α) (a : α) : l.filter (eq a) = replicate (count a l) a :=
by simp [eq_replicate, count, countp_eq_length_filter, @eq_comm _ _ a]

theorem filter_eq' (l : list α) (a : α) : l.filter (λ x, x = a) = replicate (count a l) a :=
by simp only [filter_eq, @eq_comm _ _ a]

lemma replicate_count_eq_of_count_eq_length  {a : α} {l : list α} (h : count a l = length l)  :
  replicate (count a l) a = l :=
(le_count_iff_replicate_sublist.mp le_rfl).eq_of_length $ (length_replicate (count a l) a).trans h

@[simp] lemma count_filter {p} [decidable_pred p]
  {a} {l : list α} (h : p a) : count a (filter p l) = count a l :=
by simp only [count, countp_filter, show (λ b, a = b ∧ p b) = eq a, by { ext b, constructor; cc }]

lemma count_bind {α β} [decidable_eq β] (l : list α) (f : α → list β) (x : β)  :
  count x (l.bind f) = sum (map (count x ∘ f) l) :=
by rw [list.bind, count_join, map_map]

@[simp] lemma count_map_of_injective {α β} [decidable_eq α] [decidable_eq β]
  (l : list α) (f : α → β) (hf : function.injective f) (x : α) :
  count (f x) (map f l) = count x l :=
by simp only [count, countp_map, (∘), hf.eq_iff]

lemma count_le_count_map [decidable_eq β] (l : list α) (f : α → β) (x : α) :
  count x l ≤ count (f x) (map f l) :=
begin
  rw [count, count, countp_map],
  exact countp_mono_left (λ y hyl, congr_arg f),
end

lemma count_erase (a b : α) : ∀ l : list α, count a (l.erase b) = count a l - ite (a = b) 1 0
| [] := by simp
| (c :: l) :=
begin
  rw [erase_cons],
  by_cases hc : c = b,
  { rw [if_pos hc, hc, count_cons', nat.add_sub_cancel] },
  { rw [if_neg hc, count_cons', count_cons', count_erase],
    by_cases ha : a = b,
    { rw [← ha, eq_comm] at hc,
      rw [if_pos ha, if_neg hc, add_zero, add_zero] },
    { rw [if_neg ha, tsub_zero, tsub_zero] } }
end

@[simp] lemma count_erase_self (a : α) (l : list α) : count a (list.erase l a) = count a l - 1 :=
by rw [count_erase, if_pos rfl]

@[simp] lemma count_erase_of_ne {a b : α} (ab : a ≠ b) (l : list α) :
  count a (l.erase b) = count a l :=
by rw [count_erase, if_neg ab, tsub_zero]

@[to_additive]
lemma prod_map_eq_pow_single [monoid β] {l : list α} (a : α) (f : α → β)
  (hf : ∀ a' ≠ a, a' ∈ l → f a' = 1) : (l.map f).prod = (f a) ^ (l.count a) :=
begin
  induction l with a' as h generalizing a,
  { rw [map_nil, prod_nil, count_nil, pow_zero] },
  { specialize h a (λ a' ha' hfa', hf a' ha' (mem_cons_of_mem _ hfa')),
    rw [list.map_cons, list.prod_cons, count_cons, h],
    split_ifs with ha',
    { rw [ha', pow_succ] },
    { rw [hf a' (ne.symm ha') (list.mem_cons_self a' as), one_mul] } }
end

@[to_additive]
lemma prod_eq_pow_single [monoid α] {l : list α} (a : α)
  (h : ∀ a' ≠ a, a' ∈ l → a' = 1) : l.prod = a ^ (l.count a) :=
trans (by rw [map_id'']) (prod_map_eq_pow_single a id h)

end count

end list


import topology.order.basic

open_locale topology
open filter set

variables {α : Type*}  [linear_order α] [no_max_order α] [no_min_order α]
  [topological_space α] [order_topology α]

-- TODO: golf the next proof

lemma has_basis_nhds_set_Iic (a : α) : (𝓝ˢ $ Iic a).has_basis (λ b, a < b) (λ b, Iio b) :=
⟨begin
  intros u,
  rw [mem_nhds_set_iff_forall],
  simp only [mem_Iic, exists_prop],
  split,
  { intros h,
    have : ∀ x ≤ a, ∃ p : α × α, x ∈ Ioo p.1 p.2 ∧ Ioo p.1 p.2 ⊆ u,
    { intros x hx,
      rcases (nhds_basis_Ioo x).mem_iff.mp (h x hx) with ⟨⟨c, d⟩, ⟨hc, hd⟩, H⟩,
      exact ⟨(c, d), ⟨hc, hd⟩, H⟩ },
    choose! p hp using this,
    rcases (nhds_basis_Ioo a).mem_iff.mp (h a le_rfl) with ⟨⟨c, d⟩, ⟨hc, hd⟩, H⟩,
    dsimp only at H hc hd,
    use [d, hd],
    rintros x (hx : x < d),
    cases le_or_lt x c with hx' hx',
    { cases hp x (hx'.trans hc.le) with H H',
      exact H' H },
    { exact H ⟨hx', hx⟩ }, },
  { rintros ⟨b, hb, hb'⟩ x hx,
    apply mem_of_superset _ hb',
    apply Iio_mem_nhds (hx.trans_lt hb) }
end⟩

lemma has_basis_nhds_set_Iic' [densely_ordered α] (a : α) : (𝓝ˢ $ Iic a).has_basis (λ b, a < b) (λ b, Iic b) :=
⟨λ u, begin
  rw (has_basis_nhds_set_Iic a).mem_iff,
  dsimp only,
  split; rintro ⟨b, hb, hb'⟩,
  { rcases exists_between hb with ⟨c, hc, hc'⟩,
    exact ⟨c, hc, subset_trans (Iic_subset_Iio.mpr hc') hb'⟩ },
  { exact ⟨b, hb, Iio_subset_Iic_self.trans hb'⟩ }
end⟩

lemma has_basis_nhds_set_Ici (a : α) : (𝓝ˢ $ Ici a).has_basis (λ b, b < a) (λ b, Ioi b) :=
@has_basis_nhds_set_Iic (order_dual α) _ _ _ _ _ _

lemma has_basis_nhds_set_Ici' [densely_ordered α] (a : α) : (𝓝ˢ $ Ici a).has_basis (λ b, b < a) (λ b, Ici b) :=
@has_basis_nhds_set_Iic' (order_dual α) _ _ _ _ _ _ _


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

import ..todo
import topology.separation

/-!
A formal roadmap for the shrinking lemma for local finite countable covers.

It contains the statement of the lemma, and an informal sketch of the proof,
along with references.

The lemma is now formalized as `exists_subset_Union_closure_subset` in `topology/shrinking_lemma`.
This file is preserved as an example of a formal roadmap.

The actual implementation differs from the roadmap in two aspects:

- it uses a custom `structure` with a `partial_order` instead of a combination
  of `sigma` and `subtype`;
- it provides a version for coverings of a closed set in a normal space. While mathematically it's
  almost the same (just add `sᶜ` to the covering), it's easier to prove a version for a closed set,
  then apply it to `univ` than to deal with coverings indexed by `option α`.
-/

open set

universes u v

/-- A point-finite open cover of a closed subset of a normal space can be "shrunk" to a new open
cover so that the closure of each new open set is contained in the corresponding original open
set. -/
lemma roadmap.shrinking_lemma {X : Type u} [topological_space X] [normal_space X]
  {s : set X} (hs : is_closed s) {α : Type v} (u : α → set X) (uo : ∀ a, is_open (u a))
  (uf : ∀ x, finite {a | x ∈ u a}) (su : s ⊆ Union u) :
  ∃ v : α → set X, s ⊆ Union v ∧ ∀ a, is_open (v a) ∧ closure (v a) ⊆ u a :=
todo
/-
Apply Zorn's lemma to
 T = Σ (i : set α), {v : α → set X // s ⊆ Union v ∧ (∀ a, is_open (v a)) ∧
                                      (∀ a ∈ i, closure (v a) ⊆ u a) ∧ (∀ a ∉ i, v a = u a)}
with the ordering
 ⟨i, v, _⟩ ≤ ⟨i', v', _⟩ ↔ i ⊆ i' ∧ ∀ a ∈ i, v a = v' a
The hypothesis that `X` is normal implies that a maximal element must have `i = univ`.
Point-finiteness of `u` (hypothesis `uf`) implies that
the least upper bound of a chain in `T` again yields a covering of `s`.

Compare proofs in
* https://ncatlab.org/nlab/show/shrinking+lemma#ShrinkingLemmaForLocallyFiniteCountableCovers
* Bourbaki, General Topology, Chapter IX, §4.3
* Dugundji, Topology, Chapter VII, Theorem 6.1
-/


/-
Copyright (c) 2021 Kexing Ying. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kexing Ying
-/
import measure_theory.measure.measure_space
import analysis.complex.basic

/-!

# Vector valued measures

This file defines vector valued measures, which are σ-additive functions from a set to a add monoid
`M` such that it maps the empty set and non-measurable sets to zero. In the case
that `M = ℝ`, we called the vector measure a signed measure and write `signed_measure α`.
Similarly, when `M = ℂ`, we call the measure a complex measure and write `complex_measure α`.

## Main definitions

* `measure_theory.vector_measure` is a vector valued, σ-additive function that maps the empty
  and non-measurable set to zero.
* `measure_theory.vector_measure.map` is the pushforward of a vector measure along a function.
* `measure_theory.vector_measure.restrict` is the restriction of a vector measure on some set.

## Notation

* `v ≤[i] w` means that the vector measure `v` restricted on the set `i` is less than or equal
  to the vector measure `w` restricted on `i`, i.e. `v.restrict i ≤ w.restrict i`.

## Implementation notes

We require all non-measurable sets to be mapped to zero in order for the extensionality lemma
to only compare the underlying functions for measurable sets.

We use `has_sum` instead of `tsum` in the definition of vector measures in comparison to `measure`
since this provides summablity.

## Tags

vector measure, signed measure, complex measure
-/

noncomputable theory

open_locale classical big_operators nnreal ennreal measure_theory

namespace measure_theory

variables {α β : Type*} {m : measurable_space α}

/-- A vector measure on a measurable space `α` is a σ-additive `M`-valued function (for some `M`
an add monoid) such that the empty set and non-measurable sets are mapped to zero. -/
structure vector_measure (α : Type*) [measurable_space α]
  (M : Type*) [add_comm_monoid M] [topological_space M] :=
(measure_of' : set α → M)
(empty' : measure_of' ∅ = 0)
(not_measurable' ⦃i : set α⦄ : ¬ measurable_set i → measure_of' i = 0)
(m_Union' ⦃f : ℕ → set α⦄ :
  (∀ i, measurable_set (f i)) → pairwise (disjoint on f) →
  has_sum (λ i, measure_of' (f i)) (measure_of' (⋃ i, f i)))

/-- A `signed_measure` is a `ℝ`-vector measure. -/
abbreviation signed_measure (α : Type*) [measurable_space α] := vector_measure α ℝ
/-- A `complex_measure` is a `ℂ`-vector_measure. -/
abbreviation complex_measure (α : Type*) [measurable_space α] := vector_measure α ℂ

open set measure_theory

namespace vector_measure

section

variables {M : Type*} [add_comm_monoid M] [topological_space M]

include m

instance : has_coe_to_fun (vector_measure α M) (λ _, set α → M) :=
⟨vector_measure.measure_of'⟩

initialize_simps_projections vector_measure (measure_of' → apply)

@[simp]
lemma measure_of_eq_coe (v : vector_measure α M) : v.measure_of' = v := rfl

@[simp]
lemma empty (v : vector_measure α M) : v ∅ = 0 := v.empty'

lemma not_measurable (v : vector_measure α M)
  {i : set α} (hi : ¬ measurable_set i) : v i = 0 := v.not_measurable' hi

lemma m_Union (v : vector_measure α M) {f : ℕ → set α}
  (hf₁ : ∀ i, measurable_set (f i)) (hf₂ : pairwise (disjoint on f)) :
  has_sum (λ i, v (f i)) (v (⋃ i, f i)) :=
v.m_Union' hf₁ hf₂

lemma of_disjoint_Union_nat [t2_space M] (v : vector_measure α M) {f : ℕ → set α}
  (hf₁ : ∀ i, measurable_set (f i)) (hf₂ : pairwise (disjoint on f)) :
  v (⋃ i, f i) = ∑' i, v (f i) :=
(v.m_Union hf₁ hf₂).tsum_eq.symm

lemma coe_injective : @function.injective (vector_measure α M) (set α → M) coe_fn :=
λ v w h, by { cases v, cases w, congr' }

lemma ext_iff' (v w : vector_measure α M) :
  v = w ↔ ∀ i : set α, v i = w i :=
by rw [← coe_injective.eq_iff, function.funext_iff]

lemma ext_iff (v w : vector_measure α M) :
  v = w ↔ ∀ i : set α, measurable_set i → v i = w i :=
begin
  split,
  { rintro rfl _ _, refl },
  { rw ext_iff',
    intros h i,
    by_cases hi : measurable_set i,
    { exact h i hi },
    { simp_rw [not_measurable _ hi] } }
end

@[ext] lemma ext {s t : vector_measure α M}
  (h : ∀ i : set α, measurable_set i → s i = t i) : s = t :=
(ext_iff s t).2 h

variables [t2_space M] {v : vector_measure α M} {f : ℕ → set α}

lemma has_sum_of_disjoint_Union [countable β] {f : β → set α}
  (hf₁ : ∀ i, measurable_set (f i)) (hf₂ : pairwise (disjoint on f)) :
  has_sum (λ i, v (f i)) (v (⋃ i, f i)) :=
begin
  casesI nonempty_encodable β,
  set g := λ i : ℕ, ⋃ (b : β) (H : b ∈ encodable.decode₂ β i), f b with hg,
  have hg₁ : ∀ i, measurable_set (g i),
  { exact λ _, measurable_set.Union (λ b, measurable_set.Union $ λ _, hf₁ b) },
  have hg₂ : pairwise (disjoint on g),
  { exact encodable.Union_decode₂_disjoint_on hf₂ },
  have := v.of_disjoint_Union_nat hg₁ hg₂,
  rw [hg, encodable.Union_decode₂] at this,

  have hg₃ : (λ (i : β), v (f i)) = (λ i, v (g (encodable.encode i))),
  { ext, rw hg, simp only,
    congr, ext y, simp only [exists_prop, mem_Union, option.mem_def],
    split,
    { intro hy,
      refine ⟨x, (encodable.decode₂_is_partial_inv _ _).2 rfl, hy⟩ },
    { rintro ⟨b, hb₁, hb₂⟩,
      rw (encodable.decode₂_is_partial_inv _ _) at hb₁,
      rwa ← encodable.encode_injective hb₁ } },

  rw [summable.has_sum_iff, this, ← tsum_Union_decode₂],
  { exact v.empty },
  { rw hg₃, change summable ((λ i, v (g i)) ∘ encodable.encode),
    rw function.injective.summable_iff encodable.encode_injective,
    { exact (v.m_Union hg₁ hg₂).summable },
    { intros x hx,
      convert v.empty,
      simp only [Union_eq_empty, option.mem_def, not_exists, mem_range] at ⊢ hx,
      intros i hi,
      exact false.elim ((hx i) ((encodable.decode₂_is_partial_inv _ _).1 hi)) } }
end

lemma of_disjoint_Union [countable β] {f : β → set α}
  (hf₁ : ∀ i, measurable_set (f i)) (hf₂ : pairwise (disjoint on f)) :
  v (⋃ i, f i) = ∑' i, v (f i) :=
(has_sum_of_disjoint_Union hf₁ hf₂).tsum_eq.symm

lemma of_union {A B : set α}
  (h : disjoint A B) (hA : measurable_set A) (hB : measurable_set B) :
  v (A ∪ B) = v A + v B :=
begin
  rw [union_eq_Union, of_disjoint_Union, tsum_fintype, fintype.sum_bool, cond, cond],
  exacts [λ b, bool.cases_on b hB hA, pairwise_disjoint_on_bool.2 h]
end

lemma of_add_of_diff {A B : set α} (hA : measurable_set A) (hB : measurable_set B)
  (h : A ⊆ B) : v A + v (B \ A) = v B :=
begin
  rw [← of_union disjoint_sdiff_right hA (hB.diff hA), union_diff_cancel h],
  apply_instance,
end

lemma of_diff {M : Type*} [add_comm_group M]
  [topological_space M] [t2_space M] {v : vector_measure α M}
  {A B : set α} (hA : measurable_set A) (hB : measurable_set B)
  (h : A ⊆ B) : v (B \ A) = v B - (v A) :=
begin
  rw [← of_add_of_diff hA hB h, add_sub_cancel'],
  apply_instance,
end

lemma of_diff_of_diff_eq_zero {A B : set α}
  (hA : measurable_set A) (hB : measurable_set B) (h' : v (B \ A) = 0) :
  v (A \ B) + v B = v A :=
begin
  symmetry,
  calc v A = v (A \ B ∪ A ∩ B) : by simp only [set.diff_union_inter]
       ... = v (A \ B) + v (A ∩ B) :
  by { rw of_union,
       { rw disjoint.comm,
         exact set.disjoint_of_subset_left (A.inter_subset_right B) disjoint_sdiff_self_right },
       { exact hA.diff hB },
       { exact hA.inter hB } }
       ... = v (A \ B) + v (A ∩ B ∪ B \ A) :
  by { rw [of_union, h', add_zero],
       { exact set.disjoint_of_subset_left (A.inter_subset_left B) disjoint_sdiff_self_right },
       { exact hA.inter hB },
       { exact hB.diff hA } }
       ... = v (A \ B) + v B :
  by { rw [set.union_comm, set.inter_comm, set.diff_union_inter] }
end

lemma of_Union_nonneg {M : Type*} [topological_space M]
  [ordered_add_comm_monoid M] [order_closed_topology M]
  {v : vector_measure α M} (hf₁ : ∀ i, measurable_set (f i))
  (hf₂ : pairwise (disjoint on f)) (hf₃ : ∀ i, 0 ≤ v (f i)) :
  0 ≤ v (⋃ i, f i) :=
(v.of_disjoint_Union_nat hf₁ hf₂).symm ▸ tsum_nonneg hf₃

lemma of_Union_nonpos {M : Type*} [topological_space M]
  [ordered_add_comm_monoid M] [order_closed_topology M]
  {v : vector_measure α M} (hf₁ : ∀ i, measurable_set (f i))
  (hf₂ : pairwise (disjoint on f)) (hf₃ : ∀ i, v (f i) ≤ 0) :
  v (⋃ i, f i) ≤ 0 :=
(v.of_disjoint_Union_nat hf₁ hf₂).symm ▸ tsum_nonpos hf₃

lemma of_nonneg_disjoint_union_eq_zero {s : signed_measure α} {A B : set α}
  (h : disjoint A B) (hA₁ : measurable_set A) (hB₁ : measurable_set B)
  (hA₂ : 0 ≤ s A) (hB₂ : 0 ≤ s B)
  (hAB : s (A ∪ B) = 0) : s A = 0 :=
begin
  rw of_union h hA₁ hB₁ at hAB,
  linarith,
  apply_instance,
end

lemma of_nonpos_disjoint_union_eq_zero {s : signed_measure α} {A B : set α}
  (h : disjoint A B) (hA₁ : measurable_set A) (hB₁ : measurable_set B)
  (hA₂ : s A ≤ 0) (hB₂ : s B ≤ 0)
  (hAB : s (A ∪ B) = 0) : s A = 0 :=
begin
  rw of_union h hA₁ hB₁ at hAB,
  linarith,
  apply_instance,
end

end

section has_smul
variables {M : Type*} [add_comm_monoid M] [topological_space M]
variables {R : Type*} [semiring R] [distrib_mul_action R M] [has_continuous_const_smul R M]

include m

/-- Given a real number `r` and a signed measure `s`, `smul r s` is the signed
measure corresponding to the function `r • s`. -/
def smul (r : R) (v : vector_measure α M) : vector_measure α M :=
{ measure_of' := r • v,
  empty' := by rw [pi.smul_apply, empty, smul_zero],
  not_measurable' := λ _ hi, by rw [pi.smul_apply, v.not_measurable hi, smul_zero],
  m_Union' := λ _ hf₁ hf₂, has_sum.const_smul _ (v.m_Union hf₁ hf₂) }

instance : has_smul R (vector_measure α M) := ⟨smul⟩

@[simp] lemma coe_smul (r : R) (v : vector_measure α M) : ⇑(r • v) = r • v := rfl
lemma smul_apply (r : R) (v : vector_measure α M) (i : set α) :
  (r • v) i = r • v i := rfl

end has_smul

section add_comm_monoid

variables {M : Type*} [add_comm_monoid M] [topological_space M]

include m

instance : has_zero (vector_measure α M) :=
⟨⟨0, rfl, λ _ _, rfl, λ _ _ _, has_sum_zero⟩⟩

instance : inhabited (vector_measure α M) := ⟨0⟩

@[simp] lemma coe_zero : ⇑(0 : vector_measure α M) = 0 := rfl
lemma zero_apply (i : set α) : (0 : vector_measure α M) i = 0 := rfl

variables [has_continuous_add M]

/-- The sum of two vector measure is a vector measure. -/
def add (v w : vector_measure α M) : vector_measure α M :=
{ measure_of' := v + w,
  empty' := by simp,
  not_measurable' := λ _ hi,
    by simp [v.not_measurable hi, w.not_measurable hi],
  m_Union' := λ f hf₁ hf₂,
    has_sum.add (v.m_Union hf₁ hf₂) (w.m_Union hf₁ hf₂) }

instance : has_add (vector_measure α M) := ⟨add⟩

@[simp] lemma coe_add (v w : vector_measure α M) : ⇑(v + w) = v + w := rfl
lemma add_apply (v w : vector_measure α M) (i : set α) : (v + w) i = v i + w i := rfl

instance : add_comm_monoid (vector_measure α M) :=
function.injective.add_comm_monoid _ coe_injective coe_zero coe_add (λ _ _, coe_smul _ _)

/-- `coe_fn` is an `add_monoid_hom`. -/
@[simps]
def coe_fn_add_monoid_hom : vector_measure α M →+ (set α → M) :=
{ to_fun := coe_fn, map_zero' := coe_zero, map_add' := coe_add }

end add_comm_monoid

section add_comm_group

variables {M : Type*} [add_comm_group M] [topological_space M] [topological_add_group M]

include m

/-- The negative of a vector measure is a vector measure. -/
def neg (v : vector_measure α M) : vector_measure α M :=
{ measure_of' := -v,
  empty' := by simp,
  not_measurable' := λ _ hi, by simp [v.not_measurable hi],
  m_Union' := λ f hf₁ hf₂, has_sum.neg $ v.m_Union hf₁ hf₂ }

instance : has_neg (vector_measure α M) := ⟨neg⟩

@[simp] lemma coe_neg (v : vector_measure α M) : ⇑(-v) = - v := rfl
lemma neg_apply (v : vector_measure α M) (i : set α) :(-v) i = - v i := rfl

/-- The difference of two vector measure is a vector measure. -/
def sub (v w : vector_measure α M) : vector_measure α M :=
{ measure_of' := v - w,
  empty' := by simp,
  not_measurable' := λ _ hi,
    by simp [v.not_measurable hi, w.not_measurable hi],
  m_Union' := λ f hf₁ hf₂,
    has_sum.sub (v.m_Union hf₁ hf₂)
      (w.m_Union hf₁ hf₂) }

instance : has_sub (vector_measure α M) := ⟨sub⟩

@[simp] lemma coe_sub (v w : vector_measure α M) : ⇑(v - w) = v - w := rfl
lemma sub_apply (v w : vector_measure α M) (i : set α) : (v - w) i = v i - w i := rfl

instance : add_comm_group (vector_measure α M) :=
function.injective.add_comm_group _ coe_injective coe_zero coe_add coe_neg coe_sub
  (λ _ _, coe_smul _ _) (λ _ _, coe_smul _ _)

end add_comm_group

section distrib_mul_action
variables {M : Type*} [add_comm_monoid M] [topological_space M]
variables {R : Type*} [semiring R] [distrib_mul_action R M] [has_continuous_const_smul R M]

include m

instance [has_continuous_add M] : distrib_mul_action R (vector_measure α M) :=
function.injective.distrib_mul_action coe_fn_add_monoid_hom coe_injective coe_smul

end distrib_mul_action

section module

variables {M : Type*} [add_comm_monoid M] [topological_space M]
variables {R : Type*} [semiring R] [module R M] [has_continuous_const_smul R M]

include m

instance [has_continuous_add M] : module R (vector_measure α M) :=
function.injective.module R coe_fn_add_monoid_hom coe_injective coe_smul

end module

end vector_measure

namespace measure

include m

/-- A finite measure coerced into a real function is a signed measure. -/
@[simps]
def to_signed_measure (μ : measure α) [hμ : is_finite_measure μ] : signed_measure α :=
{ measure_of' := λ i : set α, if measurable_set i then (μ.measure_of i).to_real else 0,
  empty' := by simp [μ.empty],
  not_measurable' := λ _ hi, if_neg hi,
  m_Union' :=
  begin
    intros _ hf₁ hf₂,
    rw [μ.m_Union hf₁ hf₂, ennreal.tsum_to_real_eq, if_pos (measurable_set.Union hf₁),
        summable.has_sum_iff],
    { congr, ext n, rw if_pos (hf₁ n) },
    { refine @summable_of_nonneg_of_le _ (ennreal.to_real ∘ μ ∘ f) _ _ _ _,
      { intro, split_ifs,
        exacts [ennreal.to_real_nonneg, le_rfl] },
      { intro, split_ifs,
        exacts [le_rfl, ennreal.to_real_nonneg] },
        exact summable_measure_to_real hf₁ hf₂ },
    { intros a ha,
      apply ne_of_lt hμ.measure_univ_lt_top,
      rw [eq_top_iff, ← ha, outer_measure.measure_of_eq_coe, coe_to_outer_measure],
      exact measure_mono (set.subset_univ _) }
  end }

lemma to_signed_measure_apply_measurable {μ : measure α} [is_finite_measure μ]
  {i : set α} (hi : measurable_set i) :
  μ.to_signed_measure i = (μ i).to_real :=
if_pos hi

-- Without this lemma, `singular_part_neg` in `measure_theory.decomposition.lebesgue` is
-- extremely slow
lemma to_signed_measure_congr {μ ν : measure α} [is_finite_measure μ] [is_finite_measure ν]
  (h : μ = ν) : μ.to_signed_measure = ν.to_signed_measure :=
by { congr, exact h }

lemma to_signed_measure_eq_to_signed_measure_iff
  {μ ν : measure α} [is_finite_measure μ] [is_finite_measure ν] :
  μ.to_signed_measure = ν.to_signed_measure ↔ μ = ν :=
begin
  refine ⟨λ h, _, λ h, _⟩,
  { ext1 i hi,
    have : μ.to_signed_measure i = ν.to_signed_measure i,
    { rw h },
    rwa [to_signed_measure_apply_measurable hi, to_signed_measure_apply_measurable hi,
        ennreal.to_real_eq_to_real] at this;
    { exact measure_ne_top _ _ } },
  { congr, assumption }
end

@[simp] lemma to_signed_measure_zero :
  (0 : measure α).to_signed_measure = 0 :=
by { ext i hi, simp }

@[simp] lemma to_signed_measure_add (μ ν : measure α) [is_finite_measure μ] [is_finite_measure ν] :
  (μ + ν).to_signed_measure = μ.to_signed_measure + ν.to_signed_measure :=
begin
  ext i hi,
  rw [to_signed_measure_apply_measurable hi, add_apply,
      ennreal.to_real_add (ne_of_lt (measure_lt_top _ _ )) (ne_of_lt (measure_lt_top _ _)),
      vector_measure.add_apply, to_signed_measure_apply_measurable hi,
      to_signed_measure_apply_measurable hi],
  all_goals { apply_instance }
end

@[simp] lemma to_signed_measure_smul (μ : measure α) [is_finite_measure μ] (r : ℝ≥0) :
  (r • μ).to_signed_measure = r • μ.to_signed_measure :=
begin
  ext i hi,
  rw [to_signed_measure_apply_measurable hi, vector_measure.smul_apply,
      to_signed_measure_apply_measurable hi, coe_smul, pi.smul_apply,
      ennreal.to_real_smul],
end

/-- A measure is a vector measure over `ℝ≥0∞`. -/
@[simps]
def to_ennreal_vector_measure (μ : measure α) : vector_measure α ℝ≥0∞ :=
{ measure_of' := λ i : set α, if measurable_set i then μ i else 0,
  empty' := by simp [μ.empty],
  not_measurable' := λ _ hi, if_neg hi,
  m_Union' := λ _ hf₁ hf₂,
  begin
    rw summable.has_sum_iff ennreal.summable,
    { rw [if_pos (measurable_set.Union hf₁), measure_theory.measure_Union hf₂ hf₁],
      exact tsum_congr (λ n, if_pos (hf₁ n)) },
  end }

lemma to_ennreal_vector_measure_apply_measurable
  {μ : measure α} {i : set α} (hi : measurable_set i) :
  μ.to_ennreal_vector_measure i = μ i :=
if_pos hi

@[simp] lemma to_ennreal_vector_measure_zero :
  (0 : measure α).to_ennreal_vector_measure = 0 :=
by { ext i hi, simp }

@[simp] lemma to_ennreal_vector_measure_add (μ ν : measure α) :
  (μ + ν).to_ennreal_vector_measure = μ.to_ennreal_vector_measure + ν.to_ennreal_vector_measure :=
begin
  refine measure_theory.vector_measure.ext (λ i hi, _),
  rw [to_ennreal_vector_measure_apply_measurable hi, add_apply, vector_measure.add_apply,
      to_ennreal_vector_measure_apply_measurable hi, to_ennreal_vector_measure_apply_measurable hi]
end

lemma to_signed_measure_sub_apply {μ ν : measure α} [is_finite_measure μ] [is_finite_measure ν]
  {i : set α} (hi : measurable_set i) :
  (μ.to_signed_measure - ν.to_signed_measure) i = (μ i).to_real - (ν i).to_real :=
begin
  rw [vector_measure.sub_apply, to_signed_measure_apply_measurable hi,
      measure.to_signed_measure_apply_measurable hi, sub_eq_add_neg]
end

end measure

namespace vector_measure

open measure

section

/-- A vector measure over `ℝ≥0∞` is a measure. -/
def ennreal_to_measure {m : measurable_space α} (v : vector_measure α ℝ≥0∞) : measure α :=
of_measurable (λ s _, v s) v.empty (λ f hf₁ hf₂, v.of_disjoint_Union_nat hf₁ hf₂)

lemma ennreal_to_measure_apply {m : measurable_space α} {v : vector_measure α ℝ≥0∞}
  {s : set α} (hs : measurable_set s) : ennreal_to_measure v s = v s :=
by rw [ennreal_to_measure, of_measurable_apply _ hs]

/-- The equiv between `vector_measure α ℝ≥0∞` and `measure α` formed by
`measure_theory.vector_measure.ennreal_to_measure` and
`measure_theory.measure.to_ennreal_vector_measure`. -/
@[simps] def equiv_measure [measurable_space α] : vector_measure α ℝ≥0∞ ≃ measure α :=
{ to_fun := ennreal_to_measure,
  inv_fun := to_ennreal_vector_measure,
  left_inv := λ _, ext (λ s hs,
    by rw [to_ennreal_vector_measure_apply_measurable hs, ennreal_to_measure_apply hs]),
  right_inv := λ _, measure.ext (λ s hs,
    by rw [ennreal_to_measure_apply hs, to_ennreal_vector_measure_apply_measurable hs]) }

end

section

variables [measurable_space α] [measurable_space β]
variables {M : Type*} [add_comm_monoid M] [topological_space M]
variables (v : vector_measure α M)

/-- The pushforward of a vector measure along a function. -/
def map (v : vector_measure α M) (f : α → β) :
  vector_measure β M :=
if hf : measurable f then
{ measure_of' := λ s, if measurable_set s then v (f ⁻¹' s) else 0,
  empty' := by simp,
  not_measurable' := λ i hi, if_neg hi,
  m_Union' :=
  begin
    intros g hg₁ hg₂,
    convert v.m_Union (λ i, hf (hg₁ i)) (λ i j hij, (hg₂ hij).preimage _),
    { ext i, rw if_pos (hg₁ i) },
    { rw [preimage_Union, if_pos (measurable_set.Union hg₁)] },
  end } else 0

lemma map_not_measurable {f : α → β} (hf : ¬ measurable f) : v.map f = 0 :=
dif_neg hf

lemma map_apply {f : α → β} (hf : measurable f) {s : set β} (hs : measurable_set s) :
  v.map f s = v (f ⁻¹' s) :=
by { rw [map, dif_pos hf], exact if_pos hs }

@[simp] lemma map_id : v.map id = v :=
ext (λ i hi, by rw [map_apply v measurable_id hi, preimage_id])

@[simp] lemma map_zero (f : α → β) : (0 : vector_measure α M).map f = 0 :=
begin
  by_cases hf : measurable f,
  { ext i hi,
    rw [map_apply _ hf hi, zero_apply, zero_apply] },
  { exact dif_neg hf }
end

section

variables {N : Type*} [add_comm_monoid N] [topological_space N]

/-- Given a vector measure `v` on `M` and a continuous add_monoid_hom `f : M → N`, `f ∘ v` is a
vector measure on `N`. -/
def map_range (v : vector_measure α M) (f : M →+ N) (hf : continuous f) : vector_measure α N :=
{ measure_of' := λ s, f (v s),
  empty' := by rw [empty, add_monoid_hom.map_zero],
  not_measurable' := λ i hi, by rw [not_measurable v hi, add_monoid_hom.map_zero],
  m_Union' := λ g hg₁ hg₂, has_sum.map (v.m_Union hg₁ hg₂) f hf }

@[simp] lemma map_range_apply {f : M →+ N} (hf : continuous f) {s : set α} :
  v.map_range f hf s = f (v s) :=
rfl

@[simp] lemma map_range_id :
  v.map_range (add_monoid_hom.id M) continuous_id = v :=
by { ext, refl }

@[simp] lemma map_range_zero {f : M →+ N} (hf : continuous f) :
  map_range (0 : vector_measure α M) f hf = 0 :=
by { ext, simp }

section has_continuous_add

variables [has_continuous_add M] [has_continuous_add N]

@[simp] lemma map_range_add {v w : vector_measure α M} {f : M →+ N} (hf : continuous f) :
  (v + w).map_range f hf = v.map_range f hf + w.map_range f hf :=
by { ext, simp }

/-- Given a continuous add_monoid_hom `f : M → N`, `map_range_hom` is the add_monoid_hom mapping the
vector measure `v` on `M` to the vector measure `f ∘ v` on `N`. -/
def map_range_hom (f : M →+ N) (hf : continuous f) : vector_measure α M →+ vector_measure α N :=
{ to_fun := λ v, v.map_range f hf,
  map_zero' := map_range_zero hf,
  map_add' := λ _ _, map_range_add hf }

end has_continuous_add

section module

variables {R : Type*} [semiring R] [module R M] [module R N]
variables [has_continuous_add M] [has_continuous_add N]
  [has_continuous_const_smul R M] [has_continuous_const_smul R N]

/-- Given a continuous linear map `f : M → N`, `map_rangeₗ` is the linear map mapping the
vector measure `v` on `M` to the vector measure `f ∘ v` on `N`. -/
def map_rangeₗ (f : M →ₗ[R] N) (hf : continuous f) : vector_measure α M →ₗ[R] vector_measure α N :=
{ to_fun := λ v, v.map_range f.to_add_monoid_hom hf,
  map_add' := λ _ _, map_range_add hf,
  map_smul' := by { intros, ext, simp } }

end module

end

/-- The restriction of a vector measure on some set. -/
def restrict (v : vector_measure α M) (i : set α) :
  vector_measure α M :=
if hi : measurable_set i then
{ measure_of' := λ s, if measurable_set s then v (s ∩ i) else 0,
  empty' := by simp,
  not_measurable' := λ i hi, if_neg hi,
  m_Union' :=
  begin
    intros f hf₁ hf₂,
    convert v.m_Union (λ n, (hf₁ n).inter hi)
      (hf₂.mono $ λ i j, disjoint.mono inf_le_left inf_le_left),
    { ext n, rw if_pos (hf₁ n) },
    { rw [Union_inter, if_pos (measurable_set.Union hf₁)] }
  end } else 0

lemma restrict_not_measurable {i : set α} (hi : ¬ measurable_set i) :
  v.restrict i = 0 :=
dif_neg hi

lemma restrict_apply {i : set α} (hi : measurable_set i)
  {j : set α} (hj : measurable_set j) : v.restrict i j = v (j ∩ i) :=
by { rw [restrict, dif_pos hi], exact if_pos hj }

lemma restrict_eq_self {i : set α} (hi : measurable_set i)
  {j : set α} (hj : measurable_set j) (hij : j ⊆ i) : v.restrict i j = v j :=
by rw [restrict_apply v hi hj, inter_eq_left_iff_subset.2 hij]

@[simp] lemma restrict_empty : v.restrict ∅ = 0 :=
ext (λ i hi, by rw [restrict_apply v measurable_set.empty hi, inter_empty, v.empty, zero_apply])

@[simp] lemma restrict_univ : v.restrict univ = v :=
ext (λ i hi, by rw [restrict_apply v measurable_set.univ hi, inter_univ])

@[simp] lemma restrict_zero {i : set α} :
  (0 : vector_measure α M).restrict i = 0 :=
begin
  by_cases hi : measurable_set i,
  { ext j hj, rw [restrict_apply 0 hi hj], refl },
  { exact dif_neg hi }
end

section has_continuous_add

variables [has_continuous_add M]

lemma map_add (v w : vector_measure α M) (f : α → β) :
  (v + w).map f = v.map f + w.map f :=
begin
  by_cases hf : measurable f,
  { ext i hi,
    simp [map_apply _ hf hi] },
  { simp [map, dif_neg hf] }
end

/-- `vector_measure.map` as an additive monoid homomorphism. -/
@[simps] def map_gm (f : α → β) : vector_measure α M →+ vector_measure β M :=
{ to_fun := λ v, v.map f,
  map_zero' := map_zero f,
  map_add' := λ _ _, map_add _ _ f }

lemma restrict_add (v w : vector_measure α M) (i : set α) :
  (v + w).restrict i = v.restrict i + w.restrict i :=
begin
  by_cases hi : measurable_set i,
  { ext j hj,
    simp [restrict_apply _ hi hj] },
  { simp [restrict_not_measurable _ hi] }
end

/--`vector_measure.restrict` as an additive monoid homomorphism. -/
@[simps] def restrict_gm (i : set α) : vector_measure α M →+ vector_measure α M :=
{ to_fun := λ v, v.restrict i,
  map_zero' := restrict_zero,
  map_add' := λ _ _, restrict_add _ _ i }

end has_continuous_add

end

section

variables [measurable_space β]
variables {M : Type*} [add_comm_monoid M] [topological_space M]
variables {R : Type*} [semiring R] [distrib_mul_action R M] [has_continuous_const_smul R M]

include m

@[simp] lemma map_smul {v : vector_measure α M} {f : α → β} (c : R) :
  (c • v).map f = c • v.map f :=
begin
  by_cases hf : measurable f,
  { ext i hi,
    simp [map_apply _ hf hi] },
  { simp only [map, dif_neg hf],
    -- `smul_zero` does not work since we do not require `has_continuous_add`
    ext i hi, simp }
end

@[simp] lemma restrict_smul {v :vector_measure α M} {i : set α} (c : R) :
  (c • v).restrict i = c • v.restrict i :=
begin
  by_cases hi : measurable_set i,
  { ext j hj,
    simp [restrict_apply _ hi hj] },
  { simp only [restrict_not_measurable _ hi],
    -- `smul_zero` does not work since we do not require `has_continuous_add`
    ext j hj, simp }
end

end

section

variables [measurable_space β]
variables {M : Type*} [add_comm_monoid M] [topological_space M]
variables {R : Type*} [semiring R] [module R M]
  [has_continuous_const_smul R M] [has_continuous_add M]

include m

/-- `vector_measure.map` as a linear map. -/
@[simps] def mapₗ (f : α → β) : vector_measure α M →ₗ[R] vector_measure β M :=
{ to_fun := λ v, v.map f,
  map_add' := λ _ _, map_add _ _ f,
  map_smul' := λ _ _, map_smul _ }

/-- `vector_measure.restrict` as an additive monoid homomorphism. -/
@[simps] def restrictₗ (i : set α) : vector_measure α M →ₗ[R] vector_measure α M :=
{ to_fun := λ v, v.restrict i,
  map_add' := λ _ _, restrict_add _ _ i,
  map_smul' := λ _ _, restrict_smul _ }

end

section

variables {M : Type*} [topological_space M] [add_comm_monoid M] [partial_order M]

include m

/-- Vector measures over a partially ordered monoid is partially ordered.

This definition is consistent with `measure.partial_order`. -/
instance : partial_order (vector_measure α M) :=
{ le          := λ v w, ∀ i, measurable_set i → v i ≤ w i,
  le_refl     := λ v i hi, le_rfl,
  le_trans    := λ u v w h₁ h₂ i hi, le_trans (h₁ i hi) (h₂ i hi),
  le_antisymm := λ v w h₁ h₂, ext (λ i hi, le_antisymm (h₁ i hi) (h₂ i hi)) }

variables {u v w : vector_measure α M}

lemma le_iff : v ≤ w ↔ ∀ i, measurable_set i → v i ≤ w i :=
iff.rfl

lemma le_iff' : v ≤ w ↔ ∀ i, v i ≤ w i :=
begin
  refine ⟨λ h i, _, λ h i hi, h i⟩,
  by_cases hi : measurable_set i,
  { exact h i hi },
  { rw [v.not_measurable hi, w.not_measurable hi] }
end

end

localized "notation (name := vector_measure.restrict) v ` ≤[`:50 i:50 `] `:0 w:50 :=
  measure_theory.vector_measure.restrict v i ≤ measure_theory.vector_measure.restrict w i"
  in measure_theory

section

variables {M : Type*} [topological_space M] [add_comm_monoid M] [partial_order M]
variables (v w : vector_measure α M)

lemma restrict_le_restrict_iff {i : set α} (hi : measurable_set i) :
  v ≤[i] w ↔ ∀ ⦃j⦄, measurable_set j → j ⊆ i → v j ≤ w j :=
⟨λ h j hj₁ hj₂, (restrict_eq_self v hi hj₁ hj₂) ▸ (restrict_eq_self w hi hj₁ hj₂) ▸ h j hj₁,
 λ h, le_iff.1 (λ j hj, (restrict_apply v hi hj).symm ▸ (restrict_apply w hi hj).symm ▸
   h (hj.inter hi) (set.inter_subset_right j i))⟩

lemma subset_le_of_restrict_le_restrict {i : set α}
  (hi : measurable_set i) (hi₂ : v ≤[i] w) {j : set α} (hj : j ⊆ i) :
  v j ≤ w j :=
begin
  by_cases hj₁ : measurable_set j,
  { exact (restrict_le_restrict_iff _ _ hi).1 hi₂ hj₁ hj },
  { rw [v.not_measurable hj₁, w.not_measurable hj₁] },
end

lemma restrict_le_restrict_of_subset_le {i : set α}
  (h : ∀ ⦃j⦄, measurable_set j → j ⊆ i → v j ≤ w j) : v ≤[i] w :=
begin
  by_cases hi : measurable_set i,
  { exact (restrict_le_restrict_iff _ _ hi).2 h },
  { rw [restrict_not_measurable v hi, restrict_not_measurable w hi],
    exact le_rfl },
end

lemma restrict_le_restrict_subset {i j : set α}
  (hi₁ : measurable_set i) (hi₂ : v ≤[i] w) (hij : j ⊆ i) : v ≤[j] w :=
restrict_le_restrict_of_subset_le v w (λ k hk₁ hk₂,
  subset_le_of_restrict_le_restrict v w hi₁ hi₂ (set.subset.trans hk₂ hij))

lemma le_restrict_empty : v ≤[∅] w :=
begin
  intros j hj,
  rw [restrict_empty, restrict_empty]
end

lemma le_restrict_univ_iff_le : v ≤[univ] w ↔ v ≤ w :=
begin
  split,
  { intros h s hs,
    have := h s hs,
    rwa [restrict_apply _ measurable_set.univ hs, inter_univ,
         restrict_apply _ measurable_set.univ hs, inter_univ] at this },
  { intros h s hs,
    rw [restrict_apply _ measurable_set.univ hs, inter_univ,
        restrict_apply _ measurable_set.univ hs, inter_univ],
    exact h s hs }
end

end

section

variables {M : Type*} [topological_space M] [ordered_add_comm_group M] [topological_add_group M]
variables (v w : vector_measure α M)

lemma neg_le_neg {i : set α} (hi : measurable_set i) (h : v ≤[i] w) : -w ≤[i] -v :=
begin
  intros j hj₁,
  rw [restrict_apply _ hi hj₁, restrict_apply _ hi hj₁, neg_apply, neg_apply],
  refine neg_le_neg _,
  rw [← restrict_apply _ hi hj₁, ← restrict_apply _ hi hj₁],
  exact h j hj₁,
end

@[simp]
lemma neg_le_neg_iff {i : set α} (hi : measurable_set i) : -w ≤[i] -v ↔ v ≤[i] w :=
⟨λ h, neg_neg v ▸ neg_neg w ▸ neg_le_neg _ _ hi h, λ h, neg_le_neg _ _ hi h⟩

end

section

variables {M : Type*} [topological_space M] [ordered_add_comm_monoid M] [order_closed_topology M]
variables (v w : vector_measure α M) {i j : set α}

lemma restrict_le_restrict_Union {f : ℕ → set α}
  (hf₁ : ∀ n, measurable_set (f n)) (hf₂ : ∀ n, v ≤[f n] w) :
  v ≤[⋃ n, f n] w :=
begin
  refine restrict_le_restrict_of_subset_le v w (λ a ha₁ ha₂, _),
  have ha₃ : (⋃ n, a ∩ disjointed f n) = a,
  { rwa [← inter_Union, Union_disjointed, inter_eq_left_iff_subset] },
  have ha₄ : pairwise (disjoint on (λ n, a ∩ disjointed f n)),
  { exact (disjoint_disjointed _).mono (λ i j, disjoint.mono inf_le_right inf_le_right) },
  rw [← ha₃, v.of_disjoint_Union_nat _ ha₄, w.of_disjoint_Union_nat _ ha₄],
  refine tsum_le_tsum (λ n, (restrict_le_restrict_iff v w (hf₁ n)).1 (hf₂ n) _ _) _ _,
  { exact (ha₁.inter (measurable_set.disjointed hf₁ n)) },
  { exact set.subset.trans (set.inter_subset_right _ _) (disjointed_subset _ _) },
  { refine (v.m_Union (λ n, _) _).summable,
    { exact ha₁.inter (measurable_set.disjointed hf₁ n) },
    { exact (disjoint_disjointed _).mono (λ i j, disjoint.mono inf_le_right inf_le_right) } },
  { refine (w.m_Union (λ n, _) _).summable,
    { exact ha₁.inter (measurable_set.disjointed hf₁ n) },
    { exact (disjoint_disjointed _).mono (λ i j, disjoint.mono inf_le_right inf_le_right) } },
  { intro n, exact (ha₁.inter (measurable_set.disjointed hf₁ n)) },
  { exact λ n, ha₁.inter (measurable_set.disjointed hf₁ n) }
end

lemma restrict_le_restrict_countable_Union [countable β] {f : β → set α}
  (hf₁ : ∀ b, measurable_set (f b)) (hf₂ : ∀ b, v ≤[f b] w) :
  v ≤[⋃ b, f b] w :=
begin
  casesI nonempty_encodable β,
  rw ← encodable.Union_decode₂,
  refine restrict_le_restrict_Union v w _ _,
  { intro n, measurability },
  { intro n,
    cases encodable.decode₂ β n with b,
    { simp },
    { simp [hf₂ b] } }
end

lemma restrict_le_restrict_union
  (hi₁ : measurable_set i) (hi₂ : v ≤[i] w)
  (hj₁ : measurable_set j) (hj₂ : v ≤[j] w) :
  v ≤[i ∪ j] w :=
begin
  rw union_eq_Union,
  refine restrict_le_restrict_countable_Union v w _ _,
  { measurability },
  { rintro (_ | _); simpa }
end

end

section

variables {M : Type*} [topological_space M] [ordered_add_comm_monoid M]
variables (v w : vector_measure α M) {i j : set α}

lemma nonneg_of_zero_le_restrict (hi₂ : 0 ≤[i] v) :
  0 ≤ v i :=
begin
  by_cases hi₁ : measurable_set i,
  { exact (restrict_le_restrict_iff _ _ hi₁).1 hi₂ hi₁ set.subset.rfl },
  { rw v.not_measurable hi₁ },
end

lemma nonpos_of_restrict_le_zero (hi₂ : v ≤[i] 0) :
  v i ≤ 0 :=
begin
  by_cases hi₁ : measurable_set i,
  { exact (restrict_le_restrict_iff _ _ hi₁).1 hi₂ hi₁ set.subset.rfl },
  { rw v.not_measurable hi₁ }
end

lemma zero_le_restrict_not_measurable (hi : ¬ measurable_set i) :
  0 ≤[i] v :=
begin
  rw [restrict_zero, restrict_not_measurable _ hi],
  exact le_rfl,
end

lemma restrict_le_zero_of_not_measurable (hi : ¬ measurable_set i) :
  v ≤[i] 0 :=
begin
  rw [restrict_zero, restrict_not_measurable _ hi],
  exact le_rfl,
end

lemma measurable_of_not_zero_le_restrict (hi : ¬ 0 ≤[i] v) : measurable_set i :=
not.imp_symm (zero_le_restrict_not_measurable _) hi

lemma measurable_of_not_restrict_le_zero (hi : ¬ v ≤[i] 0) : measurable_set i :=
not.imp_symm (restrict_le_zero_of_not_measurable _) hi

lemma zero_le_restrict_subset (hi₁ : measurable_set i) (hij : j ⊆ i) (hi₂ : 0 ≤[i] v):
  0 ≤[j] v :=
restrict_le_restrict_of_subset_le _ _
  (λ k hk₁ hk₂, (restrict_le_restrict_iff _ _ hi₁).1 hi₂ hk₁ (set.subset.trans hk₂ hij))

lemma restrict_le_zero_subset (hi₁ : measurable_set i) (hij : j ⊆ i) (hi₂ : v ≤[i] 0):
  v ≤[j] 0 :=
restrict_le_restrict_of_subset_le _ _
  (λ k hk₁ hk₂, (restrict_le_restrict_iff _ _ hi₁).1 hi₂ hk₁ (set.subset.trans hk₂ hij))

end

section

variables {M : Type*} [topological_space M] [linear_ordered_add_comm_monoid M]
variables (v w : vector_measure α M) {i j : set α}

include m

lemma exists_pos_measure_of_not_restrict_le_zero (hi : ¬ v ≤[i] 0) :
  ∃ j : set α, measurable_set j ∧ j ⊆ i ∧ 0 < v j :=
begin
  have hi₁ : measurable_set i := measurable_of_not_restrict_le_zero _ hi,
  rw [restrict_le_restrict_iff _ _ hi₁] at hi,
  push_neg at hi,
  obtain ⟨j, hj₁, hj₂, hj⟩ := hi,
  exact ⟨j, hj₁, hj₂, hj⟩,
end

end

section

variables {M : Type*} [topological_space M] [add_comm_monoid M] [partial_order M]
  [covariant_class M M (+) (≤)] [has_continuous_add M]

include m

instance covariant_add_le :
  covariant_class (vector_measure α M) (vector_measure α M) (+) (≤) :=
⟨λ u v w h i hi, add_le_add_left (h i hi) _⟩

end

section

variables {L M N : Type*}
variables [add_comm_monoid L] [topological_space L] [add_comm_monoid M] [topological_space M]
  [add_comm_monoid N] [topological_space N]

include m

/-- A vector measure `v` is absolutely continuous with respect to a measure `μ` if for all sets
`s`, `μ s = 0`, we have `v s = 0`. -/
def absolutely_continuous (v : vector_measure α M) (w : vector_measure α N) :=
∀ ⦃s : set α⦄, w s = 0 → v s = 0

localized "infix (name := vector_measure.absolutely_continuous)
  ` ≪ᵥ `:50 := measure_theory.vector_measure.absolutely_continuous"
  in measure_theory

open_locale measure_theory

namespace absolutely_continuous

variables {v : vector_measure α M} {w : vector_measure α N}

lemma mk (h : ∀ ⦃s : set α⦄, measurable_set s → w s = 0 → v s = 0) : v ≪ᵥ w :=
begin
  intros s hs,
  by_cases hmeas : measurable_set s,
  { exact h hmeas hs },
  { exact not_measurable v hmeas }
end

@[refl] lemma refl (v : vector_measure α M) : v ≪ᵥ v :=
eq rfl

@[trans] lemma trans {u : vector_measure α L} {v : vector_measure α M} {w : vector_measure α N}
  (huv : u ≪ᵥ v) (hvw : v ≪ᵥ w) : u ≪ᵥ w :=
λ _ hs, huv $ hvw hs

lemma zero (v : vector_measure α N) : (0 : vector_measure α M) ≪ᵥ v :=
λ s _, vector_measure.zero_apply s

lemma neg_left {M : Type*} [add_comm_group M] [topological_space M] [topological_add_group M]
  {v : vector_measure α M} {w : vector_measure α N} (h : v ≪ᵥ w) : -v ≪ᵥ w :=
λ s hs, by { rw [neg_apply, h hs, neg_zero] }

lemma neg_right {N : Type*} [add_comm_group N] [topological_space N] [topological_add_group N]
  {v : vector_measure α M} {w : vector_measure α N} (h : v ≪ᵥ w) : v ≪ᵥ -w :=
begin
  intros s hs,
  rw [neg_apply, neg_eq_zero] at hs,
  exact h hs
end

lemma add [has_continuous_add M] {v₁ v₂ : vector_measure α M} {w : vector_measure α N}
  (hv₁ : v₁ ≪ᵥ w) (hv₂ : v₂ ≪ᵥ w) : v₁ + v₂ ≪ᵥ w :=
λ s hs, by { rw [add_apply, hv₁ hs, hv₂ hs, zero_add] }

lemma sub {M : Type*} [add_comm_group M] [topological_space M] [topological_add_group M]
  {v₁ v₂ : vector_measure α M} {w : vector_measure α N} (hv₁ : v₁ ≪ᵥ w) (hv₂ : v₂ ≪ᵥ w) :
  v₁ - v₂ ≪ᵥ w :=
λ s hs, by { rw [sub_apply, hv₁ hs, hv₂ hs, zero_sub, neg_zero] }

lemma smul {R : Type*} [semiring R] [distrib_mul_action R M] [has_continuous_const_smul R M]
  {r : R} {v : vector_measure α M} {w : vector_measure α N} (h : v ≪ᵥ w) :
  r • v ≪ᵥ w :=
λ s hs, by { rw [smul_apply, h hs, smul_zero] }

lemma map [measure_space β] (h : v ≪ᵥ w) (f : α → β) :
  v.map f ≪ᵥ w.map f :=
begin
  by_cases hf : measurable f,
  { refine mk (λ s hs hws, _),
    rw map_apply _ hf hs at hws ⊢,
    exact h hws },
  { intros s hs,
    rw [map_not_measurable v hf, zero_apply] }
end

lemma ennreal_to_measure {μ : vector_measure α ℝ≥0∞} :
  (∀ ⦃s : set α⦄, μ.ennreal_to_measure s = 0 → v s = 0) ↔ v ≪ᵥ μ :=
begin
  split; intro h,
  { refine mk (λ s hmeas hs, h _),
    rw [← hs, ennreal_to_measure_apply hmeas] },
  { intros s hs,
    by_cases hmeas : measurable_set s,
    { rw ennreal_to_measure_apply hmeas at hs,
      exact h hs },
    { exact not_measurable v hmeas } },
end

end absolutely_continuous

/-- Two vector measures `v` and `w` are said to be mutually singular if there exists a measurable
set `s`, such that for all `t ⊆ s`, `v t = 0` and for all `t ⊆ sᶜ`, `w t = 0`.

We note that we do not require the measurability of `t` in the definition since this makes it easier
to use. This is equivalent to the definition which requires measurability. To prove
`mutually_singular` with the measurability condition, use
`measure_theory.vector_measure.mutually_singular.mk`. -/
def mutually_singular (v : vector_measure α M) (w : vector_measure α N) : Prop :=
∃ (s : set α), measurable_set s ∧ (∀ t ⊆ s, v t = 0) ∧ (∀ t ⊆ sᶜ, w t = 0)

localized "infix (name := vector_measure.mutually_singular)
  ` ⟂ᵥ `:60 := measure_theory.vector_measure.mutually_singular" in measure_theory

namespace mutually_singular

variables {v v₁ v₂ : vector_measure α M} {w w₁ w₂ : vector_measure α N}

lemma mk (s : set α) (hs : measurable_set s)
  (h₁ : ∀ t ⊆ s, measurable_set t → v t = 0)
  (h₂ : ∀ t ⊆ sᶜ, measurable_set t → w t = 0) : v ⟂ᵥ w :=
begin
  refine ⟨s, hs, λ t hst, _, λ t hst, _⟩;
  by_cases ht : measurable_set t,
  { exact h₁ t hst ht },
  { exact not_measurable v ht },
  { exact h₂ t hst ht },
  { exact not_measurable w ht }
end

lemma symm (h : v ⟂ᵥ w) : w ⟂ᵥ v :=
let ⟨s, hmeas, hs₁, hs₂⟩ := h in
  ⟨sᶜ, hmeas.compl, hs₂, λ t ht, hs₁ _ (compl_compl s ▸ ht : t ⊆ s)⟩

lemma zero_right : v ⟂ᵥ (0 : vector_measure α N) :=
⟨∅, measurable_set.empty, λ t ht, (subset_empty_iff.1 ht).symm ▸ v.empty, λ _ _, zero_apply _⟩

lemma zero_left : (0 : vector_measure α M) ⟂ᵥ w :=
zero_right.symm

lemma add_left [t2_space N] [has_continuous_add M] (h₁ : v₁ ⟂ᵥ w) (h₂ : v₂ ⟂ᵥ w) : v₁ + v₂ ⟂ᵥ w :=
begin
  obtain ⟨u, hmu, hu₁, hu₂⟩ := h₁,
  obtain ⟨v, hmv, hv₁, hv₂⟩ := h₂,
  refine mk (u ∩ v) (hmu.inter hmv) (λ t ht hmt, _) (λ t ht hmt, _),
  { rw [add_apply, hu₁ _ (subset_inter_iff.1 ht).1, hv₁ _ (subset_inter_iff.1 ht).2, zero_add] },
  { rw compl_inter at ht,
    rw [(_ : t = (uᶜ ∩ t) ∪ (vᶜ \ uᶜ ∩ t)),
        of_union _ (hmu.compl.inter hmt) ((hmv.compl.diff hmu.compl).inter hmt),
        hu₂, hv₂, add_zero],
    { exact subset.trans (inter_subset_left _ _) (diff_subset _ _) },
    { exact inter_subset_left _ _ },
    { apply_instance },
    { exact disjoint_sdiff_self_right.mono (inter_subset_left _ _) (inter_subset_left _ _) },
    { apply subset.antisymm;
      intros x hx,
      { by_cases hxu' : x ∈ uᶜ,
        { exact or.inl ⟨hxu', hx⟩ },
        rcases ht hx with (hxu | hxv),
        exacts [false.elim (hxu' hxu), or.inr ⟨⟨hxv, hxu'⟩, hx⟩] },
      { rcases hx; exact hx.2 } } },
end

lemma add_right [t2_space M] [has_continuous_add N] (h₁ : v ⟂ᵥ w₁) (h₂ : v ⟂ᵥ w₂) : v ⟂ᵥ w₁ + w₂ :=
(add_left h₁.symm h₂.symm).symm

lemma smul_right {R : Type*} [semiring R] [distrib_mul_action R N] [has_continuous_const_smul R N]
  (r : R) (h : v ⟂ᵥ w) : v ⟂ᵥ r • w :=
let ⟨s, hmeas, hs₁, hs₂⟩ := h in
  ⟨s, hmeas, hs₁, λ t ht, by simp only [coe_smul, pi.smul_apply, hs₂ t ht, smul_zero]⟩

lemma smul_left {R : Type*} [semiring R] [distrib_mul_action R M] [has_continuous_const_smul R M]
  (r : R) (h : v ⟂ᵥ w) : r • v ⟂ᵥ w :=
(smul_right r h.symm).symm

lemma neg_left {M : Type*} [add_comm_group M] [topological_space M] [topological_add_group M]
  {v : vector_measure α M} {w : vector_measure α N} (h : v ⟂ᵥ w) : -v ⟂ᵥ w :=
begin
  obtain ⟨u, hmu, hu₁, hu₂⟩ := h,
  refine ⟨u, hmu, λ s hs, _, hu₂⟩,
  rw [neg_apply v s, neg_eq_zero],
  exact hu₁ s hs
end

lemma neg_right {N : Type*} [add_comm_group N] [topological_space N] [topological_add_group N]
  {v : vector_measure α M} {w : vector_measure α N} (h : v ⟂ᵥ w) : v ⟂ᵥ -w :=
h.symm.neg_left.symm

@[simp]
lemma neg_left_iff {M : Type*} [add_comm_group M] [topological_space M] [topological_add_group M]
  {v : vector_measure α M} {w : vector_measure α N} :
  -v ⟂ᵥ w ↔ v ⟂ᵥ w :=
⟨λ h, neg_neg v ▸ h.neg_left, neg_left⟩

@[simp]
lemma neg_right_iff {N : Type*} [add_comm_group N] [topological_space N] [topological_add_group N]
  {v : vector_measure α M} {w : vector_measure α N} :
  v ⟂ᵥ -w ↔ v ⟂ᵥ w :=
⟨λ h, neg_neg w ▸ h.neg_right, neg_right⟩

end mutually_singular

section trim

omit m

/-- Restriction of a vector measure onto a sub-σ-algebra. -/
@[simps] def trim {m n : measurable_space α} (v : vector_measure α M) (hle : m ≤ n) :
  @vector_measure α m M _ _ :=
{ measure_of' := λ i, if measurable_set[m] i then v i else 0,
  empty' := by rw [if_pos measurable_set.empty, v.empty],
  not_measurable' := λ i hi, by rw if_neg hi,
  m_Union' := λ f hf₁ hf₂,
  begin
    have hf₁' : ∀ k, measurable_set[n] (f k) := λ k, hle _ (hf₁ k),
    convert v.m_Union hf₁' hf₂,
    { ext n, rw if_pos (hf₁ n) },
    { rw if_pos (@measurable_set.Union _ _ m _ _ hf₁) }
  end }

variables {n : measurable_space α} {v : vector_measure α M}

lemma trim_eq_self : v.trim le_rfl = v :=
begin
  ext1 i hi,
  exact if_pos hi,
end

@[simp] lemma zero_trim (hle : m ≤ n) :
  (0 : vector_measure α M).trim hle = 0 :=
begin
  ext1 i hi,
  exact if_pos hi,
end

lemma trim_measurable_set_eq (hle : m ≤ n) {i : set α} (hi : measurable_set[m] i) :
  v.trim hle i = v i :=
if_pos hi

lemma restrict_trim (hle : m ≤ n) {i : set α} (hi : measurable_set[m] i) :
  @vector_measure.restrict α m M _ _ (v.trim hle) i = (v.restrict i).trim hle :=
begin
  ext j hj,
  rw [restrict_apply, trim_measurable_set_eq hle hj, restrict_apply, trim_measurable_set_eq],
  all_goals { measurability }
end

end trim

end

end vector_measure

namespace signed_measure

open vector_measure

open_locale measure_theory

include m

/-- The underlying function for `signed_measure.to_measure_of_zero_le`. -/
def to_measure_of_zero_le' (s : signed_measure α) (i : set α) (hi : 0 ≤[i] s)
  (j : set α) (hj : measurable_set j) : ℝ≥0∞ :=
@coe ℝ≥0 ℝ≥0∞ _ ⟨s.restrict i j, le_trans (by simp) (hi j hj)⟩

/-- Given a signed measure `s` and a positive measurable set `i`, `to_measure_of_zero_le`
provides the measure, mapping measurable sets `j` to `s (i ∩ j)`. -/
def to_measure_of_zero_le (s : signed_measure α) (i : set α)
  (hi₁ : measurable_set i) (hi₂ : 0 ≤[i] s) : measure α :=
measure.of_measurable (s.to_measure_of_zero_le' i hi₂)
  (by { simp_rw [to_measure_of_zero_le', s.restrict_apply hi₁ measurable_set.empty,
                 set.empty_inter i, s.empty], refl })
  begin
    intros f hf₁ hf₂,
    have h₁ : ∀ n, measurable_set (i ∩ f n) := λ n, hi₁.inter (hf₁ n),
    have h₂ : pairwise (disjoint on λ (n : ℕ), i ∩ f n),
    { intros n m hnm,
      exact (((hf₂ hnm).inf_left' i).inf_right' i) },
    simp only [to_measure_of_zero_le', s.restrict_apply hi₁ (measurable_set.Union hf₁),
               set.inter_comm, set.inter_Union, s.of_disjoint_Union_nat h₁ h₂,
               ennreal.some_eq_coe, id.def],
    have h : ∀ n, 0 ≤ s (i ∩ f n) :=
      λ n, s.nonneg_of_zero_le_restrict
          (s.zero_le_restrict_subset hi₁ (inter_subset_left _ _) hi₂),
    rw [nnreal.coe_tsum_of_nonneg h, ennreal.coe_tsum],
    { refine tsum_congr (λ n, _),
      simp_rw [s.restrict_apply hi₁ (hf₁ n), set.inter_comm] },
    { exact (nnreal.summable_coe_of_nonneg h).2 (s.m_Union h₁ h₂).summable }
  end

variables (s : signed_measure α) {i j : set α}

lemma to_measure_of_zero_le_apply (hi : 0 ≤[i] s)
  (hi₁ : measurable_set i) (hj₁ : measurable_set j) :
  s.to_measure_of_zero_le i hi₁ hi j =
  @coe ℝ≥0 ℝ≥0∞ _ ⟨s (i ∩ j), nonneg_of_zero_le_restrict s
    (zero_le_restrict_subset s hi₁ (set.inter_subset_left _ _) hi)⟩ :=
by simp_rw [to_measure_of_zero_le, measure.of_measurable_apply _ hj₁, to_measure_of_zero_le',
              s.restrict_apply hi₁ hj₁, set.inter_comm]

/-- Given a signed measure `s` and a negative measurable set `i`, `to_measure_of_le_zero`
provides the measure, mapping measurable sets `j` to `-s (i ∩ j)`. -/
def to_measure_of_le_zero (s : signed_measure α) (i : set α) (hi₁ : measurable_set i)
  (hi₂ : s ≤[i] 0) : measure α :=
to_measure_of_zero_le (-s) i hi₁ $ (@neg_zero (vector_measure α ℝ) _) ▸ neg_le_neg _ _ hi₁ hi₂

lemma to_measure_of_le_zero_apply (hi : s ≤[i] 0)
  (hi₁ : measurable_set i) (hj₁ : measurable_set j) :
  s.to_measure_of_le_zero i hi₁ hi j =
  @coe ℝ≥0 ℝ≥0∞ _ ⟨-s (i ∩ j), neg_apply s (i ∩ j) ▸ nonneg_of_zero_le_restrict _
    (zero_le_restrict_subset _ hi₁ (set.inter_subset_left _ _)
    ((@neg_zero (vector_measure α ℝ) _) ▸ neg_le_neg _ _ hi₁ hi))⟩ :=
begin
  erw [to_measure_of_zero_le_apply],
  { simp },
  { assumption },
end

/-- `signed_measure.to_measure_of_zero_le` is a finite measure. -/
instance to_measure_of_zero_le_finite (hi : 0 ≤[i] s) (hi₁ : measurable_set i) :
  is_finite_measure (s.to_measure_of_zero_le i hi₁ hi) :=
{ measure_univ_lt_top :=
  begin
    rw [to_measure_of_zero_le_apply s hi hi₁ measurable_set.univ],
    exact ennreal.coe_lt_top,
  end }

/-- `signed_measure.to_measure_of_le_zero` is a finite measure. -/
instance to_measure_of_le_zero_finite (hi : s ≤[i] 0) (hi₁ : measurable_set i) :
  is_finite_measure (s.to_measure_of_le_zero i hi₁ hi) :=
{ measure_univ_lt_top :=
  begin
    rw [to_measure_of_le_zero_apply s hi hi₁ measurable_set.univ],
    exact ennreal.coe_lt_top,
  end }

lemma to_measure_of_zero_le_to_signed_measure (hs : 0 ≤[univ] s) :
  (s.to_measure_of_zero_le univ measurable_set.univ hs).to_signed_measure = s :=
begin
  ext i hi,
  simp [measure.to_signed_measure_apply_measurable hi, to_measure_of_zero_le_apply _ _ _ hi],
end

lemma to_measure_of_le_zero_to_signed_measure (hs : s ≤[univ] 0) :
  (s.to_measure_of_le_zero univ measurable_set.univ hs).to_signed_measure = -s :=
begin
  ext i hi,
  simp [measure.to_signed_measure_apply_measurable hi, to_measure_of_le_zero_apply _ _ _ hi],
end

end signed_measure

namespace measure

open vector_measure

variables (μ : measure α) [is_finite_measure μ]

lemma zero_le_to_signed_measure : 0 ≤ μ.to_signed_measure :=
begin
  rw ← le_restrict_univ_iff_le,
  refine restrict_le_restrict_of_subset_le _ _ (λ j hj₁ _, _),
  simp only [measure.to_signed_measure_apply_measurable hj₁, coe_zero, pi.zero_apply,
             ennreal.to_real_nonneg, vector_measure.coe_zero]
end

lemma to_signed_measure_to_measure_of_zero_le :
  μ.to_signed_measure.to_measure_of_zero_le univ measurable_set.univ
    ((le_restrict_univ_iff_le _ _).2 (zero_le_to_signed_measure μ)) = μ :=
begin
  refine measure.ext (λ i hi, _),
  lift μ i to ℝ≥0 using (measure_lt_top _ _).ne with m hm,
  simp [signed_measure.to_measure_of_zero_le_apply _ _ _ hi,
        measure.to_signed_measure_apply_measurable hi, ← hm],
end

end measure

end measure_theory