File: Mathlib/Topology/MetricSpace/PiNat.lean

full_name: PiNat.firstDiff
code: /-- In a product space `Π n, E n`, then `firstDiff x y` is the first index at which `x` and `y`
differ. If `x = y`, then by convention we set `firstDiff x x = 0`. -/
irreducible_def firstDiff (x y : ∀ n, E n) : ℕ 
goal: ℕ

full_name: PiNat.definition._@.Mathlib.Topology.MetricSpace.PiNat._hyg.17
code: /-- In a product space `Π n, E n`, then `firstDiff x y` is the first index at which `x` and `y`
differ. If `x = y`, then by convention we set `firstDiff x x = 0`. -/
irreducible_def firstDiff (x y : ∀ n, E n) : ℕ 
goal: ℕ

full_name: PiNat.wrapped._@.Mathlib.Topology.MetricSpace.PiNat._hyg.17
code: /-- In a product space `Π n, E n`, then `firstDiff x y` is the first index at which `x` and `y`
differ. If `x = y`, then by convention we set `firstDiff x x = 0`. -/
irreducible_def firstDiff (x y : ∀ n, E n) : ℕ 
goal: Subtype (Eq @PiNat.definition✝)

full_name: PiNat.firstDiff_def
code: /-- In a product space `Π n, E n`, then `firstDiff x y` is the first index at which `x` and `y`
differ. If `x = y`, then by convention we set `firstDiff x x = 0`. -/
irreducible_def firstDiff (x y : ∀ n, E n) : ℕ 
goal: PiNat.firstDiff x y = if h : x ≠ y then Nat.find ⋯ else 0

full_name: PiNat.apply_firstDiff_ne
code: theorem apply_firstDiff_ne {x y : ∀ n, E n} (h : x ≠ y) :
    x (firstDiff x y) ≠ y (firstDiff x y) 
goal: x (PiNat.firstDiff x y) ≠ y (PiNat.firstDiff x y)

full_name: PiNat.apply_eq_of_lt_firstDiff
code: theorem apply_eq_of_lt_firstDiff {x y : ∀ n, E n} {n : ℕ} (hn : n < firstDiff x y) : x n = y n 
goal: x n = y n

full_name: PiNat.firstDiff_comm
code: theorem firstDiff_comm (x y : ∀ n, E n) : firstDiff x y = firstDiff y x 
goal: PiNat.firstDiff x y = PiNat.firstDiff y x

full_name: PiNat.min_firstDiff_le
code: theorem min_firstDiff_le (x y z : ∀ n, E n) (h : x ≠ z) :
    min (firstDiff x y) (firstDiff y z) ≤ firstDiff x z 
goal: min (PiNat.firstDiff x y) (PiNat.firstDiff y z) ≤ PiNat.firstDiff x z

full_name: PiNat.cylinder
code: /-- In a product space `Π n, E n`, the cylinder set of length `n` around `x`, denoted
`cylinder x n`, is the set of sequences `y` that coincide with `x` on the first `n` symbols, i.e.,
such that `y i = x i` for all `i < n`.
-/
def cylinder (x : ∀ n, E n) (n : ℕ) : Set (∀ n, E n) 
goal: Set ((n : ℕ) → E n)

full_name: PiNat.cylinder_eq_pi
code: theorem cylinder_eq_pi (x : ∀ n, E n) (n : ℕ) :
    cylinder x n = Set.pi (Finset.range n : Set ℕ) fun i : ℕ => {x i} 
goal: PiNat.cylinder x n = (↑(Finset.range n)).pi fun i => {x i}

full_name: PiNat.cylinder_zero
code: @[simp]
theorem cylinder_zero (x : ∀ n, E n) : cylinder x 0 = univ 
goal: PiNat.cylinder x 0 = Set.univ

full_name: PiNat.cylinder_anti
code: theorem cylinder_anti (x : ∀ n, E n) {m n : ℕ} (h : m ≤ n) : cylinder x n ⊆ cylinder x m 
goal: PiNat.cylinder x n ⊆ PiNat.cylinder x m

