l3lab/ntp-mathlib huggingface dataset:
/-- The variance of a finite sum of pairwise independent random variables is the sum of the
variances. -/
theorem IndepFun.variance_sum [@IsProbabilityMeasure Ω _ ℙ] {ι : Type*} {X : ι → Ω → ℝ}
    {s : Finset ι} (hs : ∀ i ∈ s, @Memℒp _ _ _ (_) (X i) 2 ℙ)
    (h : Set.Pairwise ↑s fun i j => @IndepFun _ _ _ (_) _ _ (X i) (X j) ℙ) :
    Var[∑ i in s, X i] = ∑ i in s, Var[X i] := by
  classical
  induction' s using Finset.induction_on with k s ks IH
  · simp only [Finset.sum_empty, variance_zero]
  rw [variance_def' (memℒp_finset_sum' _ hs), sum_insert ks, sum_insert ks]
  simp only [add_sq']
  calc
    𝔼[X k ^ 2 + (∑ i in s, X i) ^ 2 + 2 * X k * ∑ i in s, X i] - 𝔼[X k + ∑ i in s, X i] ^ 2 =
        𝔼[X k ^ 2] + 𝔼[(∑ i in s, X i) ^ 2] + 𝔼[2 * X k * ∑ i in s, X i] -
          (𝔼[X k] + 𝔼[∑ i in s, X i]) ^ 2 := by
      rw [integral_add', integral_add', integral_add']
      · exact Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _))
      · apply integrable_finset_sum' _ fun i hi => ?_
        exact Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi))
      · exact Memℒp.integrable_sq (hs _ (mem_insert_self _ _))
      · apply Memℒp.integrable_sq
        exact memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi)
      · apply Integrable.add
        · exact Memℒp.integrable_sq (hs _ (mem_insert_self _ _))
        · apply Memℒp.integrable_sq
          exact memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi)
      · rw [mul_assoc]
        apply Integrable.const_mul _ (2 : ℝ)
        simp only [mul_sum, sum_apply, Pi.mul_apply]
        apply integrable_finset_sum _ fun i hi => ?_
        apply IndepFun.integrable_mul _ (Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _)))
          (Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi)))
        apply h (mem_insert_self _ _) (mem_insert_of_mem hi)
        exact fun hki => ks (hki.symm ▸ hi)
    _ = Var[X k] + Var[∑ i in s, X i] +
        (𝔼[2 * X k * ∑ i in s, X i] - 2 * 𝔼[X k] * 𝔼[∑ i in s, X i]) := by
      rw [variance_def' (hs _ (mem_insert_self _ _)),
        variance_def' (memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi))]
      ring
    _ = Var[X k] + Var[∑ i in s, X i] := by
      simp only [mul_assoc, integral_mul_left, Pi.mul_apply, Pi.one_apply, sum_apply,
        add_right_eq_self, mul_sum]
      rw [integral_finset_sum s fun i hi => ?_]; swap
      · apply Integrable.const_mul _ (2 : ℝ)
        

Proof state:
Ω : Type u_1
m : MeasurableSpace Ω
X✝ : Ω → ℝ
μ : Measure Ω
inst✝¹ : MeasureSpace Ω
inst✝ : IsProbabilityMeasure ℙ
ι : Type u_2
X : ι → Ω → ℝ
k : ι
s : Finset ι
ks : k ∉ s
IH :
  (∀ i ∈ s, Memℒp (X i) 2) →
    (Set.Pairwise ↑s fun i j => IndepFun (X i) (X j)) → variance (∑ i in s, X i) ℙ = ∑ i in s, variance (X i) ℙ
hs : ∀ i ∈ insert k s, Memℒp (X i) 2
h : Set.Pairwise ↑(insert k s) fun i j => IndepFun (X i) (X j)
i : ι
hi : i ∈ s
⊢ Integrable fun x => X k x * X i x

Next tactic:
apply IndepFun.integrable_mul _ (Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _)))
          (Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi)))
