l3lab/ntp-mathlib huggingface dataset:
/-- A positive solution is a generator (up to sign) of the group of all solutions to the
Pell equation `x^2 - d*y^2 = 1` if and only if it is a fundamental solution. -/
theorem pos_generator_iff_fundamental (a : Solution₁ d) :
    (1 < a.x ∧ 0 < a.y ∧ ∀ b : Solution₁ d, ∃ n : ℤ, b = a ^ n ∨ b = -a ^ n) ↔ IsFundamental a := by
  refine' ⟨fun h => _, fun H => ⟨H.1, H.2.1, H.eq_zpow_or_neg_zpow⟩⟩
  

Proof state:
d : ℤ
a : Solution₁ d
h : 1 < Solution₁.x a ∧ 0 < Solution₁.y a ∧ ∀ (b : Solution₁ d), ∃ n, b = a ^ n ∨ b = -a ^ n
⊢ IsFundamental a

Next tactic:
have h₀ := d_pos_of_one_lt_x h.1
/-- A positive solution is a generator (up to sign) of the group of all solutions to the
Pell equation `x^2 - d*y^2 = 1` if and only if it is a fundamental solution. -/
theorem pos_generator_iff_fundamental (a : Solution₁ d) :
    (1 < a.x ∧ 0 < a.y ∧ ∀ b : Solution₁ d, ∃ n : ℤ, b = a ^ n ∨ b = -a ^ n) ↔ IsFundamental a := by
  refine' ⟨fun h => _, fun H => ⟨H.1, H.2.1, H.eq_zpow_or_neg_zpow⟩⟩
  have h₀ := d_pos_of_one_lt_x h.1
  

Proof state:
d : ℤ
a : Solution₁ d
h : 1 < Solution₁.x a ∧ 0 < Solution₁.y a ∧ ∀ (b : Solution₁ d), ∃ n, b = a ^ n ∨ b = -a ^ n
h₀ : 0 < d
⊢ IsFundamental a

Next tactic:
have hd := d_nonsquare_of_one_lt_x h.1
/-- A positive solution is a generator (up to sign) of the group of all solutions to the
Pell equation `x^2 - d*y^2 = 1` if and only if it is a fundamental solution. -/
theorem pos_generator_iff_fundamental (a : Solution₁ d) :
    (1 < a.x ∧ 0 < a.y ∧ ∀ b : Solution₁ d, ∃ n : ℤ, b = a ^ n ∨ b = -a ^ n) ↔ IsFundamental a := by
  refine' ⟨fun h => _, fun H => ⟨H.1, H.2.1, H.eq_zpow_or_neg_zpow⟩⟩
  have h₀ := d_pos_of_one_lt_x h.1
  have hd := d_nonsquare_of_one_lt_x h.1
  

Proof state:
d : ℤ
a : Solution₁ d
h : 1 < Solution₁.x a ∧ 0 < Solution₁.y a ∧ ∀ (b : Solution₁ d), ∃ n, b = a ^ n ∨ b = -a ^ n
h₀ : 0 < d
hd : ¬IsSquare d
⊢ IsFundamental a

Next tactic:
obtain ⟨a₁, ha₁⟩ := IsFundamental.exists_of_not_isSquare h₀ hd
/-- A positive solution is a generator (up to sign) of the group of all solutions to the
Pell equation `x^2 - d*y^2 = 1` if and only if it is a fundamental solution. -/
theorem pos_generator_iff_fundamental (a : Solution₁ d) :
    (1 < a.x ∧ 0 < a.y ∧ ∀ b : Solution₁ d, ∃ n : ℤ, b = a ^ n ∨ b = -a ^ n) ↔ IsFundamental a := by
  refine' ⟨fun h => _, fun H => ⟨H.1, H.2.1, H.eq_zpow_or_neg_zpow⟩⟩
  have h₀ := d_pos_of_one_lt_x h.1
  have hd := d_nonsquare_of_one_lt_x h.1
  obtain ⟨a₁, ha₁⟩ := IsFundamental.exists_of_not_isSquare h₀ hd
  

Proof state:
case intro
d : ℤ
a : Solution₁ d
h : 1 < Solution₁.x a ∧ 0 < Solution₁.y a ∧ ∀ (b : Solution₁ d), ∃ n, b = a ^ n ∨ b = -a ^ n
h₀ : 0 < d
hd : ¬IsSquare d
a₁ : Solution₁ d
ha₁ : IsFundamental a₁
⊢ IsFundamental a

