Skip to content

Commit d0060d7

Browse files
committed
feat(Data/Finset/Card): iterating a function's image on a finite set stabilises (leanprover-community#38488)
...and does so in a bounded number of steps (which is why this is Finset-specific). In a later PR, I'll add this for endofunctions on a fintype, as well as add a Set.Finite version.
1 parent d0f60b5 commit d0060d7

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

Mathlib/Data/Finset/Card.lean

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,4 +932,38 @@ theorem eraseInduction [DecidableEq α] {p : Finset α → Prop}
932932
(H : (S : Finset α) → (∀ s ∈ S, p (S.erase s)) → p S) (S : Finset α) : p S :=
933933
S.strongInduction fun S ih => H S fun _ hs => ih _ (erase_ssubset hs)
934934

935+
/--
936+
Given a function `f` which sends the finite set `s` to itself, the sequence of images of `s` under
937+
iterates of `f` is eventually constant. Furthermore, the sequence of images stabilises in fewer
938+
than `#s` steps.
939+
-/
940+
theorem image_iterate_stabilises_lt_card [DecidableEq α] {f : α → α} {s : Finset α}
941+
(hs : Set.MapsTo f s s) (hs₀ : s.Nonempty) :
942+
∃ n < #s, ∀ m, n ≤ m → s.image f^[m] = s.image f^[n] := by
943+
let g (i : ℕ) : Finset α := s.image f^[i]
944+
have (i : ℕ) : 0 < #(g i) := (hs₀.image _).card_pos
945+
have hg : Antitone g := antitone_nat_of_succ_le <| fun i ↦ by
946+
simp_rw [g, Function.iterate_succ, ← image_image]
947+
grw [hs.finsetImage_subset]
948+
have eq_iff (i j : ℕ) : #(g i) - 1 = #(g j) - 1 ↔ g i = g j := by
949+
wlog hij : j ≤ i generalizing i j
950+
· grind
951+
exact ⟨fun h ↦ eq_of_subset_of_card_le (hg hij) (by grind), by grind⟩
952+
have hG : Antitone (fun i ↦ #(g i) - 1) := fun i j h ↦ by dsimp; gcongr #?_ - 1; exact hg h
953+
rcases Nat.stabilises_of_antitone hG (by grind [=_ image_image, iterate_succ']) with ⟨n, hn, hn'⟩
954+
exact ⟨n, by grind⟩
955+
956+
/--
957+
Given a function `f` which sends the finite set `s` to itself, the sequence of images of `s` under
958+
iterates of `f` is eventually constant. Furthermore, the sequence of images stabilises in at most
959+
`#s` steps.
960+
-/
961+
theorem image_iterate_stabilises_le_card [DecidableEq α] {f : α → α} {s : Finset α}
962+
(hs : Set.MapsTo f s s) :
963+
∃ n ≤ #s, ∀ m, n ≤ m → s.image f^[m] = s.image f^[n] := by
964+
obtain rfl | hs₀ := s.eq_empty_or_nonempty
965+
· simp
966+
obtain ⟨n, hn', hn⟩ := image_iterate_stabilises_lt_card hs hs₀
967+
exact ⟨n, hn'.le, hn⟩
968+
935969
end Finset

Mathlib/Data/Finset/Image.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ theorem _root_.Function.Commute.finset_image [DecidableEq α] {f g : α → α}
403403
(h : Function.Commute f g) : Function.Commute (image f) (image g) :=
404404
Function.Semiconj.finset_image h
405405

406+
@[gcongr]
406407
theorem image_subset_image {s₁ s₂ : Finset α} (h : s₁ ⊆ s₂) : s₁.image f ⊆ s₂.image f := by
407408
simp only [subset_def, image_val, subset_dedup', dedup_subset', Multiset.map_subset_map h]
408409

0 commit comments

Comments
 (0)