l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem image_mul_const_uIcc (a b c : α) : (· * a) '' [[b, c]] = [[b * a, c * a]] :=
  if ha : a = 0 then by simp [ha]
  else calc
    (fun x => x * a) '' [[b, c]] = (· * a⁻¹) ⁻¹' [[b, c]] :=
      (Units.mk0 a ha).mulRight.image_eq_preimage _
    _ = (fun x => x / a) ⁻¹' [[b, c]] := by 

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
ha : ¬a = 0
⊢ (fun x => x * a⁻¹) ⁻¹' [[b, c]] = (fun x => x / a) ⁻¹' [[b, c]]

Next tactic:
simp only [div_eq_mul_inv]
@[simp]
theorem image_const_mul_uIcc (a b c : α) : (a * ·) '' [[b, c]] = [[a * b, a * c]] := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
⊢ (fun x => a * x) '' [[b, c]] = [[a * b, a * c]]

Next tactic:
simpa only [mul_comm] using image_mul_const_uIcc a b c
@[simp]
theorem image_div_const_uIcc (a b c : α) : (fun x => x / a) '' [[b, c]] = [[b / a, c / a]] := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
⊢ (fun x => x / a) '' [[b, c]] = [[b / a, c / a]]

Next tactic:
simp only [div_eq_mul_inv, image_mul_const_uIcc]
theorem image_mul_right_Icc' (a b : α) {c : α} (h : 0 < c) :
    (fun x => x * c) '' Icc a b = Icc (a * c) (b * c) :=
  ((Units.mk0 c h.ne').mulRight.image_eq_preimage _).trans (by 

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
h : 0 < c
⊢ ⇑(Units.mulRight (Units.mk0 c (_ : c ≠ 0))).symm ⁻¹' Icc a b = Icc (a * c) (b * c)

Next tactic:
simp [h, division_def]
theorem image_mul_right_Icc {a b c : α} (hab : a ≤ b) (hc : 0 ≤ c) :
    (fun x => x * c) '' Icc a b = Icc (a * c) (b * c) := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
hab : a ≤ b
hc : 0 ≤ c
⊢ (fun x => x * c) '' Icc a b = Icc (a * c) (b * c)

Next tactic:
cases eq_or_lt_of_le hc
theorem image_mul_right_Icc {a b c : α} (hab : a ≤ b) (hc : 0 ≤ c) :
    (fun x => x * c) '' Icc a b = Icc (a * c) (b * c) := by
  cases eq_or_lt_of_le hc
  · 

Proof state:
case inl
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
hab : a ≤ b
hc : 0 ≤ c
h✝ : 0 = c
⊢ (fun x => x * c) '' Icc a b = Icc (a * c) (b * c)

Next tactic:
subst c
theorem image_mul_right_Icc {a b c : α} (hab : a ≤ b) (hc : 0 ≤ c) :
    (fun x => x * c) '' Icc a b = Icc (a * c) (b * c) := by
  cases eq_or_lt_of_le hc
  · subst c
    

Proof state:
case inl
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b : α
hab : a ≤ b
hc : 0 ≤ 0
⊢ (fun x => x * 0) '' Icc a b = Icc (a * 0) (b * 0)

Next tactic:
simp [(nonempty_Icc.2 hab).image_const]
theorem image_mul_right_Icc {a b c : α} (hab : a ≤ b) (hc : 0 ≤ c) :
    (fun x => x * c) '' Icc a b = Icc (a * c) (b * c) := by
  cases eq_or_lt_of_le hc
  · subst c
    simp [(nonempty_Icc.2 hab).image_const]
  

Proof state:
case inr
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
hab : a ≤ b
hc : 0 ≤ c
h✝ : 0 < c
⊢ (fun x => x * c) '' Icc a b = Icc (a * c) (b * c)

Next tactic:
exact image_mul_right_Icc' a b ‹0 < c›
theorem image_mul_left_Icc' {a : α} (h : 0 < a) (b c : α) :
    (a * ·) '' Icc b c = Icc (a * b) (a * c) := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c : α
⊢ (fun x => a * x) '' Icc b c = Icc (a * b) (a * c)

Next tactic:
convert image_mul_right_Icc' b c h using 1
theorem image_mul_left_Icc' {a : α} (h : 0 < a) (b c : α) :
    (a * ·) '' Icc b c = Icc (a * b) (a * c) := by
  convert image_mul_right_Icc' b c h using 1 <;> 

Proof state:
case h.e'_2
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c : α
⊢ (fun x => a * x) '' Icc b c = (fun x => x * a) '' Icc b c

Next tactic:
simp only [mul_comm _ a]
theorem image_mul_left_Icc' {a : α} (h : 0 < a) (b c : α) :
    (a * ·) '' Icc b c = Icc (a * b) (a * c) := by
  convert image_mul_right_Icc' b c h using 1 <;> 

Proof state:
case h.e'_3
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c : α
⊢ Icc (a * b) (a * c) = Icc (b * a) (c * a)

Next tactic:
simp only [mul_comm _ a]
theorem image_mul_left_Icc {a b c : α} (ha : 0 ≤ a) (hbc : b ≤ c) :
    (a * ·) '' Icc b c = Icc (a * b) (a * c) := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
ha : 0 ≤ a
hbc : b ≤ c
⊢ (fun x => a * x) '' Icc b c = Icc (a * b) (a * c)

Next tactic:
convert image_mul_right_Icc hbc ha using 1
theorem image_mul_left_Icc {a b c : α} (ha : 0 ≤ a) (hbc : b ≤ c) :
    (a * ·) '' Icc b c = Icc (a * b) (a * c) := by
  convert image_mul_right_Icc hbc ha using 1 <;> 

Proof state:
case h.e'_2
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
ha : 0 ≤ a
hbc : b ≤ c
⊢ (fun x => a * x) '' Icc b c = (fun x => x * a) '' Icc b c

Next tactic:
simp only [mul_comm _ a]
theorem image_mul_left_Icc {a b c : α} (ha : 0 ≤ a) (hbc : b ≤ c) :
    (a * ·) '' Icc b c = Icc (a * b) (a * c) := by
  convert image_mul_right_Icc hbc ha using 1 <;> 

Proof state:
case h.e'_3
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
ha : 0 ≤ a
hbc : b ≤ c
⊢ Icc (a * b) (a * c) = Icc (b * a) (c * a)

Next tactic:
simp only [mul_comm _ a]
theorem image_mul_right_Ioo (a b : α) {c : α} (h : 0 < c) :
    (fun x => x * c) '' Ioo a b = Ioo (a * c) (b * c) :=
  ((Units.mk0 c h.ne').mulRight.image_eq_preimage _).trans (by 

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a b c : α
h : 0 < c
⊢ ⇑(Units.mulRight (Units.mk0 c (_ : c ≠ 0))).symm ⁻¹' Ioo a b = Ioo (a * c) (b * c)

Next tactic:
simp [h, division_def]
theorem image_mul_left_Ioo {a : α} (h : 0 < a) (b c : α) :
    (a * ·) '' Ioo b c = Ioo (a * b) (a * c) := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c : α
⊢ (fun x => a * x) '' Ioo b c = Ioo (a * b) (a * c)

Next tactic:
convert image_mul_right_Ioo b c h using 1
theorem image_mul_left_Ioo {a : α} (h : 0 < a) (b c : α) :
    (a * ·) '' Ioo b c = Ioo (a * b) (a * c) := by
  convert image_mul_right_Ioo b c h using 1 <;> 

Proof state:
case h.e'_2
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c : α
⊢ (fun x => a * x) '' Ioo b c = (fun x => x * a) '' Ioo b c

Next tactic:
simp only [mul_comm _ a]
theorem image_mul_left_Ioo {a : α} (h : 0 < a) (b c : α) :
    (a * ·) '' Ioo b c = Ioo (a * b) (a * c) := by
  convert image_mul_right_Ioo b c h using 1 <;> 

Proof state:
case h.e'_3
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c : α
⊢ Ioo (a * b) (a * c) = Ioo (b * a) (c * a)

Next tactic:
simp only [mul_comm _ a]
/-- The (pre)image under `inv` of `Ioo 0 a` is `Ioi a⁻¹`. -/
theorem inv_Ioo_0_left {a : α} (ha : 0 < a) : (Ioo 0 a)⁻¹ = Ioi a⁻¹ := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
ha : 0 < a
⊢ (Ioo 0 a)⁻¹ = Ioi a⁻¹

Next tactic:
ext x
/-- The (pre)image under `inv` of `Ioo 0 a` is `Ioi a⁻¹`. -/
theorem inv_Ioo_0_left {a : α} (ha : 0 < a) : (Ioo 0 a)⁻¹ = Ioi a⁻¹ := by
  ext x
  

Proof state:
case h
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
ha : 0 < a
x : α
⊢ x ∈ (Ioo 0 a)⁻¹ ↔ x ∈ Ioi a⁻¹

Next tactic:
exact
    ⟨fun h => inv_inv x ▸ (inv_lt_inv ha h.1).2 h.2, fun h =>
      ⟨inv_pos.2 <| (inv_pos.2 ha).trans h,
        inv_inv a ▸ (inv_lt_inv ((inv_pos.2 ha).trans h) (inv_pos.2 ha)).2 h⟩⟩
theorem inv_Ioi {a : α} (ha : 0 < a) : (Ioi a)⁻¹ = Ioo 0 a⁻¹ := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
ha : 0 < a
⊢ (Ioi a)⁻¹ = Ioo 0 a⁻¹

Next tactic:
rw [inv_eq_iff_eq_inv, inv_Ioo_0_left (inv_pos.2 ha), inv_inv]
theorem image_const_mul_Ioi_zero {k : Type*} [LinearOrderedField k] {x : k} (hx : 0 < x) :
    (fun y => x * y) '' Ioi (0 : k) = Ioi 0 := by
  

Proof state:
α : Type u_1
inst✝¹ : LinearOrderedField α
a : α
k : Type u_2
inst✝ : LinearOrderedField k
x : k
hx : 0 < x
⊢ (fun y => x * y) '' Ioi 0 = Ioi 0

Next tactic:
erw [(Units.mk0 x hx.ne').mulLeft.image_eq_preimage, preimage_const_mul_Ioi 0 (inv_pos.mpr hx),
    zero_div]
@[simp]
theorem image_affine_Icc' {a : α} (h : 0 < a) (b c d : α) :
    (a * · + b) '' Icc c d = Icc (a * c + b) (a * d + b) := by
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c d : α
⊢ (fun x => a * x + b) '' Icc c d = Icc (a * c + b) (a * d + b)

Next tactic:
suffices (· + b) '' ((a * ·) '' Icc c d) = Icc (a * c + b) (a * d + b) by
    rwa [Set.image_image] at this
@[simp]
theorem image_affine_Icc' {a : α} (h : 0 < a) (b c d : α) :
    (a * · + b) '' Icc c d = Icc (a * c + b) (a * d + b) := by
  suffices (· + b) '' ((a * ·) '' Icc c d) = Icc (a * c + b) (a * d + b) by
    

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c d : α
this : (fun x => x + b) '' ((fun x => a * x) '' Icc c d) = Icc (a * c + b) (a * d + b)
⊢ (fun x => a * x + b) '' Icc c d = Icc (a * c + b) (a * d + b)

Next tactic:
rwa [Set.image_image] at this
@[simp]
theorem image_affine_Icc' {a : α} (h : 0 < a) (b c d : α) :
    (a * · + b) '' Icc c d = Icc (a * c + b) (a * d + b) := by
  suffices (· + b) '' ((a * ·) '' Icc c d) = Icc (a * c + b) (a * d + b) by
    rwa [Set.image_image] at this
  

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
a✝ a : α
h : 0 < a
b c d : α
⊢ (fun x => x + b) '' ((fun x => a * x) '' Icc c d) = Icc (a * c + b) (a * d + b)

Next tactic:
rw [image_mul_left_Icc' h, image_add_const_Icc]
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
E : Fin n → Type u_2
inst✝¹ : (i : Fin n) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin n), SigmaFinite volume
f : (i : Fin n) → E i → 𝕜
⊢ ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x

Next tactic:
induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  | succ n n_ih =>
      calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
          simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply,
            Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ]
          rfl
        _ = (∫ x, f 0 x) *  ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x := by
          rw [← n_ih, ← integral_prod_mul, volume_eq_prod]
        _ =  ∏ i, ∫ x, f i x := by rw [Fin.prod_univ_succ]
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  

Proof state:
case zero
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
E : Fin Nat.zero → Type u_2
inst✝¹ : (i : Fin Nat.zero) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin Nat.zero), SigmaFinite volume
f : (i : Fin Nat.zero) → E i → 𝕜
⊢ ∫ (x : (i : Fin Nat.zero) → E i), ∏ i : Fin Nat.zero, f i (x i) = ∏ i : Fin Nat.zero, ∫ (x : E i), f i x

Next tactic:
| zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      

Proof state:
case zero
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
E : Fin Nat.zero → Type u_2
inst✝¹ : (i : Fin Nat.zero) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin Nat.zero), SigmaFinite volume
f : (i : Fin Nat.zero) → E i → 𝕜
⊢ ∫ (x : (i : Fin Nat.zero) → E i), ∏ i : Fin Nat.zero, f i (x i) = ∏ i : Fin Nat.zero, ∫ (x : E i), f i x

Next tactic:
simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  

Proof state:
case succ
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
n_ih :
  ∀ {E : Fin n → Type u_2} [inst : (i : Fin n) → MeasureSpace (E i)] [inst_1 : ∀ (i : Fin n), SigmaFinite volume]
    (f : (i : Fin n) → E i → 𝕜), ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x
E : Fin (Nat.succ n) → Type u_2
inst✝¹ : (i : Fin (Nat.succ n)) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin (Nat.succ n)), SigmaFinite volume
f : (i : Fin (Nat.succ n)) → E i → 𝕜
⊢ ∫ (x : (i : Fin (Nat.succ n)) → E i), ∏ i : Fin (Nat.succ n), f i (x i) = ∏ i : Fin (Nat.succ n), ∫ (x : E i), f i x

Next tactic:
| succ n n_ih =>
      calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
          simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply,
            Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ]
          rfl
        _ = (∫ x, f 0 x) *  ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x := by
          rw [← n_ih, ← integral_prod_mul, volume_eq_prod]
        _ =  ∏ i, ∫ x, f i x := by rw [Fin.prod_univ_succ]
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  | succ n n_ih =>
      