full_name: PiNat.mem_cylinder_iff
code: @[simp]
theorem mem_cylinder_iff {x y : ∀ n, E n} {n : ℕ} : y ∈ cylinder x n ↔ ∀ i < n, y i = x i 
goal: y ∈ PiNat.cylinder x n ↔ ∀ i < n, y i = x i

full_name: PiNat.self_mem_cylinder
code: theorem self_mem_cylinder (x : ∀ n, E n) (n : ℕ) : x ∈ cylinder x n 
goal: x ∈ PiNat.cylinder x n

full_name: PiNat.mem_cylinder_iff_eq
code: theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n 
goal: y ∈ PiNat.cylinder x n ↔ PiNat.cylinder y n = PiNat.cylinder x n

full_name: PiNat.mem_cylinder_comm
code: theorem mem_cylinder_comm (x y : ∀ n, E n) (n : ℕ) : y ∈ cylinder x n ↔ x ∈ cylinder y n 
goal: y ∈ PiNat.cylinder x n ↔ x ∈ PiNat.cylinder y n

full_name: PiNat.mem_cylinder_iff_le_firstDiff
code: theorem mem_cylinder_iff_le_firstDiff {x y : ∀ n, E n} (hne : x ≠ y) (i : ℕ) :
    x ∈ cylinder y i ↔ i ≤ firstDiff x y 
goal: x ∈ PiNat.cylinder y i ↔ i ≤ PiNat.firstDiff x y

full_name: PiNat.mem_cylinder_firstDiff
code: theorem mem_cylinder_firstDiff (x y : ∀ n, E n) : x ∈ cylinder y (firstDiff x y) 
goal: x ∈ PiNat.cylinder y (PiNat.firstDiff x y)

full_name: PiNat.cylinder_eq_cylinder_of_le_firstDiff
code: theorem cylinder_eq_cylinder_of_le_firstDiff (x y : ∀ n, E n) {n : ℕ} (hn : n ≤ firstDiff x y) :
    cylinder x n = cylinder y n 
goal: PiNat.cylinder x n = PiNat.cylinder y n

full_name: PiNat.iUnion_cylinder_update
code: theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n 
goal: ⋃ k, PiNat.cylinder (Function.update x n k) (n + 1) = PiNat.cylinder x n

full_name: PiNat.update_mem_cylinder
code: theorem update_mem_cylinder (x : ∀ n, E n) (n : ℕ) (y : E n) : update x n y ∈ cylinder x n 
goal: Function.update x n y ∈ PiNat.cylinder x n

full_name: PiNat.res
code: /-- In the case where `E` has constant value `α`,
the cylinder `cylinder x n` can be identified with the element of `List α`
consisting of the first `n` entries of `x`. See `cylinder_eq_res`.
We call this list `res x n`, the restriction of `x` to `n`. -/
def res (x : ℕ → α) : ℕ → List α
  
goal: ℕ → List α

full_name: PiNat.res_zero
code: @[simp]
theorem res_zero (x : ℕ → α) : res x 0 = @nil α 
goal: PiNat.res x 0 = []

full_name: PiNat.res_succ
code: @[simp]
theorem res_succ (x : ℕ → α) (n : ℕ) : res x n.succ = x n :: res x n 
goal: PiNat.res x n.succ = x n :: PiNat.res x n

full_name: PiNat.res_length
code: @[simp]
theorem res_length (x : ℕ → α) (n : ℕ) : (res x n).length = n 
goal: (PiNat.res x n).length = n

