/-
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,
Scott Morrison

! This file was ported from Lean 3 source module data.list.lattice
! leanprover-community/mathlib commit be24ec5de6701447e5df5ca75400ffee19d65659
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Data.List.Count
import Mathbin.Data.List.Infix
import Mathbin.Algebra.Order.Monoid.MinMax

/-!
# Lattice structure of lists

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

This files prove basic properties about `list.disjoint`, `list.union`, `list.inter` and
`list.bag_inter`, which are defined in core Lean and `data.list.defs`.

`l₁ ∪ l₂` is the list where all elements of `l₁` have been inserted in `l₂` in order. For example,
`[0, 0, 1, 2, 2, 3] ∪ [4, 3, 3, 0] = [1, 2, 4, 3, 3, 0]`

`l₁ ∩ l₂` is the list of elements of `l₁` in order which are in `l₂`. For example,
`[0, 0, 1, 2, 2, 3] ∪ [4, 3, 3, 0] = [0, 0, 3]`

`bag_inter l₁ l₂` is the list of elements that are in both `l₁` and `l₂`, counted with multiplicity
and in the order they appear in `l₁`. As opposed to `list.inter`, `list.bag_inter` copes well with
multiplicity. For example,
`bag_inter [0, 1, 2, 3, 2, 1, 0] [1, 0, 1, 4, 3] = [0, 1, 3, 1]`
-/

open Nat

namespace List

variable {α : Type _} {l l₁ l₂ : List α} {p : α → Prop} {a : α}

/-! ### `disjoint` -/

section Disjoint

#print List.Disjoint.symm /-
theorem Disjoint.symm (d : Disjoint l₁ l₂) : Disjoint l₂ l₁ := fun a i₂ i₁ => d i₁ i₂
#align list.disjoint.symm List.Disjoint.symm
-/

#print List.disjoint_comm /-
theorem disjoint_comm : Disjoint l₁ l₂ ↔ Disjoint l₂ l₁ :=
  ⟨Disjoint.symm, Disjoint.symm⟩
#align list.disjoint_comm List.disjoint_comm
-/

#print List.disjoint_left /-
theorem disjoint_left : Disjoint l₁ l₂ ↔ ∀ ⦃a⦄, a ∈ l₁ → a ∉ l₂ :=
  Iff.rfl
#align list.disjoint_left List.disjoint_left
-/

#print List.disjoint_right /-
theorem disjoint_right : Disjoint l₁ l₂ ↔ ∀ ⦃a⦄, a ∈ l₂ → a ∉ l₁ :=
  disjoint_comm
#align list.disjoint_right List.disjoint_right
-/

#print List.disjoint_iff_ne /-
theorem disjoint_iff_ne : Disjoint l₁ l₂ ↔ ∀ a ∈ l₁, ∀ b ∈ l₂, a ≠ b := by
  simp only [disjoint_left, imp_not_comm, forall_eq']
#align list.disjoint_iff_ne List.disjoint_iff_ne
-/

theorem disjoint_of_subset_left (ss : l₁ ⊆ l) (d : Disjoint l l₂) : Disjoint l₁ l₂ := fun x m =>
  d (ss m)
#align list.disjoint_of_subset_left List.disjoint_of_subset_leftₓ

/- warning: list.disjoint_of_subset_right -> List.disjoint_of_subset_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {l : List.{u1} α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (HasSubset.Subset.{u1} (List.{u1} α) (List.hasSubset.{u1} α) l₂ l) -> (List.Disjoint.{u1} α l₁ l) -> (List.Disjoint.{u1} α l₁ l₂)
but is expected to have type
  forall {α : Type.{u1}} {l : List.{u1} α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (HasSubset.Subset.{u1} (List.{u1} α) (List.instHasSubsetList.{u1} α) l l₁) -> (List.Disjoint.{u1} α l₂ l₁) -> (List.Disjoint.{u1} α l₂ l)
Case conversion may be inaccurate. Consider using '#align list.disjoint_of_subset_right List.disjoint_of_subset_rightₓ'. -/
theorem disjoint_of_subset_right (ss : l₂ ⊆ l) (d : Disjoint l₁ l) : Disjoint l₁ l₂ := fun x m m₁ =>
  d m (ss m₁)
#align list.disjoint_of_subset_right List.disjoint_of_subset_right

#print List.disjoint_of_disjoint_cons_left /-
theorem disjoint_of_disjoint_cons_left {l₁ l₂} : Disjoint (a :: l₁) l₂ → Disjoint l₁ l₂ :=
  disjoint_of_subset_left (List.subset_cons _ _)
#align list.disjoint_of_disjoint_cons_left List.disjoint_of_disjoint_cons_left
-/

#print List.disjoint_of_disjoint_cons_right /-
theorem disjoint_of_disjoint_cons_right {l₁ l₂} : Disjoint l₁ (a :: l₂) → Disjoint l₁ l₂ :=
  disjoint_of_subset_right (List.subset_cons _ _)
#align list.disjoint_of_disjoint_cons_right List.disjoint_of_disjoint_cons_right
-/

#print List.disjoint_nil_left /-
@[simp]
theorem disjoint_nil_left (l : List α) : Disjoint [] l := fun a => (not_mem_nil a).elim
#align list.disjoint_nil_left List.disjoint_nil_left
-/

#print List.disjoint_nil_right /-
@[simp]
theorem disjoint_nil_right (l : List α) : Disjoint l [] :=
  by
  rw [disjoint_comm]
  exact disjoint_nil_left _
#align list.disjoint_nil_right List.disjoint_nil_right
-/

@[simp]
theorem singleton_disjoint : Disjoint [a] l ↔ a ∉ l :=
  by
  simp only [Disjoint, mem_singleton, forall_eq]
  rfl
#align list.singleton_disjoint List.singleton_disjointₓ

#print List.disjoint_singleton /-
@[simp]
theorem disjoint_singleton : Disjoint l [a] ↔ a ∉ l := by rw [disjoint_comm, singleton_disjoint]
#align list.disjoint_singleton List.disjoint_singleton
-/

@[simp]
theorem disjoint_append_left : Disjoint (l₁ ++ l₂) l ↔ Disjoint l₁ l ∧ Disjoint l₂ l := by
  simp only [Disjoint, mem_append, or_imp, forall_and]
#align list.disjoint_append_left List.disjoint_append_leftₓ

#print List.disjoint_append_right /-
@[simp]
theorem disjoint_append_right : Disjoint l (l₁ ++ l₂) ↔ Disjoint l l₁ ∧ Disjoint l l₂ :=
  disjoint_comm.trans <| by simp only [disjoint_comm, disjoint_append_left]
#align list.disjoint_append_right List.disjoint_append_right
-/

@[simp]
theorem disjoint_cons_left : Disjoint (a :: l₁) l₂ ↔ a ∉ l₂ ∧ Disjoint l₁ l₂ :=
  (@disjoint_append_left _ l₂ [a] l₁).trans <| by simp only [singleton_disjoint]
#align list.disjoint_cons_left List.disjoint_cons_leftₓ

/- warning: list.disjoint_cons_right -> List.disjoint_cons_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : List.{u1} α} {a : α}, Iff (List.Disjoint.{u1} α l₁ (List.cons.{u1} α a l₂)) (And (Not (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₁)) (List.Disjoint.{u1} α l₁ l₂))
but is expected to have type
  forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : α} {a : List.{u1} α}, Iff (List.Disjoint.{u1} α l₁ (List.cons.{u1} α l₂ a)) (And (Not (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) l₂ l₁)) (List.Disjoint.{u1} α l₁ a))
Case conversion may be inaccurate. Consider using '#align list.disjoint_cons_right List.disjoint_cons_rightₓ'. -/
@[simp]
theorem disjoint_cons_right : Disjoint l₁ (a :: l₂) ↔ a ∉ l₁ ∧ Disjoint l₁ l₂ :=
  disjoint_comm.trans <| by simp only [disjoint_comm, disjoint_cons_left]
#align list.disjoint_cons_right List.disjoint_cons_right

theorem disjoint_of_disjoint_append_left_left (d : Disjoint (l₁ ++ l₂) l) : Disjoint l₁ l :=
  (disjoint_append_left.1 d).1
#align list.disjoint_of_disjoint_append_left_left List.disjoint_of_disjoint_append_left_leftₓ

theorem disjoint_of_disjoint_append_left_right (d : Disjoint (l₁ ++ l₂) l) : Disjoint l₂ l :=
  (disjoint_append_left.1 d).2
#align list.disjoint_of_disjoint_append_left_right List.disjoint_of_disjoint_append_left_rightₓ

#print List.disjoint_of_disjoint_append_right_left /-
theorem disjoint_of_disjoint_append_right_left (d : Disjoint l (l₁ ++ l₂)) : Disjoint l l₁ :=
  (disjoint_append_right.1 d).1
#align list.disjoint_of_disjoint_append_right_left List.disjoint_of_disjoint_append_right_left
-/

#print List.disjoint_of_disjoint_append_right_right /-
theorem disjoint_of_disjoint_append_right_right (d : Disjoint l (l₁ ++ l₂)) : Disjoint l l₂ :=
  (disjoint_append_right.1 d).2
#align list.disjoint_of_disjoint_append_right_right List.disjoint_of_disjoint_append_right_right
-/

theorem disjoint_take_drop {m n : ℕ} (hl : l.Nodup) (h : m ≤ n) : Disjoint (l.take m) (l.drop n) :=
  by
  induction l generalizing m n
  case nil m n => simp
  case
    cons x xs xs_ih m n =>
    cases m <;> cases n <;>
      simp only [disjoint_cons_left, mem_cons_iff, disjoint_cons_right, drop, true_or_iff,
        eq_self_iff_true, not_true, false_and_iff, disjoint_nil_left, take]
    · cases h
    cases' hl with _ _ h₀ h₁; constructor
    · intro h
      exact h₀ _ (mem_of_mem_drop h) rfl
    solve_by_elim (config := { max_depth := 4 }) [le_of_succ_le_succ]
#align list.disjoint_take_drop List.disjoint_take_dropₓ

end Disjoint

variable [DecidableEq α]

/-! ### `union` -/

section Union

#print List.nil_union /-
@[simp]
theorem nil_union (l : List α) : [] ∪ l = l :=
  rfl
#align list.nil_union List.nil_union
-/

@[simp]
theorem cons_union (l₁ l₂ : List α) (a : α) : a :: l₁ ∪ l₂ = insert a (l₁ ∪ l₂) :=
  rfl
#align list.cons_union List.cons_unionₓ