Next tactic:
obtain ⟨b, -, hb₂⟩ := existsUnique_pos_generator h₀ hd
/-- A positive solution is a generator (up to sign) of the group of all solutions to the
Pell equation `x^2 - d*y^2 = 1` if and only if it is a fundamental solution. -/
theorem pos_generator_iff_fundamental (a : Solution₁ d) :
    (1 < a.x ∧ 0 < a.y ∧ ∀ b : Solution₁ d, ∃ n : ℤ, b = a ^ n ∨ b = -a ^ n) ↔ IsFundamental a := by
  refine' ⟨fun h => _, fun H => ⟨H.1, H.2.1, H.eq_zpow_or_neg_zpow⟩⟩
  have h₀ := d_pos_of_one_lt_x h.1
  have hd := d_nonsquare_of_one_lt_x h.1
  obtain ⟨a₁, ha₁⟩ := IsFundamental.exists_of_not_isSquare h₀ hd
  obtain ⟨b, -, hb₂⟩ := existsUnique_pos_generator h₀ hd
  

Proof state:
case intro.intro.intro
d : ℤ
a : Solution₁ d
h : 1 < Solution₁.x a ∧ 0 < Solution₁.y a ∧ ∀ (b : Solution₁ d), ∃ n, b = a ^ n ∨ b = -a ^ n
h₀ : 0 < d
hd : ¬IsSquare d
a₁ : Solution₁ d
ha₁ : IsFundamental a₁
b : Solution₁ d
hb₂ :
  ∀ (y : Solution₁ d),
    (fun a₁ => 1 < Solution₁.x a₁ ∧ 0 < Solution₁.y a₁ ∧ ∀ (a : Solution₁ d), ∃ n, a = a₁ ^ n ∨ a = -a₁ ^ n) y → y = b
⊢ IsFundamental a

Next tactic:
rwa [hb₂ a h, ← hb₂ a₁ ⟨ha₁.1, ha₁.2.1, ha₁.eq_zpow_or_neg_zpow⟩]
@[simp]
theorem idRel_subset {s : Set (α × α)} : idRel ⊆ s ↔ ∀ a, (a, a) ∈ s := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
s : Set (α × α)
⊢ idRel ⊆ s ↔ ∀ (a : α), (a, a) ∈ s

Next tactic:
simp [subset_def]
@[simp]
theorem swap_idRel : Prod.swap '' idRel = @idRel α :=
  Set.ext fun ⟨a, b⟩ => by 

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
x✝ : α × α
a b : α
⊢ (a, b) ∈ Prod.swap '' idRel ↔ (a, b) ∈ idRel

Next tactic:
simpa [image_swap_eq_preimage_swap] using eq_comm
@[simp]
theorem id_compRel {r : Set (α × α)} : idRel ○ r = r :=
  Set.ext fun ⟨a, b⟩ => by 

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
r : Set (α × α)
x✝ : α × α
a b : α
⊢ (a, b) ∈ idRel ○ r ↔ (a, b) ∈ r

Next tactic:
simp
theorem compRel_assoc {r s t : Set (α × α)} : r ○ s ○ t = r ○ (s ○ t) := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
r s t : Set (α × α)
⊢ r ○ s ○ t = r ○ (s ○ t)

Next tactic:
ext ⟨a, b⟩
theorem compRel_assoc {r s t : Set (α × α)} : r ○ s ○ t = r ○ (s ○ t) := by
  ext ⟨a, b⟩; 

Proof state:
case h.mk
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
r s t : Set (α × α)
a b : α
⊢ (a, b) ∈ r ○ s ○ t ↔ (a, b) ∈ r ○ (s ○ t)

Next tactic:
simp only [mem_compRel]
theorem compRel_assoc {r s t : Set (α × α)} : r ○ s ○ t = r ○ (s ○ t) := by
  ext ⟨a, b⟩; simp only [mem_compRel]; 

Proof state:
case h.mk
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
r s t : Set (α × α)
a b : α
⊢ (∃ z, (∃ z_1, (a, z_1) ∈ r ∧ (z_1, z) ∈ s) ∧ (z, b) ∈ t) ↔ ∃ z, (a, z) ∈ r ∧ ∃ z_1, (z, z_1) ∈ s ∧ (z_1, b) ∈ t