/-- The variance of a finite sum of pairwise independent random variables is the sum of the
variances. -/
theorem IndepFun.variance_sum [@IsProbabilityMeasure Ω _ ℙ] {ι : Type*} {X : ι → Ω → ℝ}
    {s : Finset ι} (hs : ∀ i ∈ s, @Memℒp _ _ _ (_) (X i) 2 ℙ)
    (h : Set.Pairwise ↑s fun i j => @IndepFun _ _ _ (_) _ _ (X i) (X j) ℙ) :
    Var[∑ i in s, X i] = ∑ i in s, Var[X i] := by
  classical
  induction' s using Finset.induction_on with k s ks IH
  · simp only [Finset.sum_empty, variance_zero]
  rw [variance_def' (memℒp_finset_sum' _ hs), sum_insert ks, sum_insert ks]
  simp only [add_sq']
  calc
    𝔼[X k ^ 2 + (∑ i in s, X i) ^ 2 + 2 * X k * ∑ i in s, X i] - 𝔼[X k + ∑ i in s, X i] ^ 2 =
        𝔼[X k ^ 2] + 𝔼[(∑ i in s, X i) ^ 2] + 𝔼[2 * X k * ∑ i in s, X i] -
          (𝔼[X k] + 𝔼[∑ i in s, X i]) ^ 2 := by
      rw [integral_add', integral_add', integral_add']
      · exact Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _))
      · apply integrable_finset_sum' _ fun i hi => ?_
        exact Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi))
      · exact Memℒp.integrable_sq (hs _ (mem_insert_self _ _))
      · apply Memℒp.integrable_sq
        exact memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi)
      · apply Integrable.add
        · exact Memℒp.integrable_sq (hs _ (mem_insert_self _ _))
        · apply Memℒp.integrable_sq
          exact memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi)
      · rw [mul_assoc]
        apply Integrable.const_mul _ (2 : ℝ)
        simp only [mul_sum, sum_apply, Pi.mul_apply]
        apply integrable_finset_sum _ fun i hi => ?_
        apply IndepFun.integrable_mul _ (Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _)))
          (Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi)))
        apply h (mem_insert_self _ _) (mem_insert_of_mem hi)
        exact fun hki => ks (hki.symm ▸ hi)
    _ = Var[X k] + Var[∑ i in s, X i] +
        (𝔼[2 * X k * ∑ i in s, X i] - 2 * 𝔼[X k] * 𝔼[∑ i in s, X i]) := by
      rw [variance_def' (hs _ (mem_insert_self _ _)),
        variance_def' (memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi))]
      ring
    _ = Var[X k] + Var[∑ i in s, X i] := by
      simp only [mul_assoc, integral_mul_left, Pi.mul_apply, Pi.one_apply, sum_apply,
        add_right_eq_self, mul_sum]
      rw [integral_finset_sum s fun i hi => ?_]; swap
      · apply Integrable.const_mul _ (2 : ℝ)
        apply IndepFun.integrable_mul _ (Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _)))
          (Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi)))
        

Proof state:
Ω : Type u_1
m : MeasurableSpace Ω
X✝ : Ω → ℝ
μ : Measure Ω
inst✝¹ : MeasureSpace Ω
inst✝ : IsProbabilityMeasure ℙ
ι : Type u_2
X : ι → Ω → ℝ
k : ι
s : Finset ι
ks : k ∉ s
IH :
  (∀ i ∈ s, Memℒp (X i) 2) →
    (Set.Pairwise ↑s fun i j => IndepFun (X i) (X j)) → variance (∑ i in s, X i) ℙ = ∑ i in s, variance (X i) ℙ
hs : ∀ i ∈ insert k s, Memℒp (X i) 2
h : Set.Pairwise ↑(insert k s) fun i j => IndepFun (X i) (X j)
i : ι
hi : i ∈ s
⊢ IndepFun (X k) (X i)

