CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".

Project: Xena
Views: 18536
License: APACHE
/-
Copyright (c) 2019 Zhouhang Zhou. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Zhouhang Zhou

The pointwise operations on filters have nice properties, such as
  • map m (f₁ * f₂) = map m f₁ * map m f₂
  • 𝓝 x * 𝓝 y = 𝓝 (x * y)

-/

import algebra.pointwise
import order.filter.basic

open classical set lattice

universes u v w
variables {α : Type u} {β : Type v} {γ : Type w}

open_locale classical
local attribute [instance] pointwise_one pointwise_mul pointwise_add

namespace filter
open set

@[to_additive]
def pointwise_one [has_one α] : has_one (filter α) := ⟨principal {1}⟩

local attribute [instance] pointwise_one

@[simp, to_additive]
lemma mem_pointwise_one [has_one α] (s : set α) :
  s ∈ (1 : filter α) ↔ (1:α) ∈ s :=
calc
  s ∈ (1:filter α) ↔ {(1:α)} ⊆ s : iff.rfl
  ... ↔ (1:α) ∈ s : by simp

@[to_additive]
def pointwise_mul [monoid α] : has_mul (filter α) := ⟨λf g,
{ sets             := { s | ∃t₁∈f, ∃t₂∈g, t₁ * t₂  ⊆ s },
  univ_sets        :=
  begin
    have h₁ : (∃x, x ∈ f) := ⟨univ, univ_sets f⟩,
    have h₂ : (∃x, x ∈ g) := ⟨univ, univ_sets g⟩,
    simpa using and.intro h₁ h₂
  end,
  sets_of_superset := λx y hx hxy,
  begin
   rcases hx with ⟨t₁, ht₁, t₂, ht₂, t₁t₂⟩,
   exact ⟨t₁, ht₁, t₂, ht₂, subset.trans t₁t₂ hxy⟩
  end,
  inter_sets       := λx y,
  begin
    simp only [exists_prop, mem_set_of_eq, subset_inter_iff],
    rintros ⟨s₁, hs₁, s₂, hs₂, s₁s₂⟩ ⟨t₁, ht₁, t₂, ht₂, t₁t₂⟩,
    exact ⟨s₁ ∩ t₁, inter_sets f hs₁ ht₁, s₂ ∩ t₂, inter_sets g hs₂ ht₂,
    subset.trans (pointwise_mul_subset_mul (inter_subset_left _ _) (inter_subset_left _ _)) s₁s₂,
    subset.trans (pointwise_mul_subset_mul (inter_subset_right _ _) (inter_subset_right _ _)) t₁t₂⟩,
  end }⟩

local attribute [instance] pointwise_mul pointwise_add

@[to_additive]
lemma mem_pointwise_mul [monoid α] {f g : filter α} {s : set α} :
  s ∈ f * g ↔ ∃ t₁ ∈ f, ∃ t₂ ∈ g, t₁ * t₂ ⊆ s := iff.rfl

@[to_additive]
lemma mul_mem_pointwise_mul [monoid α] {f g : filter α} {s t : set α} (hs : s ∈ f) (ht : t ∈ g) :
  s * t ∈ f * g := ⟨_, hs, _, ht, subset.refl _⟩

@[to_additive]
lemma pointwise_mul_le_mul [monoid α] {f₁ f₂ g₁ g₂ : filter α} (hf : f₁ ≤ f₂) (hg : g₁ ≤ g₂) :
  f₁ * g₁ ≤ f₂ * g₂ := assume _ ⟨s, hs, t, ht, hst⟩, ⟨s, hf hs, t, hg ht, hst⟩

@[to_additive]
lemma pointwise_mul_ne_bot [monoid α] {f g : filter α} : f ≠ ⊥ → g ≠ ⊥ → f * g ≠ ⊥ :=
begin
  simp only [forall_sets_nonempty_iff_ne_bot.symm],
  rintros hf hg s ⟨a, ha, b, hb, ab⟩,
  exact ((hf a ha).pointwise_mul (hg b hb)).mono ab
end

@[to_additive]
lemma pointwise_mul_assoc [monoid α] (f g h : filter α) : f * g * h = f * (g * h) :=
begin
  ext s, split,
  { rintros ⟨a, ⟨a₁, ha₁, a₂, ha₂, a₁a₂⟩, b, hb, ab⟩,
    refine ⟨a₁, ha₁, a₂ * b, mul_mem_pointwise_mul ha₂ hb, _⟩,
    rw [← pointwise_mul_semigroup.mul_assoc],
    exact calc
      a₁ * a₂ * b ⊆ a * b : pointwise_mul_subset_mul a₁a₂ (subset.refl _)
      ...         ⊆ s     : ab },
  { rintros ⟨a, ha, b, ⟨b₁, hb₁, b₂, hb₂, b₁b₂⟩, ab⟩,
    refine ⟨a * b₁, mul_mem_pointwise_mul ha hb₁, b₂, hb₂, _⟩,
    rw [pointwise_mul_semigroup.mul_assoc],
    exact calc
      a * (b₁ * b₂) ⊆ a * b : pointwise_mul_subset_mul (subset.refl _) b₁b₂
      ...           ⊆ s     : ab }
end

local attribute [instance] pointwise_mul_monoid