Next tactic:
tauto
theorem subset_iterate_compRel {s t : Set (α × α)} (h : idRel ⊆ s) (n : ℕ) :
    t ⊆ (s ○ ·)^[n] t := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
s t : Set (α × α)
h : idRel ⊆ s
n : ℕ
⊢ t ⊆ (fun x => s ○ x)^[n] t

Next tactic:
induction' n with n ihn generalizing t
theorem subset_iterate_compRel {s t : Set (α × α)} (h : idRel ⊆ s) (n : ℕ) :
    t ⊆ (s ○ ·)^[n] t := by
  induction' n with n ihn generalizing t
  

Proof state:
case zero
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
s : Set (α × α)
h : idRel ⊆ s
t : Set (α × α)
⊢ t ⊆ (fun x => s ○ x)^[Nat.zero] t
case succ
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
s : Set (α × α)
h : idRel ⊆ s
n : ℕ
ihn : ∀ {t : Set (α × α)}, t ⊆ (fun x => s ○ x)^[n] t
t : Set (α × α)
⊢ t ⊆ (fun x => s ○ x)^[Nat.succ n] t

Next tactic:
exacts [Subset.rfl, (right_subset_compRel h).trans ihn]
theorem symmetric_symmetrizeRel (V : Set (α × α)) : SymmetricRel (symmetrizeRel V) := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
V : Set (α × α)
⊢ SymmetricRel (symmetrizeRel V)

Next tactic:
simp [SymmetricRel, symmetrizeRel, preimage_inter, inter_comm, ← preimage_comp]
theorem SymmetricRel.inter {U V : Set (α × α)} (hU : SymmetricRel U) (hV : SymmetricRel V) :
    SymmetricRel (U ∩ V) := by 

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
U V : Set (α × α)
hU : SymmetricRel U
hV : SymmetricRel V
⊢ SymmetricRel (U ∩ V)

Next tactic:
rw [SymmetricRel, preimage_inter, hU.eq, hV.eq]
/-- A uniform space generates a topological space -/
def UniformSpace.Core.toTopologicalSpace {α : Type u} (u : UniformSpace.Core α) :
    TopologicalSpace α where
  IsOpen s := ∀ x ∈ s, { p : α × α | p.1 = x → p.2 ∈ s } ∈ u.uniformity
  isOpen_univ := by 

Proof state:
α✝ : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
α : Type u
u : Core α
⊢ (fun s => ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u.uniformity) univ

Next tactic:
simp
/-- A uniform space generates a topological space -/
def UniformSpace.Core.toTopologicalSpace {α : Type u} (u : UniformSpace.Core α) :
    TopologicalSpace α where
  IsOpen s := ∀ x ∈ s, { p : α × α | p.1 = x → p.2 ∈ s } ∈ u.uniformity
  isOpen_univ := by simp
  isOpen_inter := fun s t hs ht x ⟨xs, xt⟩ => by
    

Proof state:
α✝ : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
α : Type u
u : Core α
s t : Set α
hs : (fun s => ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u.uniformity) s
ht : (fun s => ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u.uniformity) t
x : α
x✝ : x ∈ s ∩ t
xs : x ∈ s
xt : x ∈ t
⊢ {p | p.1 = x → p.2 ∈ s ∩ t} ∈ u.uniformity

Next tactic:
filter_upwards [hs x xs, ht x xt] with x hxs hxt hx using ⟨hxs hx, hxt hx⟩
/-- A uniform space generates a topological space -/
def UniformSpace.Core.toTopologicalSpace {α : Type u} (u : UniformSpace.Core α) :
    TopologicalSpace α where
  IsOpen s := ∀ x ∈ s, { p : α × α | p.1 = x → p.2 ∈ s } ∈ u.uniformity
  isOpen_univ := by simp
  isOpen_inter := fun s t hs ht x ⟨xs, xt⟩ => by
    filter_upwards [hs x xs, ht x xt] with x hxs hxt hx using ⟨hxs hx, hxt hx⟩
  isOpen_sUnion := fun s hs x ⟨t, ts, xt⟩ => by
    

Proof state:
α✝ : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
α : Type u
u : Core α
s : Set (Set α)
hs : ∀ t ∈ s, (fun s => ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u.uniformity) t
x : α
x✝ : x ∈ ⋃₀ s
t : Set α
ts : t ∈ s
xt : x ∈ t
⊢ {p | p.1 = x → p.2 ∈ ⋃₀ s} ∈ u.uniformity