Next tactic:
apply h (mem_insert_self _ _) (mem_insert_of_mem hi)
/-- The variance of a finite sum of pairwise independent random variables is the sum of the
variances. -/
theorem IndepFun.variance_sum [@IsProbabilityMeasure Ω _ ℙ] {ι : Type*} {X : ι → Ω → ℝ}
    {s : Finset ι} (hs : ∀ i ∈ s, @Memℒp _ _ _ (_) (X i) 2 ℙ)
    (h : Set.Pairwise ↑s fun i j => @IndepFun _ _ _ (_) _ _ (X i) (X j) ℙ) :
    Var[∑ i in s, X i] = ∑ i in s, Var[X i] := by
  classical
  induction' s using Finset.induction_on with k s ks IH
  · simp only [Finset.sum_empty, variance_zero]
  rw [variance_def' (memℒp_finset_sum' _ hs), sum_insert ks, sum_insert ks]
  simp only [add_sq']
  calc
    𝔼[X k ^ 2 + (∑ i in s, X i) ^ 2 + 2 * X k * ∑ i in s, X i] - 𝔼[X k + ∑ i in s, X i] ^ 2 =
        𝔼[X k ^ 2] + 𝔼[(∑ i in s, X i) ^ 2] + 𝔼[2 * X k * ∑ i in s, X i] -
          (𝔼[X k] + 𝔼[∑ i in s, X i]) ^ 2 := by
      rw [integral_add', integral_add', integral_add']
      · exact Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _))
      · apply integrable_finset_sum' _ fun i hi => ?_
        exact Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi))
      · exact Memℒp.integrable_sq (hs _ (mem_insert_self _ _))
      · apply Memℒp.integrable_sq
        exact memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi)
      · apply Integrable.add
        · exact Memℒp.integrable_sq (hs _ (mem_insert_self _ _))
        · apply Memℒp.integrable_sq
          exact memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi)
      · rw [mul_assoc]
        apply Integrable.const_mul _ (2 : ℝ)
        simp only [mul_sum, sum_apply, Pi.mul_apply]
        apply integrable_finset_sum _ fun i hi => ?_
        apply IndepFun.integrable_mul _ (Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _)))
          (Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi)))
        apply h (mem_insert_self _ _) (mem_insert_of_mem hi)
        exact fun hki => ks (hki.symm ▸ hi)
    _ = Var[X k] + Var[∑ i in s, X i] +
        (𝔼[2 * X k * ∑ i in s, X i] - 2 * 𝔼[X k] * 𝔼[∑ i in s, X i]) := by
      rw [variance_def' (hs _ (mem_insert_self _ _)),
        variance_def' (memℒp_finset_sum' _ fun i hi => hs _ (mem_insert_of_mem hi))]
      ring
    _ = Var[X k] + Var[∑ i in s, X i] := by
      simp only [mul_assoc, integral_mul_left, Pi.mul_apply, Pi.one_apply, sum_apply,
        add_right_eq_self, mul_sum]
      rw [integral_finset_sum s fun i hi => ?_]; swap
      · apply Integrable.const_mul _ (2 : ℝ)
        apply IndepFun.integrable_mul _ (Memℒp.integrable one_le_two (hs _ (mem_insert_self _ _)))
          (Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi)))
        apply h (mem_insert_self _ _) (mem_insert_of_mem hi)
        

Proof state:
Ω : Type u_1
m : MeasurableSpace Ω
X✝ : Ω → ℝ
μ : Measure Ω
inst✝¹ : MeasureSpace Ω
inst✝ : IsProbabilityMeasure ℙ
ι : Type u_2
X : ι → Ω → ℝ
k : ι
s : Finset ι
ks : k ∉ s
IH :
  (∀ i ∈ s, Memℒp (X i) 2) →
    (Set.Pairwise ↑s fun i j => IndepFun (X i) (X j)) → variance (∑ i in s, X i) ℙ = ∑ i in s, variance (X i) ℙ
hs : ∀ i ∈ insert k s, Memℒp (X i) 2
h : Set.Pairwise ↑(insert k s) fun i j => IndepFun (X i) (X j)
i : ι
hi : i ∈ s
⊢ k ≠ i