@[to_additive]
lemma pointwise_one_mul [monoid α] (f : filter α) : 1 * f = f :=
begin
  ext s, split,
  { rintros ⟨t₁, ht₁, t₂, ht₂, t₁t₂⟩,
    refine mem_sets_of_superset (mem_sets_of_superset ht₂ _) t₁t₂,
    assume x hx,
    exact ⟨1, by rwa [← mem_pointwise_one], x, hx, (one_mul _).symm⟩ },
  { assume hs,
    refine ⟨(1:set α), mem_principal_self _, s, hs, by simp only [one_mul]⟩ }
end

@[to_additive]
lemma pointwise_mul_one [monoid α] (f : filter α) : f * 1 = f :=
begin
  ext s, split,
  { rintros ⟨t₁, ht₁, t₂, ht₂, t₁t₂⟩,
    refine mem_sets_of_superset (mem_sets_of_superset ht₁ _) t₁t₂,
    assume x hx,
    exact ⟨x, hx, 1, by rwa [← mem_pointwise_one], (mul_one _).symm⟩ },
  { assume hs,
    refine ⟨s, hs, (1:set α), mem_principal_self _, by simp only [mul_one]⟩ }
end

@[to_additive pointwise_add_add_monoid]
def pointwise_mul_monoid [monoid α] : monoid (filter α) :=
{ mul_assoc := pointwise_mul_assoc,
  one_mul := pointwise_one_mul,
  mul_one := pointwise_mul_one,
  .. pointwise_mul,
  .. pointwise_one }

local attribute [instance] filter.pointwise_mul_monoid filter.pointwise_add_add_monoid

section map
open is_mul_hom

variables [monoid α] [monoid β] {f : filter α} (m : α → β)

@[to_additive]
lemma map_pointwise_mul [is_mul_hom m] {f₁ f₂ : filter α} : map m (f₁ * f₂) = map m f₁ * map m f₂ :=
filter_eq $ set.ext $ assume s,
begin
  simp only [mem_pointwise_mul], split,
  { rintro ⟨t₁, ht₁, t₂, ht₂, t₁t₂⟩,
    have : m '' (t₁ * t₂) ⊆ s := subset.trans (image_subset m t₁t₂) (image_preimage_subset _ _),
    refine ⟨m '' t₁, image_mem_map ht₁, m '' t₂, image_mem_map ht₂, _⟩,
    rwa ← image_pointwise_mul m t₁ t₂ },
  { rintro ⟨t₁, ht₁, t₂, ht₂, t₁t₂⟩,
    refine ⟨m ⁻¹' t₁, ht₁, m ⁻¹' t₂, ht₂, image_subset_iff.1 _⟩,
    rw image_pointwise_mul m,
    exact subset.trans
      (pointwise_mul_subset_mul (image_preimage_subset _ _) (image_preimage_subset _ _)) t₁t₂ },
end

@[to_additive]
lemma map_pointwise_one [is_monoid_hom m] : map m (1:filter α) = 1 :=
le_antisymm
  (le_principal_iff.2 $ mem_map_sets_iff.2 ⟨(1:set α), by simp,
    by { assume x, simp [is_monoid_hom.map_one m], rintros rfl, refl  }⟩)
  (le_map $ assume s hs,
   begin
     simp only [mem_pointwise_one],
     exact ⟨(1:α), (mem_pointwise_one s).1 hs, is_monoid_hom.map_one _⟩
   end)

-- TODO: prove similar statements when `m` is group homomorphism etc.
lemma pointwise_mul_map_is_monoid_hom [is_monoid_hom m] : is_monoid_hom (map m) :=
{ map_one := map_pointwise_one m,
  map_mul := λ _ _, map_pointwise_mul m }

lemma pointwise_add_map_is_add_monoid_hom {α : Type*} {β : Type*} [add_monoid α] [add_monoid β]
  (m : α → β) [is_add_monoid_hom m] : is_add_monoid_hom (map m) :=
{ map_zero := map_pointwise_zero m,
  map_add := λ _ _, map_pointwise_add m }

attribute [to_additive pointwise_add_map_is_add_monoid_hom] pointwise_mul_map_is_monoid_hom

-- The other direction does not hold in general.
@[to_additive]
lemma comap_mul_comap_le [is_mul_hom m] {f₁ f₂ : filter β} :
  comap m f₁ * comap m f₂ ≤ comap m (f₁ * f₂) :=
begin
  rintros s ⟨t, ⟨t₁, ht₁, t₂, ht₂, t₁t₂⟩, mt⟩,
  refine ⟨m ⁻¹' t₁, ⟨t₁, ht₁, subset.refl _⟩, m ⁻¹' t₂, ⟨t₂, ht₂, subset.refl _⟩, _⟩,
  have := subset.trans (preimage_mono t₁t₂) mt,
  exact subset.trans (preimage_pointwise_mul_preimage_subset m _ _) this
end

variables {m}

@[to_additive]
lemma tendsto.mul_mul [is_mul_hom m] {f₁ g₁ : filter α} {f₂ g₂ : filter β} :
  tendsto m f₁ f₂ → tendsto m g₁ g₂ → tendsto m (f₁ * g₁) (f₂ * g₂) :=
assume hf hg, by { rw [tendsto, map_pointwise_mul m], exact pointwise_mul_le_mul hf hg }

end map

end filter