import tactic.interactive tactic.basic
import tactic.basic
import tactic.ring
import data.real.basic

open tactic real

meta def get_tactic_state : tactic tactic_state := λ s, interaction_monad.result.success s s

-- Takes a single tactic and the complexity function and checks if it is "less complex" than the previous best
meta def run_each (c : tactic ℕ) (best : ℕ) (s₀ : tactic_state) (t : tactic unit) : tactic ℕ
| s := match t s₀ with -- Get the current tactic state and try running the tactic on the original tactic state
    | result.success _ s₁ := do match c s₁ with | result.success c₁ _ := -- If it succeeds, try running our complexity function
                                                   if (c₁ < best) then result.success c₁ s₁ -- If the result is less complex, store the new complexity
                                                                                -- and the new tactic state (before the complexity function was run)
                                                                  else result.success best s -- If it is more complex, change nothing
                                                | _ := result.success best s -- If it fails, change nothing
                                end
    | _ := result.success best s -- If it fails, change nothing
    end

-- Recursor function to deal with a list of tactics. Terminates if the list is done.
-- Otherwise, use run_each to check if the head of the list is the best and then repeat.
meta def run_list (c : tactic nat) (s₀ : tactic_state): ℕ → list (tactic unit) → tactic unit
| _ [] := do skip -- We have no more tactics left to try
| best (t :: ts) := do best' ← run_each c best s₀ t, -- Run the first tactic and store its complexity
                        out ← run_list best' ts, -- Repeat on tail of list
                        return out

-- Note that the best tactic state is carried along by being set as current tactic state
-- Can be invoked using the syntax "run_best c [`[simp], `[refl], `[trivial, dsimp]]"
-- Tried to remove the backtick syntax and use an interactive block, but Keeley
-- explained that these are not foundational in Lean and are instead "tacked on",
-- so a new parser would have had to be written. This would have been difficult,
-- hard to maintain and likely quite inefficient.
meta def run_best (c : tactic nat) (L : list (tactic unit)) : tactic unit :=
do s₀ ← get_tactic_state,
   run_list c s₀ 1000000000 L -- A large starting best value is used, because the natural numbers have no upper bound
   -- and it needs to be larger than the output of the complexity function after the first iteration