Next tactic:
filter_upwards [hs t ts x xt] with p ph h using ⟨t, ts, ph h⟩
/-- An alternative constructor for `UniformSpace` that takes the proof of `nhds_eq_comap_uniformity`
as an argument. -/
@[reducible]
def UniformSpace.ofNhdsEqComap (u : UniformSpace.Core α) (t : TopologicalSpace α)
    (h : ∀ x, 𝓝 x = u.uniformity.comap (Prod.mk x)) : UniformSpace α where
  toCore := u
  toTopologicalSpace := t
  isOpen_uniformity := fun u => by 

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
u✝ : Core α
t : TopologicalSpace α
h : ∀ (x : α), 𝓝 x = comap (Prod.mk x) u✝.uniformity
u : Set α
⊢ IsOpen u ↔ ∀ x ∈ u, {p | p.1 = x → p.2 ∈ u} ∈ u✝.uniformity

Next tactic:
simp only [isOpen_iff_mem_nhds, h, mem_comap_prod_mk]
@[ext]
protected theorem UniformSpace.ext : ∀ {u₁ u₂ : UniformSpace α}, 𝓤[u₁] = 𝓤[u₂] → u₁ = u₂
  | .mk' t₁ u₁ o₁, .mk' t₂ u₂ o₂, h => by
    

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
t₁ : TopologicalSpace α
u₁ : Core α
o₁ : ∀ (s : Set α), IsOpen s ↔ ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u₁.uniformity
t₂ : TopologicalSpace α
u₂ : Core α
o₂ : ∀ (s : Set α), IsOpen s ↔ ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u₂.uniformity
h : uniformity α = uniformity α
⊢ mk' t₁ u₁ o₁ = mk' t₂ u₂ o₂

Next tactic:
obtain rfl : u₁ = u₂ := UniformSpace.Core.ext h
@[ext]
protected theorem UniformSpace.ext : ∀ {u₁ u₂ : UniformSpace α}, 𝓤[u₁] = 𝓤[u₂] → u₁ = u₂
  | .mk' t₁ u₁ o₁, .mk' t₂ u₂ o₂, h => by
    obtain rfl : u₁ = u₂ := UniformSpace.Core.ext h
    

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
t₁ : TopologicalSpace α
u₁ : Core α
o₁ : ∀ (s : Set α), IsOpen s ↔ ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u₁.uniformity
t₂ : TopologicalSpace α
o₂ : ∀ (s : Set α), IsOpen s ↔ ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u₁.uniformity
h : uniformity α = uniformity α
⊢ mk' t₁ u₁ o₁ = mk' t₂ u₁ o₂

Next tactic:
obtain rfl : t₁ = t₂ := TopologicalSpace.ext <| funext fun s => by rw [o₁, o₂]
@[ext]
protected theorem UniformSpace.ext : ∀ {u₁ u₂ : UniformSpace α}, 𝓤[u₁] = 𝓤[u₂] → u₁ = u₂
  | .mk' t₁ u₁ o₁, .mk' t₂ u₂ o₂, h => by
    obtain rfl : u₁ = u₂ := UniformSpace.Core.ext h
    obtain rfl : t₁ = t₂ := TopologicalSpace.ext <| funext fun s => by 

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
t₁ : TopologicalSpace α
u₁ : Core α
o₁ : ∀ (s : Set α), IsOpen s ↔ ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u₁.uniformity
t₂ : TopologicalSpace α
o₂ : ∀ (s : Set α), IsOpen s ↔ ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u₁.uniformity
h : uniformity α = uniformity α
s : Set α
⊢ IsOpen s = IsOpen s

Next tactic:
rw [o₁, o₂]
@[ext]
protected theorem UniformSpace.ext : ∀ {u₁ u₂ : UniformSpace α}, 𝓤[u₁] = 𝓤[u₂] → u₁ = u₂
  | .mk' t₁ u₁ o₁, .mk' t₂ u₂ o₂, h => by
    obtain rfl : u₁ = u₂ := UniformSpace.Core.ext h
    obtain rfl : t₁ = t₂ := TopologicalSpace.ext <| funext fun s => by rw [o₁, o₂]
    

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
t₁ : TopologicalSpace α
u₁ : Core α
o₁ o₂ : ∀ (s : Set α), IsOpen s ↔ ∀ x ∈ s, {p | p.1 = x → p.2 ∈ s} ∈ u₁.uniformity
h : uniformity α = uniformity α
⊢ mk' t₁ u₁ o₁ = mk' t₁ u₁ o₂