Proof state:
case succ
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
n_ih :
  ∀ {E : Fin n → Type u_2} [inst : (i : Fin n) → MeasureSpace (E i)] [inst_1 : ∀ (i : Fin n), SigmaFinite volume]
    (f : (i : Fin n) → E i → 𝕜), ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x
E : Fin (Nat.succ n) → Type u_2
inst✝¹ : (i : Fin (Nat.succ n)) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin (Nat.succ n)), SigmaFinite volume
f : (i : Fin (Nat.succ n)) → E i → 𝕜
⊢ ∫ (x : (i : Fin (Nat.succ n)) → E i), ∏ i : Fin (Nat.succ n), f i (x i) = ∏ i : Fin (Nat.succ n), ∫ (x : E i), f i x

Next tactic:
calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
          simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply,
            Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ]
          rfl
        _ = (∫ x, f 0 x) *  ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x := by
          rw [← n_ih, ← integral_prod_mul, volume_eq_prod]
        _ =  ∏ i, ∫ x, f i x := by rw [Fin.prod_univ_succ]
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  | succ n n_ih =>
      calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
n_ih :
  ∀ {E : Fin n → Type u_2} [inst : (i : Fin n) → MeasureSpace (E i)] [inst_1 : ∀ (i : Fin n), SigmaFinite volume]
    (f : (i : Fin n) → E i → 𝕜), ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x
