[GOAL]
⊢ Tendsto (fun n => ↑(numDerangements n) / ↑(Nat.factorial n)) atTop (𝓝 (Real.exp (-1)))
[PROOFSTEP]
let s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1 : ℝ) ^ k / k.factorial
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
⊢ Tendsto (fun n => ↑(numDerangements n) / ↑(Nat.factorial n)) atTop (𝓝 (Real.exp (-1)))
[PROOFSTEP]
suffices ∀ n : ℕ, (numDerangements n : ℝ) / n.factorial = s (n + 1)
  by
  simp_rw [this]
    -- shift the function by 1, and then use the fact that the partial sums
        -- converge to the infinite sum
  rw [tendsto_add_atTop_iff_nat (f := fun n => ∑ k in Finset.range n, (-1 : ℝ) ^ k / k.factorial) 1]
  apply HasSum.tendsto_sum_nat
  rw [Real.exp_eq_exp_ℝ]
  exact expSeries_div_hasSum_exp ℝ (-1 : ℝ)
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ Tendsto (fun n => ↑(numDerangements n) / ↑(Nat.factorial n)) atTop (𝓝 (Real.exp (-1)))
[PROOFSTEP]
simp_rw [this]
  -- shift the function by 1, and then use the fact that the partial sums
      -- converge to the infinite sum
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ Tendsto (fun n => ∑ k in Finset.range (n + 1), (-1) ^ k / ↑(Nat.factorial k)) atTop (𝓝 (Real.exp (-1)))
[PROOFSTEP]
rw [tendsto_add_atTop_iff_nat (f := fun n => ∑ k in Finset.range n, (-1 : ℝ) ^ k / k.factorial) 1]
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ Tendsto (fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)) atTop (𝓝 (Real.exp (-1)))
[PROOFSTEP]
apply HasSum.tendsto_sum_nat
[GOAL]
case h
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ HasSum (fun i => (-1) ^ i / ↑(Nat.factorial i)) (Real.exp (-1))
[PROOFSTEP]
rw [Real.exp_eq_exp_ℝ]
[GOAL]
case h
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ HasSum (fun i => (-1) ^ i / ↑(Nat.factorial i)) (exp ℝ (-1))
[PROOFSTEP]
exact expSeries_div_hasSum_exp ℝ (-1 : ℝ)
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
⊢ ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
[PROOFSTEP]
intro n
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
[PROOFSTEP]
rw [← Int.cast_ofNat, numDerangements_sum]
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ↑(∑ k in Finset.range (n + 1), (-1) ^ k * ↑(Nat.ascFactorial k (n - k))) / ↑(Nat.factorial n) = s (n + 1)
[PROOFSTEP]
push_cast
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ (∑ x in Finset.range (n + 1), (-1) ^ x * ↑(Nat.ascFactorial x (n - x))) / ↑(Nat.factorial n) =
    ∑ k in Finset.range (n + 1), (-1) ^ k / ↑(Nat.factorial k)
[PROOFSTEP]
rw [Finset.sum_div]
  -- get down to individual terms
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ∑ x in Finset.range (n + 1), (-1) ^ x * ↑(Nat.ascFactorial x (n - x)) / ↑(Nat.factorial n) =
    ∑ k in Finset.range (n + 1), (-1) ^ k / ↑(Nat.factorial k)
[PROOFSTEP]
refine' Finset.sum_congr (refl _) _
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ∀ (x : ℕ),
    x ∈ Finset.range (n + 1) →
      (-1) ^ x * ↑(Nat.ascFactorial x (n - x)) / ↑(Nat.factorial n) = (-1) ^ x / ↑(Nat.factorial x)
[PROOFSTEP]
intro k hk
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
⊢ (-1) ^ k * ↑(Nat.ascFactorial k (n - k)) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)
[PROOFSTEP]
have h_le : k ≤ n := Finset.mem_range_succ_iff.mp hk
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * ↑(Nat.ascFactorial k (n - k)) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)
[PROOFSTEP]
rw [Nat.ascFactorial_eq_div, add_tsub_cancel_of_le h_le]
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * ↑(Nat.factorial n / Nat.factorial k) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)
[PROOFSTEP]
push_cast [Nat.factorial_dvd_factorial h_le]
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * (↑(Nat.factorial n) / ↑(Nat.factorial k)) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)
[PROOFSTEP]
field_simp [Nat.factorial_ne_zero]
[GOAL]
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * ↑(Nat.factorial n) * ↑(Nat.factorial k) = (-1) ^ k * (↑(Nat.factorial k) * ↑(Nat.factorial n))
[PROOFSTEP]
ring


[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f : α → β
s : Set α
x : α
h : IsLUB s x
⊢ IsLUB (id '' s) (id x)
[PROOFSTEP]
simpa only [image_id] using h
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f : α → β
hf : LeftOrdContinuous f
a₁ a₂ : α
h : a₁ ≤ a₂
⊢ a₂ ∈ upperBounds {a₁, a₂}
[PROOFSTEP]
simp [*]
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f : α → β
hg : LeftOrdContinuous g
hf : LeftOrdContinuous f
s : Set α
x : α
h : IsLUB s x
⊢ IsLUB (g ∘ f '' s) ((g ∘ f) x)
[PROOFSTEP]
simpa only [image_image] using hg (hf h)
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f✝ : α → β
f : α → α
hf : LeftOrdContinuous f
n : ℕ
⊢ LeftOrdContinuous f^[n]
[PROOFSTEP]
induction n with
| zero => exact LeftOrdContinuous.id α
| succ n ihn => exact ihn.comp hf
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f✝ : α → β
f : α → α
hf : LeftOrdContinuous f
n : ℕ
⊢ LeftOrdContinuous f^[n]
[PROOFSTEP]
induction n with
| zero => exact LeftOrdContinuous.id α
| succ n ihn => exact ihn.comp hf
[GOAL]
case zero
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f✝ : α → β
f : α → α
hf : LeftOrdContinuous f
⊢ LeftOrdContinuous f^[Nat.zero]
[PROOFSTEP]

| zero => exact LeftOrdContinuous.id α
[GOAL]
case zero
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f✝ : α → β
f : α → α
hf : LeftOrdContinuous f
⊢ LeftOrdContinuous f^[Nat.zero]
[PROOFSTEP]
exact LeftOrdContinuous.id α
[GOAL]
case succ
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f✝ : α → β
f : α → α
hf : LeftOrdContinuous f
n : ℕ
ihn : LeftOrdContinuous f^[n]
⊢ LeftOrdContinuous f^[Nat.succ n]
[PROOFSTEP]

| succ n ihn => exact ihn.comp hf
[GOAL]
case succ
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f✝ : α → β
f : α → α
hf : LeftOrdContinuous f
n : ℕ
ihn : LeftOrdContinuous f^[n]
⊢ LeftOrdContinuous f^[Nat.succ n]
[PROOFSTEP]
exact ihn.comp hf
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝¹ : SemilatticeSup α
inst✝ : SemilatticeSup β
f : α → β
hf : LeftOrdContinuous f
x y : α
⊢ IsLUB (f '' {x, y}) (f x ⊔ f y)
[PROOFSTEP]
simp only [image_pair, isLUB_pair]
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝¹ : SemilatticeSup α
inst✝ : SemilatticeSup β
f : α → β
hf : LeftOrdContinuous f
h : Injective f
x y : α
⊢ f x ≤ f y ↔ x ≤ y
[PROOFSTEP]
simp only [← sup_eq_right, ← hf.map_sup, h.eq_iff]
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝¹ : SemilatticeSup α
inst✝ : SemilatticeSup β
f : α → β
hf : LeftOrdContinuous f
h : Injective f
x y : α
⊢ f x < f y ↔ x < y
[PROOFSTEP]
simp only [lt_iff_le_not_le, hf.le_iff h]
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝¹ : CompleteLattice α
inst✝ : CompleteLattice β
f : α → β
hf : LeftOrdContinuous f
s : Set α
⊢ f (sSup s) = ⨆ (x : α) (_ : x ∈ s), f x
[PROOFSTEP]
rw [hf.map_sSup', sSup_image]
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝¹ : CompleteLattice α
inst✝ : CompleteLattice β
f : α → β
hf : LeftOrdContinuous f
g : ι → α
⊢ f (⨆ (i : ι), g i) = ⨆ (i : ι), f (g i)
[PROOFSTEP]
simp only [iSup, hf.map_sSup', ← range_comp]
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝¹ : CompleteLattice α
inst✝ : CompleteLattice β
f : α → β
hf : LeftOrdContinuous f
g : ι → α
⊢ sSup (range (f ∘ fun i => g i)) = sSup (range fun i => f (g i))
[PROOFSTEP]
rfl
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : ConditionallyCompleteLattice α
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : Nonempty ι
f : α → β
hf : LeftOrdContinuous f
g : ι → α
hg : BddAbove (range g)
⊢ f (⨆ (i : ι), g i) = ⨆ (i : ι), f (g i)
[PROOFSTEP]
simp only [iSup, hf.map_csSup (range_nonempty _) hg, ← range_comp]
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : ConditionallyCompleteLattice α
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : Nonempty ι
f : α → β
hf : LeftOrdContinuous f
g : ι → α
hg : BddAbove (range g)
⊢ sSup (range (f ∘ g)) = sSup (range fun i => f (g i))
[PROOFSTEP]
rfl
[GOAL]
α : Type u
β : Type v
γ : Type w
ι : Sort x
inst✝² : Preorder α
inst✝¹ : Preorder β
inst✝ : Preorder γ
g : β → γ
f : α → β
s : Set α
x : α
h : IsGLB s x
⊢ IsGLB (id '' s) (id x)
[PROOFSTEP]
simpa only [image_id] using h


[GOAL]
I : Type u_1
A : Type u_2
X : I → Type u_3
inst✝¹ : (i : I) → TopologicalSpace (X i)
inst✝ : TopologicalSpace A
f g : (i : I) → C(A, X i)
S : Set A
homotopies : (i : I) → HomotopyRel (f i) (g i) S
src✝ : Homotopy (ContinuousMap.pi fun i => f i) (ContinuousMap.pi fun i => g i) :=
  Homotopy.pi fun i => (homotopies i).toHomotopy
⊢ ∀ (t : ↑unitInterval) (x : A),
    x ∈ S →
      ↑(mk fun x =>
                ContinuousMap.toFun
                  { toContinuousMap := src✝.toContinuousMap,
                      map_zero_left :=
                        (_ :
                          ∀ (x : A),
                            ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(ContinuousMap.pi fun i => f i) x),
                      map_one_left :=
                        (_ :
                          ∀ (x : A),
                            ContinuousMap.toFun src✝.toContinuousMap (1, x) =
                              ↑(ContinuousMap.pi fun i => g i) x) }.toContinuousMap
                  (t, x))
            x =
          ↑(ContinuousMap.pi f) x ∧
        ↑(mk fun x =>
                ContinuousMap.toFun
                  { toContinuousMap := src✝.toContinuousMap,
                      map_zero_left :=
                        (_ :
                          ∀ (x : A),
                            ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(ContinuousMap.pi fun i => f i) x),
                      map_one_left :=
                        (_ :
                          ∀ (x : A),
                            ContinuousMap.toFun src✝.toContinuousMap (1, x) =
                              ↑(ContinuousMap.pi fun i => g i) x) }.toContinuousMap
                  (t, x))
            x =
          ↑(ContinuousMap.pi g) x
[PROOFSTEP]
intro t x hx
[GOAL]
I : Type u_1
A : Type u_2
X : I → Type u_3
inst✝¹ : (i : I) → TopologicalSpace (X i)
inst✝ : TopologicalSpace A
f g : (i : I) → C(A, X i)
S : Set A
homotopies : (i : I) → HomotopyRel (f i) (g i) S
src✝ : Homotopy (ContinuousMap.pi fun i => f i) (ContinuousMap.pi fun i => g i) :=
  Homotopy.pi fun i => (homotopies i).toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
⊢ ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(ContinuousMap.pi fun i => f i) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A),
                        ContinuousMap.toFun src✝.toContinuousMap (1, x) =
                          ↑(ContinuousMap.pi fun i => g i) x) }.toContinuousMap
              (t, x))
        x =
      ↑(ContinuousMap.pi f) x ∧
    ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(ContinuousMap.pi fun i => f i) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A),
                        ContinuousMap.toFun src✝.toContinuousMap (1, x) =
                          ↑(ContinuousMap.pi fun i => g i) x) }.toContinuousMap
              (t, x))
        x =
      ↑(ContinuousMap.pi g) x