#print List.mem_union /-
@[simp]
theorem mem_union : a ∈ l₁ ∪ l₂ ↔ a ∈ l₁ ∨ a ∈ l₂ := by
  induction l₁ <;>
    simp only [nil_union, not_mem_nil, false_or_iff, cons_union, mem_insert_iff, mem_cons_iff,
      or_assoc', *]
#align list.mem_union List.mem_union
-/

#print List.mem_union_left /-
theorem mem_union_left (h : a ∈ l₁) (l₂ : List α) : a ∈ l₁ ∪ l₂ :=
  mem_union.2 (Or.inl h)
#align list.mem_union_left List.mem_union_left
-/

#print List.mem_union_right /-
theorem mem_union_right (l₁ : List α) (h : a ∈ l₂) : a ∈ l₁ ∪ l₂ :=
  mem_union.2 (Or.inr h)
#align list.mem_union_right List.mem_union_right
-/

#print List.sublist_suffix_of_union /-
theorem sublist_suffix_of_union : ∀ l₁ l₂ : List α, ∃ t, t <+ l₁ ∧ t ++ l₂ = l₁ ∪ l₂
  | [], l₂ => ⟨[], by rfl, rfl⟩
  | a :: l₁, l₂ =>
    let ⟨t, s, e⟩ := sublist_suffix_of_union l₁ l₂
    if h : a ∈ l₁ ∪ l₂ then
      ⟨t, sublist_cons_of_sublist _ s, by simp only [e, cons_union, insert_of_mem h]⟩
    else
      ⟨a :: t, s.cons_cons _, by
        simp only [cons_append, cons_union, e, insert_of_not_mem h] <;> constructor <;> rfl⟩
#align list.sublist_suffix_of_union List.sublist_suffix_of_union
-/

#print List.suffix_union_right /-
theorem suffix_union_right (l₁ l₂ : List α) : l₂ <:+ l₁ ∪ l₂ :=
  (sublist_suffix_of_union l₁ l₂).imp fun a => And.right
#align list.suffix_union_right List.suffix_union_right
-/

#print List.union_sublist_append /-
theorem union_sublist_append (l₁ l₂ : List α) : l₁ ∪ l₂ <+ l₁ ++ l₂ :=
  let ⟨t, s, e⟩ := sublist_suffix_of_union l₁ l₂
  e ▸ (append_sublist_append_right _).2 s
#align list.union_sublist_append List.union_sublist_append
-/

#print List.forall_mem_union /-
theorem forall_mem_union : (∀ x ∈ l₁ ∪ l₂, p x) ↔ (∀ x ∈ l₁, p x) ∧ ∀ x ∈ l₂, p x := by
  simp only [mem_union, or_imp, forall_and]
#align list.forall_mem_union List.forall_mem_union
-/

#print List.forall_mem_of_forall_mem_union_left /-
theorem forall_mem_of_forall_mem_union_left (h : ∀ x ∈ l₁ ∪ l₂, p x) : ∀ x ∈ l₁, p x :=
  (forall_mem_union.1 h).1
#align list.forall_mem_of_forall_mem_union_left List.forall_mem_of_forall_mem_union_left
-/

#print List.forall_mem_of_forall_mem_union_right /-
theorem forall_mem_of_forall_mem_union_right (h : ∀ x ∈ l₁ ∪ l₂, p x) : ∀ x ∈ l₂, p x :=
  (forall_mem_union.1 h).2
#align list.forall_mem_of_forall_mem_union_right List.forall_mem_of_forall_mem_union_right
-/

end Union

/-! ### `inter` -/

section Inter

#print List.inter_nil /-
@[simp]
theorem inter_nil (l : List α) : [] ∩ l = [] :=
  rfl
#align list.inter_nil List.inter_nil
-/

#print List.inter_cons_of_mem /-
@[simp]
theorem inter_cons_of_mem (l₁ : List α) (h : a ∈ l₂) : (a :: l₁) ∩ l₂ = a :: l₁ ∩ l₂ :=
  if_pos h
#align list.inter_cons_of_mem List.inter_cons_of_mem
-/

#print List.inter_cons_of_not_mem /-
@[simp]
theorem inter_cons_of_not_mem (l₁ : List α) (h : a ∉ l₂) : (a :: l₁) ∩ l₂ = l₁ ∩ l₂ :=
  if_neg h
#align list.inter_cons_of_not_mem List.inter_cons_of_not_mem
-/

#print List.mem_of_mem_inter_left /-
theorem mem_of_mem_inter_left : a ∈ l₁ ∩ l₂ → a ∈ l₁ :=
  mem_of_mem_filter
#align list.mem_of_mem_inter_left List.mem_of_mem_inter_left
-/

#print List.mem_of_mem_inter_right /-
theorem mem_of_mem_inter_right : a ∈ l₁ ∩ l₂ → a ∈ l₂ :=
  of_mem_filter
#align list.mem_of_mem_inter_right List.mem_of_mem_inter_right
-/

#print List.mem_inter_of_mem_of_mem /-
theorem mem_inter_of_mem_of_mem : a ∈ l₁ → a ∈ l₂ → a ∈ l₁ ∩ l₂ :=
  mem_filter_of_mem
#align list.mem_inter_of_mem_of_mem List.mem_inter_of_mem_of_mem
-/

#print List.mem_inter /-
@[simp]
theorem mem_inter : a ∈ l₁ ∩ l₂ ↔ a ∈ l₁ ∧ a ∈ l₂ :=
  mem_filter
#align list.mem_inter List.mem_inter
-/

#print List.inter_subset_left /-
theorem inter_subset_left (l₁ l₂ : List α) : l₁ ∩ l₂ ⊆ l₁ :=
  filter_subset _
#align list.inter_subset_left List.inter_subset_left
-/

#print List.inter_subset_right /-
theorem inter_subset_right (l₁ l₂ : List α) : l₁ ∩ l₂ ⊆ l₂ := fun a => mem_of_mem_inter_right
#align list.inter_subset_right List.inter_subset_right
-/

#print List.subset_inter /-
theorem subset_inter {l l₁ l₂ : List α} (h₁ : l ⊆ l₁) (h₂ : l ⊆ l₂) : l ⊆ l₁ ∩ l₂ := fun a h =>
  mem_inter.2 ⟨h₁ h, h₂ h⟩
#align list.subset_inter List.subset_inter
-/

#print List.inter_eq_nil_iff_disjoint /-
theorem inter_eq_nil_iff_disjoint : l₁ ∩ l₂ = [] ↔ Disjoint l₁ l₂ :=
  by
  simp only [eq_nil_iff_forall_not_mem, mem_inter, not_and]
  rfl
#align list.inter_eq_nil_iff_disjoint List.inter_eq_nil_iff_disjoint
-/

#print List.forall_mem_inter_of_forall_left /-
theorem forall_mem_inter_of_forall_left (h : ∀ x ∈ l₁, p x) (l₂ : List α) :
    ∀ x, x ∈ l₁ ∩ l₂ → p x :=
  BAll.imp_left (fun x => mem_of_mem_inter_left) h
#align list.forall_mem_inter_of_forall_left List.forall_mem_inter_of_forall_left
-/

#print List.forall_mem_inter_of_forall_right /-
theorem forall_mem_inter_of_forall_right (l₁ : List α) (h : ∀ x ∈ l₂, p x) :
    ∀ x, x ∈ l₁ ∩ l₂ → p x :=
  BAll.imp_left (fun x => mem_of_mem_inter_right) h
#align list.forall_mem_inter_of_forall_right List.forall_mem_inter_of_forall_right
-/

#print List.inter_reverse /-
@[simp]
theorem inter_reverse {xs ys : List α} : xs.inter ys.reverse = xs.inter ys := by
  simp only [List.inter, mem_reverse]
#align list.inter_reverse List.inter_reverse
-/

end Inter

/-! ### `bag_inter` -/

section BagInter

/- warning: list.nil_bag_inter -> List.nil_bagInter is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α), Eq.{succ u1} (List.{u1} α) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) (List.nil.{u1} α) l) (List.nil.{u1} α)
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α), Eq.{succ u1} (List.{u1} α) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) (List.nil.{u1} α) l) (List.nil.{u1} α)
Case conversion may be inaccurate. Consider using '#align list.nil_bag_inter List.nil_bagInterₓ'. -/
@[simp]
theorem nil_bagInter (l : List α) : [].bagInterₓ l = [] := by cases l <;> rfl
#align list.nil_bag_inter List.nil_bagInter

/- warning: list.bag_inter_nil -> List.bagInter_nil is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α), Eq.{succ u1} (List.{u1} α) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l (List.nil.{u1} α)) (List.nil.{u1} α)
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α), Eq.{succ u1} (List.{u1} α) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l (List.nil.{u1} α)) (List.nil.{u1} α)
Case conversion may be inaccurate. Consider using '#align list.bag_inter_nil List.bagInter_nilₓ'. -/
@[simp]
theorem bagInter_nil (l : List α) : l.bagInterₓ [] = [] := by cases l <;> rfl
#align list.bag_inter_nil List.bagInter_nil

/- warning: list.cons_bag_inter_of_pos -> List.cons_bagInter_of_pos is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {l₂ : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α), (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₂) -> (Eq.{succ u1} (List.{u1} α) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) (List.cons.{u1} α a l₁) l₂) (List.cons.{u1} α a (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ a))))
but is expected to have type
  forall {α : Type.{u1}} {l₂ : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α), (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₂) -> (Eq.{succ u1} (List.{u1} α) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) (List.cons.{u1} α a l₁) l₂) (List.cons.{u1} α a (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ a))))
Case conversion may be inaccurate. Consider using '#align list.cons_bag_inter_of_pos List.cons_bagInter_of_posₓ'. -/
@[simp]
theorem cons_bagInter_of_pos (l₁ : List α) (h : a ∈ l₂) :
    (a :: l₁).bagInterₓ l₂ = a :: l₁.bagInterₓ (l₂.eraseₓ a) := by cases l₂ <;> exact if_pos h
#align list.cons_bag_inter_of_pos List.cons_bagInter_of_pos

/- warning: list.cons_bag_inter_of_neg -> List.cons_bagInter_of_neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {l₂ : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α), (Not (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₂)) -> (Eq.{succ u1} (List.{u1} α) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) (List.cons.{u1} α a l₁) l₂) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂))
but is expected to have type
  forall {α : Type.{u1}} {l₂ : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α), (Not (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₂)) -> (Eq.{succ u1} (List.{u1} α) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) (List.cons.{u1} α a l₁) l₂) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂))
Case conversion may be inaccurate. Consider using '#align list.cons_bag_inter_of_neg List.cons_bagInter_of_negₓ'. -/
@[simp]
theorem cons_bagInter_of_neg (l₁ : List α) (h : a ∉ l₂) :
    (a :: l₁).bagInterₓ l₂ = l₁.bagInterₓ l₂ :=
  by
  cases l₂; · simp only [bag_inter_nil]
  simp only [erase_of_not_mem h, List.bagInter, if_neg h]
#align list.cons_bag_inter_of_neg List.cons_bagInter_of_neg

/- warning: list.mem_bag_inter -> List.mem_bagInter is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, Iff (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂)) (And (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₁) (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₂))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, Iff (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂)) (And (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₁) (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₂))
Case conversion may be inaccurate. Consider using '#align list.mem_bag_inter List.mem_bagInterₓ'. -/
@[simp]
theorem mem_bagInter {a : α} : ∀ {l₁ l₂ : List α}, a ∈ l₁.bagInterₓ l₂ ↔ a ∈ l₁ ∧ a ∈ l₂
  | [], l₂ => by simp only [nil_bag_inter, not_mem_nil, false_and_iff]
  | b :: l₁, l₂ => by
    by_cases b ∈ l₂
    · rw [cons_bag_inter_of_pos _ h, mem_cons_iff, mem_cons_iff, mem_bag_inter]
      by_cases ba : a = b
      · simp only [ba, h, eq_self_iff_true, true_or_iff, true_and_iff]
      · simp only [mem_erase_of_ne ba, ba, false_or_iff]
    · rw [cons_bag_inter_of_neg _ h, mem_bag_inter, mem_cons_iff, or_and_right]
      symm
      apply or_iff_right_of_imp
      rintro ⟨rfl, h'⟩
      exact h.elim h'
#align list.mem_bag_inter List.mem_bagInter

#print List.count_bagInter /-
@[simp]
theorem count_bagInter {a : α} :
    ∀ {l₁ l₂ : List α}, count a (l₁.bagInterₓ l₂) = min (count a l₁) (count a l₂)
  | [], l₂ => by simp
  | l₁, [] => by simp
  | b :: l₁, l₂ => by
    by_cases hb : b ∈ l₂
    · rw [cons_bag_inter_of_pos _ hb, count_cons', count_cons', count_bag_inter, count_erase, ←
        min_add_add_right]
      by_cases ab : a = b
      · rw [if_pos ab, tsub_add_cancel_of_le]
        rwa [succ_le_iff, count_pos, ab]
      · rw [if_neg ab, tsub_zero, add_zero, add_zero]
    · rw [cons_bag_inter_of_neg _ hb, count_bag_inter]
      by_cases ab : a = b
      · rw [← ab] at hb
        rw [count_eq_zero.2 hb, min_zero, min_zero]
      · rw [count_cons_of_ne ab]
#align list.count_bag_inter List.count_bagInter
-/

/- warning: list.bag_inter_sublist_left -> List.bagInter_sublist_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α) (l₂ : List.{u1} α), List.Sublist.{u1} α (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂) l₁
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α) (l₂ : List.{u1} α), List.Sublist.{u1} α (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂) l₁
Case conversion may be inaccurate. Consider using '#align list.bag_inter_sublist_left List.bagInter_sublist_leftₓ'. -/
theorem bagInter_sublist_left : ∀ l₁ l₂ : List α, l₁.bagInterₓ l₂ <+ l₁
  | [], l₂ => by simp
  | b :: l₁, l₂ =>
    by
    by_cases b ∈ l₂ <;> simp only [h, cons_bag_inter_of_pos, cons_bag_inter_of_neg, not_false_iff]
    · exact (bag_inter_sublist_left _ _).cons_cons _
    · apply sublist_cons_of_sublist
      apply bag_inter_sublist_left