full_name: PiNat.res_eq_res
code: /-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`. -/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m 
goal: PiNat.res x n = PiNat.res y n ↔ ∀ ⦃m : ℕ⦄, m < n → x m = y m

full_name: PiNat.res_injective
code: theorem res_injective : Injective (@res α) 
goal: Function.Injective PiNat.res

full_name: PiNat.cylinder_eq_res
code: /-- `cylinder x n` is equal to the set of sequences `y` with the same restriction to `n` as `x`. -/
theorem cylinder_eq_res (x : ℕ → α) (n : ℕ) :
    cylinder x n = { y | res y n = res x n } 
goal: PiNat.cylinder x n = {y | PiNat.res y n = PiNat.res x n}

full_name: PiNat.dist
code: /-- The distance function on a product space `Π n, E n`, given by `dist x y = (1/2)^n` where `n` is
the first index at which `x` and `y` differ. -/
protected def dist : Dist (∀ n, E n) 
goal: Dist ((n : ℕ) → E n)

full_name: PiNat.dist_eq_of_ne
code: theorem dist_eq_of_ne {x y : ∀ n, E n} (h : x ≠ y) : dist x y = (1 / 2 : ℝ) ^ firstDiff x y 
goal: dist x y = (1 / 2) ^ PiNat.firstDiff x y

full_name: PiNat.dist_self
code: protected theorem dist_self (x : ∀ n, E n) : dist x x = 0 
goal: dist x x = 0

full_name: PiNat.dist_comm
code: protected theorem dist_comm (x y : ∀ n, E n) : dist x y = dist y x 
goal: dist x y = dist y x

full_name: PiNat.dist_nonneg
code: protected theorem dist_nonneg (x y : ∀ n, E n) : 0 ≤ dist x y 
goal: 0 ≤ dist x y

full_name: PiNat.dist_triangle_nonarch
code: theorem dist_triangle_nonarch (x y z : ∀ n, E n) : dist x z ≤ max (dist x y) (dist y z) 
goal: dist x z ≤ max (dist x y) (dist y z)

full_name: PiNat.dist_triangle
code: protected theorem dist_triangle (x y z : ∀ n, E n) : dist x z ≤ dist x y + dist y z 
goal: dist x z ≤ dist x y + dist y z

full_name: PiNat.eq_of_dist_eq_zero
code: protected theorem eq_of_dist_eq_zero (x y : ∀ n, E n) (hxy : dist x y = 0) : x = y 
goal: x = y

full_name: PiNat.mem_cylinder_iff_dist_le
code: theorem mem_cylinder_iff_dist_le {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ dist y x ≤ (1 / 2) ^ n 
goal: y ∈ PiNat.cylinder x n ↔ dist y x ≤ (1 / 2) ^ n

full_name: PiNat.apply_eq_of_dist_lt
code: theorem apply_eq_of_dist_lt {x y : ∀ n, E n} {n : ℕ} (h : dist x y < (1 / 2) ^ n) {i : ℕ}
    (hi : i ≤ n) : x i = y i 
goal: x i = y i

full_name: PiNat.lipschitz_with_one_iff_forall_dist_image_le_of_mem_cylinder
code: /-- A function to a pseudo-metric-space is `1`-Lipschitz if and only if points in the same cylinder
of length `n` are sent to points within distance `(1/2)^n`.
Not expressed using `LipschitzWith` as we don't have a metric space structure -/
theorem lipschitz_with_one_iff_forall_dist_image_le_of_mem_cylinder {α : Type*}
    [PseudoMetricSpace α] {f : (∀ n, E n) → α} :
    (∀ x y : ∀ n, E n, dist (f x) (f y) ≤ dist x y) ↔
      ∀ x y n, y ∈ cylinder x n → dist (f x) (f y) ≤ (1 / 2) ^ n 
goal: (∀ (x y : (n : ℕ) → E n), dist (f x) (f y) ≤ dist x y) ↔
  ∀ (x y : (n : ℕ) → E n) (n : ℕ), y ∈ PiNat.cylinder x n → dist (f x) (f y) ≤ (1 / 2) ^ n

full_name: PiNat.isOpen_cylinder
code: theorem isOpen_cylinder (x : ∀ n, E n) (n : ℕ) : IsOpen (cylinder x n) 
goal: IsOpen (PiNat.cylinder x n)

full_name: PiNat.isTopologicalBasis_cylinders
code: theorem isTopologicalBasis_cylinders :
    IsTopologicalBasis { s : Set (∀ n, E n) | ∃ (x : ∀ n, E n) (n : ℕ), s = cylinder x n } 
goal: TopologicalSpace.IsTopologicalBasis {s | ∃ x n, s = PiNat.cylinder x n}

full_name: PiNat.isOpen_iff_dist
code: theorem isOpen_iff_dist (s : Set (∀ n, E n)) :
    IsOpen s ↔ ∀ x ∈ s, ∃ ε > 0, ∀ y, dist x y < ε → y ∈ s 
goal: IsOpen s ↔ ∀ x ∈ s, ∃ ε > 0, ∀ (y : (n : ℕ) → E n), dist x y < ε → y ∈ s

full_name: PiNat.metricSpace
code: /-- Metric space structure on `Π (n : ℕ), E n` when the spaces `E n` have the discrete topology,
where the distance is given by `dist x y = (1/2)^n`, where `n` is the smallest index where `x` and
`y` differ. Not registered as a global instance by default.
Warning: this definition makes sure that the topology is defeq to the original product topology,
but it does not take care of a possible uniformity. If the `E n` have a uniform structure, then
there will be two non-defeq uniform structures on `Π n, E n`, the product one and the one coming
from the metric structure. In this case, use `metricSpaceOfDiscreteUniformity` instead. -/
protected def metricSpace : MetricSpace (∀ n, E n) 
goal: MetricSpace ((n : ℕ) → E n)

full_name: PiNat.metricSpaceOfDiscreteUniformity
code: /-- Metric space structure on `Π (n : ℕ), E n` when the spaces `E n` have the discrete uniformity,
where the distance is given by `dist x y = (1/2)^n`, where `n` is the smallest index where `x` and
`y` differ. Not registered as a global instance by default. -/
protected def metricSpaceOfDiscreteUniformity {E : ℕ → Type*} [∀ n, UniformSpace (E n)]
    (h : ∀ n, uniformity (E n) = 𝓟 idRel) : MetricSpace (∀ n, E n) 
goal: MetricSpace ((n : ℕ) → E n)

full_name: PiNat.metricSpaceNatNat
code: /-- Metric space structure on `ℕ → ℕ` where the distance is given by `dist x y = (1/2)^n`,
where `n` is the smallest index where `x` and `y` differ.
Not registered as a global instance by default. -/
def metricSpaceNatNat : MetricSpace (ℕ → ℕ) 
goal: MetricSpace (ℕ → ℕ)

full_name: PiNat.completeSpace
code: protected theorem completeSpace : CompleteSpace (∀ n, E n) 
goal: CompleteSpace ((n : ℕ) → E n)

full_name: PiNat.exists_disjoint_cylinder
code: theorem exists_disjoint_cylinder {s : Set (∀ n, E n)} (hs : IsClosed s) {x : ∀ n, E n}
    (hx : x ∉ s) : ∃ n, Disjoint s (cylinder x n) 
goal: ∃ n, Disjoint s (PiNat.cylinder x n)

full_name: PiNat.shortestPrefixDiff
code: /-- Given a point `x` in a product space `Π (n : ℕ), E n`, and `s` a subset of this space, then
`shortestPrefixDiff x s` if the smallest `n` for which there is no element of `s` having the same
prefix of length `n` as `x`. If there is no such `n`, then use `0` by convention. -/
def shortestPrefixDiff {E : ℕ → Type*} (x : ∀ n, E n) (s : Set (∀ n, E n)) : ℕ 
goal: ℕ

full_name: PiNat.firstDiff_lt_shortestPrefixDiff
code: theorem firstDiff_lt_shortestPrefixDiff {s : Set (∀ n, E n)} (hs : IsClosed s) {x y : ∀ n, E n}
    (hx : x ∉ s) (hy : y ∈ s) : firstDiff x y < shortestPrefixDiff x s 
goal: PiNat.firstDiff x y < PiNat.shortestPrefixDiff x s

full_name: PiNat.shortestPrefixDiff_pos
code: theorem shortestPrefixDiff_pos {s : Set (∀ n, E n)} (hs : IsClosed s) (hne : s.Nonempty)
    {x : ∀ n, E n} (hx : x ∉ s) : 0 < shortestPrefixDiff x s 
goal: 0 < PiNat.shortestPrefixDiff x s

full_name: PiNat.longestPrefix
code: /-- Given a point `x` in a product space `Π (n : ℕ), E n`, and `s` a subset of this space, then
`longestPrefix x s` if the largest `n` for which there is an element of `s` having the same
prefix of length `n` as `x`. If there is no such `n`, use `0` by convention. -/
def longestPrefix {E : ℕ → Type*} (x : ∀ n, E n) (s : Set (∀ n, E n)) : ℕ 
goal: ℕ

full_name: PiNat.firstDiff_le_longestPrefix
code: theorem firstDiff_le_longestPrefix {s : Set (∀ n, E n)} (hs : IsClosed s) {x y : ∀ n, E n}
    (hx : x ∉ s) (hy : y ∈ s) : firstDiff x y ≤ longestPrefix x s 
goal: PiNat.firstDiff x y ≤ PiNat.longestPrefix x s

full_name: PiNat.inter_cylinder_longestPrefix_nonempty
code: theorem inter_cylinder_longestPrefix_nonempty {s : Set (∀ n, E n)} (hs : IsClosed s)
    (hne : s.Nonempty) (x : ∀ n, E n) : (s ∩ cylinder x (longestPrefix x s)).Nonempty 
goal: (s ∩ PiNat.cylinder x (PiNat.longestPrefix x s)).Nonempty

full_name: PiNat.disjoint_cylinder_of_longestPrefix_lt
code: theorem disjoint_cylinder_of_longestPrefix_lt {s : Set (∀ n, E n)} (hs : IsClosed s) {x : ∀ n, E n}
    (hx : x ∉ s) {n : ℕ} (hn : longestPrefix x s < n) : Disjoint s (cylinder x n) 
goal: Disjoint s (PiNat.cylinder x n)

full_name: PiNat.cylinder_longestPrefix_eq_of_longestPrefix_lt_firstDiff
code: /-- If two points `x, y` coincide up to length `n`, and the longest common prefix of `x` with `s`
is strictly shorter than `n`, then the longest common prefix of `y` with `s` is the same, and both
cylinders of this length based at `x` and `y` coincide. -/
theorem cylinder_longestPrefix_eq_of_longestPrefix_lt_firstDiff {x y : ∀ n, E n}
    {s : Set (∀ n, E n)} (hs : IsClosed s) (hne : s.Nonempty)
    (H : longestPrefix x s < firstDiff x y) (xs : x ∉ s) (ys : y ∉ s) :
    cylinder x (longestPrefix x s) = cylinder y (longestPrefix y s) 
goal: PiNat.cylinder x (PiNat.longestPrefix x s) = PiNat.cylinder y (PiNat.longestPrefix y s)

full_name: PiNat.exists_lipschitz_retraction_of_isClosed
code: /-- Given a closed nonempty subset `s` of `Π (n : ℕ), E n`, there exists a Lipschitz retraction
onto this set, i.e., a Lipschitz map with range equal to `s`, equal to the identity on `s`. -/
theorem exists_lipschitz_retraction_of_isClosed {s : Set (∀ n, E n)} (hs : IsClosed s)
    (hne : s.Nonempty) :
    ∃ f : (∀ n, E n) → ∀ n, E n, (∀ x ∈ s, f x = x) ∧ range f = s ∧ LipschitzWith 1 f 
goal: ∃ f, (∀ x ∈ s, f x = x) ∧ Set.range f = s ∧ LipschitzWith 1 f

full_name: PiNat.exists_retraction_of_isClosed
code: /-- Given a closed nonempty subset `s` of `Π (n : ℕ), E n`, there exists a retraction onto this
set, i.e., a continuous map with range equal to `s`, equal to the identity on `s`. -/
theorem exists_retraction_of_isClosed {s : Set (∀ n, E n)} (hs : IsClosed s) (hne : s.Nonempty) :
    ∃ f : (∀ n, E n) → ∀ n, E n, (∀ x ∈ s, f x = x) ∧ range f = s ∧ Continuous f 
goal: ∃ f, (∀ x ∈ s, f x = x) ∧ Set.range f = s ∧ Continuous f

full_name: PiNat.exists_retraction_subtype_of_isClosed
code: theorem exists_retraction_subtype_of_isClosed {s : Set (∀ n, E n)} (hs : IsClosed s)
    (hne : s.Nonempty) :
    ∃ f : (∀ n, E n) → s, (∀ x : s, f x = x) ∧ Surjective f ∧ Continuous f 
goal: ∃ f, (∀ (x : ↑s), f ↑x = x) ∧ Function.Surjective f ∧ Continuous f

full_name: exists_nat_nat_continuous_surjective_of_completeSpace
code: /-- Any nonempty complete second countable metric space is the continuous image of the
fundamental space `ℕ → ℕ`. For a version of this theorem in the context of Polish spaces, see
`exists_nat_nat_continuous_surjective_of_polishSpace`. -/
theorem exists_nat_nat_continuous_surjective_of_completeSpace (α : Type*) [MetricSpace α]
    [CompleteSpace α] [SecondCountableTopology α] [Nonempty α] :
    ∃ f : (ℕ → ℕ) → α, Continuous f ∧ Surjective f 
goal: ∃ f, Continuous f ∧ Function.Surjective f

full_name: PiCountable.dist
code: /-- Given a countable family of metric spaces, one may put a distance on their product `Π i, E i`.
It is highly non-canonical, though, and therefore not registered as a global instance.
The distance we use here is `dist x y = ∑' i, min (1/2)^(encode i) (dist (x i) (y i))`. -/
protected def dist : Dist (∀ i, F i) 
goal: Dist ((i : ι) → F i)