Next tactic:
exact fun hki => ks (hki.symm ▸ hi)
/-- The projection from a trivial fiber bundle to its base is surjective. -/
protected theorem surjective_proj [Nonempty F] (h : IsHomeomorphicTrivialFiberBundle F proj) :
    Function.Surjective proj := by
  

Proof state:
B : Type u_1
F : Type u_2
Z : Type u_3
inst✝³ : TopologicalSpace B
inst✝² : TopologicalSpace F
inst✝¹ : TopologicalSpace Z
proj : Z → B
inst✝ : Nonempty F
h : IsHomeomorphicTrivialFiberBundle F proj
⊢ Function.Surjective proj

Next tactic:
obtain ⟨e, rfl⟩ := h.proj_eq
/-- The projection from a trivial fiber bundle to its base is surjective. -/
protected theorem surjective_proj [Nonempty F] (h : IsHomeomorphicTrivialFiberBundle F proj) :
    Function.Surjective proj := by
  obtain ⟨e, rfl⟩ := h.proj_eq
  

Proof state:
case intro
B : Type u_1
F : Type u_2
Z : Type u_3
inst✝³ : TopologicalSpace B
inst✝² : TopologicalSpace F
inst✝¹ : TopologicalSpace Z
inst✝ : Nonempty F
e : Z ≃ₜ B × F
h : IsHomeomorphicTrivialFiberBundle F (Prod.fst ∘ ⇑e)
⊢ Function.Surjective (Prod.fst ∘ ⇑e)

Next tactic:
exact Prod.fst_surjective.comp e.surjective
/-- The projection from a trivial fiber bundle to its base is continuous. -/
protected theorem continuous_proj (h : IsHomeomorphicTrivialFiberBundle F proj) :
    Continuous proj := by
  

Proof state:
B : Type u_1
F : Type u_2
Z : Type u_3
inst✝² : TopologicalSpace B
inst✝¹ : TopologicalSpace F
inst✝ : TopologicalSpace Z
proj : Z → B
h : IsHomeomorphicTrivialFiberBundle F proj
⊢ Continuous proj

Next tactic:
obtain ⟨e, rfl⟩ := h.proj_eq
/-- The projection from a trivial fiber bundle to its base is continuous. -/
protected theorem continuous_proj (h : IsHomeomorphicTrivialFiberBundle F proj) :
    Continuous proj := by
  obtain ⟨e, rfl⟩ := h.proj_eq; 

Proof state:
case intro
B : Type u_1
F : Type u_2
Z : Type u_3
inst✝² : TopologicalSpace B
inst✝¹ : TopologicalSpace F
inst✝ : TopologicalSpace Z
e : Z ≃ₜ B × F
h : IsHomeomorphicTrivialFiberBundle F (Prod.fst ∘ ⇑e)
⊢ Continuous (Prod.fst ∘ ⇑e)

Next tactic:
exact continuous_fst.comp e.continuous
/-- The projection from a trivial fiber bundle to its base is open. -/
protected theorem isOpenMap_proj (h : IsHomeomorphicTrivialFiberBundle F proj) :
    IsOpenMap proj := by
  

Proof state:
B : Type u_1
F : Type u_2
Z : Type u_3
inst✝² : TopologicalSpace B
inst✝¹ : TopologicalSpace F
inst✝ : TopologicalSpace Z
proj : Z → B
h : IsHomeomorphicTrivialFiberBundle F proj
⊢ IsOpenMap proj

Next tactic:
obtain ⟨e, rfl⟩ := h.proj_eq
/-- The projection from a trivial fiber bundle to its base is open. -/
protected theorem isOpenMap_proj (h : IsHomeomorphicTrivialFiberBundle F proj) :
    IsOpenMap proj := by
  obtain ⟨e, rfl⟩ := h.proj_eq; 

Proof state:
case intro
B : Type u_1
F : Type u_2
Z : Type u_3
inst✝² : TopologicalSpace B
inst✝¹ : TopologicalSpace F
inst✝ : TopologicalSpace Z
e : Z ≃ₜ B × F
h : IsHomeomorphicTrivialFiberBundle F (Prod.fst ∘ ⇑e)
⊢ IsOpenMap (Prod.fst ∘ ⇑e)

