Sometimes you need to read filter algebra rather than write a limit: a proof
you are following pivots through ≤, Filter.map, Filter.comap,
or ×ˢ, or you want to reshape a Tendsto goal into an equivalent one.
This entry explains what those operations mean and the goal each one serves.
F≤G reads as "F is finer than {lean}G": every
{lean}G-eventual set is already {lean}F-eventual. A finer filter carries
more constraints and sits closer to "a single point".
This order is what lets you weaken a limit. Say you have
TendstofG(𝓝L) and want TendstofF(𝓝L) for a finer source
F≤G. Then Filter.Tendsto.mono_left reduces the goal to proving
F≤G: convergence along a coarser filter implies convergence along any
finer one. For instance a two-sided limit gives the one-sided limit,
because 𝓝[>]a≤𝓝a.
The mnemonic that prevents the sign-flip everyone trips over: on
principal filters, the order is just inclusion of the underlying
sets:
example(st:Setα):𝓟s≤𝓟t↔s⊆t:=Filter.principal_mono
The lattice on Filter α:
Filter
"Eventually in this filter" means
F ⊓ G
eventually for both F and G
F ⊔ G
eventually for either F or G
⊥
every set is ⊥-eventual (vacuous; see NeBot below)
⊤
only Set.univ is ⊤-eventual ("everywhere")
This is exactly why nhdsWithinxs=𝓝x⊓𝓟s: "near xand in
s":
example(x:X)(s:SetX):𝓝[s]x=𝓝x⊓𝓟s:=rfl
7.4.2. Push-forward and pull-back: Filter.map and Filter.comap🔗
For f : α → β:
Filter.mapf F : Filter β is the push-forward. A set
t is map f F-eventual iff its preimage f ⁻¹' t is F-eventual.
Filter.comapf G : Filter α is the pull-back. A set s
is comap f G-eventual iff it contains the preimage of some
G-eventual set.
These are the algebraic content of Tendsto. By definition:
When you read a proof that pivots through Filter.map or
Filter.comap, the author is manipulating filters algebraically. A
common shape is Tendstou(atTop.comapφ)_, which expresses "a limit along
the subsequence φ" as a Tendsto along atTop.
F ×ˢ G : Filter (α × β) (called prod in theorem names) is the product
filter: a set is F ×ˢ G-eventual iff it contains a rectangle s ×ˢ t with
s ∈ F and t ∈ G. The notation ×ˢ covers both the product of sets and
filters; the elaborator disambiguates from the types.
The single fact that drives every joint-limit proof:
example(x:α)(y:β):𝓝(x,y)=𝓝x×ˢ𝓝y:=nhds_prod_eq
So a two-variable continuity statement is just a Tendsto on a
product filter:
example(xy:ℝ):Tendsto(funp:ℝ×ℝ=>p.1+p.2)(𝓝(x,y))(𝓝(x+y)):=x:ℝy:ℝ⊢ Tendsto(funp=>p.1+p.2)(𝓝(x,y))(𝓝(x+y))x:ℝy:ℝ⊢ Tendsto(funp=>p.1+p.2)(𝓝x×ˢ𝓝y)(𝓝(x+y))-- New goal: Tendsto _ (𝓝 x ×ˢ 𝓝 y) (𝓝 (x + y))exacttendsto_fst.addtendsto_sndAll goals completed! 🐙
This is exactly how Mathlib phrases continuity of two-variable
operations (+, *, •). To go the other way (package two
continuous functions into a product), reach for
Continuous.prodMk.
Filter.NeBotl is the typeclass asserting l ≠ ⊥. Many limit
lemmas (anything that pulls a witness out of a ∀ᶠ, in particular)
require it, because over ⊥ everything is vacuously true. Common
instances fire automatically:
atTop on a nonempty [SemilatticeSupα] (the instance is
Filter.atTop_neBot).
𝓝x in any topological space.
Filter.mapfF whenever F is non-trivial.
The instance for atTop requires [Nonempty α]; forget it and
typeclass synthesis fails:
openFilterinexample{α:Type*}[SemilatticeSupα](s:Setα)(hs:∀ᶠxin(atTop:Filterα),x∈s):s.Nonempty:=failed to synthesize instance of type classatTop.NeBotHint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.hs.exists
failed to synthesize instance of type classatTop.NeBotHint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
Adding [Nonempty α] to the variables makes Filter.atTop_neBot
fire and the proof goes through.
Every limit in this chapter is a Tendsto (or ∀ᶠ) between two of the
filters below. To translate a classical statement, read off the source
and target from this table.