[PROOFSTEP]
dsimp only [coe_mk, pi_eval, toFun_eq_coe, HomotopyWith.coe_toContinuousMap]
[GOAL]
I : Type u_1
A : Type u_2
X : I → Type u_3
inst✝¹ : (i : I) → TopologicalSpace (X i)
inst✝ : TopologicalSpace A
f g : (i : I) → C(A, X i)
S : Set A
homotopies : (i : I) → HomotopyRel (f i) (g i) S
src✝ : Homotopy (ContinuousMap.pi fun i => f i) (ContinuousMap.pi fun i => g i) :=
  Homotopy.pi fun i => (homotopies i).toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
⊢ (↑(Homotopy.pi fun i => (homotopies i).toHomotopy).toContinuousMap (t, x) = fun i => ↑(f i) x) ∧
    ↑(Homotopy.pi fun i => (homotopies i).toHomotopy).toContinuousMap (t, x) = fun i => ↑(g i) x
[PROOFSTEP]
simp only [Function.funext_iff, ← forall_and]
[GOAL]
I : Type u_1
A : Type u_2
X : I → Type u_3
inst✝¹ : (i : I) → TopologicalSpace (X i)
inst✝ : TopologicalSpace A
f g : (i : I) → C(A, X i)
S : Set A
homotopies : (i : I) → HomotopyRel (f i) (g i) S
src✝ : Homotopy (ContinuousMap.pi fun i => f i) (ContinuousMap.pi fun i => g i) :=
  Homotopy.pi fun i => (homotopies i).toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
⊢ ∀ (x_1 : I),
    ↑(Homotopy.pi fun i => (homotopies i).toHomotopy).toContinuousMap (t, x) x_1 = ↑(f x_1) x ∧
      ↑(Homotopy.pi fun i => (homotopies i).toHomotopy).toContinuousMap (t, x) x_1 = ↑(g x_1) x
[PROOFSTEP]
intro i
[GOAL]
I : Type u_1
A : Type u_2
X : I → Type u_3
inst✝¹ : (i : I) → TopologicalSpace (X i)
inst✝ : TopologicalSpace A
f g : (i : I) → C(A, X i)
S : Set A
homotopies : (i : I) → HomotopyRel (f i) (g i) S
src✝ : Homotopy (ContinuousMap.pi fun i => f i) (ContinuousMap.pi fun i => g i) :=
  Homotopy.pi fun i => (homotopies i).toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
i : I
⊢ ↑(Homotopy.pi fun i => (homotopies i).toHomotopy).toContinuousMap (t, x) i = ↑(f i) x ∧
    ↑(Homotopy.pi fun i => (homotopies i).toHomotopy).toContinuousMap (t, x) i = ↑(g i) x
[PROOFSTEP]
exact (homotopies i).prop' t x hx
[GOAL]
α : Type u_1
β : Type u_2
inst✝² : TopologicalSpace α
inst✝¹ : TopologicalSpace β
A : Type u_3
inst✝ : TopologicalSpace A
f₀ f₁ : C(A, α)
g₀ g₁ : C(A, β)
S : Set A
F : Homotopy f₀ f₁
G : Homotopy g₀ g₁
x : A
⊢ ContinuousMap.toFun (ContinuousMap.mk fun t => (↑F t, ↑G t)) (0, x) = ↑(ContinuousMap.prodMk f₀ g₀) x
[PROOFSTEP]
simp only [prod_eval, Homotopy.apply_zero]
[GOAL]
α : Type u_1
β : Type u_2
inst✝² : TopologicalSpace α
inst✝¹ : TopologicalSpace β
A : Type u_3
inst✝ : TopologicalSpace A
f₀ f₁ : C(A, α)
g₀ g₁ : C(A, β)
S : Set A
F : Homotopy f₀ f₁
G : Homotopy g₀ g₁
x : A
⊢ ContinuousMap.toFun (ContinuousMap.mk fun t => (↑F t, ↑G t)) (1, x) = ↑(ContinuousMap.prodMk f₁ g₁) x
[PROOFSTEP]
simp only [prod_eval, Homotopy.apply_one]
[GOAL]
α : Type u_1
β : Type u_2
inst✝² : TopologicalSpace α
inst✝¹ : TopologicalSpace β
A : Type u_3
inst✝ : TopologicalSpace A
f₀ f₁ : C(A, α)
g₀ g₁ : C(A, β)
S : Set A
F : HomotopyRel f₀ f₁ S
G : HomotopyRel g₀ g₁ S
src✝ : Homotopy (prodMk f₀ g₀) (prodMk f₁ g₁) := Homotopy.prod F.toHomotopy G.toHomotopy
⊢ ∀ (t : ↑unitInterval) (x : A),
    x ∈ S →
      ↑(mk fun x =>
                ContinuousMap.toFun
                  { toContinuousMap := src✝.toContinuousMap,
                      map_zero_left :=
                        (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                      map_one_left :=
                        (_ :
                          ∀ (x : A),
                            ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
                  (t, x))
            x =
          ↑(prodMk f₀ g₀) x ∧
        ↑(mk fun x =>
                ContinuousMap.toFun
                  { toContinuousMap := src✝.toContinuousMap,
                      map_zero_left :=
                        (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                      map_one_left :=
                        (_ :
                          ∀ (x : A),
                            ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
                  (t, x))
            x =
          ↑(prodMk f₁ g₁) x
[PROOFSTEP]
intro t x hx
[GOAL]
α : Type u_1
β : Type u_2
inst✝² : TopologicalSpace α
inst✝¹ : TopologicalSpace β
A : Type u_3
inst✝ : TopologicalSpace A
f₀ f₁ : C(A, α)
g₀ g₁ : C(A, β)
S : Set A
F : HomotopyRel f₀ f₁ S
G : HomotopyRel g₀ g₁ S
src✝ : Homotopy (prodMk f₀ g₀) (prodMk f₁ g₁) := Homotopy.prod F.toHomotopy G.toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
⊢ ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left := (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
              (t, x))
        x =
      ↑(prodMk f₀ g₀) x ∧
    ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left := (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
              (t, x))
        x =
      ↑(prodMk f₁ g₁) x
[PROOFSTEP]
have hF := F.prop' t x hx
[GOAL]
α : Type u_1
β : Type u_2
inst✝² : TopologicalSpace α
inst✝¹ : TopologicalSpace β
A : Type u_3
inst✝ : TopologicalSpace A
f₀ f₁ : C(A, α)
g₀ g₁ : C(A, β)
S : Set A
F : HomotopyRel f₀ f₁ S
G : HomotopyRel g₀ g₁ S
src✝ : Homotopy (prodMk f₀ g₀) (prodMk f₁ g₁) := Homotopy.prod F.toHomotopy G.toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
hF :
  ↑(mk fun x => ContinuousMap.toFun F.toContinuousMap (t, x)) x = ↑f₀ x ∧
    ↑(mk fun x => ContinuousMap.toFun F.toContinuousMap (t, x)) x = ↑f₁ x
⊢ ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left := (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
              (t, x))
        x =
      ↑(prodMk f₀ g₀) x ∧
    ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left := (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
              (t, x))
        x =
      ↑(prodMk f₁ g₁) x
[PROOFSTEP]
have hG := G.prop' t x hx
[GOAL]
α : Type u_1
β : Type u_2
inst✝² : TopologicalSpace α
inst✝¹ : TopologicalSpace β
A : Type u_3
inst✝ : TopologicalSpace A
f₀ f₁ : C(A, α)
g₀ g₁ : C(A, β)
S : Set A
F : HomotopyRel f₀ f₁ S
G : HomotopyRel g₀ g₁ S
src✝ : Homotopy (prodMk f₀ g₀) (prodMk f₁ g₁) := Homotopy.prod F.toHomotopy G.toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
hF :
  ↑(mk fun x => ContinuousMap.toFun F.toContinuousMap (t, x)) x = ↑f₀ x ∧
    ↑(mk fun x => ContinuousMap.toFun F.toContinuousMap (t, x)) x = ↑f₁ x
hG :
  ↑(mk fun x => ContinuousMap.toFun G.toContinuousMap (t, x)) x = ↑g₀ x ∧
    ↑(mk fun x => ContinuousMap.toFun G.toContinuousMap (t, x)) x = ↑g₁ x
⊢ ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left := (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
              (t, x))
        x =
      ↑(prodMk f₀ g₀) x ∧
    ↑(mk fun x =>
            ContinuousMap.toFun
              { toContinuousMap := src✝.toContinuousMap,
                  map_zero_left := (_ : ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (0, x) = ↑(prodMk f₀ g₀) x),
                  map_one_left :=
                    (_ :
                      ∀ (x : A), ContinuousMap.toFun src✝.toContinuousMap (1, x) = ↑(prodMk f₁ g₁) x) }.toContinuousMap
              (t, x))
        x =
      ↑(prodMk f₁ g₁) x
[PROOFSTEP]
simp only [coe_mk, prod_eval, Prod.mk.inj_iff, Homotopy.prod] at hF hG ⊢
[GOAL]
α : Type u_1
β : Type u_2
inst✝² : TopologicalSpace α
inst✝¹ : TopologicalSpace β
A : Type u_3
inst✝ : TopologicalSpace A
f₀ f₁ : C(A, α)
g₀ g₁ : C(A, β)
S : Set A
F : HomotopyRel f₀ f₁ S
G : HomotopyRel g₀ g₁ S
src✝ : Homotopy (prodMk f₀ g₀) (prodMk f₁ g₁) := Homotopy.prod F.toHomotopy G.toHomotopy
t : ↑unitInterval
x : A
hx : x ∈ S
hF : ContinuousMap.toFun F.toContinuousMap (t, x) = ↑f₀ x ∧ ContinuousMap.toFun F.toContinuousMap (t, x) = ↑f₁ x
hG : ContinuousMap.toFun G.toContinuousMap (t, x) = ↑g₀ x ∧ ContinuousMap.toFun G.toContinuousMap (t, x) = ↑g₁ x
⊢ (↑F.toHomotopy (t, x) = ↑f₀ x ∧ ↑G.toHomotopy (t, x) = ↑g₀ x) ∧
    ↑F.toHomotopy (t, x) = ↑f₁ x ∧ ↑G.toHomotopy (t, x) = ↑g₁ x
[PROOFSTEP]
exact ⟨⟨hF.1, hG.1⟩, ⟨hF.2, hG.2⟩⟩
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ : (i : ι) → Path (as i) (bs i)
⊢ (pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (γ i)) =
    Quotient.mk (Homotopic.setoid (fun i => as i) fun i => bs i) (Path.pi γ)
[PROOFSTEP]
unfold pi
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ : (i : ι) → Path (as i) (bs i)
⊢ Quotient.map Path.pi (_ : ∀ (x y : (i : ι) → Path (as i) (bs i)), x ≈ y → Nonempty (Homotopy (Path.pi x) (Path.pi y)))
      (Quotient.choice fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (γ i)) =
    Quotient.mk (Homotopic.setoid (fun i => as i) fun i => bs i) (Path.pi γ)
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ₀ : (i : ι) → Homotopic.Quotient (as i) (bs i)
γ₁ : (i : ι) → Homotopic.Quotient (bs i) (cs i)
⊢ pi γ₀ ⬝ pi γ₁ = pi fun i => γ₀ i ⬝ γ₁ i
[PROOFSTEP]
apply Quotient.induction_on_pi (p := _) γ₁
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ₀ : (i : ι) → Homotopic.Quotient (as i) (bs i)
γ₁ : (i : ι) → Homotopic.Quotient (bs i) (cs i)
⊢ ∀ (a : (i : ι) → Path (bs i) (cs i)),
    (pi γ₀ ⬝ pi fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) =
      pi fun i => γ₀ i ⬝ (fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) i
[PROOFSTEP]
intro a
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ₀ : (i : ι) → Homotopic.Quotient (as i) (bs i)
γ₁ : (i : ι) → Homotopic.Quotient (bs i) (cs i)
a : (i : ι) → Path (bs i) (cs i)
⊢ (pi γ₀ ⬝ pi fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) =
    pi fun i => γ₀ i ⬝ (fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) i
[PROOFSTEP]
apply Quotient.induction_on_pi (p := _) γ₀
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ₀ : (i : ι) → Homotopic.Quotient (as i) (bs i)
γ₁ : (i : ι) → Homotopic.Quotient (bs i) (cs i)
a : (i : ι) → Path (bs i) (cs i)
⊢ ∀ (a_1 : (i : ι) → Path (as i) (bs i)),
    ((pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a_1 i)) ⬝
        pi fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) =
      pi fun i =>
        (fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a_1 i)) i ⬝
          (fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) i
[PROOFSTEP]
intros
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ₀ : (i : ι) → Homotopic.Quotient (as i) (bs i)
γ₁ : (i : ι) → Homotopic.Quotient (bs i) (cs i)
a : (i : ι) → Path (bs i) (cs i)
a✝ : (i : ι) → Path (as i) (bs i)
⊢ ((pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i)) ⬝
      pi fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) =
    pi fun i =>
      (fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i)) i ⬝
        (fun i => Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)) i
[PROOFSTEP]
simp only [pi_lift]
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ₀ : (i : ι) → Homotopic.Quotient (as i) (bs i)
γ₁ : (i : ι) → Homotopic.Quotient (bs i) (cs i)
a : (i : ι) → Path (bs i) (cs i)
a✝ : (i : ι) → Path (as i) (bs i)
⊢ Quotient.mk (Homotopic.setoid (fun i => as i) fun i => bs i) (Path.pi fun i => a✝ i) ⬝
      Quotient.mk (Homotopic.setoid (fun i => bs i) fun i => cs i) (Path.pi fun i => a i) =
    pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i) ⬝ Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)