Next tactic:
exact isOpenMap_fst.comp e.isOpenMap
theorem eq_zero_of_mul_eq_zero : ∀ {n m : ℕ}, n * m = 0 → n = 0 ∨ m = 0
  | 0, m => fun _ => Or.inl rfl
  | succ n, m => by
    

Proof state:
n m : ℕ
⊢ succ n * m = 0 → succ n = 0 ∨ m = 0

Next tactic:
rw [succ_mul]
theorem eq_zero_of_mul_eq_zero : ∀ {n m : ℕ}, n * m = 0 → n = 0 ∨ m = 0
  | 0, m => fun _ => Or.inl rfl
  | succ n, m => by
    rw [succ_mul]; 

Proof state:
n m : ℕ
⊢ n * m + m = 0 → succ n = 0 ∨ m = 0

Next tactic:
intro h
theorem eq_zero_of_mul_eq_zero : ∀ {n m : ℕ}, n * m = 0 → n = 0 ∨ m = 0
  | 0, m => fun _ => Or.inl rfl
  | succ n, m => by
    rw [succ_mul]; intro h
    

Proof state:
n m : ℕ
h : n * m + m = 0
⊢ succ n = 0 ∨ m = 0

Next tactic:
exact Or.inr (Nat.eq_zero_of_add_eq_zero_left h)
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by 

Proof state:
m : ℕ
h : bit0 0 = bit0 (m + 1)
⊢ 0 = m + 1

Next tactic:
contradiction
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by 

Proof state:
n : ℕ
h : bit0 (n + 1) = bit0 0
⊢ n + 1 = 0

Next tactic:
contradiction
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
⊢ n + 1 = m + 1

Next tactic:
have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
⊢ succ (succ (n + n)) = succ (succ (m + m))

Next tactic:
unfold bit0 at h
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; 

Proof state:
n m : ℕ
h : n + 1 + (n + 1) = m + 1 + (m + 1)
⊢ succ (succ (n + n)) = succ (succ (m + m))

Next tactic:
simp [add_one, add_succ, succ_add] at h
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      

Proof state:
n m : ℕ
h : n + n = m + m
⊢ succ (succ (n + n)) = succ (succ (m + m))

Next tactic:
have aux : n + n = m + m := h
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; 

Proof state:
n m : ℕ
h aux : n + n = m + m
⊢ succ (succ (n + n)) = succ (succ (m + m))

Next tactic:
rw [aux]
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
    

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
this : succ (succ (n + n)) = succ (succ (m + m))
⊢ n + 1 = m + 1

Next tactic:
have : n + n = m + m := by repeat injection this with this
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
    have : n + n = m + m := by 

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
this : succ (succ (n + n)) = succ (succ (m + m))
⊢ n + n = m + m

Next tactic:
repeat injection this with this
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
    have : n + n = m + m := by repeat 

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
this : succ (succ (n + n)) = succ (succ (m + m))
⊢ n + n = m + m

Next tactic:
injection this with this
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
    have : n + n = m + m := by repeat 

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
this : succ (n + n) = succ (m + m)
⊢ n + n = m + m

Next tactic:
injection this with this
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
    have : n + n = m + m := by repeat 

Proof state:

Next tactic:
injection this with this
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
    have : n + n = m + m := by repeat injection this with this
    

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
this✝ : succ (succ (n + n)) = succ (succ (m + m))
this : n + n = m + m
⊢ n + 1 = m + 1

Next tactic:
have : n = m := Nat.bit0_inj this
protected theorem bit0_inj : ∀ {n m : ℕ}, bit0 n = bit0 m → n = m
  | 0, 0, _h => rfl
  | 0, m + 1, h => by contradiction
  | n + 1, 0, h => by contradiction
  | n + 1, m + 1, h => by
    have : succ (succ (n + n)) = succ (succ (m + m)) := by
      unfold bit0 at h; simp [add_one, add_succ, succ_add] at h
      have aux : n + n = m + m := h; rw [aux]
    have : n + n = m + m := by repeat injection this with this
    have : n = m := Nat.bit0_inj this
    