full_name: PiCountable.dist_eq_tsum
code: theorem dist_eq_tsum (x y : ∀ i, F i) :
    dist x y = ∑' i : ι, min ((1 / 2) ^ encode i : ℝ) (dist (x i) (y i)) 
goal: dist x y = ∑' (i : ι), min ((1 / 2) ^ Encodable.encode i) (dist (x i) (y i))

full_name: PiCountable.dist_summable
code: theorem dist_summable (x y : ∀ i, F i) :
    Summable fun i : ι => min ((1 / 2) ^ encode i : ℝ) (dist (x i) (y i)) 
goal: Summable fun i => min ((1 / 2) ^ Encodable.encode i) (dist (x i) (y i))

full_name: PiCountable.min_dist_le_dist_pi
code: theorem min_dist_le_dist_pi (x y : ∀ i, F i) (i : ι) :
    min ((1 / 2) ^ encode i : ℝ) (dist (x i) (y i)) ≤ dist x y 
goal: min ((1 / 2) ^ Encodable.encode i) (dist (x i) (y i)) ≤ dist x y

full_name: PiCountable.dist_le_dist_pi_of_dist_lt
code: theorem dist_le_dist_pi_of_dist_lt {x y : ∀ i, F i} {i : ι} (h : dist x y < (1 / 2) ^ encode i) :
    dist (x i) (y i) ≤ dist x y 
goal: dist (x i) (y i) ≤ dist x y

full_name: PiCountable.metricSpace
code: /-- Given a countable family of metric spaces, one may put a distance on their product `Π i, E i`,
defining the right topology and uniform structure. It is highly non-canonical, though, and therefore
not registered as a global instance.
The distance we use here is `dist x y = ∑' n, min (1/2)^(encode i) (dist (x n) (y n))`. -/
protected def metricSpace : MetricSpace (∀ i, F i) 
goal: MetricSpace ((i : ι) → F i)