Skip to content

Commit 9aeba39

Browse files
committed
feat(Dynamics/Flow): define semiconjugacy, factor and orbit (leanprover-community#28000)
We add definitions relating to flows. This contribution was created as part of the Utrecht Summerschool "Formalizing Mathematics in Lean" in July 2025. Co-authored-by: figud <40865765+figud@users.noreply.github.com>
1 parent f83741b commit 9aeba39

7 files changed

Lines changed: 141 additions & 21 deletions

File tree

Mathlib/CategoryTheory/Galois/Examples.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ theorem Action.pretransitive_of_isConnected (X : Action FintypeCat G)
120120
have : IsIso i := by
121121
apply IsConnected.noTrivialComponent T' i
122122
apply (not_initial_iff_fiber_nonempty (Action.forget _ _) T').mpr
123-
exact Set.Nonempty.coe_sort (MulAction.orbit_nonempty x)
123+
exact Set.Nonempty.coe_sort (MulAction.nonempty_orbit x)
124124
have hb : Function.Bijective i.hom := by
125125
apply (ConcreteCategory.isIso_iff_bijective i.hom).mp
126126
exact map_isIso (forget₂ _ FintypeCat) i

Mathlib/Data/ZMod/QuotientGroup.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ instance minimalPeriod_pos [Finite <| orbit (zpowers a) b] :
139139
NeZero <| minimalPeriod (a • ·) b :=
140140
by
141141
cases nonempty_fintype (orbit (zpowers a) b)
142-
haveI : Nonempty (orbit (zpowers a) b) := (orbit_nonempty b).to_subtype
142+
haveI : Nonempty (orbit (zpowers a) b) := (nonempty_orbit b).to_subtype
143143
rw [minimalPeriod_eq_card]
144144
exact Fintype.card_ne_zero⟩
145145

Mathlib/Dynamics/Flow.lean

Lines changed: 128 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Authors: Jean Lo
66
import Mathlib.Logic.Function.Iterate
77
import Mathlib.Topology.Algebra.Monoid
88
import Mathlib.Topology.Algebra.Group.Defs
9+
import Mathlib.Algebra.Order.Monoid.Submonoid
910

1011
/-!
1112
# Flows and invariant sets
@@ -22,9 +23,9 @@ if `ϕₜ s ⊆ s` for all `t`. In many cases `ϕ` will be a flow on
2223
commutative) monoid, we additionally define forward invariance, where
2324
`t` ranges over those elements which are nonnegative.
2425
25-
Additionally, we define such constructions as the restriction of a
26-
flow onto an invariant subset, and the time-reversal of a flow by a
27-
group.
26+
Additionally, we define such constructions as the (forward) orbit, a
27+
semiconjugacy between flows, a factor of a flow, the restriction of a
28+
flow onto an invariant subset, and the time-reversal of a flow by a group.
2829
-/
2930

3031

@@ -47,24 +48,35 @@ theorem isInvariant_iff_image : IsInvariant ϕ s ↔ ∀ t, ϕ t '' s ⊆ s := b
4748
simp_rw [IsInvariant, mapsTo_iff_image_subset]
4849

4950
/-- A set `s ⊆ α` is forward-invariant under `ϕ : τ → α → α` if `ϕ t s ⊆ s` for all `t ≥ 0`. -/
50-
def IsFwInvariant [Preorder τ] [Zero τ] (ϕ : τ → α → α) (s : Set α) : Prop :=
51+
def IsForwardInvariant [Preorder τ] [Zero τ] (ϕ : τ → α → α) (s : Set α) : Prop :=
5152
∀ ⦃t⦄, 0 ≤ t → MapsTo (ϕ t) s s
5253

53-
theorem IsInvariant.isFwInvariant [Preorder τ] [Zero τ] {ϕ : τ → α → α} {s : Set α}
54-
(h : IsInvariant ϕ s) : IsFwInvariant ϕ s := fun t _ht => h t
54+
@[deprecated (since := "2025-09-25")] alias IsFwInvariant := IsForwardInvariant
55+
56+
theorem IsInvariant.isForwardInvariant [Preorder τ] [Zero τ] {ϕ : τ → α → α} {s : Set α}
57+
(h : IsInvariant ϕ s) : IsForwardInvariant ϕ s := fun t _ht => h t
58+
59+
@[deprecated (since := "2025-09-25")]
60+
alias IsInvariant.isFwInvariant := IsInvariant.isForwardInvariant
5561

5662
/-- If `τ` is a `CanonicallyOrderedAdd` monoid (e.g., `ℕ` or `ℝ≥0`), then the notions
57-
`IsFwInvariant` and `IsInvariant` are equivalent. -/
58-
theorem IsFwInvariant.isInvariant [AddMonoid τ] [PartialOrder τ] [CanonicallyOrderedAdd τ]
63+
`IsForwardInvariant` and `IsInvariant` are equivalent. -/
64+
theorem IsForwardInvariant.isInvariant [AddMonoid τ] [PartialOrder τ] [CanonicallyOrderedAdd τ]
5965
{ϕ : τ → α → α} {s : Set α}
60-
(h : IsFwInvariant ϕ s) : IsInvariant ϕ s := fun t => h (zero_le t)
66+
(h : IsForwardInvariant ϕ s) : IsInvariant ϕ s := fun t => h (zero_le t)
67+
68+
@[deprecated (since := "2025-09-25")]
69+
alias IsFwInvariant.isInvariant := IsForwardInvariant.isInvariant
6170

6271
/-- If `τ` is a `CanonicallyOrderedAdd` monoid (e.g., `ℕ` or `ℝ≥0`), then the notions
63-
`IsFwInvariant` and `IsInvariant` are equivalent. -/
64-
theorem isFwInvariant_iff_isInvariant [AddMonoid τ] [PartialOrder τ] [CanonicallyOrderedAdd τ]
72+
`IsForwardInvariant` and `IsInvariant` are equivalent. -/
73+
theorem isForwardInvariant_iff_isInvariant [AddMonoid τ] [PartialOrder τ] [CanonicallyOrderedAdd τ]
6574
{ϕ : τ → α → α} {s : Set α} :
66-
IsFwInvariant ϕ s ↔ IsInvariant ϕ s :=
67-
⟨IsFwInvariant.isInvariant, IsInvariant.isFwInvariant⟩
75+
IsForwardInvariant ϕ s ↔ IsInvariant ϕ s :=
76+
⟨IsForwardInvariant.isInvariant, IsInvariant.isForwardInvariant⟩
77+
78+
@[deprecated (since := "2025-09-25")]
79+
alias isFwInvariant_iff_isInvariant := isForwardInvariant_iff_isInvariant
6880

6981
end Invariant
7082

@@ -131,6 +143,109 @@ def restrict {s : Set α} (h : IsInvariant ϕ s) : Flow τ (↥s) where
131143
map_add' _ _ _ := Subtype.ext (map_add _ _ _ _)
132144
map_zero' _ := Subtype.ext (map_zero_apply _ _)
133145

146+
@[simp]
147+
theorem coe_restrict_apply {s : Set α} (h : IsInvariant ϕ s) (t : τ) (x : s) :
148+
restrict ϕ h t x = ϕ t x := rfl
149+
150+
/-- Convert a flow to an additive monoid action. -/
151+
def toAddAction : AddAction τ α where
152+
vadd := ϕ
153+
add_vadd := ϕ.map_add'
154+
zero_vadd := ϕ.map_zero'
155+
156+
/-- Restrict a flow by `τ` to a flow by an additive submonoid of `τ`. -/
157+
def restrictAddSubmonoid (S : AddSubmonoid τ) : Flow S α where
158+
toFun t x := ϕ t x
159+
cont' := ϕ.continuous (continuous_subtype_val.comp continuous_fst) continuous_snd
160+
map_add' t₁ t₂ x := ϕ.map_add' t₁ t₂ x
161+
map_zero' := ϕ.map_zero'
162+
163+
theorem restrictAddSubmonoid_apply (S : AddSubmonoid τ) (t : S) (x : α) :
164+
restrictAddSubmonoid ϕ S t x = ϕ t x := rfl
165+
166+
section Orbit
167+
168+
/-- The orbit of a point under a flow. -/
169+
def orbit (x : α) : Set α := ϕ.toAddAction.orbit _ x
170+
171+
theorem orbit_eq_range (x : α) : orbit ϕ x = Set.range (fun t => ϕ t x) := rfl
172+
173+
theorem mem_orbit_iff {x₁ x₂ : α} : x₂ ∈ orbit ϕ x₁ ↔ ∃ t : τ, ϕ t x₁ = x₂ :=
174+
ϕ.toAddAction.mem_orbit_iff
175+
176+
theorem mem_orbit (x : α) (t : τ) : ϕ t x ∈ orbit ϕ x := ϕ.toAddAction.mem_orbit ..
177+
178+
theorem mem_orbit_self (x : α) : x ∈ orbit ϕ x := ϕ.toAddAction.mem_orbit_self x
179+
180+
theorem nonempty_orbit (x : α) : Set.Nonempty (orbit ϕ x) := ϕ.toAddAction.nonempty_orbit x
181+
182+
theorem mem_orbit_of_mem_orbit {x₁ x₂ : α} (t : τ) (h : x₂ ∈ orbit ϕ x₁) : ϕ t x₂ ∈ orbit ϕ x₁ :=
183+
ϕ.toAddAction.mem_orbit_of_mem_orbit t h
184+
185+
/-- The orbit of a point under a flow `ϕ` is invariant under `ϕ`. -/
186+
theorem isInvariant_orbit (x : α) : IsInvariant ϕ (orbit ϕ x) :=
187+
fun t _ => ϕ.toAddAction.mem_orbit_of_mem_orbit t
188+
189+
theorem orbit_restrict (s : Set α) (hs : IsInvariant ϕ s) (x : s) :
190+
orbit (ϕ.restrict hs) x = Subtype.val ⁻¹' orbit ϕ x :=
191+
Set.ext (fun x => by simp [orbit_eq_range, Subtype.ext_iff])
192+
193+
variable [Preorder τ] [AddLeftMono τ]
194+
195+
/-- Restrict a flow by `τ` to a flow by the additive submonoid of nonnegative elements of `τ`. -/
196+
def restrictNonneg : Flow (AddSubmonoid.nonneg τ) α := ϕ.restrictAddSubmonoid (.nonneg τ)
197+
198+
/-- The forward orbit of a point under a flow. -/
199+
def forwardOrbit (x : α) : Set α := orbit ϕ.restrictNonneg x
200+
201+
theorem forwardOrbit_eq_range_nonneg (x : α) :
202+
forwardOrbit ϕ x = Set.range (fun t : {t : τ // 0 ≤ t} => ϕ t x) := rfl
203+
204+
/-- The forward orbit of a point under a flow `ϕ` is forward-invariant under `ϕ`. -/
205+
theorem isForwardInvariant_forwardOrbit (x : α) : IsForwardInvariant ϕ (forwardOrbit ϕ x) :=
206+
fun t h => IsInvariant.isForwardInvariant (isInvariant_orbit ϕ.restrictNonneg x) (t := ⟨t, h⟩) h
207+
208+
/-- The forward orbit of a point `x` is contained in the orbit of `x`. -/
209+
theorem forwardOrbit_subset_orbit (x : α) : forwardOrbit ϕ x ⊆ orbit ϕ x :=
210+
ϕ.toAddAction.orbit_addSubmonoid_subset (AddSubmonoid.nonneg τ) x
211+
212+
theorem mem_orbit_of_mem_forwardOrbit {x₁ x₂ : α} (h : x₁ ∈ forwardOrbit ϕ x₂) : x₁ ∈ orbit ϕ x₂ :=
213+
ϕ.forwardOrbit_subset_orbit x₂ h
214+
215+
end Orbit
216+
217+
variable {β γ : Type*} [TopologicalSpace β] [TopologicalSpace γ] (ψ : Flow τ β) (χ : Flow τ γ)
218+
219+
/-- Given flows `ϕ` by `τ` on `α` and `ψ` by `τ` on `β`, a function `π : α → β` is called a
220+
*semiconjugacy* from `ϕ` to `ψ` if `π` is continuous and surjective, and `π ∘ (ϕ t) = (ψ t) ∘ π` for
221+
all `t : τ`. -/
222+
structure IsSemiconjugacy (π : α → β) (ϕ : Flow τ α) (ψ : Flow τ β) : Prop where
223+
cont : Continuous π
224+
surj : Function.Surjective π
225+
semiconj : ∀ t, Function.Semiconj π (ϕ t) (ψ t)
226+
227+
/-- The composition of semiconjugacies is a semiconjugacy. -/
228+
theorem IsSemiconjugacy.comp {π : α → β} {ρ : β → γ}
229+
(h₁ : IsSemiconjugacy π ϕ ψ) (h₂ : IsSemiconjugacy ρ ψ χ) : IsSemiconjugacy (ρ ∘ π) ϕ χ :=
230+
⟨h₂.cont.comp h₁.cont, h₂.surj.comp h₁.surj, fun t => (h₂.semiconj t).comp_left (h₁.semiconj t)⟩
231+
232+
/-- The identity is a semiconjugacy from `ϕ` to `ψ` if and only if `ϕ` and `ψ` are equal. -/
233+
theorem isSemiconjugacy_id_iff_eq (ϕ ψ : Flow τ α) : IsSemiconjugacy id ϕ ψ ↔ ϕ = ψ :=
234+
fun h => ext h.semiconj, fun h => h.recOn ⟨continuous_id, surjective_id, fun _ => .id_left⟩⟩
235+
236+
/-- A flow `ψ` is called a *factor* of `ϕ` if there exists a semiconjugacy from `ϕ` to `ψ`. -/
237+
def IsFactorOf (ψ : Flow τ β) (ϕ : Flow τ α) : Prop := ∃ π : α → β, IsSemiconjugacy π ϕ ψ
238+
239+
theorem IsSemiconjugacy.isFactorOf {π : α → β} (h : IsSemiconjugacy π ϕ ψ) : IsFactorOf ψ ϕ :=
240+
⟨π, h⟩
241+
242+
/-- Transitivity of factors of flows. -/
243+
theorem IsFactorOf.trans (h₁ : IsFactorOf ϕ ψ) (h₂ : IsFactorOf ψ χ) : IsFactorOf ϕ χ :=
244+
h₁.elim fun π hπ => h₂.elim fun ρ hρ => ⟨π ∘ ρ, hρ.comp χ ψ ϕ hπ⟩
245+
246+
/-- Every flow is a factor of itself. -/
247+
theorem IsFactorOf.self : IsFactorOf ϕ ϕ := ⟨id, (isSemiconjugacy_id_iff_eq ϕ ϕ).mpr (by rfl)⟩
248+
134249
end Flow
135250

136251
namespace Flow

Mathlib/Dynamics/Minimal.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,4 @@ theorem isMinimal_iff_isClosed_smul_invariant [ContinuousConstSMul M α] :
100100
exact eq_empty_or_univ_of_smul_invariant_closed M
101101
refine fun H ↦ ⟨fun _ ↦ dense_iff_closure_eq.2 <| (H _ ?_ ?_).resolve_left ?_⟩
102102
exacts [isClosed_closure, fun _ ↦ smul_closure_orbit_subset _ _,
103-
(orbit_nonempty _).closure.ne_empty]
103+
(nonempty_orbit _).closure.ne_empty]

Mathlib/GroupTheory/GroupAction/Basic.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ theorem mem_fixedPoints_iff_card_orbit_eq_one {a : α} [Fintype (orbit M a)] :
8787
a ∈ fixedPoints M α ↔ Fintype.card (orbit M a) = 1 := by
8888
simp only [← subsingleton_orbit_iff_mem_fixedPoints, le_antisymm_iff,
8989
Fintype.card_le_one_iff_subsingleton, Nat.add_one_le_iff, Fintype.card_pos_iff,
90-
Set.subsingleton_coe, iff_self_and, Set.nonempty_coe_sort, orbit_nonempty, implies_true]
90+
Set.subsingleton_coe, iff_self_and, Set.nonempty_coe_sort, nonempty_orbit, implies_true]
9191

9292
@[to_additive instDecidablePredMemSetFixedByAddOfDecidableEq]
9393
instance (m : M) [DecidableEq β] :

Mathlib/GroupTheory/GroupAction/Blocks.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ theorem IsPartition.of_orbits :
7878
· intro x
7979
exact ⟨_, ⟨x, rfl⟩, mem_orbit_self x⟩
8080
· rintro ⟨a, ha : orbit G a = ∅⟩
81-
exact (MulAction.orbit_nonempty a).ne_empty ha
81+
exact (MulAction.nonempty_orbit a).ne_empty ha
8282

8383
end orbits
8484

Mathlib/GroupTheory/GroupAction/Defs.lean

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ theorem mem_orbit_self (a : α) : a ∈ orbit M a :=
6565
1, by simp⟩
6666

6767
@[to_additive]
68-
theorem orbit_nonempty (a : α) : Set.Nonempty (orbit M a) :=
68+
theorem nonempty_orbit (a : α) : Set.Nonempty (orbit M a) :=
6969
Set.range_nonempty _
7070

71+
@[deprecated (since := "2025-09-25")] alias orbit_nonempty := nonempty_orbit
72+
7173
@[to_additive]
7274
theorem mapsTo_smul_orbit (m : M) (a : α) : Set.MapsTo (m • ·) (orbit M a) (orbit M a) :=
7375
Set.range_subset_iff.2 fun m' => ⟨m * m', mul_smul _ _ _⟩
@@ -388,10 +390,13 @@ lemma orbitRel.quotient_eq_of_quotient_subgroup_eq' {H : Subgroup G} {a b : α}
388390
orbitRel.quotient_eq_of_quotient_subgroup_eq h
389391

390392
@[to_additive]
391-
nonrec lemma orbitRel.Quotient.orbit_nonempty (x : orbitRel.Quotient G α) :
393+
nonrec lemma orbitRel.Quotient.nonempty_orbit (x : orbitRel.Quotient G α) :
392394
Set.Nonempty x.orbit := by
393395
rw [orbitRel.Quotient.orbit_eq_orbit_out x Quotient.out_eq']
394-
exact orbit_nonempty _
396+
exact nonempty_orbit _
397+
398+
@[deprecated (since := "2025-09-25")]
399+
alias orbitRel.Quotient.orbit_nonempty := orbitRel.Quotient.nonempty_orbit
395400

396401
@[to_additive]
397402
nonrec lemma orbitRel.Quotient.mapsTo_smul_orbit (g : G) (x : orbitRel.Quotient G α) :

0 commit comments

Comments
 (0)