E : Fin (Nat.succ n) → Type u_2
inst✝¹ : (i : Fin (Nat.succ n)) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin (Nat.succ n)), SigmaFinite volume
f : (i : Fin (Nat.succ n)) → E i → 𝕜
⊢ ∫ (x : (i : Fin (Nat.succ n)) → E i), ∏ i : Fin (Nat.succ n), f i (x i) =
    ∫ (x : E 0 × ((i : Fin n) → E (Fin.succ i))), f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i)

Next tactic:
rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  | succ n n_ih =>
      calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
          

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
n_ih :
  ∀ {E : Fin n → Type u_2} [inst : (i : Fin n) → MeasureSpace (E i)] [inst_1 : ∀ (i : Fin n), SigmaFinite volume]
    (f : (i : Fin n) → E i → 𝕜), ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x
E : Fin (Nat.succ n) → Type u_2
inst✝¹ : (i : Fin (Nat.succ n)) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin (Nat.succ n)), SigmaFinite volume
f : (i : Fin (Nat.succ n)) → E i → 𝕜
⊢ ∫ (x : E 0 × ((j : Fin n) → E (Fin.succAbove 0 j))),
      ∏ i : Fin (Nat.succ n),
        f i
          ((MeasurableEquiv.piFinSuccAbove (fun i => E i) 0).symm x
            i) ∂Measure.prod volume (Measure.pi fun j => volume) =
    ∫ (x : E 0 × ((i : Fin n) → E (Fin.succ i))), f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i)