[PROOFSTEP]
rw [← Path.Homotopic.comp_lift, Path.trans_pi_eq_pi_trans, ← pi_lift]
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
γ₀ : (i : ι) → Homotopic.Quotient (as i) (bs i)
γ₁ : (i : ι) → Homotopic.Quotient (bs i) (cs i)
a : (i : ι) → Path (bs i) (cs i)
a✝ : (i : ι) → Path (as i) (bs i)
⊢ (pi fun i => Quotient.mk (Homotopic.setoid (as i) (cs i)) (Path.trans (a✝ i) (a i))) =
    pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i) ⬝ Quotient.mk (Homotopic.setoid (bs i) (cs i)) (a i)
[PROOFSTEP]
rfl
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
i : ι
paths : (i : ι) → Homotopic.Quotient (as i) (bs i)
⊢ proj i (pi paths) = paths i
[PROOFSTEP]
apply Quotient.induction_on_pi (p := _) paths
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
i : ι
paths : (i : ι) → Homotopic.Quotient (as i) (bs i)
⊢ ∀ (a : (i : ι) → Path (as i) (bs i)),
    proj i (pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a i)) =
      (fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a i)) i
[PROOFSTEP]
intro
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
i : ι
paths : (i : ι) → Homotopic.Quotient (as i) (bs i)
a✝ : (i : ι) → Path (as i) (bs i)
⊢ proj i (pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i)) =
    (fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i)) i
[PROOFSTEP]
unfold proj
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
i : ι
paths : (i : ι) → Homotopic.Quotient (as i) (bs i)
a✝ : (i : ι) → Path (as i) (bs i)
⊢ Quotient.mapFn (pi fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i)) (ContinuousMap.mk fun p => p i) =
    (fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i)) i
[PROOFSTEP]
rw [pi_lift, ← Path.Homotopic.map_lift]
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
i : ι
paths : (i : ι) → Homotopic.Quotient (as i) (bs i)
a✝ : (i : ι) → Path (as i) (bs i)
⊢ Quotient.mk
      (Homotopic.setoid (↑(ContinuousMap.mk fun p => p i) fun i => as i)
        (↑(ContinuousMap.mk fun p => p i) fun i => bs i))
      (Path.map (Path.pi fun i => a✝ i) (_ : Continuous ↑(ContinuousMap.mk fun p => p i))) =
    (fun i => Quotient.mk (Homotopic.setoid (as i) (bs i)) (a✝ i)) i
[PROOFSTEP]
congr
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
p : Homotopic.Quotient as bs
⊢ (pi fun i => proj i p) = p
[PROOFSTEP]
apply Quotient.inductionOn (motive := _) p
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
p : Homotopic.Quotient as bs
⊢ ∀ (a : Path as bs),
    (pi fun i => proj i (Quotient.mk (Homotopic.setoid as bs) a)) = Quotient.mk (Homotopic.setoid as bs) a
[PROOFSTEP]
intro
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
p : Homotopic.Quotient as bs
a✝ : Path as bs
⊢ (pi fun i => proj i (Quotient.mk (Homotopic.setoid as bs) a✝)) = Quotient.mk (Homotopic.setoid as bs) a✝
[PROOFSTEP]
unfold proj
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
p : Homotopic.Quotient as bs
a✝ : Path as bs
⊢ (pi fun i => Quotient.mapFn (Quotient.mk (Homotopic.setoid as bs) a✝) (ContinuousMap.mk fun p => p i)) =
    Quotient.mk (Homotopic.setoid as bs) a✝
[PROOFSTEP]
simp_rw [← Path.Homotopic.map_lift]
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
p : Homotopic.Quotient as bs
a✝ : Path as bs
⊢ (pi fun i =>
      Quotient.mk (Homotopic.setoid (↑(ContinuousMap.mk fun p => p i) as) (↑(ContinuousMap.mk fun p => p i) bs))
        (Path.map a✝ (_ : Continuous ↑(ContinuousMap.mk fun p => p i)))) =
    Quotient.mk (Homotopic.setoid as bs) a✝
[PROOFSTEP]
erw [pi_lift]
[GOAL]
ι : Type u_1
X : ι → Type u_2
inst✝ : (i : ι) → TopologicalSpace (X i)
as bs cs : (i : ι) → X i
p : Homotopic.Quotient as bs
a✝ : Path as bs
⊢ Quotient.mk (Homotopic.setoid (fun i => as i) fun i => bs i)
      (Path.pi fun i => Path.map a✝ (_ : Continuous ↑(ContinuousMap.mk fun p => p i))) =
    Quotient.mk (Homotopic.setoid as bs) a✝
[PROOFSTEP]
congr
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
⊢ prod q₁ q₂ ⬝ prod r₁ r₂ = prod (q₁ ⬝ r₁) (q₂ ⬝ r₂)
[PROOFSTEP]
apply Quotient.inductionOn₂ (motive := _) q₁ q₂
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
⊢ ∀ (a : Path a₁ a₂) (b : Path b₁ b₂),
    prod (Quotient.mk (Homotopic.setoid a₁ a₂) a) (Quotient.mk (Homotopic.setoid b₁ b₂) b) ⬝ prod r₁ r₂ =
      prod (Quotient.mk (Homotopic.setoid a₁ a₂) a ⬝ r₁) (Quotient.mk (Homotopic.setoid b₁ b₂) b ⬝ r₂)