example : true ∨ (false ∧ true) :=
begin
    run_best (num_goals) [`[trivial, refl], `[constructor], `[ring]], -- Constructor is only tactic that makes progress, so constructor runs
    run_best (num_goals) [`[intros], `[trivial]], -- Trivial finishes the proof
end


import model_theory.substructures
import model_theory.bundled

--OUTPUT 1
theorem overflow {L : first_order.language} {F : L.Theory} (h : ∀ n : ℕ, ∃ (m : F.Model) [mfin : fintype m], n ≤ @fintype.card m mfin) : ∃ (M : F.Model), infinite M :=
begin
  let A := λ n : ℕ, ∃ x₁ x₂ x₃ x₄ x₅ x₆ x₇ x₈ x₉ x₁₀ x₁₁ x₁₂ x₁₃ x₁₄ x₁₅ x₁₆ x₁₇ x₁₈ x₁₉ x₂₀ x₂₁ x₂₂ x₂₃ x₂₄ x₂₅ x₂₆ x₂₇ x₂₈ x₂₉x₃₀x₃₁x₃₂x₃₃x₃₄x₃₅x₃₆x₃₇x₃₈x₃₉x₄₀x₄₁x₄₂x₄₃x₄₄x₄₅x₄₆x₄₇x₄₈x₄₉x₅₀x₅₁x₅₂x₅₃x₅₄x₅₅x₅₆x₅₇x₅₈x₅₉x₆₀x₆₁x₆₂x₆₃x₆₄x₆₅x₆₆x₆₇x₆₈x₆₉x₇₀x₇₁x₇₂x₇₃x₇₄x₇₅x₇₆x₇₇x₇₈x₇₉x₈₀x₈₁x₈₂x₈₃x₈₄x₈₅x₈₆x₈₇x₈₈x₈₉x₉₀x₉₁x₉₂x₉₃x₉₄x₉₅x₉₆x₉₇x₉₈x₉₉x₁₀₀x₁₀₁x₁₀₂x₁₀₃x₁₀₄x₁₀₅x₁₀₆x₁₀₇x₁₀₈x₁₀₉x₁₁₀x₁₁₁x₁₁₂x₁₁₃x₁₁₄x₁₁₅x₁₁₆x₁₁₇x₁₁₈x₁₁₉x₁₂₀x₁₂₁x₁₂₂x₁₂₃x₁₂₄x₁₂₅x₁₂₆x₁₂₇x₁₂₈x₁₂₉x₁₃₀x₁₃₁x₁₃₂x₁₃₃x₁₃₄x₁₃₅x₁₃₆x₁₃₇x₁₃₈x₁₃₉x₁₄₀x₁₄₁x₁₄₂x₁₄₃x₁₄₄x₁₄₅x₁₄₆x₁₄₇x₁₄₈x₁₄₉x₁₅₀x₁₅₁x₁₅₂x₁₅₃x₁₅₄x₁₅₅x₁₅₆x₁₅₇x₁₅₈x₁₅₉x₁₆₀x₁₆₁x₁₆₂x₁₆₃x₁₆₄x₁₆₅x₁₆₆x₁₆₇x₁₆₈x₁₆₉x₁₇₀x₁₇₁x₁₇₂x₁₇₃x₁₇₄x₁₇₅x₁₇₆x₁₇₇x₁₇₈x₁₇₉x₁₈₀x₁₈₁x₁₈₂x₁₈₃x₁₈₄x₁₈₅x₁₈₆x₁₈₇x₁₈₈x₁₈₉x₁₉₀x₁₉₁x₁₉₂x₁₉₃x₁₉₄x₁₉₅x₁₉₆x₁₉₇x₁₉₈x₁₉₉x₂₀₀x₂₀₁x₂₀₂x₂₀₃x₂₀₄x₂₀₅x₂₀₆x₂₀₇x₂₀₈x₂₀₉x₂₁₀x₂₁₁x₂₁₂x₂₁₃x₂₁₄x₂₁₅x₂₁₆x₂₁₇x₂₁₈x₂₁₉x₂₂₀x₂₂₁x₂₂₂x₂₂₃x₂₂₄x₂₂₅x₂₂₆x₂₂₇x₂₂₈x₂₂₉x₂₃₀x₂₃
end --Needs more than 2000 tokens!

/- FEW SHOT PROMPTS TO CODEX(START)
/--`theorem`
Power Set is Closed under Intersection
Let $S$ be a set.

Let $\powerset S$ be the power set of $S$.

Then:
:$\forall A, B \in \powerset S: A \cap B \in \powerset S$
`proof`
Let $A, B \in \powerset S$.

Then by the definition of power set, $A \subseteq S$ and $B \subseteq S$.

From Intersection is Subset we have that $A \cap B \subseteq A$.

It follows from Subset Relation is Transitive that $A \cap B \subseteq S$.

Thus $A \cap B \in \powerset S$ and closure is proved.
{{qed}}
-/
theorem power_set_intersection_closed {α : Type*} (S : set α) : ∀ A B ∈ 𝒫 S, (A ∩ B) ∈ 𝒫 S :=
begin
  assume (A : set α) (hA : A ∈ 𝒫 S) (B : set α) (hB : B ∈ 𝒫 S),
  have h1 : (A ⊆ S) ∧ (B ⊆ S), from by auto [set.subset_of_mem_powerset, set.subset_of_mem_powerset],
  have h2 : (A ∩ B) ⊆ A, from by auto [set.inter_subset_left],
  have h3 : (A ∩ B) ⊆ S, from by auto [set.subset.trans],
  show (A ∩ B) ∈  𝒫 S, from by auto [set.mem_powerset],
end

/--`theorem`
Square of Sum
 :$\forall x, y \in \R: \paren {x + y}^2 = x^2 + 2 x y + y^2$
`proof`
Follows from the distribution of multiplication over addition:

{{begin-eqn}}
{{eqn | l = \left({x + y}\right)^2
      | r = \left({x + y}\right) \cdot \left({x + y}\right)
}}
{{eqn | r = x \cdot \left({x + y}\right) + y \cdot \left({x + y}\right)
      | c = Real Multiplication Distributes over Addition
}}
{{eqn | r = x \cdot x + x \cdot y + y \cdot x + y \cdot y
      | c = Real Multiplication Distributes over Addition
}}
{{eqn | r = x^2 + 2xy + y^2
      | c =
}}
{{end-eqn}}
{{qed}}
-/
theorem square_of_sum (x y : ℝ) : (x + y)^2 = (x^2 + 2*x*y + y^2) :=
begin
  calc (x + y)^2 = (x+y)*(x+y) : by auto [sq]
  ... = x*(x+y) + y*(x+y) : by auto [add_mul]
  ... = x*x + x*y + y*x + y*y : by auto [mul_comm, add_mul] using [ring]
  ... = x^2 + 2*x*y + y^2 : by auto [sq, mul_comm] using [ring]
end

/--`theorem`
Identity of Group is Unique
Let $\struct {G, \circ}$ be a group. Then there is a unique identity element $e \in G$.
`proof`
From Group has Latin Square Property, there exists a unique $x \in G$ such that:
:$a x = b$

and there exists a unique $y \in G$ such that:
:$y a = b$

Setting $b = a$, this becomes:

There exists a unique $x \in G$ such that:
:$a x = a$

and there exists a unique $y \in G$ such that:
:$y a = a$

These $x$ and $y$ are both $e$, by definition of identity element.
{{qed}}
-/
theorem group_identity_unique {G : Type*} [group G] : ∃! e : G, ∀ a : G, e * a = a ∧ a * e = a :=
begin
  have h1 : ∀ a b : G, ∃! x : G, a * x = b, from by auto using [use (a⁻¹ * b)],
  have h2 : ∀ a b : G, ∃! y : G, y * a = b, from by auto using [use b * a⁻¹],

  have h3 : ∀ a : G, ∃! x : G, a * x = a, from by auto [h1],
  have h4 : ∀ a : G, ∃! y : G, y * a = a, from by auto [h2],

  have h5 : ∀ a : G, classical.some (h3 a).exists = (1 : G), from by auto [exists_unique.unique, h3, classical.some_spec, exists_unique.exists, mul_one],
  have h6 : ∀ a : G, classical.some (h4 a).exists = (1 : G), from by auto [exists_unique.unique, h4, classical.some_spec, exists_unique.exists, one_mul],

  show ∃! e : G, ∀ a : G, e * a = a ∧ a * e = a, from by auto [h3, h4, exists_unique.unique, classical.some_spec, exists_unique.exists] using [use (1 : G)],
end

/--`theorem`
Overflow theorem
Let $F$ be a set of first-order formulas which has finite models of arbitrarily large size. Then $F$ has an infinite model.
`proof`
For each $n$, let $\mathbf A_n$ be the formula:

$\exists x_1 \exists x_2 \ldots \exists x_n: \{x_1 \ne x_2 \land x_1 \ne x_3 \land \ldots \land x_{n - 1} \ne x_n\}$

Then $\mathbf A_i$ is true in a structure $\AA$ iff $\AA$ has at least $n$ elements.

Take:
$$ \Gamma := F \cup \bigcup_{i \mathop = 1}^\infty A_i $$

Since $F$ has models of arbitrarily large size, every finite subset of $\Gamma$ is satisfiable.

From the Compactness Theorem, $\Gamma$ is satisfiable in some model $\mathbf{M}$.

But since $\mathbf{M} \models A_i$ for each $i$, $\mathbf{M}$ must be infinite.

So $F$ has an infinite model.

QED
-/
theorem  overflow {L : first_order.language} {F : L.Theory} (h : ∀ n : ℕ, ∃ (m : F.Model) [mfin : fintype m], n ≤ @fintype.card m mfin) : ∃ (M : F.Model), infinite M :=
FEW SHOT PROMPTS TO CODEX(END)-/


/-
Copyright (c) 2019 Zhouhang Zhou. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Zhouhang Zhou, Yury Kudryashov
-/
import Mathlib.PrePort
import Mathlib.Lean3Lib.init.default
import Mathlib.measure_theory.simple_func_dense
import Mathlib.analysis.normed_space.bounded_linear_maps
import Mathlib.topology.sequences
import Mathlib.PostPort

universes u_1 u_2 u_3 u_4

namespace Mathlib

/-!
# Bochner integral

The Bochner integral extends the definition of the Lebesgue integral to functions that map from a
measure space into a Banach space (complete normed vector space). It is constructed here by
extending the integral on simple functions.

## Main definitions

The Bochner integral is defined following these steps:

1. Define the integral on simple functions of the type `simple_func α E` (notation : `α →ₛ E`)
  where `E` is a real normed space.

  (See `simple_func.bintegral` and section `bintegral` for details. Also see `simple_func.integral`
  for the integral on simple functions of the type `simple_func α ennreal`.)

2. Use `α →ₛ E` to cut out the simple functions from L1 functions, and define integral
  on these. The type of simple functions in L1 space is written as `α →₁ₛ[μ] E`.

3. Show that the embedding of `α →₁ₛ[μ] E` into L1 is a dense and uniform one.

4. Show that the integral defined on `α →₁ₛ[μ] E` is a continuous linear map.

5. Define the Bochner integral on L1 functions by extending the integral on integrable simple
  functions `α →₁ₛ[μ] E` using `continuous_linear_map.extend`. Define the Bochner integral on
  functions as the Bochner integral of its equivalence class in L1 space.

## Main statements

1. Basic properties of the Bochner integral on functions of type `α → E`, where `α` is a measure
   space and `E` is a real normed space.

  * `integral_zero`                  : `∫ 0 ∂μ = 0`
  * `integral_add`                   : `∫ x, f x + g x ∂μ = ∫ x, f ∂μ + ∫ x, g x ∂μ`
  * `integral_neg`                   : `∫ x, - f x ∂μ = - ∫ x, f x ∂μ`
  * `integral_sub`                   : `∫ x, f x - g x ∂μ = ∫ x, f x ∂μ - ∫ x, g x ∂μ`
  * `integral_smul`                  : `∫ x, r • f x ∂μ = r • ∫ x, f x ∂μ`
  * `integral_congr_ae`              : `f =ᵐ[μ] g → ∫ x, f x ∂μ = ∫ x, g x ∂μ`
  * `norm_integral_le_integral_norm` : `∥∫ x, f x ∂μ∥ ≤ ∫ x, ∥f x∥ ∂μ`

2. Basic properties of the Bochner integral on functions of type `α → ℝ`, where `α` is a measure
  space.

  * `integral_nonneg_of_ae` : `0 ≤ᵐ[μ] f → 0 ≤ ∫ x, f x ∂μ`
  * `integral_nonpos_of_ae` : `f ≤ᵐ[μ] 0 → ∫ x, f x ∂μ ≤ 0`
  * `integral_mono_ae`      : `f ≤ᵐ[μ] g → ∫ x, f x ∂μ ≤ ∫ x, g x ∂μ`
  * `integral_nonneg`       : `0 ≤ f → 0 ≤ ∫ x, f x ∂μ`
  * `integral_nonpos`       : `f ≤ 0 → ∫ x, f x ∂μ ≤ 0`
  * `integral_mono`         : `f ≤ᵐ[μ] g → ∫ x, f x ∂μ ≤ ∫ x, g x ∂μ`

3. Propositions connecting the Bochner integral with the integral on `ennreal`-valued functions,
   which is called `lintegral` and has the notation `∫⁻`.

  * `integral_eq_lintegral_max_sub_lintegral_min` : `∫ x, f x ∂μ = ∫⁻ x, f⁺ x ∂μ - ∫⁻ x, f⁻ x ∂μ`,
    where `f⁺` is the positive part of `f` and `f⁻` is the negative part of `f`.
  * `integral_eq_lintegral_of_nonneg_ae`          : `0 ≤ᵐ[μ] f → ∫ x, f x ∂μ = ∫⁻ x, f x ∂μ`

4. `tendsto_integral_of_dominated_convergence` : the Lebesgue dominated convergence theorem

## Notes

Some tips on how to prove a proposition if the API for the Bochner integral is not enough so that
you need to unfold the definition of the Bochner integral and go back to simple functions.

One method is to use the theorem `integrable.induction` in the file `set_integral`, which allows
you to prove something for an arbitrary measurable + integrable function.

Another method is using the following steps.
See `integral_eq_lintegral_max_sub_lintegral_min` for a complicated example, which proves that
`∫ f = ∫⁻ f⁺ - ∫⁻ f⁻`, with the first integral sign being the Bochner integral of a real-valued
function `f : α → ℝ`, and second and third integral sign being the integral on ennreal-valued
functions (called `lintegral`). The proof of `integral_eq_lintegral_max_sub_lintegral_min` is
scattered in sections with the name `pos_part`.

Here are the usual steps of proving that a property `p`, say `∫ f = ∫⁻ f⁺ - ∫⁻ f⁻`, holds for all
functions :

1. First go to the `L¹` space.

   For example, if you see `ennreal.to_real (∫⁻ a, ennreal.of_real $ ∥f a∥)`, that is the norm of
   `f` in `L¹` space. Rewrite using `l1.norm_of_fun_eq_lintegral_norm`.

2. Show that the set `{f ∈ L¹ | ∫ f = ∫⁻ f⁺ - ∫⁻ f⁻}` is closed in `L¹` using `is_closed_eq`.

3. Show that the property holds for all simple functions `s` in `L¹` space.

   Typically, you need to convert various notions to their `simple_func` counterpart, using lemmas
   like `l1.integral_coe_eq_integral`.

4. Since simple functions are dense in `L¹`,
```
univ = closure {s simple}
     = closure {s simple | ∫ s = ∫⁻ s⁺ - ∫⁻ s⁻} : the property holds for all simple functions
     ⊆ closure {f | ∫ f = ∫⁻ f⁺ - ∫⁻ f⁻}
     = {f | ∫ f = ∫⁻ f⁺ - ∫⁻ f⁻} : closure of a closed set is itself
```
Use `is_closed_property` or `dense_range.induction_on` for this argument.

## Notations

* `α →ₛ E`  : simple functions (defined in `measure_theory/integration`)
* `α →₁[μ] E` : functions in L1 space, i.e., equivalence classes of integrable functions (defined in
                `measure_theory/l1_space`)
* `α →₁ₛ[μ] E` : simple functions in L1 space, i.e., equivalence classes of integrable simple
                 functions

Note : `ₛ` is typed using `\_s`. Sometimes it shows as a box if font is missing.

## Tags

Bochner integral, simple function, function space, Lebesgue dominated convergence theorem

-/

namespace measure_theory

namespace simple_func

/-- Positive part of a simple function. -/
def pos_part {α : Type u_1} {E : Type u_2} [measurable_space α] [linear_order E] [HasZero E]
    (f : simple_func α E) : simple_func α E :=
  map (fun (b : E) => max b 0) f

/-- Negative part of a simple function. -/
def neg_part {α : Type u_1} {E : Type u_2} [measurable_space α] [linear_order E] [HasZero E] [Neg E]
    (f : simple_func α E) : simple_func α E :=
  pos_part (-f)

theorem pos_part_map_norm {α : Type u_1} [measurable_space α] (f : simple_func α ℝ) :
    map norm (pos_part f) = pos_part f :=
  sorry

theorem neg_part_map_norm {α : Type u_1} [measurable_space α] (f : simple_func α ℝ) :
    map norm (neg_part f) = neg_part f :=
  eq.mpr
    (id (Eq._oldrec (Eq.refl (map norm (neg_part f) = neg_part f)) (neg_part.equations._eqn_1 f)))
    (pos_part_map_norm (-f))

theorem pos_part_sub_neg_part {α : Type u_1} [measurable_space α] (f : simple_func α ℝ) :
    pos_part f - neg_part f = f :=
  sorry

end simple_func

end measure_theory

namespace measure_theory

namespace simple_func

/-!
### The Bochner integral of simple functions

Define the Bochner integral of simple functions of the type `α →ₛ β` where `β` is a normed group,
and prove basic property of this integral.
-/

/-- For simple functions with a `normed_group` as codomain, being integrable is the same as having
    finite volume support. -/
theorem integrable_iff_fin_meas_supp {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [measurable_space E] {f : simple_func α E} {μ : measure α} :
    integrable ⇑f ↔ simple_func.fin_meas_supp f μ :=
  sorry

theorem fin_meas_supp.integrable {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} {f : simple_func α E} (h : simple_func.fin_meas_supp f μ) :
    integrable ⇑f :=
  iff.mpr integrable_iff_fin_meas_supp h

theorem integrable_pair {α : Type u_1} {E : Type u_2} {F : Type u_3} [measurable_space α]
    [normed_group E] [measurable_space E] [normed_group F] {μ : measure α} [measurable_space F]
    {f : simple_func α E} {g : simple_func α F} :
    integrable ⇑f → integrable ⇑g → integrable ⇑(pair f g) :=
  sorry

/-- Bochner integral of simple functions whose codomain is a real `normed_space`. -/
def integral {α : Type u_1} {F : Type u_3} [measurable_space α] [normed_group F] [normed_space ℝ F]
    (μ : measure α) (f : simple_func α F) : F :=
  finset.sum (simple_func.range f)
    fun (x : F) => ennreal.to_real (coe_fn μ (⇑f ⁻¹' singleton x)) • x

theorem integral_eq_sum_filter {α : Type u_1} {F : Type u_3} [measurable_space α] [normed_group F]
    [normed_space ℝ F] (f : simple_func α F) (μ : measure α) :
    integral μ f =
        finset.sum (finset.filter (fun (x : F) => x ≠ 0) (simple_func.range f))
          fun (x : F) => ennreal.to_real (coe_fn μ (⇑f ⁻¹' singleton x)) • x :=
  sorry

/-- The Bochner integral is equal to a sum over any set that includes `f.range` (except `0`). -/
theorem integral_eq_sum_of_subset {α : Type u_1} {F : Type u_3} [measurable_space α]
    [normed_group F] [normed_space ℝ F] {f : simple_func α F} {μ : measure α} {s : finset F}
    (hs : finset.filter (fun (x : F) => x ≠ 0) (simple_func.range f) ⊆ s) :
    integral μ f =
        finset.sum s fun (x : F) => ennreal.to_real (coe_fn μ (⇑f ⁻¹' singleton x)) • x :=
  sorry

/-- Calculate the integral of `g ∘ f : α →ₛ F`, where `f` is an integrable function from `α` to `E`
    and `g` is a function from `E` to `F`. We require `g 0 = 0` so that `g ∘ f` is integrable. -/
theorem map_integral {α : Type u_1} {E : Type u_2} {F : Type u_3} [measurable_space α]
    [normed_group E] [measurable_space E] [normed_group F] {μ : measure α} [normed_space ℝ F]
    (f : simple_func α E) (g : E → F) (hf : integrable ⇑f) (hg : g 0 = 0) :
    integral μ (map g f) =
        finset.sum (simple_func.range f)
          fun (x : E) => ennreal.to_real (coe_fn μ (⇑f ⁻¹' singleton x)) • g x :=
  sorry

/-- `simple_func.integral` and `simple_func.lintegral` agree when the integrand has type
    `α →ₛ ennreal`. But since `ennreal` is not a `normed_space`, we need some form of coercion.
    See `integral_eq_lintegral` for a simpler version. -/
theorem integral_eq_lintegral' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} {f : simple_func α E} {g : E → ennreal}
    (hf : integrable ⇑f) (hg0 : g 0 = 0) (hgt : ∀ (b : E), g b < ⊤) :
    integral μ (map (ennreal.to_real ∘ g) f) =
        ennreal.to_real (lintegral μ fun (a : α) => g (coe_fn f a)) :=
  sorry

theorem integral_congr {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} [normed_space ℝ E] {f : simple_func α E}
    {g : simple_func α E} (hf : integrable ⇑f) (h : filter.eventually_eq (measure.ae μ) ⇑f ⇑g) :
    integral μ f = integral μ g :=
  sorry

/-- `simple_func.bintegral` and `simple_func.integral` agree when the integrand has type
    `α →ₛ ennreal`. But since `ennreal` is not a `normed_space`, we need some form of coercion. -/
theorem integral_eq_lintegral {α : Type u_1} [measurable_space α] {μ : measure α}
    {f : simple_func α ℝ} (hf : integrable ⇑f) (h_pos : filter.eventually_le (measure.ae μ) 0 ⇑f) :
    integral μ f = ennreal.to_real (lintegral μ fun (a : α) => ennreal.of_real (coe_fn f a)) :=
  sorry

theorem integral_add {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} [normed_space ℝ E] {f : simple_func α E}
    {g : simple_func α E} (hf : integrable ⇑f) (hg : integrable ⇑g) :
    integral μ (f + g) = integral μ f + integral μ g :=
  sorry

theorem integral_neg {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} [normed_space ℝ E] {f : simple_func α E}
    (hf : integrable ⇑f) : integral μ (-f) = -integral μ f :=
  sorry

theorem integral_sub {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} [normed_space ℝ E] [borel_space E] {f : simple_func α E}
    {g : simple_func α E} (hf : integrable ⇑f) (hg : integrable ⇑g) :
    integral μ (f - g) = integral μ f - integral μ g :=
  sorry

theorem integral_smul {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} [normed_space ℝ E] (r : ℝ) {f : simple_func α E}
    (hf : integrable ⇑f) : integral μ (r • f) = r • integral μ f :=
  sorry

theorem norm_integral_le_integral_norm {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [measurable_space E] {μ : measure α} [normed_space ℝ E] (f : simple_func α E)
    (hf : integrable ⇑f) : norm (integral μ f) ≤ integral μ (map norm f) :=
  sorry

theorem integral_add_measure {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [measurable_space E] {μ : measure α} [normed_space ℝ E]
    {ν :
      autoParam (measure α)
        (Lean.Syntax.ident Lean.SourceInfo.none
          (String.toSubstring "Mathlib.measure_theory.volume_tac")
          (Lean.Name.mkStr
            (Lean.Name.mkStr (Lean.Name.mkStr Lean.Name.anonymous "Mathlib") "measure_theory")
            "volume_tac")
          [])}
    (f : simple_func α E) (hf : integrable ⇑f) : integral (μ + ν) f = integral μ f + integral ν f :=
  sorry

end simple_func

namespace l1

-- We use `Type*` instead of `add_subgroup` because otherwise we loose dot notation.

/-- `l1.simple_func` is a subspace of L1 consisting of equivalence classes of an integrable simple
    function. -/
def simple_func (α : Type u_1) (E : Type u_2) [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    (μ : measure α) :=
  ↥(add_subgroup.mk
      (set_of
        fun (f : l1 α E μ) =>
          ∃ (s : simple_func α E), ae_eq_fun.mk (⇑s) (simple_func.ae_measurable s) = ↑f)
      sorry sorry sorry)

namespace simple_func

/-! Simple functions in L1 space form a `normed_space`. -/

protected instance measure_theory.l1.has_coe {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} : has_coe (simple_func α E μ) (l1 α E μ) :=
  Mathlib.coe_subtype

protected instance has_coe_to_fun {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} : has_coe_to_fun (simple_func α E μ) :=
  has_coe_to_fun.mk (fun (f : simple_func α E μ) => α → E) fun (f : simple_func α E μ) => ⇑↑f

@[simp] theorem coe_coe {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : ⇑↑f = ⇑f :=
  rfl

protected theorem eq {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {f : simple_func α E μ} {g : simple_func α E μ} : ↑f = ↑g → f = g :=
  subtype.eq

protected theorem eq' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {f : simple_func α E μ} {g : simple_func α E μ} : ↑f = ↑g → f = g :=
  subtype.eq ∘ subtype.eq

protected theorem eq_iff {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {f : simple_func α E μ} {g : simple_func α E μ} : ↑f = ↑g ↔ f = g :=
  iff.symm subtype.ext_iff

protected theorem eq_iff' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {f : simple_func α E μ} {g : simple_func α E μ} : ↑f = ↑g ↔ f = g :=
  { mp := simple_func.eq', mpr := congr_arg fun {f : simple_func α E μ} => ↑f }

/-- L1 simple functions forms a `emetric_space`, with the emetric being inherited from L1 space,
  i.e., `edist f g = ∫⁻ a, edist (f a) (g a)`.
  Not declared as an instance as `α →₁ₛ[μ] β` will only be useful in the construction of the Bochner
  integral. -/
protected def emetric_space {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : emetric_space (simple_func α E μ) :=
  subtype.emetric_space

/-- L1 simple functions forms a `metric_space`, with the metric being inherited from L1 space,
  i.e., `dist f g = ennreal.to_real (∫⁻ a, edist (f a) (g a)`).
  Not declared as an instance as `α →₁ₛ[μ] β` will only be useful in the construction of the Bochner
  integral. -/
protected def metric_space {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : metric_space (simple_func α E μ) :=
  subtype.metric_space

/-- Functions `α →₁ₛ[μ] E` form an additive commutative group. -/
protected def add_comm_group {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : add_comm_group (simple_func α E μ) :=
  add_subgroup.to_add_comm_group
    (add_subgroup.mk
      (set_of
        fun (f : l1 α E μ) =>
          ∃ (s : simple_func α E), ae_eq_fun.mk (⇑s) (simple_func.ae_measurable s) = ↑f)
      (_proof_3 α E μ) (_proof_4 α E μ) (_proof_5 α E μ))

protected instance inhabited {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : Inhabited (simple_func α E μ) :=
  { default := 0 }

@[simp] theorem coe_zero {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : ↑0 = 0 :=
  rfl

@[simp] theorem coe_add {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) : ↑(f + g) = ↑f + ↑g :=
  rfl

@[simp] theorem coe_neg {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : ↑(-f) = -↑f :=
  rfl

@[simp] theorem coe_sub {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) : ↑(f - g) = ↑f - ↑g :=
  rfl

@[simp] theorem edist_eq {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) : edist f g = edist ↑f ↑g :=
  rfl

@[simp] theorem dist_eq {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) : dist f g = dist ↑f ↑g :=
  rfl

/-- The norm on `α →₁ₛ[μ] E` is inherited from L1 space. That is, `∥f∥ = ∫⁻ a, edist (f a) 0`.
  Not declared as an instance as `α →₁ₛ[μ] E` will only be useful in the construction of the Bochner
  integral. -/
protected def has_norm {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : has_norm (simple_func α E μ) :=
  has_norm.mk fun (f : simple_func α E μ) => norm ↑f

theorem norm_eq {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : norm f = norm ↑f :=
  rfl

theorem norm_eq' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : norm f = ennreal.to_real (edist (↑f) 0) :=
  rfl

/-- Not declared as an instance as `α →₁ₛ[μ] E` will only be useful in the construction of the
Bochner integral. -/
protected def normed_group {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : normed_group (simple_func α E μ) :=
  normed_group.of_add_dist sorry sorry

/-- Not declared as an instance as `α →₁ₛ[μ] E` will only be useful in the construction of the
Bochner integral. -/
protected def has_scalar {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {𝕜 : Type u_4} [normed_field 𝕜] [normed_space 𝕜 E] :
    has_scalar 𝕜 (simple_func α E μ) :=
  has_scalar.mk fun (k : 𝕜) (f : simple_func α E μ) => { val := k • ↑f, property := sorry }

@[simp] theorem coe_smul {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {𝕜 : Type u_4} [normed_field 𝕜] [normed_space 𝕜 E] (c : 𝕜)
    (f : simple_func α E μ) : ↑(c • f) = c • ↑f :=
  rfl

/-- Not declared as an instance as `α →₁ₛ[μ] E` will only be useful in the construction of the
  Bochner integral. -/
protected def semimodule {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {𝕜 : Type u_4} [normed_field 𝕜] [normed_space 𝕜 E] :
    semimodule 𝕜 (simple_func α E μ) :=
  semimodule.mk sorry sorry

/-- Not declared as an instance as `α →₁ₛ[μ] E` will only be useful in the construction of the
Bochner integral. -/
protected def normed_space {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {𝕜 : Type u_4} [normed_field 𝕜] [normed_space 𝕜 E] :
    normed_space 𝕜 (simple_func α E μ) :=
  normed_space.mk sorry

/-- Construct the equivalence class `[f]` of an integrable simple function `f`. -/
def of_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E) (hf : integrable ⇑f) : simple_func α E μ :=
  { val := of_fun (⇑f) hf, property := sorry }

theorem of_simple_func_eq_of_fun {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E) (hf : integrable ⇑f) :
    ↑(of_simple_func f hf) = of_fun (⇑f) hf :=
  rfl

theorem of_simple_func_eq_mk {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E) (hf : integrable ⇑f) :
    ↑(of_simple_func f hf) = ae_eq_fun.mk (⇑f) (simple_func.ae_measurable f) :=
  rfl

theorem of_simple_func_zero {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : of_simple_func 0 (integrable_zero α E μ) = 0 :=
  rfl

theorem of_simple_func_add {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E) (g : simple_func α E) (hf : integrable ⇑f)
    (hg : integrable ⇑g) :
    of_simple_func (f + g) (integrable.add hf hg) = of_simple_func f hf + of_simple_func g hg :=
  rfl

theorem of_simple_func_neg {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E) (hf : integrable ⇑f) :
    of_simple_func (-f) (integrable.neg hf) = -of_simple_func f hf :=
  rfl

theorem of_simple_func_sub {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E) (g : simple_func α E) (hf : integrable ⇑f)
    (hg : integrable ⇑g) :
    of_simple_func (f - g) (integrable.sub hf hg) = of_simple_func f hf - of_simple_func g hg :=
  sorry

theorem of_simple_func_smul {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {𝕜 : Type u_4} [normed_field 𝕜] [normed_space 𝕜 E] (f : simple_func α E)
    (hf : integrable ⇑f) (c : 𝕜) :
    of_simple_func (c • f) (integrable.smul c hf) = c • of_simple_func f hf :=
  rfl

theorem norm_of_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E) (hf : integrable ⇑f) :
    norm (of_simple_func f hf) =
        ennreal.to_real (lintegral μ fun (a : α) => edist (coe_fn f a) 0) :=
  rfl

/-- Find a representative of a `l1.simple_func`. -/
def to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : simple_func α E :=
  classical.some sorry

/-- `f.to_simple_func` is measurable. -/
protected theorem measurable {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : measurable ⇑(to_simple_func f) :=
  simple_func.measurable (to_simple_func f)

protected theorem ae_measurable {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : ae_measurable ⇑(to_simple_func f) :=
  measurable.ae_measurable (simple_func.measurable f)

/-- `f.to_simple_func` is integrable. -/
protected theorem integrable {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) : integrable ⇑(to_simple_func f) :=
  sorry

theorem of_simple_func_to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} (f : simple_func α E μ) :
    of_simple_func (to_simple_func f) (simple_func.integrable f) = f :=
  sorry

theorem to_simple_func_of_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} (f : simple_func α E) (hfi : integrable ⇑f) :
    filter.eventually_eq (measure.ae μ) ⇑(to_simple_func (of_simple_func f hfi)) ⇑f :=
  sorry

theorem to_simple_func_eq_to_fun {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) :
    filter.eventually_eq (measure.ae μ) ⇑(to_simple_func f) ⇑f :=
  sorry

theorem zero_to_simple_func (α : Type u_1) (E : Type u_2) [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : filter.eventually_eq (measure.ae μ) (⇑(to_simple_func 0)) 0 :=
  sorry

theorem add_to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) :
    filter.eventually_eq (measure.ae μ) (⇑(to_simple_func (f + g)))
        (⇑(to_simple_func f) + ⇑(to_simple_func g)) :=
  sorry

theorem neg_to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) :
    filter.eventually_eq (measure.ae μ) (⇑(to_simple_func (-f))) (-⇑(to_simple_func f)) :=
  sorry

theorem sub_to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) :
    filter.eventually_eq (measure.ae μ) (⇑(to_simple_func (f - g)))
        (⇑(to_simple_func f) - ⇑(to_simple_func g)) :=
  sorry

theorem smul_to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} {𝕜 : Type u_4} [normed_field 𝕜] [normed_space 𝕜 E] (k : 𝕜)
    (f : simple_func α E μ) :
    filter.eventually_eq (measure.ae μ) (⇑(to_simple_func (k • f))) (k • ⇑(to_simple_func f)) :=
  sorry

theorem lintegral_edist_to_simple_func_lt_top {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) :
    (lintegral μ fun (x : α) => edist (coe_fn (to_simple_func f) x) (coe_fn (to_simple_func g) x)) <
        ⊤ :=
  sorry

theorem dist_to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) (g : simple_func α E μ) :
    dist f g =
        ennreal.to_real
          (lintegral μ
            fun (x : α) => edist (coe_fn (to_simple_func f) x) (coe_fn (to_simple_func g) x)) :=
  sorry

theorem norm_to_simple_func {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) :
    norm f = ennreal.to_real (lintegral μ fun (a : α) => ↑(nnnorm (coe_fn (to_simple_func f) a))) :=
  sorry

-- calc ∥f∥ = ennreal.to_real (∫⁻ (x : α), (coe ∘ nnnorm) (f.to_simple_func x) ∂μ) :

theorem norm_eq_integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (f : simple_func α E μ) :
    norm f = simple_func.integral μ (simple_func.map norm (to_simple_func f)) :=
  sorry

--   by { rw norm_to_simple_func }

-- ... = (f.to_simple_func.map norm).integral μ :

protected theorem uniform_continuous {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} : uniform_continuous coe :=
  uniform_continuous_comap

protected theorem uniform_embedding {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} : uniform_embedding coe :=
  uniform_embedding_comap subtype.val_injective

protected theorem uniform_inducing {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} : uniform_inducing coe :=
  uniform_embedding.to_uniform_inducing simple_func.uniform_embedding

protected theorem dense_embedding {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} : dense_embedding coe :=
  sorry

protected theorem dense_inducing {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : dense_inducing coe :=
  dense_embedding.to_dense_inducing simple_func.dense_embedding

protected theorem dense_range {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} : dense_range coe :=
  dense_inducing.dense simple_func.dense_inducing

/-- The uniform and dense embedding of L1 simple functions into L1 functions. -/
def coe_to_l1 (α : Type u_1) (E : Type u_2) [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} (𝕜 : Type u_4) [normed_field 𝕜] [normed_space 𝕜 E] :
    continuous_linear_map 𝕜 (simple_func α E μ) (l1 α E μ) :=
  continuous_linear_map.mk (linear_map.mk coe sorry sorry)

/-- Positive part of a simple function in L1 space.  -/
def pos_part {α : Type u_1} [measurable_space α] {μ : measure α} (f : simple_func α ℝ μ) :
    simple_func α ℝ μ :=
  { val := pos_part ↑f, property := sorry }

/-- Negative part of a simple function in L1 space. -/
def neg_part {α : Type u_1} [measurable_space α] {μ : measure α} (f : simple_func α ℝ μ) :
    simple_func α ℝ μ :=
  pos_part (-f)

theorem coe_pos_part {α : Type u_1} [measurable_space α] {μ : measure α} (f : simple_func α ℝ μ) :
    ↑(pos_part f) = pos_part ↑f :=
  rfl

theorem coe_neg_part {α : Type u_1} [measurable_space α] {μ : measure α} (f : simple_func α ℝ μ) :
    ↑(neg_part f) = neg_part ↑f :=
  rfl

/-! Define the Bochner integral on `α →₁ₛ[μ] E` and prove basic properties of this integral. -/

/-- The Bochner integral over simple functions in l1 space. -/
def integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] (f : simple_func α E μ) : E :=
  simple_func.integral μ (to_simple_func f)

theorem integral_eq_integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] (f : simple_func α E μ) :
    integral f = simple_func.integral μ (to_simple_func f) :=
  rfl

theorem integral_eq_lintegral {α : Type u_1} [measurable_space α] {μ : measure α}
    {f : simple_func α ℝ μ} (h_pos : filter.eventually_le (measure.ae μ) 0 ⇑(to_simple_func f)) :
    integral f =
        ennreal.to_real
          (lintegral μ fun (a : α) => ennreal.of_real (coe_fn (to_simple_func f) a)) :=
  sorry

theorem integral_congr {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] {f : simple_func α E μ} {g : simple_func α E μ}
    (h : filter.eventually_eq (measure.ae μ) ⇑(to_simple_func f) ⇑(to_simple_func g)) :
    integral f = integral g :=
  simple_func.integral_congr (simple_func.integrable f) h

theorem integral_add {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] (f : simple_func α E μ) (g : simple_func α E μ) :
    integral (f + g) = integral f + integral g :=
  sorry

theorem integral_smul {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] (r : ℝ) (f : simple_func α E μ) :
    integral (r • f) = r • integral f :=
  sorry

theorem norm_integral_le_norm {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] (f : simple_func α E μ) : norm (integral f) ≤ norm f :=
  eq.mpr (id (Eq._oldrec (Eq.refl (norm (integral f) ≤ norm f)) (integral.equations._eqn_1 f)))
    (eq.mpr
      (id
        (Eq._oldrec (Eq.refl (norm (simple_func.integral μ (to_simple_func f)) ≤ norm f))
          (norm_eq_integral f)))
      (simple_func.norm_integral_le_integral_norm (to_simple_func f) (simple_func.integrable f)))

/-- The Bochner integral over simple functions in l1 space as a continuous linear map. -/
def integral_clm {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] : continuous_linear_map ℝ (simple_func α E μ) E :=
  linear_map.mk_continuous (linear_map.mk integral integral_add integral_smul) 1 sorry

theorem norm_Integral_le_one {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] : norm integral_clm ≤ 1 :=
  linear_map.mk_continuous_norm_le (linear_map.mk integral integral_add integral_smul) zero_le_one
    integral_clm._proof_1

theorem pos_part_to_simple_func {α : Type u_1} [measurable_space α] {μ : measure α}
    (f : simple_func α ℝ μ) :
    filter.eventually_eq (measure.ae μ) ⇑(to_simple_func (pos_part f))
        ⇑(simple_func.pos_part (to_simple_func f)) :=
  sorry

theorem neg_part_to_simple_func {α : Type u_1} [measurable_space α] {μ : measure α}
    (f : simple_func α ℝ μ) :
    filter.eventually_eq (measure.ae μ) ⇑(to_simple_func (neg_part f))
        ⇑(simple_func.neg_part (to_simple_func f)) :=
  sorry

theorem integral_eq_norm_pos_part_sub {α : Type u_1} [measurable_space α] {μ : measure α}
    (f : simple_func α ℝ μ) : integral f = norm (pos_part f) - norm (neg_part f) :=
  sorry

end simple_func

/-- The Bochner integral in l1 space as a continuous linear map. -/
def integral_clm {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] : continuous_linear_map ℝ (l1 α E μ) E :=
  continuous_linear_map.extend simple_func.integral_clm (simple_func.coe_to_l1 α E ℝ)
    simple_func.dense_range simple_func.uniform_inducing

/-- The Bochner integral in l1 space -/
def integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] (f : l1 α E μ) : E :=
  coe_fn integral_clm f

theorem integral_eq {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] (f : l1 α E μ) :
    integral f = coe_fn integral_clm f :=
  rfl

theorem simple_func.integral_l1_eq_integral {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [measurable_space E]
    [borel_space E] {μ : measure α} [normed_space ℝ E] [complete_space E] (f : simple_func α E μ) :
    integral ↑f = simple_func.integral f :=
  uniformly_extend_of_ind simple_func.uniform_inducing simple_func.dense_range
    (continuous_linear_map.uniform_continuous simple_func.integral_clm) f

@[simp] theorem integral_zero (α : Type u_1) (E : Type u_2) [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] : integral 0 = 0 :=
  continuous_linear_map.map_zero integral_clm

theorem integral_add {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] (f : l1 α E μ) (g : l1 α E μ) :
    integral (f + g) = integral f + integral g :=
  continuous_linear_map.map_add integral_clm f g

theorem integral_neg {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] (f : l1 α E μ) :
    integral (-f) = -integral f :=
  continuous_linear_map.map_neg integral_clm f

theorem integral_sub {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] (f : l1 α E μ) (g : l1 α E μ) :
    integral (f - g) = integral f - integral g :=
  continuous_linear_map.map_sub integral_clm f g

theorem integral_smul {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] (r : ℝ) (f : l1 α E μ) :
    integral (r • f) = r • integral f :=
  continuous_linear_map.map_smul r integral_clm f

theorem norm_Integral_le_one {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] : norm integral_clm ≤ 1 :=
  sorry

theorem norm_integral_le {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] (f : l1 α E μ) :
    norm (integral f) ≤ norm f :=
  sorry

theorem continuous_integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [measurable_space E] [borel_space E]
    {μ : measure α} [normed_space ℝ E] [complete_space E] :
    continuous fun (f : l1 α E μ) => integral f :=
  sorry

theorem integral_eq_norm_pos_part_sub {α : Type u_1} [measurable_space α] {μ : measure α}
    (f : l1 α ℝ μ) : integral f = norm (pos_part f) - norm (neg_part f) :=
  sorry

end l1

/-- The Bochner integral -/
def integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] (μ : measure α) (f : α → E) : E :=
  dite (integrable f) (fun (hf : integrable f) => l1.integral (l1.of_fun f hf))
    fun (hf : ¬integrable f) => 0

/-! In the notation for integrals, an expression like `∫ x, g ∥x∥ ∂μ` will not be parsed correctly,
  and needs parentheses. We do not set the binding power of `r` to `0`, because then
  `∫ x, f x = 0` will be parsed incorrectly. -/

theorem integral_eq {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} (f : α → E) (hf : integrable f) :
    (integral μ fun (a : α) => f a) = l1.integral (l1.of_fun f hf) :=
  dif_pos hf

theorem l1.integral_eq_integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} (f : l1 α E μ) :
    l1.integral f = integral μ fun (a : α) => coe_fn f a :=
  sorry

theorem integral_undef {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {f : α → E} {μ : measure α} (h : ¬integrable f) :
    (integral μ fun (a : α) => f a) = 0 :=
  dif_neg h

theorem integral_non_ae_measurable {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {f : α → E} {μ : measure α}
    (h : ¬ae_measurable f) : (integral μ fun (a : α) => f a) = 0 :=
  integral_undef (not_and_of_not_left (has_finite_integral fun (a : α) => f a) h)

theorem integral_zero (α : Type u_1) (E : Type u_2) [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} : (integral μ fun (a : α) => 0) = 0 :=
  sorry

@[simp] theorem integral_zero' (α : Type u_1) (E : Type u_2) [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} : integral μ 0 = 0 :=
  integral_zero α E

theorem integral_add {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {f : α → E} {g : α → E} {μ : measure α} (hf : integrable f)
    (hg : integrable g) :
    (integral μ fun (a : α) => f a + g a) =
        (integral μ fun (a : α) => f a) + integral μ fun (a : α) => g a :=
  sorry

theorem integral_add' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {f : α → E} {g : α → E} {μ : measure α} (hf : integrable f)
    (hg : integrable g) :
    (integral μ fun (a : α) => Add.add f g a) =
        (integral μ fun (a : α) => f a) + integral μ fun (a : α) => g a :=
  integral_add hf hg

theorem integral_neg {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} (f : α → E) :
    (integral μ fun (a : α) => -f a) = -integral μ fun (a : α) => f a :=
  sorry

theorem integral_neg' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} (f : α → E) :
    (integral μ fun (a : α) => Neg.neg f a) = -integral μ fun (a : α) => f a :=
  integral_neg f

theorem integral_sub {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {f : α → E} {g : α → E} {μ : measure α} (hf : integrable f)
    (hg : integrable g) :
    (integral μ fun (a : α) => f a - g a) =
        (integral μ fun (a : α) => f a) - integral μ fun (a : α) => g a :=
  sorry

theorem integral_sub' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {f : α → E} {g : α → E} {μ : measure α} (hf : integrable f)
    (hg : integrable g) :
    (integral μ fun (a : α) => Sub.sub f g a) =
        (integral μ fun (a : α) => f a) - integral μ fun (a : α) => g a :=
  integral_sub hf hg

theorem integral_smul {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} (r : ℝ) (f : α → E) :
    (integral μ fun (a : α) => r • f a) = r • integral μ fun (a : α) => f a :=
  sorry

theorem integral_mul_left {α : Type u_1} [measurable_space α] {μ : measure α} (r : ℝ) (f : α → ℝ) :
    (integral μ fun (a : α) => r * f a) = r * integral μ fun (a : α) => f a :=
  integral_smul r f

theorem integral_mul_right {α : Type u_1} [measurable_space α] {μ : measure α} (r : ℝ) (f : α → ℝ) :
    (integral μ fun (a : α) => f a * r) = (integral μ fun (a : α) => f a) * r :=
  sorry

theorem integral_div {α : Type u_1} [measurable_space α] {μ : measure α} (r : ℝ) (f : α → ℝ) :
    (integral μ fun (a : α) => f a / r) = (integral μ fun (a : α) => f a) / r :=
  integral_mul_right (r⁻¹) f

theorem integral_congr_ae {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {f : α → E} {g : α → E} {μ : measure α}
    (h : filter.eventually_eq (measure.ae μ) f g) :
    (integral μ fun (a : α) => f a) = integral μ fun (a : α) => g a :=
  sorry

@[simp] theorem l1.integral_of_fun_eq_integral {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} {f : α → E}
    (hf : integrable f) :
    (integral μ fun (a : α) => coe_fn (l1.of_fun f hf) a) = integral μ fun (a : α) => f a :=
  integral_congr_ae (l1.to_fun_of_fun f hf)

theorem continuous_integral {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} :
    continuous fun (f : l1 α E μ) => integral μ fun (a : α) => coe_fn f a :=
  sorry

theorem norm_integral_le_lintegral_norm {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} (f : α → E) :
    norm (integral μ fun (a : α) => f a) ≤
        ennreal.to_real (lintegral μ fun (a : α) => ennreal.of_real (norm (f a))) :=
  sorry

theorem ennnorm_integral_le_lintegral_ennnorm {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} (f : α → E) :
    ↑(nnnorm (integral μ fun (a : α) => f a)) ≤ lintegral μ fun (a : α) => ↑(nnnorm (f a)) :=
  sorry

theorem integral_eq_zero_of_ae {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} {f : α → E}
    (hf : filter.eventually_eq (measure.ae μ) f 0) : (integral μ fun (a : α) => f a) = 0 :=
  sorry

/-- If `f` has finite integral, then `∫ x in s, f x ∂μ` is absolutely continuous in `s`: it tends
to zero as `μ s` tends to zero. -/
theorem has_finite_integral.tendsto_set_integral_nhds_zero {α : Type u_1} {E : Type u_2}
    [measurable_space α] [normed_group E] [topological_space.second_countable_topology E]
    [normed_space ℝ E] [complete_space E] [measurable_space E] [borel_space E] {μ : measure α}
    {ι : Type u_3} {f : α → E} (hf : has_finite_integral f) {l : filter ι} {s : ι → set α}
    (hs : filter.tendsto (⇑μ ∘ s) l (nhds 0)) :
    filter.tendsto (fun (i : ι) => integral (measure.restrict μ (s i)) fun (x : α) => f x) l
        (nhds 0) :=
  sorry

/-- If `f` is integrable, then `∫ x in s, f x ∂μ` is absolutely continuous in `s`: it tends
to zero as `μ s` tends to zero. -/
theorem integrable.tendsto_set_integral_nhds_zero {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} {ι : Type u_3}
    {f : α → E} (hf : integrable f) {l : filter ι} {s : ι → set α}
    (hs : filter.tendsto (⇑μ ∘ s) l (nhds 0)) :
    filter.tendsto (fun (i : ι) => integral (measure.restrict μ (s i)) fun (x : α) => f x) l
        (nhds 0) :=
  has_finite_integral.tendsto_set_integral_nhds_zero (and.right hf) hs

/-- If `F i → f` in `L1`, then `∫ x, F i x ∂μ → ∫ x, f x∂μ`. -/
theorem tendsto_integral_of_l1 {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} {ι : Type u_3} (f : α → E)
    (hfi : integrable f) {F : ι → α → E} {l : filter ι}
    (hFi : filter.eventually (fun (i : ι) => integrable (F i)) l)
    (hF :
      filter.tendsto (fun (i : ι) => lintegral μ fun (x : α) => edist (F i x) (f x)) l (nhds 0)) :
    filter.tendsto (fun (i : ι) => integral μ fun (x : α) => F i x) l
        (nhds (integral μ fun (x : α) => f x)) :=
  sorry

/-- Lebesgue dominated convergence theorem provides sufficient conditions under which almost
  everywhere convergence of a sequence of functions implies the convergence of their integrals. -/
theorem tendsto_integral_of_dominated_convergence {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} {F : ℕ → α → E}
    {f : α → E} (bound : α → ℝ) (F_measurable : ∀ (n : ℕ), ae_measurable (F n))
    (f_measurable : ae_measurable f) (bound_integrable : integrable bound)
    (h_bound : ∀ (n : ℕ), filter.eventually (fun (a : α) => norm (F n a) ≤ bound a) (measure.ae μ))
    (h_lim :
      filter.eventually
        (fun (a : α) => filter.tendsto (fun (n : ℕ) => F n a) filter.at_top (nhds (f a)))
        (measure.ae μ)) :
    filter.tendsto (fun (n : ℕ) => integral μ fun (a : α) => F n a) filter.at_top
        (nhds (integral μ fun (a : α) => f a)) :=
  sorry

/-- Lebesgue dominated convergence theorem for filters with a countable basis -/
theorem tendsto_integral_filter_of_dominated_convergence {α : Type u_1} {E : Type u_2}
    [measurable_space α] [normed_group E] [topological_space.second_countable_topology E]
    [normed_space ℝ E] [complete_space E] [measurable_space E] [borel_space E] {μ : measure α}
    {ι : Type u_3} {l : filter ι} {F : ι → α → E} {f : α → E} (bound : α → ℝ)
    (hl_cb : filter.is_countably_generated l)
    (hF_meas : filter.eventually (fun (n : ι) => ae_measurable (F n)) l)
    (f_measurable : ae_measurable f)
    (h_bound :
      filter.eventually
        (fun (n : ι) => filter.eventually (fun (a : α) => norm (F n a) ≤ bound a) (measure.ae μ)) l)
    (bound_integrable : integrable bound)
    (h_lim :
      filter.eventually (fun (a : α) => filter.tendsto (fun (n : ι) => F n a) l (nhds (f a)))
        (measure.ae μ)) :
    filter.tendsto (fun (n : ι) => integral μ fun (a : α) => F n a) l
        (nhds (integral μ fun (a : α) => f a)) :=
  sorry

/-- The Bochner integral of a real-valued function `f : α → ℝ` is the difference between the
  integral of the positive part of `f` and the integral of the negative part of `f`.  -/
theorem integral_eq_lintegral_max_sub_lintegral_min {α : Type u_1} [measurable_space α]
    {μ : measure α} {f : α → ℝ} (hf : integrable f) :
    (integral μ fun (a : α) => f a) =
        ennreal.to_real (lintegral μ fun (a : α) => ennreal.of_real (max (f a) 0)) -
          ennreal.to_real (lintegral μ fun (a : α) => ennreal.of_real (-min (f a) 0)) :=
  sorry

-- Go to the `L¹` space

-- Go to the `L¹` space

theorem integral_eq_lintegral_of_nonneg_ae {α : Type u_1} [measurable_space α] {μ : measure α}
    {f : α → ℝ} (hf : filter.eventually_le (measure.ae μ) 0 f) (hfm : ae_measurable f) :
    (integral μ fun (a : α) => f a) =
        ennreal.to_real (lintegral μ fun (a : α) => ennreal.of_real (f a)) :=
  sorry

theorem integral_nonneg_of_ae {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ℝ}
    (hf : filter.eventually_le (measure.ae μ) 0 f) : 0 ≤ integral μ fun (a : α) => f a :=
  sorry

theorem lintegral_coe_eq_integral {α : Type u_1} [measurable_space α] {μ : measure α}
    (f : α → nnreal) (hfi : integrable fun (x : α) => ↑(f x)) :
    (lintegral μ fun (a : α) => ↑(f a)) = ennreal.of_real (integral μ fun (x : α) => ↑(f x)) :=
  sorry

theorem integral_to_real {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ennreal}
    (hfm : ae_measurable f) (hf : filter.eventually (fun (x : α) => f x < ⊤) (measure.ae μ)) :
    (integral μ fun (a : α) => ennreal.to_real (f a)) =
        ennreal.to_real (lintegral μ fun (a : α) => f a) :=
  sorry

theorem integral_nonneg {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ℝ}
    (hf : 0 ≤ f) : 0 ≤ integral μ fun (a : α) => f a :=
  integral_nonneg_of_ae (filter.eventually_of_forall hf)

theorem integral_nonpos_of_ae {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ℝ}
    (hf : filter.eventually_le (measure.ae μ) f 0) : (integral μ fun (a : α) => f a) ≤ 0 :=
  sorry

theorem integral_nonpos {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ℝ}
    (hf : f ≤ 0) : (integral μ fun (a : α) => f a) ≤ 0 :=
  integral_nonpos_of_ae (filter.eventually_of_forall hf)

theorem integral_eq_zero_iff_of_nonneg_ae {α : Type u_1} [measurable_space α] {μ : measure α}
    {f : α → ℝ} (hf : filter.eventually_le (measure.ae μ) 0 f) (hfi : integrable f) :
    (integral μ fun (x : α) => f x) = 0 ↔ filter.eventually_eq (measure.ae μ) f 0 :=
  sorry

theorem integral_eq_zero_iff_of_nonneg {α : Type u_1} [measurable_space α] {μ : measure α}
    {f : α → ℝ} (hf : 0 ≤ f) (hfi : integrable f) :
    (integral μ fun (x : α) => f x) = 0 ↔ filter.eventually_eq (measure.ae μ) f 0 :=
  integral_eq_zero_iff_of_nonneg_ae (filter.eventually_of_forall hf) hfi

theorem integral_pos_iff_support_of_nonneg_ae {α : Type u_1} [measurable_space α] {μ : measure α}
    {f : α → ℝ} (hf : filter.eventually_le (measure.ae μ) 0 f) (hfi : integrable f) :
    (0 < integral μ fun (x : α) => f x) ↔ 0 < coe_fn μ (function.support f) :=
  sorry

theorem integral_pos_iff_support_of_nonneg {α : Type u_1} [measurable_space α] {μ : measure α}
    {f : α → ℝ} (hf : 0 ≤ f) (hfi : integrable f) :
    (0 < integral μ fun (x : α) => f x) ↔ 0 < coe_fn μ (function.support f) :=
  integral_pos_iff_support_of_nonneg_ae (filter.eventually_of_forall hf) hfi

theorem l1.norm_eq_integral_norm {α : Type u_1} [measurable_space α] {μ : measure α} {H : Type u_4}
    [normed_group H] [topological_space.second_countable_topology H] [measurable_space H]
    [borel_space H] (f : l1 α H μ) : norm f = integral μ fun (a : α) => norm (coe_fn f a) :=
  sorry

theorem l1.norm_of_fun_eq_integral_norm {α : Type u_1} [measurable_space α] {μ : measure α}
    {H : Type u_4} [normed_group H] [topological_space.second_countable_topology H]
    [measurable_space H] [borel_space H] {f : α → H} (hf : integrable f) :
    norm (l1.of_fun f hf) = integral μ fun (a : α) => norm (f a) :=
  sorry

theorem integral_mono_ae {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ℝ} {g : α → ℝ}
    (hf : integrable f) (hg : integrable g) (h : filter.eventually_le (measure.ae μ) f g) :
    (integral μ fun (a : α) => f a) ≤ integral μ fun (a : α) => g a :=
  le_of_sub_nonneg
    (Eq.subst (integral_sub hg hf) integral_nonneg_of_ae
      (filter.eventually.mono h fun (a : α) => sub_nonneg_of_le))

theorem integral_mono {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ℝ} {g : α → ℝ}
    (hf : integrable f) (hg : integrable g) (h : f ≤ g) :
    (integral μ fun (a : α) => f a) ≤ integral μ fun (a : α) => g a :=
  integral_mono_ae hf hg (filter.eventually_of_forall h)

theorem integral_mono_of_nonneg {α : Type u_1} [measurable_space α] {μ : measure α} {f : α → ℝ}
    {g : α → ℝ} (hf : filter.eventually_le (measure.ae μ) 0 f) (hgi : integrable g)
    (h : filter.eventually_le (measure.ae μ) f g) :
    (integral μ fun (a : α) => f a) ≤ integral μ fun (a : α) => g a :=
  sorry

theorem norm_integral_le_integral_norm {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} (f : α → E) :
    norm (integral μ fun (a : α) => f a) ≤ integral μ fun (a : α) => norm (f a) :=
  sorry

theorem norm_integral_le_of_norm_le {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} {f : α → E} {g : α → ℝ}
    (hg : integrable g) (h : filter.eventually (fun (x : α) => norm (f x) ≤ g x) (measure.ae μ)) :
    norm (integral μ fun (x : α) => f x) ≤ integral μ fun (x : α) => g x :=
  le_trans (norm_integral_le_integral_norm f)
    (integral_mono_of_nonneg (filter.eventually_of_forall fun (x : α) => norm_nonneg (f x)) hg h)

theorem integral_finset_sum {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} {ι : Type u_3} (s : finset ι)
    {f : ι → α → E} (hf : ∀ (i : ι), integrable (f i)) :
    (integral μ fun (a : α) => finset.sum s fun (i : ι) => f i a) =
        finset.sum s fun (i : ι) => integral μ fun (a : α) => f i a :=
  sorry

theorem simple_func.integral_eq_integral {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} (f : simple_func α E)
    (hfi : integrable ⇑f) : simple_func.integral μ f = integral μ fun (x : α) => coe_fn f x :=
  sorry

@[simp] theorem integral_const {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} (c : E) :
    (integral μ fun (x : α) => c) = ennreal.to_real (coe_fn μ set.univ) • c :=
  sorry

theorem norm_integral_le_of_norm_le_const {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} [finite_measure μ]
    {f : α → E} {C : ℝ} (h : filter.eventually (fun (x : α) => norm (f x) ≤ C) (measure.ae μ)) :
    norm (integral μ fun (x : α) => f x) ≤ C * ennreal.to_real (coe_fn μ set.univ) :=
  sorry

theorem tendsto_integral_approx_on_univ_of_measurable {α : Type u_1} {E : Type u_2}
    [measurable_space α] [normed_group E] [topological_space.second_countable_topology E]
    [normed_space ℝ E] [complete_space E] [measurable_space E] [borel_space E] {μ : measure α}
    {f : α → E} (fmeas : measurable f) (hf : integrable f) :
    filter.tendsto
        (fun (n : ℕ) => simple_func.integral μ (simple_func.approx_on f fmeas set.univ 0 trivial n))
        filter.at_top (nhds (integral μ fun (x : α) => f x)) :=
  sorry

theorem integral_add_measure {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} {ν : measure α} {f : α → E}
    (hμ : integrable f) (hν : integrable f) :
    (integral (μ + ν) fun (x : α) => f x) =
        (integral μ fun (x : α) => f x) + integral ν fun (x : α) => f x :=
  sorry

@[simp] theorem integral_zero_measure {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] (f : α → E) :
    (integral 0 fun (x : α) => f x) = 0 :=
  sorry

@[simp] theorem integral_smul_measure {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} (f : α → E)
    (c : ennreal) :
    (integral (c • μ) fun (x : α) => f x) = ennreal.to_real c • integral μ fun (x : α) => f x :=
  sorry

theorem integral_map_of_measurable {α : Type u_1} {E : Type u_2} [measurable_space α]
    [normed_group E] [topological_space.second_countable_topology E] [normed_space ℝ E]
    [complete_space E] [measurable_space E] [borel_space E] {μ : measure α} {β : Type u_3}
    [measurable_space β] {φ : α → β} (hφ : measurable φ) {f : β → E} (hfm : measurable f) :
    (integral (coe_fn (measure.map φ) μ) fun (y : β) => f y) = integral μ fun (x : α) => f (φ x) :=
  sorry

theorem integral_map {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] {μ : measure α} {β : Type u_3} [measurable_space β]
    {φ : α → β} (hφ : measurable φ) {f : β → E} (hfm : ae_measurable f) :
    (integral (coe_fn (measure.map φ) μ) fun (y : β) => f y) = integral μ fun (x : α) => f (φ x) :=
  sorry

theorem integral_dirac' {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] (f : α → E) (a : α) (hfm : measurable f) :
    (integral (measure.dirac a) fun (x : α) => f x) = f a :=
  sorry

theorem integral_dirac {α : Type u_1} {E : Type u_2} [measurable_space α] [normed_group E]
    [topological_space.second_countable_topology E] [normed_space ℝ E] [complete_space E]
    [measurable_space E] [borel_space E] [measurable_singleton_class α] (f : α → E) (a : α) :
    (integral (measure.dirac a) fun (x : α) => f x) = f a :=
  sorry

end Mathlib


import geometry.manifold.smooth_manifold_with_corners

example : times_cont_diff ℝ ⊤ (λ x : ℝ × ℝ, x.1 * x.2) :=
begin
  library_search,
end


/-
Copyright (c) 2022 Andrew Yang. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Andrew Yang
-/
import morphisms.basic
import algebraic_geometry.fiber
import algebraic_geometry.prime_spectrum_more
import morphisms.quasi_compact
import for_mathlib.topology
import for_mathlib.specializing
import for_mathlib.pi
import ring_theory.ideal.minimal_prime

/-!
# Universally closed morphism

A morphism of schemes `f : X ⟶ Y` is universally closed if `X ×[Y] Y' ⟶ Y'` is a closed map
for all base change `Y' ⟶ Y`.

We show that being universally closed is local at the target, and is stable under compositions and
base changes.

-/

noncomputable theory

open category_theory category_theory.limits opposite topological_space

universes v u

namespace algebraic_geometry

variables {X Y : Scheme.{u}} (f : X ⟶ Y)

open category_theory.morphism_property
open algebraic_geometry.morphism_property (topologically)

/--
A morphism of schemes `f : X ⟶ Y` is universally closed if the base change `X ×[Y] Y' ⟶ Y'`
along any morphism `Y' ⟶ Y` is (topologically) a closed map.
-/
@[mk_iff]
class universally_closed (f : X ⟶ Y) : Prop :=
(out : universally (topologically @is_closed_map) f)

lemma universally_closed_eq :
  @universally_closed = universally (topologically @is_closed_map) :=
begin
  ext X Y f, rw universally_closed_iff
end

lemma universally_closed_respects_iso :
  respects_iso @universally_closed :=
universally_closed_eq.symm ▸ universally_respects_iso (topologically @is_closed_map)

lemma universally_closed_stable_under_base_change :
  stable_under_base_change @universally_closed :=
universally_closed_eq.symm ▸ universally_stable_under_base_change (topologically @is_closed_map)

lemma universally_closed_stable_under_composition :
  stable_under_composition @universally_closed :=
begin
  rw universally_closed_eq,
  exact stable_under_composition.universally (λ X Y Z f g hf hg, is_closed_map.comp hg hf),
end

instance universally_closed_type_comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z)
  [hf : universally_closed f] [hg : universally_closed g] :
  universally_closed (f ≫ g) :=
universally_closed_stable_under_composition f g hf hg

instance universally_closed_fst {X Y Z : Scheme} (f : X ⟶ Z) (g : Y ⟶ Z)
  [hg : universally_closed g] :
  universally_closed (pullback.fst : pullback f g ⟶ _) :=
universally_closed_stable_under_base_change.fst f g hg

instance universally_closed_snd {X Y Z : Scheme} (f : X ⟶ Z) (g : Y ⟶ Z)
  [hf : universally_closed f] :
  universally_closed (pullback.snd : pullback f g ⟶ _) :=
universally_closed_stable_under_base_change.snd f g hf

lemma morphism_restrict_base {X Y : Scheme} (f : X ⟶ Y) (U : opens Y.carrier) :
  ⇑(f ∣_ U).1.base = U.1.restrict_preimage f.1 :=
funext (λ x, subtype.ext $ morphism_restrict_base_coe f U x)

lemma universally_closed_is_local_at_target :
  property_is_local_at_target @universally_closed :=
begin
  rw universally_closed_eq,
  apply universally_is_local_at_target_of_morphism_restrict,
  { exact stable_under_composition.respects_iso (λ X Y Z f g hf hg, is_closed_map.comp hg hf)
      (λ X Y f, (Top.homeo_of_iso (Scheme.forget_to_Top.map_iso f)).is_closed_map) },
  { intros X Y f ι U hU H,
    simp_rw [topologically, morphism_restrict_base] at H,
    exact (is_closed_map_iff_is_closed_map_of_supr_eq_top hU).mpr H }
end

lemma universally_closed.open_cover_iff {X Y : Scheme.{u}} (f : X ⟶ Y)
  (𝒰 : Scheme.open_cover.{u} Y) :
  universally_closed f ↔
    (∀ i, universally_closed (pullback.snd : pullback f (𝒰.map i) ⟶ _)) :=
universally_closed_is_local_at_target.open_cover_iff f 𝒰

lemma universally_closed.is_closed_map (f : X ⟶ Y) [H : universally_closed f] :
  is_closed_map f.1.base :=
(topologically @is_closed_map).universally_le _ _ _ H.out

lemma universally_closed.compact_space_of_field {R : Type*} [field R] {X : Scheme}
  (f : X ⟶ Scheme.Spec.obj (op $ CommRing.of R)) [H : universally_closed f] :
    compact_space X.carrier :=
begin
  classical,
  unfreezingI { contrapose H },
  rw universally_closed_iff,
  delta morphism_property.universally topologically is_closed_map,
  push_neg,
  let S := Scheme.Spec.obj (op $ CommRing.of R),
  let T := Scheme.Spec.obj (op $ CommRing.of $ mv_polynomial X.affine_opens R),
  let Ti : X.affine_opens → opens T.carrier := λ i, prime_spectrum.basic_open (mv_polynomial.X i),
  let g : T ⟶ S := Scheme.Spec.map (CommRing.of_hom
    (algebra_map R (mv_polynomial X.affine_opens R) : _)).op,
  let p₁ : pullback g f ⟶ _ := pullback.fst,
  let p₂ : pullback g f ⟶ _ := pullback.snd,
  let XTi : X.affine_opens → Scheme := λ i, pullback
    (T.of_restrict (Ti i).open_embedding ≫ g)
    (X.of_restrict i.1.open_embedding ≫ f),
  let hi : ∀ i, XTi i ⟶ pullback g f :=
    λ i, pullback.map _ _ _ _ _ _ _ (category.comp_id _) (category.comp_id _),
  haveI : unique S.carrier := show unique (prime_spectrum R), by apply_instance,
  let s : S.carrier := (show prime_spectrum R, from ⊥),
  let t : T.carrier := prime_spectrum.comap
    (mv_polynomial.eval $ λ (_ : X.affine_opens), (1 : R)) s,
  let Z := (⨆ i, (hi i).opens_range).compl,
  refine ⟨_, T, _, g, _, is_pullback.of_has_pullback _ _, Z.1, Z.2, λ hZ, _⟩,
  change is_closed (p₁.1.base '' Z.1) at hZ,
  have : t ∉ p₁.1.base '' Z.1,
  { rintro ⟨x, hx, hxt⟩,
    apply hx,
    apply opens.mem_supr.mpr,
    let i : X.affine_opens := ⟨_, range_is_affine_open_of_open_immersion
      (X.affine_cover.map $ p₂.1.base x)⟩,
    have : t ∈ (Ti i).val,
    { rintro ht, dsimp [s] at ht, rw [mv_polynomial.eval_X] at ht, exact one_ne_zero ht },
    refine ⟨i, _⟩,
    change x ∈ set.range _,
    simp only [pullback.range_map, Scheme.of_restrict_val_base, set.mem_inter_iff, opens.inclusion,
      set.mem_preimage, continuous_map.coe_mk, subtype.range_coe_subtype],
    exact ⟨hxt.symm ▸ this, X.affine_cover.covers _⟩ },
  obtain ⟨q : mv_polynomial _ R, hq₁, hq₂⟩ : ∃ q, p₁.1.base '' Z.1 ⊆ prime_spectrum.zero_locus {q} ∧
    t ∉ prime_spectrum.zero_locus ({q} : set (mv_polynomial X.affine_opens R)),
  { by_contra hq, push_neg at hq, apply this,
    obtain ⟨s, hs⟩ := (prime_spectrum.is_closed_iff_zero_locus _).mp hZ,
    simp_rw hs at hq ⊢,
    intros q hq',
    exact hq q (prime_spectrum.zero_locus_anti_mono $ set.singleton_subset_iff.mpr hq') rfl },
  obtain ⟨σq, q', hq'⟩ := q.exists_finset_rename,
  let ϕ := @mv_polynomial.aeval R (mv_polynomial _ R) _ _ _ _
    (λ i : X.affine_opens, if i ∈ σq then mv_polynomial.X i else 0),
  let t' := prime_spectrum.comap ϕ.to_ring_hom t,
  have ϕq : ϕ q = q,
  { rw [hq', mv_polynomial.aeval_rename, mv_polynomial.rename],
    have : ∀ i : σq, ↑i ∈ σq := subtype.prop,
    simp_rw [function.comp, if_pos (this _)] },
  have ht'₁ : t' ∉ prime_spectrum.zero_locus ({q} : set (mv_polynomial X.affine_opens R)),
  { rwa [← @set.mem_preimage _ _ (prime_spectrum.comap ϕ.to_ring_hom),
      prime_spectrum.preimage_comap_zero_locus, set.image_singleton,
      alg_hom.to_ring_hom_eq_coe, alg_hom.coe_to_ring_hom, ϕq] },
  have ht'₂ : ∀ i ∉ σq, t' ∉ Ti i,
  { intros i hi,
    change t' ∉ (prime_spectrum.basic_open (mv_polynomial.X i)).1,
    rw [subtype.val_eq_coe, prime_spectrum.basic_open_eq_zero_locus_compl, set.not_mem_compl_iff,
      ← @set.mem_preimage _ _ (prime_spectrum.comap ϕ.to_ring_hom),
      prime_spectrum.preimage_comap_zero_locus, set.image_singleton,
      alg_hom.to_ring_hom_eq_coe, alg_hom.coe_to_ring_hom, mv_polynomial.aeval_X, if_neg hi,
      prime_spectrum.zero_locus_singleton_zero],
    trivial },
  obtain ⟨x, hx⟩ : ∃ x, x ∉ ⨆ i : σq, i.1.1,
  { have : (⨆ i : σq, i.1.1) ≠ ⊤,
    { intro e, apply H, rw [← is_compact_univ_iff, ← opens.coe_top, ← e, opens.coe_supr],
      apply is_compact_Union, exact λ i, i.1.2.is_compact },
    contrapose! this, rw eq_top_iff, exact λ x _, this x },
  let Tp : pullback.triplet g f := ⟨t', x, default, unique.eq_default _, unique.eq_default _⟩,
  obtain ⟨z, hz : p₁.1.base z = t', rfl : p₂.1.base z = x⟩ := Tp.exists_preimage,
  apply ht'₁,
  apply hq₁,
  refine ⟨_, λ hz', _, hz⟩,
  obtain ⟨i, z', rfl⟩ := opens.mem_supr.mp hz',
  by_cases hi : i ∈ σq,
  { apply hx, refine opens.mem_supr.mpr ⟨⟨i, hi⟩, _⟩,
    rw [← Scheme.comp_val_base_apply, pullback.lift_snd],
    exact ((Scheme.forget_to_Top.map pullback.snd) z').prop },
  { rw [← Scheme.comp_val_base_apply, pullback.lift_fst] at hz,
    apply ht'₂ i hi, rw ← hz,
    exact ((Scheme.forget_to_Top.map pullback.fst) z').prop }
end
.
lemma universally_closed.to_closed_map (f : X ⟶ Y) [universally_closed f] :
  is_closed_map f.1.base :=
begin
  apply universally_le (topologically @is_closed_map),
  rwa ← universally_closed_eq,
end

lemma universally_closed.is_compact_preimage (f : X ⟶ Y) [H : universally_closed f]
  {K : set Y.carrier} (hK : is_compact K) : is_compact (f.1.base ⁻¹' K) :=
begin
  refine proper_of_compact_fibers _ (λ x, _) (universally_closed.to_closed_map f) hK,
  haveI : universally_closed (f.fiber_to_residue_field x),
  { delta Scheme.hom.fiber_to_residue_field, apply_instance },
  have := @universally_closed.compact_space_of_field
    (local_ring.residue_field (Y.presheaf.stalk x)) _ _ (f.fiber_to_residue_field x) _,
  rw [← f.range_fiber_ι x, ← set.image_univ],
  rw [← is_compact_univ_iff] at this,
  exact this.image (by continuity)
end

@[priority 100]
instance universally_closed.to_quasi_compact (f : X ⟶ Y) [universally_closed f] :
  quasi_compact f :=
⟨λ U hU, universally_closed.is_compact_preimage f⟩

section specializing

lemma image_is_closed_iff_is_stable_under_specialization_of_affine
  [compact_space X.carrier] {R : CommRing}
  (f : X ⟶ Scheme.Spec.obj (op R)) {Z : set X.carrier}
  (hZ : is_closed Z) : is_closed (f.1.base '' Z) ↔ stable_under_specialization (f.1.base '' Z) :=
begin
  have : ∀ i, ∃ I : ideal (X.affine_cover_ring i), (X.affine_cover.map i).1.base ⁻¹' Z =
    prime_spectrum.zero_locus (↑I : set (X.affine_cover_ring i)),
  { intro i, apply (prime_spectrum.is_closed_iff_zero_locus_ideal _).mp (is_closed.preimage _ hZ),
    continuity },
  choose I hI,
  let gi : ∀ i : X.affine_cover.J, R ⟶ CommRing.of (X.affine_cover_ring i ⧸ I i) :=
    λ i, (Scheme.Spec.preimage (X.affine_cover.map i ≫ f)).unop ≫ (ideal.quotient.mk _),
  have hgi : ∀ i, Scheme.Spec.map (gi i).op =
    Scheme.Spec.map (quiver.hom.op (ideal.quotient.mk (I i))) ≫ X.affine_cover.map i ≫ f,
  { intro i, simpa only [functor.map_comp, op_comp, quiver.hom.op_unop, functor.image_preimage] },
  let S := Π i : X.affine_cover.finite_subcover.J, X.affine_cover_ring i.1 ⧸ I i.1,
  let g : R →+* S := pi.ring_hom (λ i, gi i.1),
  have : f.1.base '' Z =
    set.range (Scheme.Spec.map (show R ⟶ CommRing.of S, from g).op).1.base,
  { apply le_antisymm,
    { rintro _ ⟨x, hxZ, rfl⟩,
      let i := X.affine_cover.finite_subcover.f x,
      obtain ⟨y, hy : (X.affine_cover.map i.1).1.base y = x⟩ :=
        X.affine_cover.finite_subcover.covers x,
      obtain ⟨y', rfl⟩ : y ∈ set.range (prime_spectrum.comap (ideal.quotient.mk (I i.1))),
      { rw prime_spectrum.range_comap_of_surjective _ _ (ideal.quotient.mk_surjective),
        rwa [ideal.mk_ker, ← hI, set.mem_preimage, hy] },
      let g' : S →+* _ ⧸ I i.1 := pi.eval_ring_hom _ (X.affine_cover.finite_subcover.f x),
      have : g'.comp g = gi i.1 := by { ext, refl },
      refine ⟨prime_spectrum.comap g' y', _⟩,
      rw [← hy, ← Scheme.comp_val_base_apply],
      transitivity (Scheme.Spec.map (gi i.1).op).1.base y',
      { rw ← this, refl }, { rw hgi, refl } },
    { rintros _ ⟨x, rfl⟩,
      obtain ⟨⟨i, x⟩, rfl⟩ := (prime_spectrum.pi_equiv _).symm.surjective x,
      refine ⟨(X.affine_cover.map i.1).val.base
        (prime_spectrum.comap (ideal.quotient.mk _) x), _, _⟩,
      { rw [← set.mem_preimage, hI], intros y hy, change (I i.1)^.quotient.mk y ∈ x.as_ideal,
        rw [ideal.quotient.eq_zero_iff_mem.mpr hy], exact zero_mem _ },
      { let g' : S →+* _ ⧸ I i.1 := pi.eval_ring_hom _ i,
        have : g'.comp g = gi i.1 := by { ext, refl },
        transitivity (Scheme.Spec.map (gi i.1).op).1.base x,
          { rw hgi, refl }, { rw ← this, refl } } } },
  rw this,
  exact prime_spectrum.image_is_closed_iff_is_stable_under_specialization _
end

lemma image_is_closed_iff_is_stable_under_specialization
  (f : X ⟶ Y) [quasi_compact f] {Z : set X.carrier}
  (hZ : is_closed Z) : is_closed (f.1.base '' Z) ↔ stable_under_specialization (f.1.base '' Z) :=
begin
  refine ⟨is_closed.stable_under_specialization, λ h, _⟩,
  rw is_closed_iff_coe_preimage_of_supr_eq_top Y.affine_cover.supr_opens_range,
  intro i,
  haveI := (quasi_compact_iff_forall_affine f).mp infer_instance _
    (range_is_affine_open_of_open_immersion (Y.affine_cover.map i)),
  haveI := (quasi_compact.affine_open_cover_iff Y.affine_cover f).mp infer_instance i,
  let Z' : set (Y.affine_cover.obj i).carrier := _,
  have : is_closed Z' ↔ stable_under_specialization Z' :=
    image_is_closed_iff_is_stable_under_specialization_of_affine
    (pullback.snd : pullback f (Y.affine_cover.map i) ⟶ _)
    (hZ.preimage (pullback.fst : pullback f (Y.affine_cover.map i) ⟶ _).1.base.2),
  let Z'' : set (Y.affine_cover.map i).opens_range := _, change is_closed Z'',
  let e := homeomorph.of_embedding (Y.affine_cover.map i).1.base
    PresheafedSpace.is_open_immersion.base_open.to_embedding,
  have hZ : e ⁻¹' Z'' = Z',
  { ext x, simp only [set.mem_preimage, set.mem_image],
    split,
    { rintro ⟨y, hyZ, hxy : f.1.base y = (Y.affine_cover.map i).1.base x⟩,
      let T : pullback.triplet f (Y.affine_cover.map i) := ⟨y, x, _, hxy, rfl⟩,
      obtain ⟨z, hzx : _ = y, hzy⟩ := T.exists_preimage,
      refine ⟨z, _, hzy⟩, rwa ← hzx at hyZ },
    { rintro ⟨x, hx, rfl⟩, refine ⟨_, hx, _⟩, rw [continuous_map.to_fun_eq_coe,
        ← Scheme.comp_val_base_apply, pullback.condition], refl } },
  rw [← e.quotient_map.is_closed_preimage, hZ, this, ← hZ],
  apply stable_under_specialization.preimage,
  apply stable_under_specialization.preimage h,
  all_goals { continuity }
end

lemma quasi_compact.is_closed_map_iff_specializing_map
  (f : X ⟶ Y) [quasi_compact f] : is_closed_map f.1.base ↔ specializing_map f.1.base :=
begin
  refine ⟨is_closed_map.specializing_map, _⟩,
  intros H Z hZ,
  rw image_is_closed_iff_is_stable_under_specialization f hZ,
  exact H.stable_under_specialization_image hZ.stable_under_specialization,
end

lemma universally_closed_eq_quasi_compact_and_universally_specializing :
  @universally_closed = @quasi_compact ⊓ (topologically @specializing_map).universally :=
begin
  ext X Y f,
  split,
  { introI _, refine ⟨infer_instance, λ X' Y' i₁ i₂ f' h, _⟩,
    haveI := universally_closed_stable_under_base_change h.flip infer_instance,
    exact (quasi_compact.is_closed_map_iff_specializing_map f').mp
      (universally_closed.is_closed_map f') },
  { rintro ⟨h₁, h₂⟩, constructor, introsI X' Y' i₁ i₂ f' h,
    haveI := quasi_compact_stable_under_base_change h.flip infer_instance,
    exact (quasi_compact.is_closed_map_iff_specializing_map f').mpr (h₂ _ _ _ h) }
end

end specializing

end algebraic_geometry


/-
Copyright (c) 2022 Devon Tuma. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Devon Tuma
-/
import computational_monads.simulation_semantics.constructions.logging.query_log.basic
import computational_monads.simulation_semantics.constructions.tracking_oracle

/-!
# Logging Oracles

This file defines a `logging_oracle` for simulating a computation while logging all queries.
The implementation is as a `tracking_oracle`, using a `query_log` as the internal state to
log the input and output of each query.
-/

open oracle_comp oracle_spec

variables {α β γ : Type} {spec spec' spec'' : oracle_spec}

def logging_oracle (spec : oracle_spec) : sim_oracle spec spec (query_log spec) :=
⟪query | λ i t u, query_log.log_query i t u, query_log.init spec⟫

namespace logging_oracle

variables (a : α) (oa : oracle_comp spec α) (ob : α → oracle_comp spec β) (i : spec.ι)
  (t : spec.domain i) (log : query_log spec)

@[simp] lemma apply : (logging_oracle spec) i (t, log) =
  query i t >>= λ u, return (u, log.log_query i t u) := rfl

section simulate

lemma simulate_return : simulate (logging_oracle _) (return a) log = return ⟨a, log⟩ := rfl

lemma simulate_query : simulate (logging_oracle _) (query i t) log =
  do {u ← query i t, return (u, log.log_query i t u)} := rfl

lemma simulate_bind : simulate (logging_oracle _) (oa >>= ob) log =
  (simulate (logging_oracle _) oa log) >>= (λ x, simulate (logging_oracle _) (ob x.1) x.2) := rfl

end simulate

section support

@[simp] lemma support_simulate' : (simulate' (logging_oracle spec) oa log).support = oa.support :=
sorry --tracking_oracle.support_simulate'_query_oracle_eq_support _ _ oa log

lemma support_default_simulate' :
  (default_simulate' (logging_oracle spec) oa).support = oa.support :=
support_simulate' oa (query_log.init spec)

end support

section distribution_semantics

section eval_dist

@[simp] lemma eval_dist_simulate' : ⁅simulate' (logging_oracle spec) oa log⁆ = ⁅oa⁆ :=
tracking_oracle.eval_dist_simulate'_query_eq_eval_dist _ _ oa log

lemma eval_dist_default_simulate' : ⁅default_simulate' (logging_oracle spec) oa⁆ = ⁅oa⁆ :=
logging_oracle.eval_dist_simulate' oa (query_log.init spec)

end eval_dist

end distribution_semantics

end logging_oracle


import mcl.defs
import mcl.rhl
--import parlang
import syncablep

open mcl
open mcl.mclk
open mcl.rhl
open parlang
open parlang.state
open parlang.thread_state

namespace assign_mcl

def sigc : signature_core
| "tid" := { scope := scope.tlocal, type := ⟨1, type.int⟩ }
| _ := { scope := scope.shared, type := ⟨1, type.int⟩ }

def sig : signature := ⟨sigc, ⟨rfl, rfl, rfl⟩⟩

lemma a_is_shared : is_shared (sig.val "a") := by apply eq.refl
lemma tid_is_tlocal : is_tlocal (sig.val "tid") := by apply eq.refl

-- TODO generate those proofs directly from signature
-- make type classes out of those
-- make name explicit in state.update
def read_tid := (@expression.tlocal_var sig _ _ "tid" (λ_, 0) rfl rfl rfl)

instance : has_one (expression sig (type_of (sig.val "b"))) := begin
    have : type_of (sig.val "b") = type.int := by apply eq.refl,
    rw this,
    apply_instance,
end

def p₁ : mclp sig := mclp.intro (λ m, 100) (
    mclk.shared_assign "a" v[read_tid] rfl rfl read_tid ;;
    mclk.shared_assign "b" v[read_tid] rfl rfl (read_tid + (expression.literal_int 1 rfl))
)

def p₂ : mclp sig := mclp.intro (λ m, 100) (
    mclk.shared_assign "b" v[read_tid] rfl rfl (read_tid + (expression.literal_int 1 rfl)) ;;
    mclk.shared_assign "a" v[read_tid] rfl rfl read_tid
)

end assign_mcl


import category_theory.limits.shapes
import category_theory.limits.types
import category_theory.types
import pullbacks
import subobject_classifier
import locally_cartesian_closed

universes v v₂ u

/-!
# Types

Show that Type has a subobject classifier (assuming choice).
-/

open category_theory category_theory.category category_theory.limits

instance types_has_pullbacks: has_pullbacks.{u} (Type u) := ⟨limits.has_limits_of_shape_of_has_limits⟩

lemma set_classifier {U X : Type} {f : U ⟶ X} {χ₁ : X ⟶ Prop} (q : @classifying _ category_theory.types _ unit _ _ (λ _, true) f χ₁) :
  ∀ x, χ₁ x ↔ ∃ a, f a = x :=
begin
  obtain ⟨ka, la, ma⟩ := q,
  intro x,
  split, intro,
    have: ((𝟙 _ : unit ⟶ unit) ≫ λ (_ : unit), true) = (λ (_ : unit), x) ≫ χ₁,
      ext y, simp, show true ↔ χ₁ x, simpa,
    set new_cone := pullback_cone.mk (𝟙 unit) (λ _, x) this,
    set g := ma.lift new_cone,
    use g (),
    have := ma.fac new_cone walking_cospan.right, simp at this,
    have := congr_fun this (), simp at this,
    exact this,
  rintro ⟨t, rfl⟩, have := congr_fun la t, simp at this, exact this,
end

-- -- TODO: can we make this computable?
noncomputable instance types_has_subobj_classifier : @has_subobject_classifier Type category_theory.types :=
{ Ω := Prop,
  Ω₀ := unit,
  truth := λ _, true,
  truth_mono' := ⟨λ A f g _, begin ext i, apply subsingleton.elim end⟩,
  classifier_of := λ A B f mon, λ b, ∃ (a : A), f a = b,
  classifies' :=
  begin
    intros A B f mon,
    refine {k := λ _, (), commutes := _, forms_pullback' := _},
    funext, simp, use x,
    refine ⟨λ c i, _, _, _⟩,
    show A,
    have: pullback_cone.fst c ≫ _ = pullback_cone.snd c ≫ _ := pullback_cone.condition c,
    have: (pullback_cone.snd c ≫ (λ (b : B), ∃ (a : A), f a = b)) i,
      rw ← this, dsimp, trivial,
    dsimp at this,
    exact classical.some this_1,
    intros c, apply pi_app_left,
    ext, apply subsingleton.elim,
    ext, dunfold pullback_cone.snd pullback_cone.mk, simp,
    have: (pullback_cone.snd c ≫ (λ (b : B), ∃ (a : A), f a = b)) x,
      rw ← pullback_cone.condition c, trivial,
    apply classical.some_spec this,
    intros c m J,
    resetI,
    rw ← cancel_mono f,
    ext, simp,
    have: (pullback_cone.snd c ≫ (λ (b : B), ∃ (a : A), f a = b)) x,
      rw ← pullback_cone.condition c, trivial,
    erw classical.some_spec this,
    simp at J, have Jl := congr_fun (J walking_cospan.right) x,
    simp at Jl, exact Jl,
  end,
  uniquely' :=
  begin
    introv _ fst, ext x,
    rw set_classifier fst x
  end
}

@[simps]
def currying_equiv (A X Y : Type u) : ((prodinl A).obj X ⟶ Y) ≃ (X ⟶ A → Y) :=
{ to_fun := λ f b a,
  begin
    refine f ⟨λ j, walking_pair.cases_on j a b, λ j₁ j₂, _⟩,
    rintros ⟨⟨rfl⟩⟩, refl
  end,
  inv_fun := λ g ab, g (ab.1 walking_pair.right) (ab.1 walking_pair.left),
  left_inv := λ f, by { ext ⟨ba⟩, dsimp, congr, ext ⟨j⟩, simp },
  right_inv := λ _, rfl }

instance type_exponentials (A : Type u) : exponentiable A :=
{ exponentiable :=
  { right := adjunction.right_adjoint_of_equiv (currying_equiv _) (
    begin
      intros X X' Y f g, ext, dsimp [currying_equiv], congr,
      show lim.map (@map_pair (Type u) _ _ _ _ _ id f) _ = _,
      rw types.types_limit_map,
      congr, ext ⟨j⟩, simp, simp
    end),
    adj := adjunction.adjunction_of_equiv_right _ _ } }

instance type_cc : is_cartesian_closed (Type u) :=
begin
  split,
  intro A,
  apply_instance
end