Next tactic:
simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply,
            Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ]
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  | succ n n_ih =>
      calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
          simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply,
            Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ]
          

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
n_ih :
  ∀ {E : Fin n → Type u_2} [inst : (i : Fin n) → MeasureSpace (E i)] [inst_1 : ∀ (i : Fin n), SigmaFinite volume]
    (f : (i : Fin n) → E i → 𝕜), ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x
E : Fin (Nat.succ n) → Type u_2
inst✝¹ : (i : Fin (Nat.succ n)) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin (Nat.succ n)), SigmaFinite volume
f : (i : Fin (Nat.succ n)) → E i → 𝕜
⊢ ∫ (x : E 0 × ((j : Fin n) → E (Fin.succAbove 0 j))),
      f 0 (Fin.cons x.1 (fun j => cast (_ : E (Fin.succAbove 0 j) = E (Fin.succ j)) (x.2 j)) 0) *
        ∏ x_1 : Fin n,
          f (Fin.succ x_1)
            (cast (_ : E (Fin.succAbove 0 x_1) = E (Fin.succ x_1))
              (x.2 x_1)) ∂Measure.prod volume (Measure.pi fun j => volume) =
    ∫ (x : E 0 × ((i : Fin n) → E (Fin.succ i))), f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i)

Next tactic:
rfl
/-- A version of **Fubini's theorem** in `n` variables, for a natural number `n`. -/
theorem MeasureTheory.integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*}
    [∀ i, MeasureSpace (E i)] [∀ i, SigmaFinite (volume : Measure (E i))]
    (f : (i : Fin n) → E i → 𝕜) :
    ∫ x : (i : Fin n) → E i, ∏ i, f i (x i) = ∏ i, ∫ x, f i x := by
  induction n with
  | zero =>
      simp only [Nat.zero_eq, volume_pi, Finset.univ_eq_empty, Finset.prod_empty, integral_const,
        pi_empty_univ, ENNReal.one_toReal, smul_eq_mul, mul_one, pow_zero, one_smul]
  | succ n n_ih =>
      calc
        _ = ∫ x : E 0 × ((i : Fin n) → E (Fin.succ i)),
            f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by
          rw [volume_pi, ← ((measurePreserving_piFinSuccAbove
            (fun i => (volume : Measure (E i))) 0).symm).integral_comp']
          simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply,
            Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ]
          rfl
        _ = (∫ x, f 0 x) *  ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x := by
          

Proof state:
𝕜 : Type u_1
inst✝² : IsROrC 𝕜
n : ℕ
n_ih :
  ∀ {E : Fin n → Type u_2} [inst : (i : Fin n) → MeasureSpace (E i)] [inst_1 : ∀ (i : Fin n), SigmaFinite volume]
    (f : (i : Fin n) → E i → 𝕜), ∫ (x : (i : Fin n) → E i), ∏ i : Fin n, f i (x i) = ∏ i : Fin n, ∫ (x : E i), f i x
E : Fin (Nat.succ n) → Type u_2
inst✝¹ : (i : Fin (Nat.succ n)) → MeasureSpace (E i)
inst✝ : ∀ (i : Fin (Nat.succ n)), SigmaFinite volume
f : (i : Fin (Nat.succ n)) → E i → 𝕜
⊢ ∫ (x : E 0 × ((i : Fin n) → E (Fin.succ i))), f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) =
    (∫ (x : E 0), f 0 x) * ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x

Next tactic:
rw [← n_ih, ← integral_prod_mul, volume_eq_prod]