[PROOFSTEP]
intro a b
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
a : Path a₁ a₂
b : Path b₁ b₂
⊢ prod (Quotient.mk (Homotopic.setoid a₁ a₂) a) (Quotient.mk (Homotopic.setoid b₁ b₂) b) ⬝ prod r₁ r₂ =
    prod (Quotient.mk (Homotopic.setoid a₁ a₂) a ⬝ r₁) (Quotient.mk (Homotopic.setoid b₁ b₂) b ⬝ r₂)
[PROOFSTEP]
apply Quotient.inductionOn₂ (motive := _) r₁ r₂
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
a : Path a₁ a₂
b : Path b₁ b₂
⊢ ∀ (a_1 : Path a₂ a₃) (b_1 : Path b₂ b₃),
    prod (Quotient.mk (Homotopic.setoid a₁ a₂) a) (Quotient.mk (Homotopic.setoid b₁ b₂) b) ⬝
        prod (Quotient.mk (Homotopic.setoid a₂ a₃) a_1) (Quotient.mk (Homotopic.setoid b₂ b₃) b_1) =
      prod (Quotient.mk (Homotopic.setoid a₁ a₂) a ⬝ Quotient.mk (Homotopic.setoid a₂ a₃) a_1)
        (Quotient.mk (Homotopic.setoid b₁ b₂) b ⬝ Quotient.mk (Homotopic.setoid b₂ b₃) b_1)
[PROOFSTEP]
intros
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
a : Path a₁ a₂
b : Path b₁ b₂
a✝ : Path a₂ a₃
b✝ : Path b₂ b₃
⊢ prod (Quotient.mk (Homotopic.setoid a₁ a₂) a) (Quotient.mk (Homotopic.setoid b₁ b₂) b) ⬝
      prod (Quotient.mk (Homotopic.setoid a₂ a₃) a✝) (Quotient.mk (Homotopic.setoid b₂ b₃) b✝) =
    prod (Quotient.mk (Homotopic.setoid a₁ a₂) a ⬝ Quotient.mk (Homotopic.setoid a₂ a₃) a✝)
      (Quotient.mk (Homotopic.setoid b₁ b₂) b ⬝ Quotient.mk (Homotopic.setoid b₂ b₃) b✝)
[PROOFSTEP]
simp only [prod_lift, ← Path.Homotopic.comp_lift, Path.trans_prod_eq_prod_trans]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
⊢ projLeft (prod q₁ q₂) = q₁
[PROOFSTEP]
apply Quotient.inductionOn₂ (motive := _) q₁ q₂
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
⊢ ∀ (a : Path a₁ a₂) (b : Path b₁ b₂),
    projLeft (prod (Quotient.mk (Homotopic.setoid a₁ a₂) a) (Quotient.mk (Homotopic.setoid b₁ b₂) b)) =
      Quotient.mk (Homotopic.setoid a₁ a₂) a
[PROOFSTEP]
intro p₁ p₂
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁✝ p₁' : Path a₁ a₂
p₂✝ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p₁ : Path a₁ a₂
p₂ : Path b₁ b₂
⊢ projLeft (prod (Quotient.mk (Homotopic.setoid a₁ a₂) p₁) (Quotient.mk (Homotopic.setoid b₁ b₂) p₂)) =
    Quotient.mk (Homotopic.setoid a₁ a₂) p₁
[PROOFSTEP]
unfold projLeft
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁✝ p₁' : Path a₁ a₂
p₂✝ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p₁ : Path a₁ a₂
p₂ : Path b₁ b₂
⊢ Quotient.mapFn (prod (Quotient.mk (Homotopic.setoid a₁ a₂) p₁) (Quotient.mk (Homotopic.setoid b₁ b₂) p₂))
      (ContinuousMap.mk Prod.fst) =
    Quotient.mk (Homotopic.setoid a₁ a₂) p₁
[PROOFSTEP]
rw [prod_lift, ← Path.Homotopic.map_lift]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁✝ p₁' : Path a₁ a₂
p₂✝ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p₁ : Path a₁ a₂
p₂ : Path b₁ b₂
⊢ Quotient.mk (Homotopic.setoid (↑(ContinuousMap.mk Prod.fst) (a₁, b₁)) (↑(ContinuousMap.mk Prod.fst) (a₂, b₂)))
      (Path.map (Path.prod p₁ p₂) (_ : Continuous ↑(ContinuousMap.mk Prod.fst))) =
    Quotient.mk (Homotopic.setoid a₁ a₂) p₁
[PROOFSTEP]
congr
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
⊢ projRight (prod q₁ q₂) = q₂
[PROOFSTEP]
apply Quotient.inductionOn₂ (motive := _) q₁ q₂
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
⊢ ∀ (a : Path a₁ a₂) (b : Path b₁ b₂),
    projRight (prod (Quotient.mk (Homotopic.setoid a₁ a₂) a) (Quotient.mk (Homotopic.setoid b₁ b₂) b)) =
      Quotient.mk (Homotopic.setoid b₁ b₂) b
[PROOFSTEP]
intro p₁ p₂
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁✝ p₁' : Path a₁ a₂
p₂✝ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p₁ : Path a₁ a₂
p₂ : Path b₁ b₂
⊢ projRight (prod (Quotient.mk (Homotopic.setoid a₁ a₂) p₁) (Quotient.mk (Homotopic.setoid b₁ b₂) p₂)) =
    Quotient.mk (Homotopic.setoid b₁ b₂) p₂
[PROOFSTEP]
unfold projRight
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁✝ p₁' : Path a₁ a₂
p₂✝ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p₁ : Path a₁ a₂
p₂ : Path b₁ b₂
⊢ Quotient.mapFn (prod (Quotient.mk (Homotopic.setoid a₁ a₂) p₁) (Quotient.mk (Homotopic.setoid b₁ b₂) p₂))
      (ContinuousMap.mk Prod.snd) =
    Quotient.mk (Homotopic.setoid b₁ b₂) p₂
[PROOFSTEP]
rw [prod_lift, ← Path.Homotopic.map_lift]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁✝ p₁' : Path a₁ a₂
p₂✝ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p₁ : Path a₁ a₂
p₂ : Path b₁ b₂
⊢ Quotient.mk (Homotopic.setoid (↑(ContinuousMap.mk Prod.snd) (a₁, b₁)) (↑(ContinuousMap.mk Prod.snd) (a₂, b₂)))
      (Path.map (Path.prod p₁ p₂) (_ : Continuous ↑(ContinuousMap.mk Prod.snd))) =
    Quotient.mk (Homotopic.setoid b₁ b₂) p₂
[PROOFSTEP]
congr
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p : Homotopic.Quotient (a₁, b₁) (a₂, b₂)
⊢ prod (projLeft p) (projRight p) = p
[PROOFSTEP]
apply Quotient.inductionOn (motive := _) p
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p : Homotopic.Quotient (a₁, b₁) (a₂, b₂)
⊢ ∀ (a : Path (a₁, b₁) (a₂, b₂)),
    prod (projLeft (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) a))
        (projRight (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) a)) =
      Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) a