Next tactic:
rfl
protected theorem UniformSpace.ext_iff {u₁ u₂ : UniformSpace α} :
    u₁ = u₂ ↔ ∀ s, s ∈ 𝓤[u₁] ↔ s ∈ 𝓤[u₂] :=
  ⟨fun h _ => h ▸ Iff.rfl, fun h => by 

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
u₁ u₂ : UniformSpace α
h : ∀ (s : Set (α × α)), s ∈ uniformity α ↔ s ∈ uniformity α
⊢ u₁ = u₂

Next tactic:
ext
protected theorem UniformSpace.ext_iff {u₁ u₂ : UniformSpace α} :
    u₁ = u₂ ↔ ∀ s, s ∈ 𝓤[u₁] ↔ s ∈ 𝓤[u₂] :=
  ⟨fun h _ => h ▸ Iff.rfl, fun h => by ext; 

Proof state:
case a.a
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
u₁ u₂ : UniformSpace α
h : ∀ (s : Set (α × α)), s ∈ uniformity α ↔ s ∈ uniformity α
s✝ : Set (α × α)
⊢ s✝ ∈ uniformity α ↔ s✝ ∈ uniformity α

Next tactic:
exact h _
/-- Define a `UniformSpace` using a "distance" function. The function can be, e.g., the
distance in a (usual or extended) metric space or an absolute value on a ring. -/
def UniformSpace.ofFun {α : Type u} {β : Type v} [OrderedAddCommMonoid β]
    (d : α → α → β) (refl : ∀ x, d x x = 0) (symm : ∀ x y, d x y = d y x)
    (triangle : ∀ x y z, d x z ≤ d x y + d y z)
    (half : ∀ ε > (0 : β), ∃ δ > (0 : β), ∀ x < δ, ∀ y < δ, x + y < ε) :
    UniformSpace α :=