#align list.bag_inter_sublist_left List.bagInter_sublist_left

/- warning: list.bag_inter_nil_iff_inter_nil -> List.bagInter_nil_iff_inter_nil is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α) (l₂ : List.{u1} α), Iff (Eq.{succ u1} (List.{u1} α) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂) (List.nil.{u1} α)) (Eq.{succ u1} (List.{u1} α) (Inter.inter.{u1} (List.{u1} α) (List.hasInter.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂) (List.nil.{u1} α))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l₁ : List.{u1} α) (l₂ : List.{u1} α), Iff (Eq.{succ u1} (List.{u1} α) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂) (List.nil.{u1} α)) (Eq.{succ u1} (List.{u1} α) (Inter.inter.{u1} (List.{u1} α) (List.instInterList.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂) (List.nil.{u1} α))
Case conversion may be inaccurate. Consider using '#align list.bag_inter_nil_iff_inter_nil List.bagInter_nil_iff_inter_nilₓ'. -/
theorem bagInter_nil_iff_inter_nil : ∀ l₁ l₂ : List α, l₁.bagInterₓ l₂ = [] ↔ l₁ ∩ l₂ = []
  | [], l₂ => by simp
  | b :: l₁, l₂ => by
    by_cases h : b ∈ l₂ <;> simp [h]
    exact bag_inter_nil_iff_inter_nil l₁ l₂
#align list.bag_inter_nil_iff_inter_nil List.bagInter_nil_iff_inter_nil

end BagInter

end List


import data.finset
import data.real.basic
import data.real.cau_seq_completion
import data.nat.gcd
import analysis.exponential

noncomputable theory

open nat
open finset
open int
open real
open complex

example : decidable_linear_ordered_comm_group ℝ := by apply_instance

-- n is the length of the arithmetic sequence we want, a is the starting number
-- and k is the common difference (k ≠ 0 or else we can choose a to be prime and we are done)
theorem green_tao : Prop :=
∀ (n : ℕ), ∃ (a k : ℕ), ∀ (i < n), k ≠ 0 ∧ prime (a + i * k)

-- The nth partial sum of a series Σf
def P_n (f : ℕ → ℝ) (n : ℕ) : ℝ :=
finset.sum (finset.Ico 1 (n+1)) f

-- The series with f inside the sum
def converges (f : ℕ → ℝ) (L : ℝ) : Prop :=
∀ (ε > 0), ∃ (N : ℕ), ∀ (n : ℕ), n ≥ N → complex.abs (P_n f n - L) < ε

-- Apery's Theorem says that the sum from n=1 to ∞ of 1/n^3 has a limit and that the limit is irrational
theorem apery's_theorem : Prop :=
∃ (L : ℝ), converges (λ n, 1/(n^3)) L ∧ ∀ (p q : ℤ), (p/q : ℝ) ≠ L

def find_prime_factors (n: ℕ) : list ℕ :=
((list.range (n+1)).filter prime).filter (∣ n)

def rad (n : ℕ) : ℕ :=
(find_prime_factors n).prod

-- We use formulation 2 of the abc conjecture from https://en.wikipedia.org/wiki/Abc_conjecture
-- Note that because 1/n → 0 as n → ∞, this is equivalent to the ε formulation
def abc_conjecture : Prop :=
∀ (n : ℕ), ∃ (K : ℝ), ∀ (a b c : ℕ),
n > 0 ∧ ∀ (z : ℕ), (z ∣ a ∧ z ∣ b ∧ z ∣ c → z = 1) ∧ a + b = c → (c : ℝ) < K*(rad a*b*c : ℝ)^(1+1/n)

section
local attribute [instance] classical.prop_decidable

theorem oops : ¬ abc_conjecture :=
begin
  dsimp [abc_conjecture],
  simp only [not_forall],
  use 0,
  rintro ⟨K, p⟩,
  replace p := p 0 0 0,
  cases p,
  cases p_left,
end
end

-- We cite the paper "An Elementary Problem Equivalent to the Riemann Hypothesis"
-- by Jeffrey Lagarias, which can be found at http://www.math.lsa.umich.edu/~lagarias/doc/elementaryrh.pdf

-- We begin by defining the harmonic series
def H_n (n : ℕ) : ℝ := P_n (λm, 1/m) n

def sum_of_divisors (n : ℕ) : ℝ :=
((list.range (n+1)).filter (∣ n)).sum

def riemann_hypothesis : Prop :=
∀ (n : ℕ), sum_of_divisors n ≤ H_n n + exp (H_n n)*log (H_n n) ∧
           sum_of_divisors n = H_n n + exp (H_n n)*log (H_n n) ↔ n = 1

section
local attribute [instance] classical.prop_decidable

example : ¬riemann_hypothesis :=
begin
  dsimp [riemann_hypothesis],
  simp only [not_forall],
  use 0,
  simp,
  dsimp [sum_of_divisors, H_n, list.range, list.range_core, P_n],
  simp,
end
end

-- what went wrong?
-- Let's redefine some things to avoid the real numbers, which we can't compute with.
def sum_of_divisors' (n : ℕ) : ℕ :=
((list.range (n+1)).filter (∣ n)).sum

def P_n' (f : ℕ → ℚ) (n : ℕ) : ℚ :=
finset.sum (finset.Ico 1 (n+1)) f
def H_n' (n : ℕ) : ℚ := P_n' (λm, 1/m) n

#eval sum_of_divisors' 0
#eval H_n' 0

-- So the problem is that we _also_ have equality at n = 0!


namespace hidden

-- what is absurd keyword?
-- absurd a ¬a = a → ¬a → any
-- We can't have a and ¬a, that would be absurd!
lemma neq_of_not_iff {a b : Prop} : ¬(a ↔ b) → a ≠ b :=
λ h₁ h₂,
have a ↔ b, from eq.subst h₂ (iff.refl a),
absurd this h₁

lemma neq_of_not_iff₂ {a b : Prop} : ¬(a ↔ b) → a ≠ b :=
begin
  intros h₁ h₂,
  have : a ↔ b, from eq.subst h₂ (iff.refl a),
  -- exact absurd h₁ (not_not_intro this), -- another way
  exact absurd this h₁,
end

-- also works if change ¬(a ↔ b) → a = b → false to ¬(a ↔ b) → a = b → c
lemma neq_of_not_iff₃ {a b c: Prop} : ¬(a ↔ b) → a = b → c :=
  assume h₁ h₂,
  have a ↔ b, from eq.subst h₂ (iff.refl a),
  absurd this h₁

end hidden


/-
Copyright (c) 2014 Robert Lewis. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Robert Lewis, Leonardo de Moura, Mario Carneiro, Floris van Doorn
-/
import algebra.order.field.canonical.defs

/-!
# Lemmas about canonically ordered semifields.

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

-/
variables {α : Type*}

section canonically_linear_ordered_semifield
variables [canonically_linear_ordered_semifield α] [has_sub α] [has_ordered_sub α]

lemma tsub_div (a b c : α) : (a - b) / c = a / c - b / c := by simp_rw [div_eq_mul_inv, tsub_mul]

end canonically_linear_ordered_semifield


/-
Copyright (c) 2017 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl, Yury Kudryashov
-/
import Mathlib.PrePort
import Mathlib.Lean3Lib.init.default
import Mathlib.measure_theory.measure_space
import Mathlib.measure_theory.ae_measurable_sequence
import Mathlib.analysis.complex.basic
import Mathlib.analysis.normed_space.finite_dimension
import Mathlib.topology.G_delta
import Mathlib.PostPort

universes u u_1 u_2 u_6 l u_3 u_5 u_4 u_7 u_8

namespace Mathlib

/-!
# Borel (measurable) space

## Main definitions

* `borel α` : the least `σ`-algebra that contains all open sets;
* `class borel_space` : a space with `topological_space` and `measurable_space` structures
  such that `‹measurable_space α› = borel α`;
* `class opens_measurable_space` : a space with `topological_space` and `measurable_space`
  structures such that all open sets are measurable; equivalently, `borel α ≤ ‹measurable_space α›`.
* `borel_space` instances on `empty`, `unit`, `bool`, `nat`, `int`, `rat`;
* `measurable` and `borel_space` instances on `ℝ`, `ℝ≥0`, `ennreal`.
* A measure is `regular` if it is finite on compact sets, inner regular and outer regular.

## Main statements

* `is_open.is_measurable`, `is_closed.is_measurable`: open and closed sets are measurable;
* `continuous.measurable` : a continuous function is measurable;
* `continuous.measurable2` : if `f : α → β` and `g : α → γ` are measurable and `op : β × γ → δ`
  is continuous, then `λ x, op (f x, g y)` is measurable;
* `measurable.add` etc : dot notation for arithmetic operations on `measurable` predicates,
  and similarly for `dist` and `edist`;
* `ae_measurable.add` : similar dot notation for almost everywhere measurable functions;
* `measurable.ennreal*` : special cases for arithmetic operations on `ennreal`s.
-/

/-- `measurable_space` structure generated by `topological_space`. -/
def borel (α : Type u) [topological_space α] : measurable_space α :=
  measurable_space.generate_from (set_of fun (s : set α) => is_open s)

theorem borel_eq_top_of_discrete {α : Type u_1} [topological_space α] [discrete_topology α] : borel α = ⊤ :=
  iff.mp top_le_iff
    fun (s : set α) (hs : measurable_space.is_measurable' ⊤ s) =>
      measurable_space.generate_measurable.basic s (is_open_discrete s)

theorem borel_eq_top_of_encodable {α : Type u_1} [topological_space α] [t1_space α] [encodable α] : borel α = ⊤ := sorry

theorem borel_eq_generate_from_of_subbasis {α : Type u_1} {s : set (set α)} [t : topological_space α] [topological_space.second_countable_topology α] (hs : t = topological_space.generate_from s) : borel α = measurable_space.generate_from s := sorry

theorem is_pi_system_is_open {α : Type u_1} [topological_space α] : is_pi_system is_open :=
  fun (s t : set α) (hs : s ∈ is_open) (ht : t ∈ is_open) (hst : set.nonempty (s ∩ t)) => is_open_inter hs ht

theorem borel_eq_generate_Iio (α : Type u_1) [topological_space α] [topological_space.second_countable_topology α] [linear_order α] [order_topology α] : borel α = measurable_space.generate_from (set.range set.Iio) := sorry

theorem borel_eq_generate_Ioi (α : Type u_1) [topological_space α] [topological_space.second_countable_topology α] [linear_order α] [order_topology α] : borel α = measurable_space.generate_from (set.range set.Ioi) :=
  borel_eq_generate_Iio (order_dual α)

theorem borel_comap {α : Type u_1} {β : Type u_2} {f : α → β} {t : topological_space β} : borel α = measurable_space.comap f (borel β) :=
  Eq.symm measurable_space.comap_generate_from

theorem continuous.borel_measurable {α : Type u_1} {β : Type u_2} [topological_space α] [topological_space β] {f : α → β} (hf : continuous f) : measurable f := sorry

/-- A space with `measurable_space` and `topological_space` structures such that
all open sets are measurable. -/
class opens_measurable_space (α : Type u_6) [topological_space α] [h : measurable_space α]
where
  borel_le : borel α ≤ h

/-- A space with `measurable_space` and `topological_space` structures such that
the `σ`-algebra of measurable sets is exactly the `σ`-algebra generated by open sets. -/
class borel_space (α : Type u_6) [topological_space α] [measurable_space α]
where
  measurable_eq : _inst_2 = borel α

/-- In a `borel_space` all open sets are measurable. -/
protected instance borel_space.opens_measurable {α : Type u_1} [topological_space α] [measurable_space α] [borel_space α] : opens_measurable_space α :=
  opens_measurable_space.mk (ge_of_eq borel_space.measurable_eq)

protected instance subtype.borel_space {α : Type u_1} [topological_space α] [measurable_space α] [hα : borel_space α] (s : set α) : borel_space ↥s :=
  borel_space.mk
    (eq.mpr (id (Eq._oldrec (Eq.refl (subtype.measurable_space = borel ↥s)) borel_space.measurable_eq))
      (eq.mpr (id (Eq._oldrec (Eq.refl (subtype.measurable_space = borel ↥s)) subtype.measurable_space.equations._eqn_1))
        (eq.mpr (id (Eq._oldrec (Eq.refl (measurable_space.comap coe (borel α) = borel ↥s)) (Eq.symm borel_comap)))
          (Eq.refl (borel (Subtype fun (x : α) => x ∈ s))))))

protected instance subtype.opens_measurable_space {α : Type u_1} [topological_space α] [measurable_space α] [h : opens_measurable_space α] (s : set α) : opens_measurable_space ↥s :=
  opens_measurable_space.mk
    (eq.mpr (id (Eq._oldrec (Eq.refl (borel ↥s ≤ subtype.measurable_space)) borel_comap))
      (measurable_space.comap_mono opens_measurable_space.borel_le))

theorem is_open.is_measurable {α : Type u_1} {s : set α} [topological_space α] [measurable_space α] [opens_measurable_space α] (h : is_open s) : is_measurable s :=
  opens_measurable_space.borel_le s (measurable_space.generate_measurable.basic s h)

theorem is_measurable_interior {α : Type u_1} {s : set α} [topological_space α] [measurable_space α] [opens_measurable_space α] : is_measurable (interior s) :=
  is_open.is_measurable is_open_interior

theorem is_Gδ.is_measurable {α : Type u_1} {s : set α} [topological_space α] [measurable_space α] [opens_measurable_space α] (h : is_Gδ s) : is_measurable s := sorry

theorem is_measurable_set_of_continuous_at {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] {β : Type u_2} [emetric_space β] (f : α → β) : is_measurable (set_of fun (x : α) => continuous_at f x) :=
  is_Gδ.is_measurable (is_Gδ_set_of_continuous_at f)

theorem is_closed.is_measurable {α : Type u_1} {s : set α} [topological_space α] [measurable_space α] [opens_measurable_space α] (h : is_closed s) : is_measurable s :=
  is_measurable.of_compl (is_open.is_measurable h)

theorem is_compact.is_measurable {α : Type u_1} {s : set α} [topological_space α] [measurable_space α] [opens_measurable_space α] [t2_space α] (h : is_compact s) : is_measurable s :=
  is_closed.is_measurable (is_compact.is_closed h)

theorem is_measurable_closure {α : Type u_1} {s : set α} [topological_space α] [measurable_space α] [opens_measurable_space α] : is_measurable (closure s) :=
  is_closed.is_measurable is_closed_closure

theorem measurable_of_is_open {γ : Type u_3} {δ : Type u_5} [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] {f : δ → γ} (hf : ∀ (s : set γ), is_open s → is_measurable (f ⁻¹' s)) : measurable f :=
  eq.mpr (id (Eq._oldrec (Eq.refl (measurable f)) borel_space.measurable_eq)) (measurable_generate_from hf)

theorem measurable_of_is_closed {γ : Type u_3} {δ : Type u_5} [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] {f : δ → γ} (hf : ∀ (s : set γ), is_closed s → is_measurable (f ⁻¹' s)) : measurable f := sorry

theorem measurable_of_is_closed' {γ : Type u_3} {δ : Type u_5} [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] {f : δ → γ} (hf : ∀ (s : set γ), is_closed s → set.nonempty s → s ≠ set.univ → is_measurable (f ⁻¹' s)) : measurable f := sorry

protected instance nhds_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] (a : α) : filter.is_measurably_generated (nhds a) :=
  eq.mpr (id (Eq._oldrec (Eq.refl (filter.is_measurably_generated (nhds a))) (nhds.equations._eqn_1 a)))
    (eq.mpr
      (id
        (Eq._oldrec
          (Eq.refl
            (filter.is_measurably_generated
              (infi
                fun (s : set α) => infi fun (H : s ∈ set_of fun (s : set α) => a ∈ s ∧ is_open s) => filter.principal s)))
          infi_subtype'))
      filter.infi_is_measurably_generated)

/-- If `s` is a measurable set, then `𝓝[s] a` is a measurably generated filter for
each `a`. This cannot be an `instance` because it depends on a non-instance `hs : is_measurable s`.
-/
theorem is_measurable.nhds_within_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] {s : set α} (hs : is_measurable s) (a : α) : filter.is_measurably_generated (nhds_within a s) :=
  filter.inf_is_measurably_generated (nhds a) (filter.principal s)

protected instance opens_measurable_space.to_measurable_singleton_class {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [t1_space α] : measurable_singleton_class α :=
  measurable_singleton_class.mk fun (x : α) => is_closed.is_measurable is_closed_singleton

protected instance pi.opens_measurable_space {ι : Type u_1} {π : ι → Type u_2} [fintype ι] [t' : (i : ι) → topological_space (π i)] [(i : ι) → measurable_space (π i)] [∀ (i : ι), topological_space.second_countable_topology (π i)] [∀ (i : ι), opens_measurable_space (π i)] : opens_measurable_space ((i : ι) → π i) := sorry

protected instance prod.opens_measurable_space {α : Type u_1} {β : Type u_2} [topological_space α] [measurable_space α] [opens_measurable_space α] [topological_space β] [measurable_space β] [opens_measurable_space β] [topological_space.second_countable_topology α] [topological_space.second_countable_topology β] : opens_measurable_space (α × β) := sorry

@[simp] theorem is_measurable_Ici {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [preorder α] [order_closed_topology α] {a : α} : is_measurable (set.Ici a) :=
  is_closed.is_measurable is_closed_Ici

@[simp] theorem is_measurable_Iic {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [preorder α] [order_closed_topology α] {a : α} : is_measurable (set.Iic a) :=
  is_closed.is_measurable is_closed_Iic

@[simp] theorem is_measurable_Icc {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [preorder α] [order_closed_topology α] {a : α} {b : α} : is_measurable (set.Icc a b) :=
  is_closed.is_measurable is_closed_Icc

protected instance nhds_within_Ici_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [preorder α] [order_closed_topology α] {a : α} {b : α} : filter.is_measurably_generated (nhds_within a (set.Ici b)) :=
  is_measurable.nhds_within_is_measurably_generated is_measurable_Ici a

protected instance nhds_within_Iic_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [preorder α] [order_closed_topology α] {a : α} {b : α} : filter.is_measurably_generated (nhds_within a (set.Iic b)) :=
  is_measurable.nhds_within_is_measurably_generated is_measurable_Iic a

protected instance at_top_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [preorder α] [order_closed_topology α] : filter.is_measurably_generated filter.at_top :=
  filter.infi_is_measurably_generated

protected instance at_bot_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [preorder α] [order_closed_topology α] : filter.is_measurably_generated filter.at_bot :=
  filter.infi_is_measurably_generated

theorem is_measurable_le' {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [partial_order α] [order_closed_topology α] [topological_space.second_countable_topology α] : is_measurable (set_of fun (p : α × α) => prod.fst p ≤ prod.snd p) :=
  is_closed.is_measurable order_closed_topology.is_closed_le'

theorem is_measurable_le {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [measurable_space δ] [partial_order α] [order_closed_topology α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} (hf : measurable f) (hg : measurable g) : is_measurable (set_of fun (a : δ) => f a ≤ g a) :=
  measurable.prod_mk hf hg is_measurable_le'

@[simp] theorem is_measurable_Iio {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} : is_measurable (set.Iio a) :=
  is_open.is_measurable is_open_Iio

@[simp] theorem is_measurable_Ioi {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} : is_measurable (set.Ioi a) :=
  is_open.is_measurable is_open_Ioi

@[simp] theorem is_measurable_Ioo {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} {b : α} : is_measurable (set.Ioo a b) :=
  is_open.is_measurable is_open_Ioo

@[simp] theorem is_measurable_Ioc {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} {b : α} : is_measurable (set.Ioc a b) :=
  is_measurable.inter is_measurable_Ioi is_measurable_Iic

@[simp] theorem is_measurable_Ico {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} {b : α} : is_measurable (set.Ico a b) :=
  is_measurable.inter is_measurable_Ici is_measurable_Iio

protected instance nhds_within_Ioi_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} {b : α} : filter.is_measurably_generated (nhds_within a (set.Ioi b)) :=
  is_measurable.nhds_within_is_measurably_generated is_measurable_Ioi a

protected instance nhds_within_Iio_is_measurably_generated {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} {b : α} : filter.is_measurably_generated (nhds_within a (set.Iio b)) :=
  is_measurable.nhds_within_is_measurably_generated is_measurable_Iio a

theorem is_measurable_lt' {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] [topological_space.second_countable_topology α] : is_measurable (set_of fun (p : α × α) => prod.fst p < prod.snd p) :=
  is_open.is_measurable (is_open_lt continuous_fst continuous_snd)

theorem is_measurable_lt {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [measurable_space δ] [linear_order α] [order_closed_topology α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} (hf : measurable f) (hg : measurable g) : is_measurable (set_of fun (a : δ) => f a < g a) :=
  measurable.prod_mk hf hg is_measurable_lt'

theorem is_measurable_interval {α : Type u_1} [topological_space α] [measurable_space α] [opens_measurable_space α] [linear_order α] [order_closed_topology α] {a : α} {b : α} : is_measurable (set.interval a b) :=
  is_measurable_Icc

theorem measurable.max {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [measurable_space δ] [linear_order α] [order_closed_topology α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} (hf : measurable f) (hg : measurable g) : measurable fun (a : δ) => max (f a) (g a) :=
  measurable.piecewise (is_measurable_le hg hf) hf hg

theorem ae_measurable.max {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [measurable_space δ] [linear_order α] [order_closed_topology α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} {μ : measure_theory.measure δ} (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (a : δ) => max (f a) (g a) :=
  Exists.intro (fun (a : δ) => max (ae_measurable.mk f hf a) (ae_measurable.mk g hg a))
    { left := measurable.max (ae_measurable.measurable_mk hf) (ae_measurable.measurable_mk hg),
      right := filter.eventually_eq.comp₂ (ae_measurable.ae_eq_mk hf) max (ae_measurable.ae_eq_mk hg) }

theorem measurable.min {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [measurable_space δ] [linear_order α] [order_closed_topology α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} (hf : measurable f) (hg : measurable g) : measurable fun (a : δ) => min (f a) (g a) :=
  measurable.piecewise (is_measurable_le hf hg) hf hg

theorem ae_measurable.min {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [measurable_space δ] [linear_order α] [order_closed_topology α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} {μ : measure_theory.measure δ} (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (a : δ) => min (f a) (g a) :=
  Exists.intro (fun (a : δ) => min (ae_measurable.mk f hf a) (ae_measurable.mk g hg a))
    { left := measurable.min (ae_measurable.measurable_mk hf) (ae_measurable.measurable_mk hg),
      right := filter.eventually_eq.comp₂ (ae_measurable.ae_eq_mk hf) min (ae_measurable.ae_eq_mk hg) }

/-- A continuous function from an `opens_measurable_space` to a `borel_space`
is measurable. -/
theorem continuous.measurable {α : Type u_1} {γ : Type u_3} [topological_space α] [measurable_space α] [opens_measurable_space α] [topological_space γ] [measurable_space γ] [borel_space γ] {f : α → γ} (hf : continuous f) : measurable f :=
  measurable.mono (continuous.borel_measurable hf) opens_measurable_space.borel_le (le_of_eq borel_space.measurable_eq)

/-- A homeomorphism between two Borel spaces is a measurable equivalence.-/
def homeomorph.to_measurable_equiv {γ : Type u_3} {γ₂ : Type u_4} [topological_space γ] [measurable_space γ] [borel_space γ] [topological_space γ₂] [measurable_space γ₂] [borel_space γ₂] (h : γ ≃ₜ γ₂) : γ ≃ᵐ γ₂ :=
  measurable_equiv.mk (homeomorph.to_equiv h) sorry sorry

@[simp] theorem homeomorph.to_measurable_equiv_coe {γ : Type u_3} {γ₂ : Type u_4} [topological_space γ] [measurable_space γ] [borel_space γ] [topological_space γ₂] [measurable_space γ₂] [borel_space γ₂] (h : γ ≃ₜ γ₂) : ⇑(homeomorph.to_measurable_equiv h) = ⇑h :=
  rfl

@[simp] theorem homeomorph.to_measurable_equiv_symm_coe {γ : Type u_3} {γ₂ : Type u_4} [topological_space γ] [measurable_space γ] [borel_space γ] [topological_space γ₂] [measurable_space γ₂] [borel_space γ₂] (h : γ ≃ₜ γ₂) : ⇑(measurable_equiv.symm (homeomorph.to_measurable_equiv h)) = ⇑(homeomorph.symm h) :=
  rfl

theorem measurable_of_continuous_on_compl_singleton {α : Type u_1} {γ : Type u_3} [topological_space α] [measurable_space α] [opens_measurable_space α] [topological_space γ] [measurable_space γ] [borel_space γ] [t1_space α] {f : α → γ} (a : α) (hf : continuous_on f (set_of fun (x : α) => x ≠ a)) : measurable f :=
  measurable_of_measurable_on_compl_singleton a (continuous.measurable (iff.mp continuous_on_iff_continuous_restrict hf))

theorem continuous.measurable2 {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [topological_space β] [measurable_space β] [opens_measurable_space β] [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] [topological_space.second_countable_topology α] [topological_space.second_countable_topology β] {f : δ → α} {g : δ → β} {c : α → β → γ} (h : continuous fun (p : α × β) => c (prod.fst p) (prod.snd p)) (hf : measurable f) (hg : measurable g) : measurable fun (a : δ) => c (f a) (g a) :=
  measurable.comp (continuous.measurable h) (measurable.prod_mk hf hg)

theorem continuous.ae_measurable2 {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [topological_space β] [measurable_space β] [opens_measurable_space β] [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] [topological_space.second_countable_topology α] [topological_space.second_countable_topology β] {f : δ → α} {g : δ → β} {c : α → β → γ} {μ : measure_theory.measure δ} (h : continuous fun (p : α × β) => c (prod.fst p) (prod.snd p)) (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (a : δ) => c (f a) (g a) :=
  measurable.comp_ae_measurable (continuous.measurable h) (ae_measurable.prod_mk hf hg)

theorem measurable.smul {α : Type u_1} {γ : Type u_3} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] [semiring α] [topological_space.second_countable_topology α] [add_comm_monoid γ] [topological_space.second_countable_topology γ] [semimodule α γ] [topological_semimodule α γ] {f : δ → α} {g : δ → γ} (hf : measurable f) (hg : measurable g) : measurable fun (c : δ) => f c • g c :=
  continuous.measurable2 continuous_smul hf hg

theorem ae_measurable.smul {α : Type u_1} {γ : Type u_3} {δ : Type u_5} [topological_space α] [measurable_space α] [opens_measurable_space α] [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] [semiring α] [topological_space.second_countable_topology α] [add_comm_monoid γ] [topological_space.second_countable_topology γ] [semimodule α γ] [topological_semimodule α γ] {f : δ → α} {g : δ → γ} {μ : measure_theory.measure δ} (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (c : δ) => f c • g c :=
  continuous.ae_measurable2 continuous_smul hf hg

theorem measurable.const_smul {δ : Type u_5} [measurable_space δ] {R : Type u_1} {M : Type u_2} [topological_space R] [semiring R] [add_comm_monoid M] [semimodule R M] [topological_space M] [topological_semimodule R M] [measurable_space M] [borel_space M] {f : δ → M} (hf : measurable f) (c : R) : measurable fun (x : δ) => c • f x :=
  measurable.comp (continuous.measurable (continuous.smul continuous_const continuous_id)) hf

theorem ae_measurable.const_smul {δ : Type u_5} [measurable_space δ] {R : Type u_1} {M : Type u_2} [topological_space R] [semiring R] [add_comm_monoid M] [semimodule R M] [topological_space M] [topological_semimodule R M] [measurable_space M] [borel_space M] {f : δ → M} {μ : measure_theory.measure δ} (hf : ae_measurable f) (c : R) : ae_measurable fun (x : δ) => c • f x :=
  measurable.comp_ae_measurable (continuous.measurable (continuous.smul continuous_const continuous_id)) hf

theorem measurable_const_smul_iff {γ : Type u_3} {δ : Type u_5} [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] {α : Type u_1} [topological_space α] [division_ring α] [add_comm_monoid γ] [semimodule α γ] [topological_semimodule α γ] {f : δ → γ} {c : α} (hc : c ≠ 0) : (measurable fun (x : δ) => c • f x) ↔ measurable f := sorry

theorem ae_measurable_const_smul_iff {γ : Type u_3} {δ : Type u_5} [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] {α : Type u_1} [topological_space α] [division_ring α] [add_comm_monoid γ] [semimodule α γ] [topological_semimodule α γ] {f : δ → γ} {μ : measure_theory.measure δ} {c : α} (hc : c ≠ 0) : (ae_measurable fun (x : δ) => c • f x) ↔ ae_measurable f := sorry

theorem measurable.const_mul {δ : Type u_5} [measurable_space δ] {R : Type u_1} [topological_space R] [measurable_space R] [borel_space R] [semiring R] [topological_semiring R] {f : δ → R} (hf : measurable f) (c : R) : measurable fun (x : δ) => c * f x :=
  measurable.const_smul hf c

theorem measurable.mul_const {δ : Type u_5} [measurable_space δ] {R : Type u_1} [topological_space R] [measurable_space R] [borel_space R] [semiring R] [topological_semiring R] {f : δ → R} (hf : measurable f) (c : R) : measurable fun (x : δ) => f x * c :=
  measurable.comp (continuous.measurable (continuous.mul continuous_id continuous_const)) hf

theorem pi_le_borel_pi {ι : Type u_1} {π : ι → Type u_2} [(i : ι) → topological_space (π i)] [(i : ι) → measurable_space (π i)] [∀ (i : ι), borel_space (π i)] : measurable_space.pi ≤ borel ((a : ι) → π a) := sorry

theorem prod_le_borel_prod {α : Type u_1} {β : Type u_2} [topological_space α] [measurable_space α] [borel_space α] [topological_space β] [measurable_space β] [borel_space β] : prod.measurable_space ≤ borel (α × β) := sorry

protected instance pi.borel_space {ι : Type u_1} {π : ι → Type u_2} [fintype ι] [t' : (i : ι) → topological_space (π i)] [(i : ι) → measurable_space (π i)] [∀ (i : ι), topological_space.second_countable_topology (π i)] [∀ (i : ι), borel_space (π i)] : borel_space ((i : ι) → π i) :=
  borel_space.mk (le_antisymm pi_le_borel_pi opens_measurable_space.borel_le)

protected instance prod.borel_space {α : Type u_1} {β : Type u_2} [topological_space α] [measurable_space α] [borel_space α] [topological_space β] [measurable_space β] [borel_space β] [topological_space.second_countable_topology α] [topological_space.second_countable_topology β] : borel_space (α × β) :=
  borel_space.mk (le_antisymm prod_le_borel_prod opens_measurable_space.borel_le)

theorem measurable_add {α : Type u_1} [topological_space α] [measurable_space α] [borel_space α] [Add α] [has_continuous_add α] [topological_space.second_countable_topology α] : measurable fun (p : α × α) => prod.fst p + prod.snd p :=
  continuous.measurable continuous_add

theorem measurable.mul {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [Mul α] [has_continuous_mul α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} : measurable f → measurable g → measurable fun (a : δ) => f a * g a :=
  continuous.measurable2 continuous_mul

theorem ae_measurable.mul {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [Mul α] [has_continuous_mul α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} {μ : measure_theory.measure δ} (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (a : δ) => f a * g a :=
  continuous.ae_measurable2 continuous_mul hf hg

/-- A variant of `measurable.mul` that uses `*` on functions -/
theorem measurable.add' {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [Add α] [has_continuous_add α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} : measurable f → measurable g → measurable (f + g) :=
  measurable.add

theorem measurable_add_left {α : Type u_1} [topological_space α] [measurable_space α] [borel_space α] [Add α] [has_continuous_add α] (x : α) : measurable fun (y : α) => x + y :=
  continuous.measurable (continuous.add continuous_const continuous_id)

theorem measurable_add_right {α : Type u_1} [topological_space α] [measurable_space α] [borel_space α] [Add α] [has_continuous_add α] (x : α) : measurable fun (y : α) => y + x :=
  continuous.measurable (continuous.add continuous_id continuous_const)

theorem finset.measurable_prod {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] {ι : Type u_2} [comm_monoid α] [has_continuous_mul α] [topological_space.second_countable_topology α] {f : ι → δ → α} (s : finset ι) (hf : ∀ (i : ι), measurable (f i)) : measurable fun (a : δ) => finset.prod s fun (i : ι) => f i a := sorry

theorem measurable_neg {α : Type u_1} [topological_space α] [measurable_space α] [borel_space α] [add_group α] [topological_add_group α] : measurable Neg.neg :=
  continuous.measurable continuous_neg

theorem measurable.inv {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [group α] [topological_group α] {f : δ → α} (hf : measurable f) : measurable fun (a : δ) => f a⁻¹ :=
  measurable.comp measurable_inv hf

theorem ae_measurable.inv {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [group α] [topological_group α] {f : δ → α} {μ : measure_theory.measure δ} (hf : ae_measurable f) : ae_measurable fun (a : δ) => f a⁻¹ :=
  measurable.comp_ae_measurable measurable_inv hf

theorem measurable_inv' {α : Type u_1} [normed_field α] [measurable_space α] [borel_space α] : measurable has_inv.inv :=
  measurable_of_continuous_on_compl_singleton 0 continuous_on_inv'

theorem measurable.inv' {δ : Type u_5} [measurable_space δ] {α : Type u_1} [normed_field α] [measurable_space α] [borel_space α] {f : δ → α} (hf : measurable f) : measurable fun (a : δ) => f a⁻¹ :=
  measurable.comp measurable_inv' hf

theorem measurable.of_inv {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [group α] [topological_group α] {f : δ → α} (hf : measurable fun (a : δ) => f a⁻¹) : measurable f := sorry

@[simp] theorem measurable_inv_iff {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [group α] [topological_group α] {f : δ → α} : (measurable fun (a : δ) => f a⁻¹) ↔ measurable f :=
  { mp := measurable.of_inv, mpr := measurable.inv }

theorem measurable.sub {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [add_group α] [topological_add_group α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} (hf : measurable f) (hg : measurable g) : measurable fun (x : δ) => f x - g x := sorry

theorem ae_measurable.sub {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [add_group α] [topological_add_group α] [topological_space.second_countable_topology α] {f : δ → α} {g : δ → α} {μ : measure_theory.measure δ} (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (x : δ) => f x - g x := sorry

theorem closed_embedding.measurable_inv_fun {β : Type u_2} {γ : Type u_3} [topological_space β] [measurable_space β] [borel_space β] [topological_space γ] [measurable_space γ] [borel_space γ] [n : Nonempty β] {g : β → γ} (hg : closed_embedding g) : measurable (function.inv_fun g) := sorry

theorem measurable_comp_iff_of_closed_embedding {β : Type u_2} {γ : Type u_3} {δ : Type u_5} [topological_space β] [measurable_space β] [borel_space β] [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] {f : δ → β} (g : β → γ) (hg : closed_embedding g) : measurable (g ∘ f) ↔ measurable f := sorry

theorem ae_measurable_comp_iff_of_closed_embedding {β : Type u_2} {γ : Type u_3} {δ : Type u_5} [topological_space β] [measurable_space β] [borel_space β] [topological_space γ] [measurable_space γ] [borel_space γ] [measurable_space δ] {f : δ → β} {μ : measure_theory.measure δ} (g : β → γ) (hg : closed_embedding g) : ae_measurable (g ∘ f) ↔ ae_measurable f := sorry

theorem measurable_of_Iio {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {f : δ → α} (hf : ∀ (x : α), is_measurable (f ⁻¹' set.Iio x)) : measurable f := sorry

theorem measurable_of_Ioi {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {f : δ → α} (hf : ∀ (x : α), is_measurable (f ⁻¹' set.Ioi x)) : measurable f := sorry

theorem measurable_of_Iic {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {f : δ → α} (hf : ∀ (x : α), is_measurable (f ⁻¹' set.Iic x)) : measurable f := sorry

theorem measurable_of_Ici {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {f : δ → α} (hf : ∀ (x : α), is_measurable (f ⁻¹' set.Ici x)) : measurable f := sorry

theorem measurable.is_lub {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} [encodable ι] {f : ι → δ → α} {g : δ → α} (hf : ∀ (i : ι), measurable (f i)) (hg : ∀ (b : δ), is_lub (set_of fun (a : α) => ∃ (i : ι), f i b = a) (g b)) : measurable g := sorry

theorem ae_measurable.is_lub {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {μ : measure_theory.measure δ} [encodable ι] {f : ι → δ → α} {g : δ → α} (hf : ∀ (i : ι), ae_measurable (f i)) (hg : filter.eventually (fun (b : δ) => is_lub (set_of fun (a : α) => ∃ (i : ι), f i b = a) (g b))
  (measure_theory.measure.ae μ)) : ae_measurable g := sorry

theorem measurable.is_glb {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} [encodable ι] {f : ι → δ → α} {g : δ → α} (hf : ∀ (i : ι), measurable (f i)) (hg : ∀ (b : δ), is_glb (set_of fun (a : α) => ∃ (i : ι), f i b = a) (g b)) : measurable g := sorry

theorem ae_measurable.is_glb {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {μ : measure_theory.measure δ} [encodable ι] {f : ι → δ → α} {g : δ → α} (hf : ∀ (i : ι), ae_measurable (f i)) (hg : filter.eventually (fun (b : δ) => is_glb (set_of fun (a : α) => ∃ (i : ι), f i b = a) (g b))
  (measure_theory.measure.ae μ)) : ae_measurable g := sorry

theorem measurable.supr_Prop {δ : Type u_5} [measurable_space δ] {α : Type u_1} [measurable_space α] [complete_lattice α] (p : Prop) {f : δ → α} (hf : measurable f) : measurable fun (b : δ) => supr fun (h : p) => f b := sorry

theorem measurable.infi_Prop {δ : Type u_5} [measurable_space δ] {α : Type u_1} [measurable_space α] [complete_lattice α] (p : Prop) {f : δ → α} (hf : measurable f) : measurable fun (b : δ) => infi fun (h : p) => f b := sorry

theorem measurable_supr {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} [encodable ι] {f : ι → δ → α} (hf : ∀ (i : ι), measurable (f i)) : measurable fun (b : δ) => supr fun (i : ι) => f i b :=
  measurable.is_lub hf fun (b : δ) => is_lub_supr

theorem ae_measurable_supr {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {μ : measure_theory.measure δ} [encodable ι] {f : ι → δ → α} (hf : ∀ (i : ι), ae_measurable (f i)) : ae_measurable fun (b : δ) => supr fun (i : ι) => f i b :=
  ae_measurable.is_lub hf (measure_theory.ae_of_all μ fun (b : δ) => is_lub_supr)

theorem measurable_infi {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} [encodable ι] {f : ι → δ → α} (hf : ∀ (i : ι), measurable (f i)) : measurable fun (b : δ) => infi fun (i : ι) => f i b :=
  measurable.is_glb hf fun (b : δ) => is_glb_infi

theorem ae_measurable_infi {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {μ : measure_theory.measure δ} [encodable ι] {f : ι → δ → α} (hf : ∀ (i : ι), ae_measurable (f i)) : ae_measurable fun (b : δ) => infi fun (i : ι) => f i b :=
  ae_measurable.is_glb hf (measure_theory.ae_of_all μ fun (b : δ) => is_glb_infi)

theorem measurable_bsupr {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} (s : set ι) {f : ι → δ → α} (hs : set.countable s) (hf : ∀ (i : ι), measurable (f i)) : measurable fun (b : δ) => supr fun (i : ι) => supr fun (H : i ∈ s) => f i b := sorry

theorem ae_measurable_bsupr {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {μ : measure_theory.measure δ} (s : set ι) {f : ι → δ → α} (hs : set.countable s) (hf : ∀ (i : ι), ae_measurable (f i)) : ae_measurable fun (b : δ) => supr fun (i : ι) => supr fun (H : i ∈ s) => f i b := sorry

theorem measurable_binfi {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} (s : set ι) {f : ι → δ → α} (hs : set.countable s) (hf : ∀ (i : ι), measurable (f i)) : measurable fun (b : δ) => infi fun (i : ι) => infi fun (H : i ∈ s) => f i b := sorry

theorem ae_measurable_binfi {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {μ : measure_theory.measure δ} (s : set ι) {f : ι → δ → α} (hs : set.countable s) (hf : ∀ (i : ι), ae_measurable (f i)) : ae_measurable fun (b : δ) => infi fun (i : ι) => infi fun (H : i ∈ s) => f i b := sorry

/-- `liminf` over a general filter is measurable. See `measurable_liminf` for the version over `ℕ`.
-/
theorem measurable_liminf' {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {ι' : Type u_3} {f : ι → δ → α} {u : filter ι} (hf : ∀ (i : ι), measurable (f i)) {p : ι' → Prop} {s : ι' → set ι} (hu : filter.has_countable_basis u p s) (hs : ∀ (i : ι'), set.countable (s i)) : measurable fun (x : δ) => filter.liminf u fun (i : ι) => f i x := sorry

/-- `limsup` over a general filter is measurable. See `measurable_limsup` for the version over `ℕ`.
-/
theorem measurable_limsup' {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {ι : Type u_2} {ι' : Type u_3} {f : ι → δ → α} {u : filter ι} (hf : ∀ (i : ι), measurable (f i)) {p : ι' → Prop} {s : ι' → set ι} (hu : filter.has_countable_basis u p s) (hs : ∀ (i : ι'), set.countable (s i)) : measurable fun (x : δ) => filter.limsup u fun (i : ι) => f i x := sorry

/-- `liminf` over `ℕ` is measurable. See `measurable_liminf'` for a version with a general filter.
-/
theorem measurable_liminf {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {f : ℕ → δ → α} (hf : ∀ (i : ℕ), measurable (f i)) : measurable fun (x : δ) => filter.liminf filter.at_top fun (i : ℕ) => f i x :=
  measurable_liminf' hf filter.at_top_countable_basis fun (i : ℕ) => set.countable_encodable (set.Ici i)

/-- `limsup` over `ℕ` is measurable. See `measurable_limsup'` for a version with a general filter.
-/
theorem measurable_limsup {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [complete_linear_order α] [order_topology α] [topological_space.second_countable_topology α] {f : ℕ → δ → α} (hf : ∀ (i : ℕ), measurable (f i)) : measurable fun (x : δ) => filter.limsup filter.at_top fun (i : ℕ) => f i x :=
  measurable_limsup' hf filter.at_top_countable_basis fun (i : ℕ) => set.countable_encodable (set.Ici i)

theorem measurable_cSup {α : Type u_1} {δ : Type u_5} [topological_space α] [measurable_space α] [borel_space α] [measurable_space δ] [conditionally_complete_linear_order α] [topological_space.second_countable_topology α] [order_topology α] {ι : Type u_2} {f : ι → δ → α} {s : set ι} (hs : set.countable s) (hf : ∀ (i : ι), measurable (f i)) (bdd : ∀ (x : δ), bdd_above ((fun (i : ι) => f i x) '' s)) : measurable fun (x : δ) => Sup ((fun (i : ι) => f i x) '' s) := sorry

/-- Convert a `homeomorph` to a `measurable_equiv`. -/
def homemorph.to_measurable_equiv {α : Type u_1} {β : Type u_2} [topological_space α] [measurable_space α] [borel_space α] [topological_space β] [measurable_space β] [borel_space β] (h : α ≃ₜ β) : α ≃ᵐ β :=
  measurable_equiv.mk (homeomorph.to_equiv h) sorry sorry

protected instance empty.borel_space : borel_space empty :=
  borel_space.mk (Eq.symm borel_eq_top_of_discrete)

protected instance unit.borel_space : borel_space Unit :=
  borel_space.mk (Eq.symm borel_eq_top_of_discrete)

protected instance bool.borel_space : borel_space Bool :=
  borel_space.mk (Eq.symm borel_eq_top_of_discrete)

protected instance nat.borel_space : borel_space ℕ :=
  borel_space.mk (Eq.symm borel_eq_top_of_discrete)

protected instance int.borel_space : borel_space ℤ :=
  borel_space.mk (Eq.symm borel_eq_top_of_discrete)

protected instance rat.borel_space : borel_space ℚ :=
  borel_space.mk (Eq.symm borel_eq_top_of_encodable)

protected instance real.measurable_space : measurable_space ℝ :=
  borel ℝ

protected instance real.borel_space : borel_space ℝ :=
  borel_space.mk rfl

protected instance nnreal.measurable_space : measurable_space nnreal :=
  borel nnreal

protected instance nnreal.borel_space : borel_space nnreal :=
  borel_space.mk rfl

protected instance ennreal.measurable_space : measurable_space ennreal :=
  borel ennreal

protected instance ennreal.borel_space : borel_space ennreal :=
  borel_space.mk rfl

protected instance complex.measurable_space : measurable_space ℂ :=
  borel ℂ

protected instance complex.borel_space : borel_space ℂ :=
  borel_space.mk rfl

theorem is_measurable_ball {α : Type u_1} [metric_space α] [measurable_space α] [opens_measurable_space α] {x : α} {ε : ℝ} : is_measurable (metric.ball x ε) :=
  is_open.is_measurable metric.is_open_ball

theorem is_measurable_closed_ball {α : Type u_1} [metric_space α] [measurable_space α] [opens_measurable_space α] {x : α} {ε : ℝ} : is_measurable (metric.closed_ball x ε) :=
  is_closed.is_measurable metric.is_closed_ball

theorem measurable_inf_dist {α : Type u_1} [metric_space α] [measurable_space α] [opens_measurable_space α] {s : set α} : measurable fun (x : α) => metric.inf_dist x s :=
  continuous.measurable (metric.continuous_inf_dist_pt s)

theorem measurable.inf_dist {α : Type u_1} {β : Type u_2} [metric_space α] [measurable_space α] [opens_measurable_space α] [measurable_space β] {f : β → α} (hf : measurable f) {s : set α} : measurable fun (x : β) => metric.inf_dist (f x) s :=
  measurable.comp measurable_inf_dist hf

theorem measurable_inf_nndist {α : Type u_1} [metric_space α] [measurable_space α] [opens_measurable_space α] {s : set α} : measurable fun (x : α) => metric.inf_nndist x s :=
  continuous.measurable (metric.continuous_inf_nndist_pt s)

theorem measurable.inf_nndist {α : Type u_1} {β : Type u_2} [metric_space α] [measurable_space α] [opens_measurable_space α] [measurable_space β] {f : β → α} (hf : measurable f) {s : set α} : measurable fun (x : β) => metric.inf_nndist (f x) s :=
  measurable.comp measurable_inf_nndist hf

theorem measurable_dist {α : Type u_1} [metric_space α] [measurable_space α] [opens_measurable_space α] [topological_space.second_countable_topology α] : measurable fun (p : α × α) => dist (prod.fst p) (prod.snd p) :=
  continuous.measurable continuous_dist

theorem measurable.dist {α : Type u_1} {β : Type u_2} [metric_space α] [measurable_space α] [opens_measurable_space α] [measurable_space β] [topological_space.second_countable_topology α] {f : β → α} {g : β → α} (hf : measurable f) (hg : measurable g) : measurable fun (b : β) => dist (f b) (g b) :=
  continuous.measurable2 continuous_dist hf hg

theorem measurable_nndist {α : Type u_1} [metric_space α] [measurable_space α] [opens_measurable_space α] [topological_space.second_countable_topology α] : measurable fun (p : α × α) => nndist (prod.fst p) (prod.snd p) :=
  continuous.measurable continuous_nndist

theorem measurable.nndist {α : Type u_1} {β : Type u_2} [metric_space α] [measurable_space α] [opens_measurable_space α] [measurable_space β] [topological_space.second_countable_topology α] {f : β → α} {g : β → α} (hf : measurable f) (hg : measurable g) : measurable fun (b : β) => nndist (f b) (g b) :=
  continuous.measurable2 continuous_nndist hf hg

theorem is_measurable_eball {α : Type u_1} [emetric_space α] [measurable_space α] [opens_measurable_space α] {x : α} {ε : ennreal} : is_measurable (emetric.ball x ε) :=
  is_open.is_measurable emetric.is_open_ball

theorem measurable_edist_right {α : Type u_1} [emetric_space α] [measurable_space α] [opens_measurable_space α] {x : α} : measurable (edist x) :=
  continuous.measurable (continuous.edist continuous_const continuous_id)

theorem measurable_edist_left {α : Type u_1} [emetric_space α] [measurable_space α] [opens_measurable_space α] {x : α} : measurable fun (y : α) => edist y x :=
  continuous.measurable (continuous.edist continuous_id continuous_const)

theorem measurable_inf_edist {α : Type u_1} [emetric_space α] [measurable_space α] [opens_measurable_space α] {s : set α} : measurable fun (x : α) => emetric.inf_edist x s :=
  continuous.measurable emetric.continuous_inf_edist

theorem measurable.inf_edist {α : Type u_1} {β : Type u_2} [emetric_space α] [measurable_space α] [opens_measurable_space α] [measurable_space β] {f : β → α} (hf : measurable f) {s : set α} : measurable fun (x : β) => emetric.inf_edist (f x) s :=
  measurable.comp measurable_inf_edist hf

theorem measurable_edist {α : Type u_1} [emetric_space α] [measurable_space α] [opens_measurable_space α] [topological_space.second_countable_topology α] : measurable fun (p : α × α) => edist (prod.fst p) (prod.snd p) :=
  continuous.measurable continuous_edist

theorem measurable.edist {α : Type u_1} {β : Type u_2} [emetric_space α] [measurable_space α] [opens_measurable_space α] [measurable_space β] [topological_space.second_countable_topology α] {f : β → α} {g : β → α} (hf : measurable f) (hg : measurable g) : measurable fun (b : β) => edist (f b) (g b) :=
  continuous.measurable2 continuous_edist hf hg

theorem ae_measurable.edist {α : Type u_1} {β : Type u_2} [emetric_space α] [measurable_space α] [opens_measurable_space α] [measurable_space β] [topological_space.second_countable_topology α] {f : β → α} {g : β → α} {μ : measure_theory.measure β} (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (a : β) => edist (f a) (g a) :=
  continuous.ae_measurable2 continuous_edist hf hg

namespace real

theorem borel_eq_generate_from_Ioo_rat : borel ℝ =
  measurable_space.generate_from
    (set.Union fun (a : ℚ) => set.Union fun (b : ℚ) => set.Union fun (h : a < b) => singleton (set.Ioo ↑a ↑b)) :=
  borel_eq_generate_from_of_subbasis (and.right (and.right is_topological_basis_Ioo_rat))

theorem measure_ext_Ioo_rat {μ : measure_theory.measure ℝ} {ν : measure_theory.measure ℝ} [measure_theory.locally_finite_measure μ] (h : ∀ (a b : ℚ), coe_fn μ (set.Ioo ↑a ↑b) = coe_fn ν (set.Ioo ↑a ↑b)) : μ = ν := sorry

theorem borel_eq_generate_from_Iio_rat : borel ℝ = measurable_space.generate_from (set.Union fun (a : ℚ) => singleton (set.Iio ↑a)) := sorry

end real

theorem measurable.sub_nnreal {α : Type u_1} [measurable_space α] {f : α → nnreal} {g : α → nnreal} : measurable f → measurable g → measurable fun (a : α) => f a - g a :=
  continuous.measurable2 continuous_sub

theorem measurable.nnreal_of_real {α : Type u_1} [measurable_space α] {f : α → ℝ} (hf : measurable f) : measurable fun (x : α) => nnreal.of_real (f x) :=
  measurable.comp (continuous.measurable nnreal.continuous_of_real) hf

theorem nnreal.measurable_coe : measurable coe :=
  continuous.measurable nnreal.continuous_coe

theorem measurable.nnreal_coe {α : Type u_1} [measurable_space α] {f : α → nnreal} (hf : measurable f) : measurable fun (x : α) => ↑(f x) :=
  measurable.comp nnreal.measurable_coe hf

theorem measurable.ennreal_coe {α : Type u_1} [measurable_space α] {f : α → nnreal} (hf : measurable f) : measurable fun (x : α) => ↑(f x) :=
  measurable.comp (continuous.measurable ennreal.continuous_coe) hf

theorem ae_measurable.ennreal_coe {α : Type u_1} [measurable_space α] {f : α → nnreal} {μ : measure_theory.measure α} (hf : ae_measurable f) : ae_measurable fun (x : α) => ↑(f x) :=
  measurable.comp_ae_measurable (continuous.measurable ennreal.continuous_coe) hf

theorem measurable.ennreal_of_real {α : Type u_1} [measurable_space α] {f : α → ℝ} (hf : measurable f) : measurable fun (x : α) => ennreal.of_real (f x) :=
  measurable.comp (continuous.measurable ennreal.continuous_of_real) hf

/-- The set of finite `ennreal` numbers is `measurable_equiv` to `ℝ≥0`. -/
def measurable_equiv.ennreal_equiv_nnreal : ↥(set_of fun (r : ennreal) => r ≠ ⊤) ≃ᵐ nnreal :=
  homeomorph.to_measurable_equiv ennreal.ne_top_homeomorph_nnreal

namespace ennreal

theorem measurable_coe : measurable coe :=
  measurable.ennreal_coe measurable_id

theorem measurable_of_measurable_nnreal {α : Type u_1} [measurable_space α] {f : ennreal → α} (h : measurable fun (p : nnreal) => f ↑p) : measurable f :=
  measurable_of_measurable_on_compl_singleton ⊤
    (iff.mp (measurable_equiv.measurable_coe_iff (measurable_equiv.symm measurable_equiv.ennreal_equiv_nnreal)) h)

/-- `ennreal` is `measurable_equiv` to `ℝ≥0 ⊕ unit`. -/
def ennreal_equiv_sum : ennreal ≃ᵐ nnreal ⊕ Unit :=
  measurable_equiv.mk
    (equiv.mk (equiv.to_fun (equiv.option_equiv_sum_punit nnreal)) (equiv.inv_fun (equiv.option_equiv_sum_punit nnreal))
      sorry sorry)
    sorry sorry

theorem measurable_of_measurable_nnreal_prod {β : Type u_2} {γ : Type u_3} [measurable_space β] [measurable_space γ] {f : ennreal × β → γ} (H₁ : measurable fun (p : nnreal × β) => f (↑(prod.fst p), prod.snd p)) (H₂ : measurable fun (x : β) => f (⊤, x)) : measurable f := sorry

theorem measurable_of_measurable_nnreal_nnreal {β : Type u_2} [measurable_space β] {f : ennreal × ennreal → β} (h₁ : measurable fun (p : nnreal × nnreal) => f (↑(prod.fst p), ↑(prod.snd p))) (h₂ : measurable fun (r : nnreal) => f (⊤, ↑r)) (h₃ : measurable fun (r : nnreal) => f (↑r, ⊤)) : measurable f :=
  measurable_of_measurable_nnreal_prod
    (iff.mp measurable_swap_iff (measurable_of_measurable_nnreal_prod (measurable.comp h₁ measurable_swap) h₃))
    (measurable_of_measurable_nnreal h₂)

theorem measurable_of_real : measurable ennreal.of_real :=
  continuous.measurable continuous_of_real

theorem measurable_to_real : measurable ennreal.to_real :=
  measurable_of_measurable_nnreal nnreal.measurable_coe

theorem measurable_to_nnreal : measurable ennreal.to_nnreal :=
  measurable_of_measurable_nnreal measurable_id

theorem measurable_mul : measurable fun (p : ennreal × ennreal) => prod.fst p * prod.snd p := sorry

theorem measurable_sub : measurable fun (p : ennreal × ennreal) => prod.fst p - prod.snd p := sorry

theorem measurable_inv : measurable has_inv.inv :=
  continuous.measurable ennreal.continuous_inv

theorem measurable_div : measurable fun (p : ennreal × ennreal) => prod.fst p / prod.snd p :=
  measurable.comp measurable_mul (measurable.prod_mk measurable_fst (measurable.comp measurable_inv measurable_snd))

end ennreal

theorem measurable.to_nnreal {α : Type u_1} [measurable_space α] {f : α → ennreal} (hf : measurable f) : measurable fun (x : α) => ennreal.to_nnreal (f x) :=
  measurable.comp ennreal.measurable_to_nnreal hf

theorem measurable_ennreal_coe_iff {α : Type u_1} [measurable_space α] {f : α → nnreal} : (measurable fun (x : α) => ↑(f x)) ↔ measurable f :=
  { mp := fun (h : measurable fun (x : α) => ↑(f x)) => measurable.to_nnreal h,
    mpr := fun (h : measurable f) => measurable.ennreal_coe h }

theorem measurable.to_real {α : Type u_1} [measurable_space α] {f : α → ennreal} (hf : measurable f) : measurable fun (x : α) => ennreal.to_real (f x) :=
  measurable.comp ennreal.measurable_to_real hf

theorem ae_measurable.to_real {α : Type u_1} [measurable_space α] {f : α → ennreal} {μ : measure_theory.measure α} (hf : ae_measurable f) : ae_measurable fun (x : α) => ennreal.to_real (f x) :=
  measurable.comp_ae_measurable ennreal.measurable_to_real hf

theorem measurable.ennreal_mul {α : Type u_1} [measurable_space α] {f : α → ennreal} {g : α → ennreal} (hf : measurable f) (hg : measurable g) : measurable fun (a : α) => f a * g a :=
  measurable.comp ennreal.measurable_mul (measurable.prod_mk hf hg)

theorem ae_measurable.ennreal_mul {α : Type u_1} [measurable_space α] {f : α → ennreal} {g : α → ennreal} {μ : measure_theory.measure α} (hf : ae_measurable f) (hg : ae_measurable g) : ae_measurable fun (a : α) => f a * g a :=
  measurable.comp_ae_measurable ennreal.measurable_mul (ae_measurable.prod_mk hf hg)

theorem measurable.ennreal_sub {α : Type u_1} [measurable_space α] {f : α → ennreal} {g : α → ennreal} (hf : measurable f) (hg : measurable g) : measurable fun (a : α) => f a - g a :=
  measurable.comp ennreal.measurable_sub (measurable.prod_mk hf hg)

/-- note: `ennreal` can probably be generalized in a future version of this lemma. -/
theorem measurable.ennreal_tsum {α : Type u_1} [measurable_space α] {ι : Type u_2} [encodable ι] {f : ι → α → ennreal} (h : ∀ (i : ι), measurable (f i)) : measurable fun (x : α) => tsum fun (i : ι) => f i x := sorry

theorem measurable.ennreal_inv {α : Type u_1} [measurable_space α] {f : α → ennreal} (hf : measurable f) : measurable fun (a : α) => f a⁻¹ :=
  measurable.comp ennreal.measurable_inv hf

theorem measurable.ennreal_div {α : Type u_1} [measurable_space α] {f : α → ennreal} {g : α → ennreal} (hf : measurable f) (hg : measurable g) : measurable fun (a : α) => f a / g a :=
  measurable.comp ennreal.measurable_div (measurable.prod_mk hf hg)

theorem measurable_norm {α : Type u_1} [measurable_space α] [normed_group α] [opens_measurable_space α] : measurable norm :=
  continuous.measurable continuous_norm

theorem measurable.norm {α : Type u_1} {β : Type u_2} [measurable_space α] [normed_group α] [opens_measurable_space α] [measurable_space β] {f : β → α} (hf : measurable f) : measurable fun (a : β) => norm (f a) :=
  measurable.comp measurable_norm hf

theorem ae_measurable.norm {α : Type u_1} {β : Type u_2} [measurable_space α] [normed_group α] [opens_measurable_space α] [measurable_space β] {f : β → α} {μ : measure_theory.measure β} (hf : ae_measurable f) : ae_measurable fun (a : β) => norm (f a) :=
  measurable.comp_ae_measurable measurable_norm hf

theorem measurable_nnnorm {α : Type u_1} [measurable_space α] [normed_group α] [opens_measurable_space α] : measurable nnnorm :=
  continuous.measurable continuous_nnnorm

theorem measurable.nnnorm {α : Type u_1} {β : Type u_2} [measurable_space α] [normed_group α] [opens_measurable_space α] [measurable_space β] {f : β → α} (hf : measurable f) : measurable fun (a : β) => nnnorm (f a) :=
  measurable.comp measurable_nnnorm hf

theorem ae_measurable.nnnorm {α : Type u_1} {β : Type u_2} [measurable_space α] [normed_group α] [opens_measurable_space α] [measurable_space β] {f : β → α} {μ : measure_theory.measure β} (hf : ae_measurable f) : ae_measurable fun (a : β) => nnnorm (f a) :=
  measurable.comp_ae_measurable measurable_nnnorm hf

theorem measurable_ennnorm {α : Type u_1} [measurable_space α] [normed_group α] [opens_measurable_space α] : measurable fun (x : α) => ↑(nnnorm x) :=
  measurable.ennreal_coe measurable_nnnorm

theorem measurable.ennnorm {α : Type u_1} {β : Type u_2} [measurable_space α] [normed_group α] [opens_measurable_space α] [measurable_space β] {f : β → α} (hf : measurable f) : measurable fun (a : β) => ↑(nnnorm (f a)) :=
  measurable.ennreal_coe (measurable.nnnorm hf)

theorem ae_measurable.ennnorm {α : Type u_1} {β : Type u_2} [measurable_space α] [normed_group α] [opens_measurable_space α] [measurable_space β] {f : β → α} {μ : measure_theory.measure β} (hf : ae_measurable f) : ae_measurable fun (a : β) => ↑(nnnorm (f a)) :=
  measurable.comp_ae_measurable measurable_ennnorm hf

/-- A limit (over a general filter) of measurable `ℝ≥0` valued functions is measurable.
The assumption `hs` can be dropped using `filter.is_countably_generated.has_antimono_basis`, but we
don't need that case yet. -/
theorem measurable_of_tendsto_nnreal' {α : Type u_1} [measurable_space α] {ι : Type u_2} {ι' : Type u_3} {f : ι → α → nnreal} {g : α → nnreal} (u : filter ι) [filter.ne_bot u] (hf : ∀ (i : ι), measurable (f i)) (lim : filter.tendsto f u (nhds g)) {p : ι' → Prop} {s : ι' → set ι} (hu : filter.has_countable_basis u p s) (hs : ∀ (i : ι'), set.countable (s i)) : measurable g := sorry

/-- A sequential limit of measurable `ℝ≥0` valued functions is measurable. -/
theorem measurable_of_tendsto_nnreal {α : Type u_1} [measurable_space α] {f : ℕ → α → nnreal} {g : α → nnreal} (hf : ∀ (i : ℕ), measurable (f i)) (lim : filter.tendsto f filter.at_top (nhds g)) : measurable g :=
  measurable_of_tendsto_nnreal' filter.at_top hf lim filter.at_top_countable_basis
    fun (i : ℕ) => set.countable_encodable (set.Ici i)

/-- A limit (over a general filter) of measurable functions valued in a metric space is measurable.
The assumption `hs` can be dropped using `filter.is_countably_generated.has_antimono_basis`, but we
don't need that case yet. -/
theorem measurable_of_tendsto_metric' {α : Type u_1} {β : Type u_2} [measurable_space α] [measurable_space β] [metric_space β] [borel_space β] {ι : Type u_3} {ι' : Type u_4} {f : ι → α → β} {g : α → β} (u : filter ι) [filter.ne_bot u] (hf : ∀ (i : ι), measurable (f i)) (lim : filter.tendsto f u (nhds g)) {p : ι' → Prop} {s : ι' → set ι} (hu : filter.has_countable_basis u p s) (hs : ∀ (i : ι'), set.countable (s i)) : measurable g := sorry

/-- A sequential limit of measurable functions valued in a metric space is measurable. -/
theorem measurable_of_tendsto_metric {α : Type u_1} {β : Type u_2} [measurable_space α] [measurable_space β] [metric_space β] [borel_space β] {f : ℕ → α → β} {g : α → β} (hf : ∀ (i : ℕ), measurable (f i)) (lim : filter.tendsto f filter.at_top (nhds g)) : measurable g :=
  measurable_of_tendsto_metric' filter.at_top hf lim filter.at_top_countable_basis
    fun (i : ℕ) => set.countable_encodable (set.Ici i)

theorem ae_measurable_of_tendsto_metric_ae {α : Type u_1} {β : Type u_2} [measurable_space α] [measurable_space β] [metric_space β] [borel_space β] {μ : measure_theory.measure α} {f : ℕ → α → β} {g : α → β} (hf : ∀ (n : ℕ), ae_measurable (f n)) (h_ae_tendsto : filter.eventually (fun (x : α) => filter.tendsto (fun (n : ℕ) => f n x) filter.at_top (nhds (g x)))
  (measure_theory.measure.ae μ)) : ae_measurable g := sorry

theorem measurable_of_tendsto_metric_ae {α : Type u_1} {β : Type u_2} [measurable_space α] [measurable_space β] [metric_space β] [borel_space β] {μ : measure_theory.measure α} [measure_theory.measure.is_complete μ] {f : ℕ → α → β} {g : α → β} (hf : ∀ (n : ℕ), measurable (f n)) (h_ae_tendsto : filter.eventually (fun (x : α) => filter.tendsto (fun (n : ℕ) => f n x) filter.at_top (nhds (g x)))
  (measure_theory.measure.ae μ)) : measurable g :=
  iff.mp ae_measurable_iff_measurable
    (ae_measurable_of_tendsto_metric_ae (fun (i : ℕ) => measurable.ae_measurable (hf i)) h_ae_tendsto)

theorem measurable_limit_of_tendsto_metric_ae {α : Type u_1} {β : Type u_2} [measurable_space α] [measurable_space β] [metric_space β] [borel_space β] {μ : measure_theory.measure α} {f : ℕ → α → β} (hf : ∀ (n : ℕ), ae_measurable (f n)) (h_ae_tendsto : filter.eventually (fun (x : α) => ∃ (l : β), filter.tendsto (fun (n : ℕ) => f n x) filter.at_top (nhds l))
  (measure_theory.measure.ae μ)) : ∃ (f_lim : α → β),
  ∃ (hf_lim_meas : measurable f_lim),
    filter.eventually (fun (x : α) => filter.tendsto (fun (n : ℕ) => f n x) filter.at_top (nhds (f_lim x)))
      (measure_theory.measure.ae μ) := sorry

namespace continuous_linear_map

protected theorem measurable {𝕜 : Type u_6} [normed_field 𝕜] {E : Type u_7} [normed_group E] [normed_space 𝕜 E] [measurable_space E] [opens_measurable_space E] {F : Type u_8} [normed_group F] [normed_space 𝕜 F] [measurable_space F] [borel_space F] (L : continuous_linear_map 𝕜 E F) : measurable ⇑L :=
  continuous.measurable (continuous_linear_map.continuous L)

theorem measurable_comp {α : Type u_1} [measurable_space α] {𝕜 : Type u_6} [normed_field 𝕜] {E : Type u_7} [normed_group E] [normed_space 𝕜 E] [measurable_space E] [opens_measurable_space E] {F : Type u_8} [normed_group F] [normed_space 𝕜 F] [measurable_space F] [borel_space F] (L : continuous_linear_map 𝕜 E F) {φ : α → E} (φ_meas : measurable φ) : measurable fun (a : α) => coe_fn L (φ a) :=
  measurable.comp (continuous_linear_map.measurable L) φ_meas

end continuous_linear_map

theorem measurable_smul_const {α : Type u_1} [measurable_space α] {𝕜 : Type u_6} [nondiscrete_normed_field 𝕜] [complete_space 𝕜] [measurable_space 𝕜] [borel_space 𝕜] {E : Type u_7} [normed_group E] [normed_space 𝕜 E] [measurable_space E] [borel_space E] {f : α → 𝕜} {c : E} (hc : c ≠ 0) : (measurable fun (x : α) => f x • c) ↔ measurable f :=
  measurable_comp_iff_of_closed_embedding (fun (y : 𝕜) => y • c) (closed_embedding_smul_left hc)

theorem ae_measurable_smul_const {α : Type u_1} [measurable_space α] {𝕜 : Type u_6} [nondiscrete_normed_field 𝕜] [complete_space 𝕜] [measurable_space 𝕜] [borel_space 𝕜] {E : Type u_7} [normed_group E] [normed_space 𝕜 E] [measurable_space E] [borel_space E] {f : α → 𝕜} {μ : measure_theory.measure α} {c : E} (hc : c ≠ 0) : (ae_measurable fun (x : α) => f x • c) ↔ ae_measurable f :=
  ae_measurable_comp_iff_of_closed_embedding (fun (y : 𝕜) => y • c) (closed_embedding_smul_left hc)

namespace measure_theory

namespace measure

/-- A measure `μ` is regular if
  - it is finite on all compact sets;
  - it is outer regular: `μ(A) = inf { μ(U) | A ⊆ U open }` for `A` measurable;
  - it is inner regular: `μ(U) = sup { μ(K) | K ⊆ U compact }` for `U` open. -/
structure regular {α : Type u_1} [measurable_space α] [topological_space α] (μ : measure α)
where
  lt_top_of_is_compact : ∀ {K : set α}, is_compact K → coe_fn μ K < ⊤
  outer_regular : ∀ {A : set α},
  is_measurable A →
    (infi fun (U : set α) => infi fun (h : is_open U) => infi fun (h2 : A ⊆ U) => coe_fn μ U) ≤ coe_fn μ A
  inner_regular : ∀ {U : set α},
  is_open U → coe_fn μ U ≤ supr fun (K : set α) => supr fun (h : is_compact K) => supr fun (h2 : K ⊆ U) => coe_fn μ K

namespace regular

theorem outer_regular_eq {α : Type u_1} [measurable_space α] [topological_space α] {μ : measure α} (hμ : regular μ) {A : set α} (hA : is_measurable A) : (infi fun (U : set α) => infi fun (h : is_open U) => infi fun (h2 : A ⊆ U) => coe_fn μ U) = coe_fn μ A := sorry

theorem inner_regular_eq {α : Type u_1} [measurable_space α] [topological_space α] {μ : measure α} (hμ : regular μ) {U : set α} (hU : is_open U) : (supr fun (K : set α) => supr fun (h : is_compact K) => supr fun (h2 : K ⊆ U) => coe_fn μ K) = coe_fn μ U := sorry

theorem exists_compact_not_null {α : Type u_1} [measurable_space α] [topological_space α] {μ : measure α} (hμ : regular μ) : (∃ (K : set α), is_compact K ∧ coe_fn μ K ≠ 0) ↔ μ ≠ 0 := sorry

protected theorem map {α : Type u_1} {β : Type u_2} [measurable_space α] [topological_space α] {μ : measure α} [opens_measurable_space α] [measurable_space β] [topological_space β] [t2_space β] [borel_space β] (hμ : regular μ) (f : α ≃ₜ β) : regular (coe_fn (map ⇑f) μ) := sorry

protected theorem smul {α : Type u_1} [measurable_space α] [topological_space α] {μ : measure α} (hμ : regular μ) {x : ennreal} (hx : x < ⊤) : regular (x • μ) := sorry

/-- A regular measure in a σ-compact space is σ-finite. -/
protected theorem sigma_finite {α : Type u_1} [measurable_space α] [topological_space α] {μ : measure α} [opens_measurable_space α] [t2_space α] [sigma_compact_space α] (hμ : regular μ) : sigma_finite μ := sorry

end regular

end measure

end measure_theory

theorem is_compact.measure_lt_top_of_nhds_within {α : Type u_1} [measurable_space α] [topological_space α] {s : set α} {μ : measure_theory.measure α} (h : is_compact s) (hμ : ∀ (x : α), x ∈ s → measure_theory.measure.finite_at_filter μ (nhds_within x s)) : coe_fn μ s < ⊤ := sorry

theorem is_compact.measure_lt_top {α : Type u_1} [measurable_space α] [topological_space α] {s : set α} {μ : measure_theory.measure α} [measure_theory.locally_finite_measure μ] (h : is_compact s) : coe_fn μ s < ⊤ :=
  is_compact.measure_lt_top_of_nhds_within h
    fun (x : α) (hx : x ∈ s) => measure_theory.measure.finite_at_nhds_within μ x s