[PROOFSTEP]
intro p'
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p : Homotopic.Quotient (a₁, b₁) (a₂, b₂)
p' : Path (a₁, b₁) (a₂, b₂)
⊢ prod (projLeft (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p'))
      (projRight (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p')) =
    Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p'
[PROOFSTEP]
unfold projLeft
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p : Homotopic.Quotient (a₁, b₁) (a₂, b₂)
p' : Path (a₁, b₁) (a₂, b₂)
⊢ prod (Quotient.mapFn (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p') (ContinuousMap.mk Prod.fst))
      (projRight (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p')) =
    Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p'
[PROOFSTEP]
unfold projRight
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p : Homotopic.Quotient (a₁, b₁) (a₂, b₂)
p' : Path (a₁, b₁) (a₂, b₂)
⊢ prod (Quotient.mapFn (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p') (ContinuousMap.mk Prod.fst))
      (Quotient.mapFn (Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p') (ContinuousMap.mk Prod.snd)) =
    Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p'
[PROOFSTEP]
simp only [← Path.Homotopic.map_lift, prod_lift]
[GOAL]
α : Type u_1
β : Type u_2
inst✝¹ : TopologicalSpace α
inst✝ : TopologicalSpace β
a₁ a₂ a₃ : α
b₁ b₂ b₃ : β
p₁ p₁' : Path a₁ a₂
p₂ p₂' : Path b₁ b₂
q₁ : Homotopic.Quotient a₁ a₂
q₂ : Homotopic.Quotient b₁ b₂
r₁ : Homotopic.Quotient a₂ a₃
r₂ : Homotopic.Quotient b₂ b₃
c₁ c₂ : α × β
p : Homotopic.Quotient (a₁, b₁) (a₂, b₂)
p' : Path (a₁, b₁) (a₂, b₂)
⊢ prod
      (Quotient.mk (Homotopic.setoid (↑(ContinuousMap.mk Prod.fst) (a₁, b₁)) (↑(ContinuousMap.mk Prod.fst) (a₂, b₂)))
        (Path.map p' (_ : Continuous ↑(ContinuousMap.mk Prod.fst))))
      (Quotient.mk (Homotopic.setoid (↑(ContinuousMap.mk Prod.snd) (a₁, b₁)) (↑(ContinuousMap.mk Prod.snd) (a₂, b₂)))
        (Path.map p' (_ : Continuous ↑(ContinuousMap.mk Prod.snd)))) =
    Quotient.mk (Homotopic.setoid (a₁, b₁) (a₂, b₂)) p'
[PROOFSTEP]
congr


[GOAL]
C : Type u_1
inst✝ : Bicategory C
X : C
⊢ ∀ {X₁ Y₁ Z₁ X₂ Y₂ Z₂ : EndMonoidal X} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (g₁ : Y₁ ⟶ Z₁) (g₂ : Y₂ ⟶ Z₂),
    (fun {X₁ Y₁ X₂ Y₂} f g => f ▷ X₂ ≫ Y₁ ◁ g) (f₁ ≫ g₁) (f₂ ≫ g₂) =
      (fun {X₁ Y₁ X₂ Y₂} f g => f ▷ X₂ ≫ Y₁ ◁ g) f₁ f₂ ≫ (fun {X₁ Y₁ X₂ Y₂} f g => f ▷ X₂ ≫ Y₁ ◁ g) g₁ g₂
[PROOFSTEP]
intros
[GOAL]
C : Type u_1
inst✝ : Bicategory C
X : C
X₁✝ Y₁✝ Z₁✝ X₂✝ Y₂✝ Z₂✝ : EndMonoidal X
f₁✝ : X₁✝ ⟶ Y₁✝
f₂✝ : X₂✝ ⟶ Y₂✝
g₁✝ : Y₁✝ ⟶ Z₁✝
g₂✝ : Y₂✝ ⟶ Z₂✝
⊢ (fun {X₁ Y₁ X₂ Y₂} f g => f ▷ X₂ ≫ Y₁ ◁ g) (f₁✝ ≫ g₁✝) (f₂✝ ≫ g₂✝) =
    (fun {X₁ Y₁ X₂ Y₂} f g => f ▷ X₂ ≫ Y₁ ◁ g) f₁✝ f₂✝ ≫ (fun {X₁ Y₁ X₂ Y₂} f g => f ▷ X₂ ≫ Y₁ ◁ g) g₁✝ g₂✝
[PROOFSTEP]
dsimp
[GOAL]
C : Type u_1
inst✝ : Bicategory C
X : C
X₁✝ Y₁✝ Z₁✝ X₂✝ Y₂✝ Z₂✝ : EndMonoidal X
f₁✝ : X₁✝ ⟶ Y₁✝
f₂✝ : X₂✝ ⟶ Y₂✝
g₁✝ : Y₁✝ ⟶ Z₁✝
g₂✝ : Y₂✝ ⟶ Z₂✝
⊢ (f₁✝ ≫ g₁✝) ▷ X₂✝ ≫ Z₁✝ ◁ (f₂✝ ≫ g₂✝) = (f₁✝ ▷ X₂✝ ≫ Y₁✝ ◁ f₂✝) ≫ g₁✝ ▷ Y₂✝ ≫ Z₁✝ ◁ g₂✝
[PROOFSTEP]
rw [Bicategory.whiskerLeft_comp, Bicategory.comp_whiskerRight, Category.assoc, Category.assoc,
  Bicategory.whisker_exchange_assoc]


[GOAL]
θ : ℂ
⊢ cos θ = 0 ↔ ∃ k, θ = (2 * ↑k + 1) * ↑π / 2
[PROOFSTEP]
have h : (exp (θ * I) + exp (-θ * I)) / 2 = 0 ↔ exp (2 * θ * I) = -1 :=
  by
  rw [@div_eq_iff _ _ (exp (θ * I) + exp (-θ * I)) 2 0 two_ne_zero, zero_mul, add_eq_zero_iff_eq_neg,
    neg_eq_neg_one_mul, ← div_eq_iff (exp_ne_zero _), ← exp_sub]
  congr 3; ring_nf
[GOAL]
θ : ℂ
⊢ (exp (θ * I) + exp (-θ * I)) / 2 = 0 ↔ exp (2 * θ * I) = -1
[PROOFSTEP]
rw [@div_eq_iff _ _ (exp (θ * I) + exp (-θ * I)) 2 0 two_ne_zero, zero_mul, add_eq_zero_iff_eq_neg, neg_eq_neg_one_mul,
  ← div_eq_iff (exp_ne_zero _), ← exp_sub]
[GOAL]
θ : ℂ
⊢ exp (θ * I - -θ * I) = -1 ↔ exp (2 * θ * I) = -1
[PROOFSTEP]
congr 3
[GOAL]
θ : ℂ
⊢ exp (θ * I - -θ * I) = -1 ↔ exp (2 * θ * I) = -1
[PROOFSTEP]
ring_nf
[GOAL]
θ : ℂ
h : (exp (θ * I) + exp (-θ * I)) / 2 = 0 ↔ exp (2 * θ * I) = -1
⊢ cos θ = 0 ↔ ∃ k, θ = (2 * ↑k + 1) * ↑π / 2
[PROOFSTEP]
rw [cos, h, ← exp_pi_mul_I, exp_eq_exp_iff_exists_int, mul_right_comm]
[GOAL]
θ : ℂ
h : (exp (θ * I) + exp (-θ * I)) / 2 = 0 ↔ exp (2 * θ * I) = -1
⊢ (∃ n, 2 * I * θ = ↑π * I + ↑n * (2 * ↑π * I)) ↔ ∃ k, θ = (2 * ↑k + 1) * ↑π / 2
[PROOFSTEP]
refine' exists_congr fun x => _
[GOAL]
θ : ℂ
h : (exp (θ * I) + exp (-θ * I)) / 2 = 0 ↔ exp (2 * θ * I) = -1
x : ℤ
⊢ 2 * I * θ = ↑π * I + ↑x * (2 * ↑π * I) ↔ θ = (2 * ↑x + 1) * ↑π / 2
[PROOFSTEP]
refine' (iff_of_eq <| congr_arg _ _).trans (mul_right_inj' <| mul_ne_zero two_ne_zero I_ne_zero)
[GOAL]
θ : ℂ
h : (exp (θ * I) + exp (-θ * I)) / 2 = 0 ↔ exp (2 * θ * I) = -1
x : ℤ
⊢ ↑π * I + ↑x * (2 * ↑π * I) = 2 * I * ((2 * ↑x + 1) * ↑π / 2)
[PROOFSTEP]
field_simp
[GOAL]
θ : ℂ
h : (exp (θ * I) + exp (-θ * I)) / 2 = 0 ↔ exp (2 * θ * I) = -1
x : ℤ
⊢ (↑π * I + ↑x * (2 * ↑π * I)) * 2 = 2 * I * ((2 * ↑x + 1) * ↑π)
[PROOFSTEP]
ring
[GOAL]
θ : ℂ
⊢ cos θ ≠ 0 ↔ ∀ (k : ℤ), θ ≠ (2 * ↑k + 1) * ↑π / 2
[PROOFSTEP]
rw [← not_exists, not_iff_not, cos_eq_zero_iff]
[GOAL]
θ : ℂ
⊢ sin θ = 0 ↔ ∃ k, θ = ↑k * ↑π
[PROOFSTEP]
rw [← Complex.cos_sub_pi_div_two, cos_eq_zero_iff]
[GOAL]
θ : ℂ
⊢ (∃ k, θ - ↑π / 2 = (2 * ↑k + 1) * ↑π / 2) ↔ ∃ k, θ = ↑k * ↑π
[PROOFSTEP]
constructor
[GOAL]
case mp
θ : ℂ
⊢ (∃ k, θ - ↑π / 2 = (2 * ↑k + 1) * ↑π / 2) → ∃ k, θ = ↑k * ↑π
[PROOFSTEP]
rintro ⟨k, hk⟩
[GOAL]
case mp.intro
θ : ℂ
k : ℤ
hk : θ - ↑π / 2 = (2 * ↑k + 1) * ↑π / 2
⊢ ∃ k, θ = ↑k * ↑π
[PROOFSTEP]
use k + 1
[GOAL]
case h
θ : ℂ
k : ℤ
hk : θ - ↑π / 2 = (2 * ↑k + 1) * ↑π / 2
⊢ θ = ↑(k + 1) * ↑π
[PROOFSTEP]
field_simp [eq_add_of_sub_eq hk]
[GOAL]
case h
θ : ℂ
k : ℤ
hk : θ - ↑π / 2 = (2 * ↑k + 1) * ↑π / 2
⊢ (2 * ↑k + 1) * ↑π + ↑π = (↑k + 1) * ↑π * 2
[PROOFSTEP]
ring
[GOAL]
case mpr
θ : ℂ
⊢ (∃ k, θ = ↑k * ↑π) → ∃ k, θ - ↑π / 2 = (2 * ↑k + 1) * ↑π / 2
[PROOFSTEP]
rintro ⟨k, rfl⟩
[GOAL]
case mpr.intro
k : ℤ
⊢ ∃ k_1, ↑k * ↑π - ↑π / 2 = (2 * ↑k_1 + 1) * ↑π / 2
[PROOFSTEP]
use k - 1
[GOAL]
case h
k : ℤ
⊢ ↑k * ↑π - ↑π / 2 = (2 * ↑(k - 1) + 1) * ↑π / 2
[PROOFSTEP]
field_simp
[GOAL]
case h
k : ℤ
⊢ ↑k * ↑π * 2 - ↑π = (2 * (↑k - 1) + 1) * ↑π
[PROOFSTEP]
ring
[GOAL]
θ : ℂ
⊢ sin θ ≠ 0 ↔ ∀ (k : ℤ), θ ≠ ↑k * ↑π
[PROOFSTEP]
rw [← not_exists, not_iff_not, sin_eq_zero_iff]
[GOAL]
θ : ℂ
⊢ tan θ = 0 ↔ ∃ k, θ = ↑k * ↑π / 2
[PROOFSTEP]
have h := (sin_two_mul θ).symm
[GOAL]
θ : ℂ
h : 2 * sin θ * cos θ = sin (2 * θ)
⊢ tan θ = 0 ↔ ∃ k, θ = ↑k * ↑π / 2
[PROOFSTEP]
rw [mul_assoc] at h
[GOAL]
θ : ℂ
h : 2 * (sin θ * cos θ) = sin (2 * θ)
⊢ tan θ = 0 ↔ ∃ k, θ = ↑k * ↑π / 2
[PROOFSTEP]
rw [tan, div_eq_zero_iff, ← mul_eq_zero, ← zero_mul (1 / 2 : ℂ), mul_one_div,
  CancelDenoms.cancel_factors_eq_div h two_ne_zero, mul_comm]
[GOAL]
θ : ℂ
h : 2 * (sin θ * cos θ) = sin (2 * θ)
⊢ sin (θ * 2) / 2 = 0 / 2 ↔ ∃ k, θ = ↑k * ↑π / 2
[PROOFSTEP]
simpa only [zero_div, zero_mul, Ne.def, not_false_iff, field_simps] using sin_eq_zero_iff
[GOAL]
θ : ℂ
⊢ tan θ ≠ 0 ↔ ∀ (k : ℤ), θ ≠ ↑k * ↑π / 2
[PROOFSTEP]
rw [← not_exists, not_iff_not, tan_eq_zero_iff]
[GOAL]
n : ℤ
⊢ ∃ k, ↑n * ↑π / 2 = ↑k * ↑π / 2
[PROOFSTEP]
use n
[GOAL]
x y : ℂ
⊢ cos x - cos y = 0 ↔ -2 * sin ((x + y) / 2) * sin ((x - y) / 2) = 0
[PROOFSTEP]
rw [cos_sub_cos]
[GOAL]
x y : ℂ
⊢ -2 * sin ((x + y) / 2) * sin ((x - y) / 2) = 0 ↔ sin ((x + y) / 2) = 0 ∨ sin ((x - y) / 2) = 0
[PROOFSTEP]
simp [(by norm_num : (2 : ℂ) ≠ 0)]
[GOAL]
x y : ℂ
⊢ 2 ≠ 0
[PROOFSTEP]
norm_num
[GOAL]
x y : ℂ
⊢ sin ((x - y) / 2) = 0 ∨ sin ((x + y) / 2) = 0 ↔ (∃ k, y = 2 * ↑k * ↑π + x) ∨ ∃ k, y = 2 * ↑k * ↑π - x
[PROOFSTEP]
apply or_congr
[GOAL]
case h₁
x y : ℂ
⊢ sin ((x - y) / 2) = 0 ↔ ∃ k, y = 2 * ↑k * ↑π + x
[PROOFSTEP]
field_simp [sin_eq_zero_iff, (by norm_num : -(2 : ℂ) ≠ 0), eq_sub_iff_add_eq', sub_eq_iff_eq_add, mul_comm (2 : ℂ),
  mul_right_comm _ (2 : ℂ)]
[GOAL]
x y : ℂ
⊢ -2 ≠ 0
[PROOFSTEP]
norm_num
[GOAL]
case h₂
x y : ℂ
⊢ sin ((x + y) / 2) = 0 ↔ ∃ k, y = 2 * ↑k * ↑π - x
[PROOFSTEP]
field_simp [sin_eq_zero_iff, (by norm_num : -(2 : ℂ) ≠ 0), eq_sub_iff_add_eq', sub_eq_iff_eq_add, mul_comm (2 : ℂ),
  mul_right_comm _ (2 : ℂ)]
[GOAL]
x y : ℂ
⊢ -2 ≠ 0
[PROOFSTEP]
norm_num
[GOAL]
case h₁
x y : ℂ
⊢ (∃ k, x = ↑k * ↑π * 2 + y) ↔ ∃ k, y = ↑k * ↑π * 2 + x
[PROOFSTEP]
constructor
[GOAL]
case h₁.mp
x y : ℂ
⊢ (∃ k, x = ↑k * ↑π * 2 + y) → ∃ k, y = ↑k * ↑π * 2 + x
[PROOFSTEP]
rintro ⟨k, rfl⟩
[GOAL]
case h₁.mp.intro
y : ℂ
k : ℤ
⊢ ∃ k_1, y = ↑k_1 * ↑π * 2 + (↑k * ↑π * 2 + y)
[PROOFSTEP]
use-k
[GOAL]
case h
y : ℂ
k : ℤ
⊢ y = ↑(-k) * ↑π * 2 + (↑k * ↑π * 2 + y)
[PROOFSTEP]
simp
[GOAL]
case h₁.mpr
x y : ℂ
⊢ (∃ k, y = ↑k * ↑π * 2 + x) → ∃ k, x = ↑k * ↑π * 2 + y
[PROOFSTEP]
rintro ⟨k, rfl⟩
[GOAL]
case h₁.mpr.intro
x : ℂ
k : ℤ
⊢ ∃ k_1, x = ↑k_1 * ↑π * 2 + (↑k * ↑π * 2 + x)
[PROOFSTEP]
use-k
[GOAL]
case h
x : ℂ
k : ℤ
⊢ x = ↑(-k) * ↑π * 2 + (↑k * ↑π * 2 + x)
[PROOFSTEP]
simp
[GOAL]
x y : ℂ
⊢ sin x = sin y ↔ ∃ k, y = 2 * ↑k * ↑π + x ∨ y = (2 * ↑k + 1) * ↑π - x
[PROOFSTEP]
simp only [← Complex.cos_sub_pi_div_two, cos_eq_cos_iff, sub_eq_iff_eq_add]
[GOAL]
x y : ℂ
⊢ (∃ k, y = 2 * ↑k * ↑π + (x - ↑π / 2) + ↑π / 2 ∨ y = 2 * ↑k * ↑π - (x - ↑π / 2) + ↑π / 2) ↔
    ∃ k, y = 2 * ↑k * ↑π + x ∨ y = (2 * ↑k + 1) * ↑π - x
[PROOFSTEP]
refine' exists_congr fun k => or_congr _ _
[GOAL]
case refine'_1
x y : ℂ
k : ℤ
⊢ y = 2 * ↑k * ↑π + (x - ↑π / 2) + ↑π / 2 ↔ y = 2 * ↑k * ↑π + x
[PROOFSTEP]
refine' Eq.congr rfl _
[GOAL]
case refine'_2
x y : ℂ
k : ℤ
⊢ y = 2 * ↑k * ↑π - (x - ↑π / 2) + ↑π / 2 ↔ y = (2 * ↑k + 1) * ↑π - x
[PROOFSTEP]
refine' Eq.congr rfl _
[GOAL]
case refine'_1
x y : ℂ
k : ℤ
⊢ 2 * ↑k * ↑π + (x - ↑π / 2) + ↑π / 2 = 2 * ↑k * ↑π + x
[PROOFSTEP]
field_simp
[GOAL]
case refine'_2
x y : ℂ
k : ℤ
⊢ 2 * ↑k * ↑π - (x - ↑π / 2) + ↑π / 2 = (2 * ↑k + 1) * ↑π - x
[PROOFSTEP]
field_simp
[GOAL]
case refine'_1
x y : ℂ
k : ℤ
⊢ 2 * ↑k * ↑π * 2 + (x * 2 - ↑π) + ↑π = (2 * ↑k * ↑π + x) * 2
[PROOFSTEP]
ring
[GOAL]
case refine'_2
x y : ℂ
k : ℤ
⊢ 2 * ↑k * ↑π * 2 - (x * 2 - ↑π) + ↑π = ((2 * ↑k + 1) * ↑π - x) * 2
[PROOFSTEP]
ring
[GOAL]
x y : ℂ
h :
  ((∀ (k : ℤ), x ≠ (2 * ↑k + 1) * ↑π / 2) ∧ ∀ (l : ℤ), y ≠ (2 * ↑l + 1) * ↑π / 2) ∨
    (∃ k, x = (2 * ↑k + 1) * ↑π / 2) ∧ ∃ l, y = (2 * ↑l + 1) * ↑π / 2
⊢ tan (x + y) = (tan x + tan y) / (1 - tan x * tan y)
[PROOFSTEP]
rcases h with (⟨h1, h2⟩ | ⟨⟨k, rfl⟩, ⟨l, rfl⟩⟩)
[GOAL]
case inl.intro
x y : ℂ
h1 : ∀ (k : ℤ), x ≠ (2 * ↑k + 1) * ↑π / 2
h2 : ∀ (l : ℤ), y ≠ (2 * ↑l + 1) * ↑π / 2
⊢ tan (x + y) = (tan x + tan y) / (1 - tan x * tan y)
[PROOFSTEP]
rw [tan, sin_add, cos_add, ←
  div_div_div_cancel_right (sin x * cos y + cos x * sin y)
    (mul_ne_zero (cos_ne_zero_iff.mpr h1) (cos_ne_zero_iff.mpr h2)),
  add_div, sub_div]
[GOAL]
case inl.intro
x y : ℂ
h1 : ∀ (k : ℤ), x ≠ (2 * ↑k + 1) * ↑π / 2
h2 : ∀ (l : ℤ), y ≠ (2 * ↑l + 1) * ↑π / 2
⊢ (sin x * cos y / (cos x * cos y) + cos x * sin y / (cos x * cos y)) /
      (cos x * cos y / (cos x * cos y) - sin x * sin y / (cos x * cos y)) =
    (tan x + tan y) / (1 - tan x * tan y)
[PROOFSTEP]
simp only [← div_mul_div_comm, tan, mul_one, one_mul, div_self (cos_ne_zero_iff.mpr h1),
  div_self (cos_ne_zero_iff.mpr h2)]
[GOAL]
case inr.intro.intro.intro
k l : ℤ
⊢ tan ((2 * ↑k + 1) * ↑π / 2 + (2 * ↑l + 1) * ↑π / 2) =
    (tan ((2 * ↑k + 1) * ↑π / 2) + tan ((2 * ↑l + 1) * ↑π / 2)) /
      (1 - tan ((2 * ↑k + 1) * ↑π / 2) * tan ((2 * ↑l + 1) * ↑π / 2))
[PROOFSTEP]
haveI t := tan_int_mul_pi_div_two
[GOAL]
case inr.intro.intro.intro
k l : ℤ
t : ∀ (n : ℤ), tan (↑n * ↑π / 2) = 0
⊢ tan ((2 * ↑k + 1) * ↑π / 2 + (2 * ↑l + 1) * ↑π / 2) =
    (tan ((2 * ↑k + 1) * ↑π / 2) + tan ((2 * ↑l + 1) * ↑π / 2)) /
      (1 - tan ((2 * ↑k + 1) * ↑π / 2) * tan ((2 * ↑l + 1) * ↑π / 2))
[PROOFSTEP]
obtain ⟨hx, hy, hxy⟩ := t (2 * k + 1), t (2 * l + 1), t (2 * k + 1 + (2 * l + 1))
[GOAL]
case inr.intro.intro.intro
k l : ℤ
t : ∀ (n : ℤ), tan (↑n * ↑π / 2) = 0
hx : tan (↑(2 * k + 1) * ↑π / 2) = 0
hy : tan (↑(2 * l + 1) * ↑π / 2) = 0
hxy : tan (↑(2 * k + 1 + (2 * l + 1)) * ↑π / 2) = 0
⊢ tan ((2 * ↑k + 1) * ↑π / 2 + (2 * ↑l + 1) * ↑π / 2) =
    (tan ((2 * ↑k + 1) * ↑π / 2) + tan ((2 * ↑l + 1) * ↑π / 2)) /
      (1 - tan ((2 * ↑k + 1) * ↑π / 2) * tan ((2 * ↑l + 1) * ↑π / 2))
[PROOFSTEP]
simp only [Int.cast_add, Int.cast_two, Int.cast_mul, Int.cast_one, hx, hy] at hx hy hxy
[GOAL]
case inr.intro.intro.intro
k l : ℤ
t : ∀ (n : ℤ), tan (↑n * ↑π / 2) = 0
hx : tan ((2 * ↑k + 1) * ↑π / 2) = 0
hy : tan ((2 * ↑l + 1) * ↑π / 2) = 0
hxy : tan ((2 * ↑k + 1 + (2 * ↑l + 1)) * ↑π / 2) = 0
⊢ tan ((2 * ↑k + 1) * ↑π / 2 + (2 * ↑l + 1) * ↑π / 2) =
    (tan ((2 * ↑k + 1) * ↑π / 2) + tan ((2 * ↑l + 1) * ↑π / 2)) /
      (1 - tan ((2 * ↑k + 1) * ↑π / 2) * tan ((2 * ↑l + 1) * ↑π / 2))
[PROOFSTEP]
rw [hx, hy, add_zero, zero_div, mul_div_assoc, mul_div_assoc, ← add_mul (2 * (k : ℂ) + 1) (2 * l + 1) (π / 2), ←
  mul_div_assoc, hxy]
[GOAL]
z : ℂ
⊢ tan (2 * z) = 2 * tan z / (1 - tan z ^ 2)
[PROOFSTEP]
by_cases h : ∀ k : ℤ, z ≠ (2 * k + 1) * π / 2
[GOAL]
case pos
z : ℂ
h : ∀ (k : ℤ), z ≠ (2 * ↑k + 1) * ↑π / 2
⊢ tan (2 * z) = 2 * tan z / (1 - tan z ^ 2)
[PROOFSTEP]
rw [two_mul, two_mul, sq, tan_add (Or.inl ⟨h, h⟩)]
[GOAL]
case neg
z : ℂ
h : ¬∀ (k : ℤ), z ≠ (2 * ↑k + 1) * ↑π / 2
⊢ tan (2 * z) = 2 * tan z / (1 - tan z ^ 2)
[PROOFSTEP]
rw [not_forall_not] at h
[GOAL]
case neg
z : ℂ
h : ∃ x, z = (2 * ↑x + 1) * ↑π / 2
⊢ tan (2 * z) = 2 * tan z / (1 - tan z ^ 2)
[PROOFSTEP]
rw [two_mul, two_mul, sq, tan_add (Or.inr ⟨h, h⟩)]
[GOAL]
x y : ℂ
h :
  ((∀ (k : ℤ), x ≠ (2 * ↑k + 1) * ↑π / 2) ∧ ∀ (l : ℤ), y * I ≠ (2 * ↑l + 1) * ↑π / 2) ∨
    (∃ k, x = (2 * ↑k + 1) * ↑π / 2) ∧ ∃ l, y * I = (2 * ↑l + 1) * ↑π / 2
⊢ tan (x + y * I) = (tan x + tanh y * I) / (1 - tan x * tanh y * I)
[PROOFSTEP]
rw [tan_add h, tan_mul_I, mul_assoc]
[GOAL]
z : ℂ
h :
  ((∀ (k : ℤ), ↑z.re ≠ (2 * ↑k + 1) * ↑π / 2) ∧ ∀ (l : ℤ), ↑z.im * I ≠ (2 * ↑l + 1) * ↑π / 2) ∨
    (∃ k, ↑z.re = (2 * ↑k + 1) * ↑π / 2) ∧ ∃ l, ↑z.im * I = (2 * ↑l + 1) * ↑π / 2
⊢ tan z = (tan ↑z.re + tanh ↑z.im * I) / (1 - tan ↑z.re * tanh ↑z.im * I)
[PROOFSTEP]
convert tan_add_mul_I h
[GOAL]
case h.e'_2.h.e'_1
z : ℂ
h :
  ((∀ (k : ℤ), ↑z.re ≠ (2 * ↑k + 1) * ↑π / 2) ∧ ∀ (l : ℤ), ↑z.im * I ≠ (2 * ↑l + 1) * ↑π / 2) ∨
    (∃ k, ↑z.re = (2 * ↑k + 1) * ↑π / 2) ∧ ∃ l, ↑z.im * I = (2 * ↑l + 1) * ↑π / 2
⊢ z = ↑z.re + ↑z.im * I
[PROOFSTEP]
exact (re_add_im z).symm
[GOAL]
z w : ℂ
⊢ cos z = w ↔ exp (z * I) ^ 2 - 2 * w * exp (z * I) + 1 = 0
[PROOFSTEP]
rw [← sub_eq_zero]
[GOAL]
z w : ℂ
⊢ cos z - w = 0 ↔ exp (z * I) ^ 2 - 2 * w * exp (z * I) + 1 = 0
[PROOFSTEP]
field_simp [cos, exp_neg, exp_ne_zero]
[GOAL]
z w : ℂ
⊢ exp (z * I) * exp (z * I) + 1 - exp (z * I) * 2 * w = 0 ↔ exp (z * I) ^ 2 - 2 * w * exp (z * I) + 1 = 0
[PROOFSTEP]
refine' Eq.congr _ rfl
[GOAL]
z w : ℂ
⊢ exp (z * I) * exp (z * I) + 1 - exp (z * I) * 2 * w = exp (z * I) ^ 2 - 2 * w * exp (z * I) + 1
[PROOFSTEP]
ring
[GOAL]
⊢ Function.Surjective cos
[PROOFSTEP]
intro x
[GOAL]
x : ℂ
⊢ ∃ a, cos a = x
[PROOFSTEP]
obtain ⟨w, w₀, hw⟩ : ∃ (w : _) (_ : w ≠ 0), 1 * w * w + -2 * x * w + 1 = 0 :=
  by
  rcases exists_quadratic_eq_zero one_ne_zero ⟨_, (cpow_nat_inv_pow _ two_ne_zero).symm.trans <| pow_two _⟩ with ⟨w, hw⟩
  refine' ⟨w, _, hw⟩
  rintro rfl
  simp only [zero_add, one_ne_zero, mul_zero] at hw
[GOAL]
x : ℂ
⊢ ∃ w x_1, 1 * w * w + -2 * x * w + 1 = 0
[PROOFSTEP]
rcases exists_quadratic_eq_zero one_ne_zero ⟨_, (cpow_nat_inv_pow _ two_ne_zero).symm.trans <| pow_two _⟩ with ⟨w, hw⟩
[GOAL]
case intro
x w : ℂ
hw : 1 * w * w + ?m.63171 * w + ?m.63172 = 0
⊢ ∃ w x_1, 1 * w * w + -2 * x * w + 1 = 0
[PROOFSTEP]
refine' ⟨w, _, hw⟩
[GOAL]
case intro
x w : ℂ
hw : 1 * w * w + -2 * x * w + 1 = 0
⊢ w ≠ 0
[PROOFSTEP]
rintro rfl
[GOAL]
case intro
x : ℂ
hw : 1 * 0 * 0 + -2 * x * 0 + 1 = 0
⊢ False
[PROOFSTEP]
simp only [zero_add, one_ne_zero, mul_zero] at hw
[GOAL]
case intro.intro
x w : ℂ
w₀ : w ≠ 0
hw : 1 * w * w + -2 * x * w + 1 = 0
⊢ ∃ a, cos a = x
[PROOFSTEP]
refine' ⟨log w / I, cos_eq_iff_quadratic.2 _⟩
[GOAL]
case intro.intro
x w : ℂ
w₀ : w ≠ 0
hw : 1 * w * w + -2 * x * w + 1 = 0
⊢ exp (log w / I * I) ^ 2 - 2 * x * exp (log w / I * I) + 1 = 0
[PROOFSTEP]
rw [div_mul_cancel _ I_ne_zero, exp_log w₀]
[GOAL]
case intro.intro
x w : ℂ
w₀ : w ≠ 0
hw : 1 * w * w + -2 * x * w + 1 = 0
⊢ w ^ 2 - 2 * x * w + 1 = 0
[PROOFSTEP]
convert hw using 1
[GOAL]
case h.e'_2
x w : ℂ
w₀ : w ≠ 0
hw : 1 * w * w + -2 * x * w + 1 = 0
⊢ w ^ 2 - 2 * x * w + 1 = 1 * w * w + -2 * x * w + 1
[PROOFSTEP]
ring
[GOAL]
⊢ Function.Surjective sin
[PROOFSTEP]
intro x
[GOAL]
x : ℂ
⊢ ∃ a, sin a = x
[PROOFSTEP]
rcases cos_surjective x with ⟨z, rfl⟩
[GOAL]
case intro
z : ℂ
⊢ ∃ a, sin a = cos z
[PROOFSTEP]
exact ⟨z + π / 2, sin_add_pi_div_two z⟩
[GOAL]
θ : ℝ
⊢ cos θ = 0 ↔ ∃ k, θ = (2 * ↑k + 1) * π / 2
[PROOFSTEP]
exact_mod_cast @Complex.cos_eq_zero_iff θ
[GOAL]
θ : ℝ
⊢ cos θ ≠ 0 ↔ ∀ (k : ℤ), θ ≠ (2 * ↑k + 1) * π / 2
[PROOFSTEP]
rw [← not_exists, not_iff_not, cos_eq_zero_iff]
[GOAL]
x y : ℝ
⊢ cos x = cos y ↔ ∃ k, y = 2 * ↑k * π + x ∨ y = 2 * ↑k * π - x
[PROOFSTEP]
exact_mod_cast @Complex.cos_eq_cos_iff x y
[GOAL]
x y : ℝ
⊢ sin x = sin y ↔ ∃ k, y = 2 * ↑k * π + x ∨ y = (2 * ↑k + 1) * π - x
[PROOFSTEP]
exact_mod_cast @Complex.sin_eq_sin_iff x y
[GOAL]
x : ℝ
hx : 0 < x
hx' : x < 1
⊢ x < sin (π / 2 * x)
[PROOFSTEP]
simpa [mul_comm x] using
  strictConcaveOn_sin_Icc.2 ⟨le_rfl, pi_pos.le⟩ ⟨pi_div_two_pos.le, half_le_self pi_pos.le⟩ pi_div_two_pos.ne
    (sub_pos.2 hx') hx
[GOAL]
x : ℝ
hx : 0 ≤ x
hx' : x ≤ 1
⊢ x ≤ sin (π / 2 * x)
[PROOFSTEP]
simpa [mul_comm x] using
  strictConcaveOn_sin_Icc.concaveOn.2 ⟨le_rfl, pi_pos.le⟩ ⟨pi_div_two_pos.le, half_le_self pi_pos.le⟩ (sub_nonneg.2 hx')
    hx
[GOAL]
x : ℝ
hx : 0 < x
hx' : x < π / 2
⊢ 2 / π * x < sin x
[PROOFSTEP]
rw [← inv_div]
[GOAL]
x : ℝ
hx : 0 < x
hx' : x < π / 2
⊢ (π / 2)⁻¹ * x < sin x
[PROOFSTEP]
simpa [-inv_div, mul_inv_cancel_left₀ pi_div_two_pos.ne'] using
  @lt_sin_mul ((π / 2)⁻¹ * x) (mul_pos (inv_pos.2 pi_div_two_pos) hx)
    (by rwa [← div_eq_inv_mul, div_lt_one pi_div_two_pos])
[GOAL]
x : ℝ
hx : 0 < x
hx' : x < π / 2
⊢ (π / 2)⁻¹ * x < 1
[PROOFSTEP]
rwa [← div_eq_inv_mul, div_lt_one pi_div_two_pos]
[GOAL]
x : ℝ
hx : 0 ≤ x
hx' : x ≤ π / 2
⊢ 2 / π * x ≤ sin x
[PROOFSTEP]
rw [← inv_div]
[GOAL]
x : ℝ
hx : 0 ≤ x
hx' : x ≤ π / 2
⊢ (π / 2)⁻¹ * x ≤ sin x
[PROOFSTEP]
simpa [-inv_div, mul_inv_cancel_left₀ pi_div_two_pos.ne'] using
  @le_sin_mul ((π / 2)⁻¹ * x) (mul_nonneg (inv_nonneg.2 pi_div_two_pos.le) hx)
    (by rwa [← div_eq_inv_mul, div_le_one pi_div_two_pos])
[GOAL]
x : ℝ
hx : 0 ≤ x
hx' : x ≤ π / 2
⊢ (π / 2)⁻¹ * x ≤ 1
[PROOFSTEP]
rwa [← div_eq_inv_mul, div_le_one pi_div_two_pos]


[GOAL]
𝕜 : Type u_1
inst✝² : NontriviallyNormedField 𝕜
E : Type u_2
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f : 𝕜 →ᵃ[𝕜] E
a b : E
L : Filter 𝕜
s : Set 𝕜
x : 𝕜
⊢ HasStrictDerivAt (↑f) (↑f.linear 1) x
[PROOFSTEP]
rw [f.decomp]
[GOAL]
𝕜 : Type u_1
inst✝² : NontriviallyNormedField 𝕜
E : Type u_2
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f : 𝕜 →ᵃ[𝕜] E
a b : E
L : Filter 𝕜
s : Set 𝕜
x : 𝕜
⊢ HasStrictDerivAt (↑f.linear + fun x => ↑f 0) (↑f.linear 1) x
[PROOFSTEP]
exact f.linear.hasStrictDerivAt.add_const (f 0)
[GOAL]
𝕜 : Type u_1
inst✝² : NontriviallyNormedField 𝕜
E : Type u_2
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f : 𝕜 →ᵃ[𝕜] E
a b : E
L : Filter 𝕜
s : Set 𝕜
x : 𝕜
⊢ HasDerivAtFilter (↑f) (↑f.linear 1) x L
[PROOFSTEP]
rw [f.decomp]
[GOAL]
𝕜 : Type u_1
inst✝² : NontriviallyNormedField 𝕜
E : Type u_2
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f : 𝕜 →ᵃ[𝕜] E
a b : E
L : Filter 𝕜
s : Set 𝕜
x : 𝕜
⊢ HasDerivAtFilter (↑f.linear + fun x => ↑f 0) (↑f.linear 1) x L
[PROOFSTEP]
exact f.linear.hasDerivAtFilter.add_const (f 0)
[GOAL]
𝕜 : Type u_1
inst✝² : NontriviallyNormedField 𝕜
E : Type u_2
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f : 𝕜 →ᵃ[𝕜] E
a b : E
L : Filter 𝕜
s : Set 𝕜
x : 𝕜
⊢ HasStrictDerivAt (↑(lineMap a b)) (b - a) x
[PROOFSTEP]
simpa using (lineMap a b : 𝕜 →ᵃ[𝕜] E).hasStrictDerivAt


[GOAL]
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝ : Group G
a b : G
⊢ (fun b => b⁻¹ * a) ((fun b => a / b) b) = b
[PROOFSTEP]
simp [div_eq_mul_inv]
[GOAL]
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝ : Group G
a b : G
⊢ (fun b => a / b) ((fun b => b⁻¹ * a) b) = b
[PROOFSTEP]
simp [div_eq_mul_inv]
[GOAL]
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝ : Group G
a b : G
⊢ (fun b => b * a) ((fun b => b / a) b) = b
[PROOFSTEP]
simp [div_eq_mul_inv]
[GOAL]
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝ : Group G
a b : G
⊢ (fun b => b / a) ((fun b => b * a) b) = b
[PROOFSTEP]
simp [div_eq_mul_inv]


[GOAL]
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
⊢ (gcd s fun b => f b / gcd s f) = 1
[PROOFSTEP]
obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
[GOAL]
case intro.intro
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℕ
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
⊢ (gcd s fun b => f b / gcd s f) = 1
[PROOFSTEP]
refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
[GOAL]
case intro.intro
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℕ
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ f a / gcd s f = g a
[PROOFSTEP]
rw [he a ha, Nat.mul_div_cancel_left]
[GOAL]
case intro.intro.H
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℕ
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ 0 < gcd s f
[PROOFSTEP]
exact Nat.pos_of_ne_zero (mt Finset.gcd_eq_zero_iff.1 fun h => hfz <| h x hx)
[GOAL]
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
⊢ (gcd s fun b => f b / gcd s f) = 1
[PROOFSTEP]
obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
[GOAL]
case intro.intro
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℤ
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
⊢ (gcd s fun b => f b / gcd s f) = 1
[PROOFSTEP]
refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
[GOAL]
case intro.intro
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℤ
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ f a / gcd s f = g a
[PROOFSTEP]
rw [he a ha, Int.mul_ediv_cancel_left]
[GOAL]
case intro.intro.H
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℤ
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ gcd s f ≠ 0
[PROOFSTEP]
exact mt Finset.gcd_eq_zero_iff.1 fun h => hfz <| h x hx
[GOAL]
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
⊢ (gcd s fun b => f b / gcd s f) = 1
[PROOFSTEP]
obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
[GOAL]
case intro.intro
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → Polynomial K
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
⊢ (gcd s fun b => f b / gcd s f) = 1
[PROOFSTEP]
refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
[GOAL]
case intro.intro
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → Polynomial K
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ f a / gcd s f = g a
[PROOFSTEP]
rw [he a ha, EuclideanDomain.mul_div_cancel_left]
[GOAL]
case intro.intro.a0
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → Polynomial K
he : ∀ (b : β), b ∈ s → f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ gcd s f ≠ 0
[PROOFSTEP]
exact mt Finset.gcd_eq_zero_iff.1 fun h => hfz <| h x hx


[GOAL]
α : Type u_1
E : Type u_2
inst✝ : SeminormedAddCommGroup E
s t : Set α
f✝ : α → E
a✝ : α
h : s ⊆ t
f : α → E
a : α
⊢ ‖indicator s f a‖ ≤ ‖indicator t f a‖
[PROOFSTEP]
simp only [norm_indicator_eq_indicator_norm]
[GOAL]
α : Type u_1
E : Type u_2
inst✝ : SeminormedAddCommGroup E
s t : Set α
f✝ : α → E
a✝ : α
h : s ⊆ t
f : α → E
a : α
⊢ indicator s (fun a => ‖f a‖) a ≤ indicator t (fun a => ‖f a‖) a
[PROOFSTEP]
exact indicator_le_indicator_of_subset ‹_› (fun _ => norm_nonneg _) _
[GOAL]
α : Type u_1
E : Type u_2
inst✝ : SeminormedAddCommGroup E
s t : Set α
f : α → E
a : α
⊢ ‖indicator s f a‖ ≤ ‖f a‖
[PROOFSTEP]
rw [norm_indicator_eq_indicator_norm]
[GOAL]
α : Type u_1
E : Type u_2
inst✝ : SeminormedAddCommGroup E
s t : Set α
f : α → E
a : α
⊢ indicator s (fun a => ‖f a‖) a ≤ ‖f a‖
[PROOFSTEP]
apply indicator_norm_le_norm_self


[GOAL]
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
n : ℤ
h : ↑n = 0
⊢ n = 0
[PROOFSTEP]
cases n
[GOAL]
case ofNat
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
a✝ : ℕ
h : ↑(ofNat a✝) = 0
⊢ ofNat a✝ = 0
[PROOFSTEP]
erw [Int.cast_ofNat] at h
[GOAL]
case ofNat
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
a✝ : ℕ
h : ↑a✝ = 0
⊢ ofNat a✝ = 0
[PROOFSTEP]
exact congr_arg _ (Nat.cast_eq_zero.1 h)
[GOAL]
case negSucc
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
a✝ : ℕ
h : ↑-[a✝+1] = 0
⊢ -[a✝+1] = 0
[PROOFSTEP]
rw [cast_negSucc, neg_eq_zero, Nat.cast_eq_zero] at h
[GOAL]
case negSucc
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
a✝ : ℕ
h : a✝ + 1 = 0
⊢ -[a✝+1] = 0
[PROOFSTEP]
contradiction
[GOAL]
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
n : ℤ
h : n = 0
⊢ ↑n = 0
[PROOFSTEP]
rw [h, cast_zero]
[GOAL]
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
m n : ℤ
⊢ ↑m = ↑n ↔ m = n
[PROOFSTEP]
rw [← sub_eq_zero, ← cast_sub, cast_eq_zero, sub_eq_zero]
[GOAL]
α : Type u_1
inst✝¹ : AddGroupWithOne α
inst✝ : CharZero α
n : ℤ
⊢ ↑n = 1 ↔ n = 1
[PROOFSTEP]
rw [← cast_one, cast_inj]
[GOAL]
α : Type u_1
k : Type u_2
inst✝¹ : DivisionRing k
inst✝ : CharZero k
m n : ℤ
n_dvd : n ∣ m
⊢ ↑(m / n) = ↑m / ↑n
[PROOFSTEP]
rcases eq_or_ne n 0 with (rfl | hn)
[GOAL]
case inl
α : Type u_1
k : Type u_2
inst✝¹ : DivisionRing k
inst✝ : CharZero k
m : ℤ
n_dvd : 0 ∣ m
⊢ ↑(m / 0) = ↑m / ↑0
[PROOFSTEP]
simp [Int.ediv_zero]
[GOAL]
case inr
α : Type u_1
k : Type u_2
inst✝¹ : DivisionRing k
inst✝ : CharZero k
m n : ℤ
n_dvd : n ∣ m
hn : n ≠ 0
⊢ ↑(m / n) = ↑m / ↑n
[PROOFSTEP]
exact cast_div n_dvd (cast_ne_zero.mpr hn)