Proof state:
n m : ℕ
h : bit0 (n + 1) = bit0 (m + 1)
this✝¹ : succ (succ (n + n)) = succ (succ (m + m))
this✝ : n + n = m + m
this : n = m
⊢ n + 1 = m + 1

Next tactic:
rw [this]
protected theorem bit1_inj : ∀ {n m : ℕ}, bit1 n = bit1 m → n = m := @fun n m h =>
  have : succ (bit0 n) = succ (bit0 m) := by 

Proof state:
n m : ℕ
h : bit1 n = bit1 m
⊢ succ (bit0 n) = succ (bit0 m)

Next tactic:
simp [Nat.bit1_eq_succ_bit0] at h
protected theorem bit1_inj : ∀ {n m : ℕ}, bit1 n = bit1 m → n = m := @fun n m h =>
  have : succ (bit0 n) = succ (bit0 m) := by simp [Nat.bit1_eq_succ_bit0] at h; 

Proof state:
n m : ℕ
h : bit0 n = bit0 m
⊢ succ (bit0 n) = succ (bit0 m)

Next tactic:
rw [h]
protected theorem bit1_inj : ∀ {n m : ℕ}, bit1 n = bit1 m → n = m := @fun n m h =>
  have : succ (bit0 n) = succ (bit0 m) := by simp [Nat.bit1_eq_succ_bit0] at h; rw [h]
  have : bit0 n = bit0 m := by 

Proof state:
n m : ℕ
h : bit1 n = bit1 m
this : succ (bit0 n) = succ (bit0 m)
⊢ bit0 n = bit0 m

Next tactic:
injection this
protected theorem one_lt_bit1 : ∀ {n : Nat}, n ≠ 0 → 1 < bit1 n
  | 0, h => by 

Proof state:
h : 0 ≠ 0
⊢ 1 < bit1 0

Next tactic:
contradiction
protected theorem one_lt_bit1 : ∀ {n : Nat}, n ≠ 0 → 1 < bit1 n
  | 0, h => by contradiction
  | succ n, _h => by
    

Proof state:
n : ℕ
_h : succ n ≠ 0
⊢ 1 < bit1 (succ n)

Next tactic:
rw [Nat.bit1_succ_eq]
protected theorem one_lt_bit1 : ∀ {n : Nat}, n ≠ 0 → 1 < bit1 n
  | 0, h => by contradiction
  | succ n, _h => by
    rw [Nat.bit1_succ_eq]
    

Proof state:
n : ℕ
_h : succ n ≠ 0
⊢ 1 < succ (succ (bit1 n))

Next tactic:
apply succ_lt_succ
protected theorem one_lt_bit1 : ∀ {n : Nat}, n ≠ 0 → 1 < bit1 n
  | 0, h => by contradiction
  | succ n, _h => by
    rw [Nat.bit1_succ_eq]
    apply succ_lt_succ
    

Proof state:
case a
n : ℕ
_h : succ n ≠ 0
⊢ 0 < bit1 n + 1

Next tactic:
apply zero_lt_succ
protected theorem one_lt_bit0 : ∀ {n : Nat}, n ≠ 0 → 1 < bit0 n
  | 0, h => by 

Proof state:
h : 0 ≠ 0
⊢ 1 < bit0 0

Next tactic:
contradiction
protected theorem one_lt_bit0 : ∀ {n : Nat}, n ≠ 0 → 1 < bit0 n
  | 0, h => by contradiction
  | succ n, _h => by
    

Proof state:
n : ℕ
_h : succ n ≠ 0
⊢ 1 < bit0 (succ n)

Next tactic:
rw [Nat.bit0_succ_eq]
protected theorem one_lt_bit0 : ∀ {n : Nat}, n ≠ 0 → 1 < bit0 n
  | 0, h => by contradiction
  | succ n, _h => by
    rw [Nat.bit0_succ_eq]
    

Proof state:
n : ℕ
_h : succ n ≠ 0
⊢ 1 < succ (succ (bit0 n))