.ofCore
  { uniformity := ⨅ r > 0, 𝓟 { x | d x.1 x.2 < r }
    refl := le_iInf₂ fun r hr => principal_mono.2 <| idRel_subset.2 fun x => by 

Proof state:
α✝ : Type ua
β✝ : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
α : Type u
β : Type v
inst✝ : OrderedAddCommMonoid β
d : α → α → β
refl : ∀ (x : α), d x x = 0
symm : ∀ (x y : α), d x y = d y x
triangle : ∀ (x y z : α), d x z ≤ d x y + d y z
half : ∀ ε > 0, ∃ δ > 0, ∀ x < δ, ∀ y < δ, x + y < ε
r : β
hr : r > 0
x : α
⊢ (x, x) ∈ {x | d x.1 x.2 < r}

Next tactic:
simpa [refl]
/-- Define a `UniformSpace` using a "distance" function. The function can be, e.g., the
distance in a (usual or extended) metric space or an absolute value on a ring. -/
def UniformSpace.ofFun {α : Type u} {β : Type v} [OrderedAddCommMonoid β]
    (d : α → α → β) (refl : ∀ x, d x x = 0) (symm : ∀ x y, d x y = d y x)
    (triangle : ∀ x y z, d x z ≤ d x y + d y z)
    (half : ∀ ε > (0 : β), ∃ δ > (0 : β), ∀ x < δ, ∀ y < δ, x + y < ε) :
    UniformSpace α :=
.ofCore
  { uniformity := ⨅ r > 0, 𝓟 { x | d x.1 x.2 < r }
    refl := le_iInf₂ fun r hr => principal_mono.2 <| idRel_subset.2 fun x => by simpa [refl]
    symm := tendsto_iInf_iInf fun r => tendsto_iInf_iInf fun _ => tendsto_principal_principal.2
      fun x hx => by 

Proof state:
α✝ : Type ua
β✝ : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
α : Type u
β : Type v
inst✝ : OrderedAddCommMonoid β
d : α → α → β
refl : ∀ (x : α), d x x = 0
symm : ∀ (x y : α), d x y = d y x
triangle : ∀ (x y z : α), d x z ≤ d x y + d y z
half : ∀ ε > 0, ∃ δ > 0, ∀ x < δ, ∀ y < δ, x + y < ε
r : β
x✝ : r > 0
x : α × α
hx : x ∈ {x | d x.1 x.2 < r}
⊢ Prod.swap x ∈ {x | d x.1 x.2 < r}

Next tactic:
rwa [mem_setOf, symm]
/-- If `s ∈ 𝓤 α`, then for any natural `n`, for a subset `t` of a sufficiently small set in `𝓤 α`,
we have `t ○ t ○ ... ○ t ⊆ s` (`n` compositions). -/
theorem eventually_uniformity_iterate_comp_subset {s : Set (α × α)} (hs : s ∈ 𝓤 α) (n : ℕ) :
    ∀ᶠ t in (𝓤 α).smallSets, (t ○ ·)^[n] t ⊆ s := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
s : Set (α × α)
hs : s ∈ 𝓤 α
n : ℕ
⊢ ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), (fun x => t ○ x)^[n] t ⊆ s

Next tactic:
suffices ∀ᶠ t in (𝓤 α).smallSets, t ⊆ s ∧ (t ○ ·)^[n] t ⊆ s from (eventually_and.1 this).2
/-- If `s ∈ 𝓤 α`, then for any natural `n`, for a subset `t` of a sufficiently small set in `𝓤 α`,
we have `t ○ t ○ ... ○ t ⊆ s` (`n` compositions). -/
theorem eventually_uniformity_iterate_comp_subset {s : Set (α × α)} (hs : s ∈ 𝓤 α) (n : ℕ) :
    ∀ᶠ t in (𝓤 α).smallSets, (t ○ ·)^[n] t ⊆ s := by
  suffices ∀ᶠ t in (𝓤 α).smallSets, t ⊆ s ∧ (t ○ ·)^[n] t ⊆ s from (eventually_and.1 this).2
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
s : Set (α × α)
hs : s ∈ 𝓤 α
n : ℕ
⊢ ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[n] t ⊆ s

Next tactic:
induction' n with n ihn generalizing s
/-- If `s ∈ 𝓤 α`, then for any natural `n`, for a subset `t` of a sufficiently small set in `𝓤 α`,
we have `t ○ t ○ ... ○ t ⊆ s` (`n` compositions). -/
theorem eventually_uniformity_iterate_comp_subset {s : Set (α × α)} (hs : s ∈ 𝓤 α) (n : ℕ) :
    ∀ᶠ t in (𝓤 α).smallSets, (t ○ ·)^[n] t ⊆ s := by
  suffices ∀ᶠ t in (𝓤 α).smallSets, t ⊆ s ∧ (t ○ ·)^[n] t ⊆ s from (eventually_and.1 this).2
  induction' n with n ihn generalizing s
  · 

Proof state:
case zero
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
s : Set (α × α)
hs : s ∈ 𝓤 α
⊢ ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[Nat.zero] t ⊆ s

Next tactic:
simpa
/-- If `s ∈ 𝓤 α`, then for any natural `n`, for a subset `t` of a sufficiently small set in `𝓤 α`,
we have `t ○ t ○ ... ○ t ⊆ s` (`n` compositions). -/
theorem eventually_uniformity_iterate_comp_subset {s : Set (α × α)} (hs : s ∈ 𝓤 α) (n : ℕ) :
    ∀ᶠ t in (𝓤 α).smallSets, (t ○ ·)^[n] t ⊆ s := by
  suffices ∀ᶠ t in (𝓤 α).smallSets, t ⊆ s ∧ (t ○ ·)^[n] t ⊆ s from (eventually_and.1 this).2
  induction' n with n ihn generalizing s
  · simpa
  

Proof state:
case succ
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
n : ℕ
ihn : ∀ {s : Set (α × α)}, s ∈ 𝓤 α → ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[n] t ⊆ s
s : Set (α × α)
hs : s ∈ 𝓤 α
⊢ ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[Nat.succ n] t ⊆ s

Next tactic:
rcases comp_mem_uniformity_sets hs with ⟨t, htU, hts⟩
/-- If `s ∈ 𝓤 α`, then for any natural `n`, for a subset `t` of a sufficiently small set in `𝓤 α`,
we have `t ○ t ○ ... ○ t ⊆ s` (`n` compositions). -/
theorem eventually_uniformity_iterate_comp_subset {s : Set (α × α)} (hs : s ∈ 𝓤 α) (n : ℕ) :
    ∀ᶠ t in (𝓤 α).smallSets, (t ○ ·)^[n] t ⊆ s := by
  suffices ∀ᶠ t in (𝓤 α).smallSets, t ⊆ s ∧ (t ○ ·)^[n] t ⊆ s from (eventually_and.1 this).2
  induction' n with n ihn generalizing s
  · simpa
  rcases comp_mem_uniformity_sets hs with ⟨t, htU, hts⟩
  

Proof state:
case succ.intro.intro
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
n : ℕ
ihn : ∀ {s : Set (α × α)}, s ∈ 𝓤 α → ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[n] t ⊆ s
s : Set (α × α)
hs : s ∈ 𝓤 α
t : Set (α × α)
htU : t ∈ 𝓤 α
hts : t ○ t ⊆ s
⊢ ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[Nat.succ n] t ⊆ s

Next tactic:
refine' (ihn htU).mono fun U hU => _
/-- If `s ∈ 𝓤 α`, then for any natural `n`, for a subset `t` of a sufficiently small set in `𝓤 α`,
we have `t ○ t ○ ... ○ t ⊆ s` (`n` compositions). -/
theorem eventually_uniformity_iterate_comp_subset {s : Set (α × α)} (hs : s ∈ 𝓤 α) (n : ℕ) :
    ∀ᶠ t in (𝓤 α).smallSets, (t ○ ·)^[n] t ⊆ s := by
  suffices ∀ᶠ t in (𝓤 α).smallSets, t ⊆ s ∧ (t ○ ·)^[n] t ⊆ s from (eventually_and.1 this).2
  induction' n with n ihn generalizing s
  · simpa
  rcases comp_mem_uniformity_sets hs with ⟨t, htU, hts⟩
  refine' (ihn htU).mono fun U hU => _
  

Proof state:
case succ.intro.intro
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
n : ℕ
ihn : ∀ {s : Set (α × α)}, s ∈ 𝓤 α → ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[n] t ⊆ s
s : Set (α × α)
hs : s ∈ 𝓤 α
t : Set (α × α)
htU : t ∈ 𝓤 α
hts : t ○ t ⊆ s
U : Set (α × α)
hU : U ⊆ t ∧ (fun x => U ○ x)^[n] U ⊆ t
⊢ U ⊆ s ∧ (fun x => U ○ x)^[Nat.succ n] U ⊆ s

Next tactic:
rw [Function.iterate_succ_apply']
/-- If `s ∈ 𝓤 α`, then for any natural `n`, for a subset `t` of a sufficiently small set in `𝓤 α`,
we have `t ○ t ○ ... ○ t ⊆ s` (`n` compositions). -/
theorem eventually_uniformity_iterate_comp_subset {s : Set (α × α)} (hs : s ∈ 𝓤 α) (n : ℕ) :
    ∀ᶠ t in (𝓤 α).smallSets, (t ○ ·)^[n] t ⊆ s := by
  suffices ∀ᶠ t in (𝓤 α).smallSets, t ⊆ s ∧ (t ○ ·)^[n] t ⊆ s from (eventually_and.1 this).2
  induction' n with n ihn generalizing s
  · simpa
  rcases comp_mem_uniformity_sets hs with ⟨t, htU, hts⟩
  refine' (ihn htU).mono fun U hU => _
  rw [Function.iterate_succ_apply']
  

Proof state:
case succ.intro.intro
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
n : ℕ
ihn : ∀ {s : Set (α × α)}, s ∈ 𝓤 α → ∀ᶠ (t : Set (α × α)) in smallSets (𝓤 α), t ⊆ s ∧ (fun x => t ○ x)^[n] t ⊆ s
s : Set (α × α)
hs : s ∈ 𝓤 α
t : Set (α × α)
htU : t ∈ 𝓤 α
hts : t ○ t ⊆ s
U : Set (α × α)
hU : U ⊆ t ∧ (fun x => U ○ x)^[n] U ⊆ t
⊢ U ⊆ s ∧ U ○ (fun x => U ○ x)^[n] U ⊆ s

Next tactic:
exact
    ⟨hU.1.trans <| (subset_comp_self <| refl_le_uniformity htU).trans hts,
      (compRel_mono hU.1 hU.2).trans hts⟩
/-- Relation `fun f g ↦ Tendsto (fun x ↦ (f x, g x)) l (𝓤 α)` is transitive. -/
theorem Filter.Tendsto.uniformity_trans {l : Filter β} {f₁ f₂ f₃ : β → α}
    (h₁₂ : Tendsto (fun x => (f₁ x, f₂ x)) l (𝓤 α))
    (h₂₃ : Tendsto (fun x => (f₂ x, f₃ x)) l (𝓤 α)) : Tendsto (fun x => (f₁ x, f₃ x)) l (𝓤 α) := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
l : Filter β
f₁ f₂ f₃ : β → α
h₁₂ : Tendsto (fun x => (f₁ x, f₂ x)) l (𝓤 α)
h₂₃ : Tendsto (fun x => (f₂ x, f₃ x)) l (𝓤 α)
⊢ Tendsto (fun x => (f₁ x, f₃ x)) l (𝓤 α)

Next tactic:
refine' le_trans (le_lift'.2 fun s hs => mem_map.2 _) comp_le_uniformity
/-- Relation `fun f g ↦ Tendsto (fun x ↦ (f x, g x)) l (𝓤 α)` is transitive. -/
theorem Filter.Tendsto.uniformity_trans {l : Filter β} {f₁ f₂ f₃ : β → α}
    (h₁₂ : Tendsto (fun x => (f₁ x, f₂ x)) l (𝓤 α))
    (h₂₃ : Tendsto (fun x => (f₂ x, f₃ x)) l (𝓤 α)) : Tendsto (fun x => (f₁ x, f₃ x)) l (𝓤 α) := by
  refine' le_trans (le_lift'.2 fun s hs => mem_map.2 _) comp_le_uniformity
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
l : Filter β
f₁ f₂ f₃ : β → α
h₁₂ : Tendsto (fun x => (f₁ x, f₂ x)) l (𝓤 α)
h₂₃ : Tendsto (fun x => (f₂ x, f₃ x)) l (𝓤 α)
s : Set (α × α)
hs : s ∈ 𝓤 α
⊢ (fun x => (f₁ x, f₃ x)) ⁻¹' (s ○ s) ∈ l

Next tactic:
filter_upwards [mem_map.1 (h₁₂ hs), mem_map.1 (h₂₃ hs)] with x hx₁₂ hx₂₃ using ⟨_, hx₁₂, hx₂₃⟩
theorem uniformity_le_symm : 𝓤 α ≤ @Prod.swap α α <$> 𝓤 α := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
⊢ 𝓤 α ≤ Prod.swap <$> 𝓤 α

Next tactic:
rw [map_swap_eq_comap_swap]
theorem uniformity_le_symm : 𝓤 α ≤ @Prod.swap α α <$> 𝓤 α := by
  rw [map_swap_eq_comap_swap]; 

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
⊢ 𝓤 α ≤ comap Prod.swap (𝓤 α)

Next tactic:
exact tendsto_swap_uniformity.le_comap
theorem symmetrize_mem_uniformity {V : Set (α × α)} (h : V ∈ 𝓤 α) : symmetrizeRel V ∈ 𝓤 α := by
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
V : Set (α × α)
h : V ∈ 𝓤 α
⊢ symmetrizeRel V ∈ 𝓤 α

Next tactic:
apply (𝓤 α).inter_sets h
theorem symmetrize_mem_uniformity {V : Set (α × α)} (h : V ∈ 𝓤 α) : symmetrizeRel V ∈ 𝓤 α := by
  apply (𝓤 α).inter_sets h
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
V : Set (α × α)
h : V ∈ 𝓤 α
⊢ Prod.swap ⁻¹' V ∈ (𝓤 α).sets

Next tactic:
rw [← image_swap_eq_preimage_swap, uniformity_eq_symm]
theorem symmetrize_mem_uniformity {V : Set (α × α)} (h : V ∈ 𝓤 α) : symmetrizeRel V ∈ 𝓤 α := by
  apply (𝓤 α).inter_sets h
  rw [← image_swap_eq_preimage_swap, uniformity_eq_symm]
  

Proof state:
α : Type ua
β : Type ub
γ : Type uc
δ : Type ud
ι : Sort u_1
inst✝ : UniformSpace α
V : Set (α × α)
h : V ∈ 𝓤 α
⊢ Prod.swap '' V ∈ (Prod.swap <$> 𝓤 α).sets

Next tactic:
exact image_mem_map h