Next tactic:
apply succ_lt_succ
protected theorem one_lt_bit0 : ∀ {n : Nat}, n ≠ 0 → 1 < bit0 n
  | 0, h => by contradiction
  | succ n, _h => by
    rw [Nat.bit0_succ_eq]
    apply succ_lt_succ
    

Proof state:
case a
n : ℕ
_h : succ n ≠ 0
⊢ 0 < bit0 n + 1

Next tactic:
apply zero_lt_succ
protected theorem bit1_lt_bit0 : ∀ {n m : Nat}, n < m → bit1 n < bit0 m
  | n, 0, h => absurd h n.not_lt_zero
  | n, succ m, h =>
    have : n ≤ m := le_of_lt_succ h
    have : succ (n + n) ≤ succ (m + m) := succ_le_succ (Nat.add_le_add this this)
    have : succ (n + n) ≤ succ m + m := by 

Proof state:
n m : ℕ
h : n < succ m
this✝ : n ≤ m
this : succ (n + n) ≤ succ (m + m)
⊢ succ (n + n) ≤ succ m + m

Next tactic:
rw [succ_add]
protected theorem bit1_lt_bit0 : ∀ {n m : Nat}, n < m → bit1 n < bit0 m
  | n, 0, h => absurd h n.not_lt_zero
  | n, succ m, h =>
    have : n ≤ m := le_of_lt_succ h
    have : succ (n + n) ≤ succ (m + m) := succ_le_succ (Nat.add_le_add this this)
    have : succ (n + n) ≤ succ m + m := by rw [succ_add]; 

Proof state:
n m : ℕ
h : n < succ m
this✝ : n ≤ m
this : succ (n + n) ≤ succ (m + m)
⊢ succ (n + n) ≤ succ (m + m)

Next tactic:
assumption
def discriminate {B : Sort u} {n : ℕ} (H1 : n = 0 → B) (H2 : ∀ m, n = succ m → B) : B := by
  

Proof state:
B : Sort u
n : ℕ
H1 : n = 0 → B
H2 : (m : ℕ) → n = succ m → B
⊢ B

Next tactic:
induction n with
  | zero => exact H1 rfl
  | succ n _ => apply H2 _ rfl
def discriminate {B : Sort u} {n : ℕ} (H1 : n = 0 → B) (H2 : ∀ m, n = succ m → B) : B := by
  induction n with
  

Proof state:
case zero
B : Sort u
H1 : zero = 0 → B
H2 : (m : ℕ) → zero = succ m → B
⊢ B

Next tactic:
| zero => exact H1 rfl
def discriminate {B : Sort u} {n : ℕ} (H1 : n = 0 → B) (H2 : ∀ m, n = succ m → B) : B := by
  induction n with
  | zero => 

Proof state:
case zero
B : Sort u
H1 : zero = 0 → B
H2 : (m : ℕ) → zero = succ m → B
⊢ B

Next tactic:
exact H1 rfl
def discriminate {B : Sort u} {n : ℕ} (H1 : n = 0 → B) (H2 : ∀ m, n = succ m → B) : B := by
  induction n with
  | zero => exact H1 rfl
  

Proof state:
case succ
B : Sort u
n : ℕ
n_ih✝ : (n = 0 → B) → ((m : ℕ) → n = succ m → B) → B
H1 : succ n = 0 → B
H2 : (m : ℕ) → succ n = succ m → B
⊢ B

Next tactic:
| succ n _ => apply H2 _ rfl
def discriminate {B : Sort u} {n : ℕ} (H1 : n = 0 → B) (H2 : ∀ m, n = succ m → B) : B := by
  induction n with
  | zero => exact H1 rfl
  | succ n _ => 

Proof state:
case succ
B : Sort u
n : ℕ
n_ih✝ : (n = 0 → B) → ((m : ℕ) → n = succ m → B) → B
H1 : succ n = 0 → B
H2 : (m : ℕ) → succ n = succ m → B
⊢ B

Next tactic:
apply H2 _ rfl