Files
AlgebraInLean/Book/LittleFermat.lean
T
2026-08-11 13:59:48 +02:00

153 lines
5.9 KiB
Lean4
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import VersoManual
import Manual.Meta
-- Minimal-Import statt `import Mathlib`: lädt nur den
-- benötigten Teil der Bibliothek und beschleunigt den
-- Buch-Build erheblich (ermittelt mit `#min_imports`).
import Mathlib.FieldTheory.Finite.Basic
open Verso.Genre Manual
open Verso.Genre.Manual.InlineLean
set_option pp.rawOnError true
set_option verso.docstring.allowMissing true
#doc (Manual) "Der kleine Satz von Fermat" =>
%%%
htmlSplit := .never
tag := "little-fermat"
file := "little-fermat"
%%%
Unser erster Beweis übersetzt Satz 17.5.1 des Skripts. Hier das
deutsche Original, Aussage und Beweis:
> *Satz 17.5.1 (Kleiner Satz von Fermat).* Es sei $`p \in \mathbb{N}`
eine Primzahl und es sei $`a \in \mathbb{Z}` irgendeine Zahl. Dann
ist $`a^p \equiv a \pmod{p}`.
> _Beweis._ Falls $`a` ein Vielfaches von $`p` ist, ist die Sache
klar. Ansonsten liefert die Restklasse von $`a` ein
nicht-verschwindendes Element
$`\overline{a} \in \mathbb{Z}/(p) = \mathbb{F}_p`, also ein Element
der multiplikativen Gruppe $`\mathbb{F}_p^*`, welche $`p-1` Elemente
hat. Nach dem Satz von Lagrange ist die Ordnung von
$`\overline{a}`, also die Größe der von $`\overline{a}` erzeugten
Untergruppe, ein Teiler von $`|\mathbb{F}_p^*| = p-1`. Es gilt also
$`\overline{a}^{p-1} = 1 \in \mathbb{F}_p^*`, oder äquivalent
$`a^p \equiv a \pmod{p}`.
Fünf Sätze. Unser Ziel ist ein Lean-Beweis mit genau dieser Struktur
jeder deutsche Satz kehrt als Kommentar über dem Lean-Code wieder, der
ihn umsetzt.
# Das Mathlib-Wörterbuch
Bevor wir den Satz überhaupt formulieren können, müssen wir wissen, wie
Mathlib über die beteiligten Objekte spricht.
* Der Restklassenring $`\mathbb{Z}/(p)` heißt `ZMod p`. Die
Restklasse einer ganzen Zahl `a : ` schreibt sich `(a : ZMod p)`
Lean fügt den kanonischen Ringmorphismus
$`\mathbb{Z} \to \mathbb{Z}/(p)` automatisch ein (eine _Koerzion_).
* Die Kongruenz $`a \equiv b \pmod{p}` für ganze Zahlen schreibt sich
`a b [ZMOD p]`.
* Die multiplikative Gruppe $`\mathbb{F}_p^*` ist die Gruppe der
_Einheiten_ des Rings `ZMod p`, geschrieben `(ZMod p)ˣ`. Eine
Einheit `u : (ZMod p)ˣ` kennt ihr Inverses; das zugrundeliegende
Ringelement schreibt sich wieder `(u : ZMod p)`.
* Das Skript sagt es sei $`p` eine Primzahl“. In Lean führen wir die
Primalität von `p` als Hypothese `hp : p.Prime` mit. Manche
Tatsachen etwa dass $`\mathbb{Z}/(p)` ein Körper ist findet
Leans Automatisierung nur, wenn die Hypothese als _Instanz_
registriert ist; genau das leistet die erste Beweiszeile
`have : Fact p.Prime := hp⟩`.
# Der Beweis, Satz für Satz
```lean
theorem little_fermat (p : ) (hp : p.Prime) (a : ) :
a ^ p a [ZMOD p] := by
have : Fact p.Prime := hp
-- Die Kongruenz „a^p ≡ a (mod p)“ bedeutet gerade, dass
-- a^p und a dieselbe Restklasse in /(p) haben. Wir
-- dürfen also stattdessen eine *Gleichung* im Ring
-- `ZMod p` zeigen; das Beweisziel wird
-- (a : ZMod p) ^ p = (a : ZMod p).
rw [ ZMod.intCast_eq_intCast_iff]
push_cast
-- „Falls a ein Vielfaches von p ist, ist die Sache klar.“
by_cases ha : (a : ZMod p) = 0
· rw [ha, zero_pow hp.ne_zero]
-- „Ansonsten liefert die Restklasse von a ein
-- nicht-verschwindendes Element ā ∈ /(p) = 𝔽_p, also
-- ein Element der multiplikativen Gruppe 𝔽_p^*, …“
· obtain u, hu : IsUnit (a : ZMod p) :=
isUnit_iff_ne_zero.mpr ha
rw [ hu]
-- „… welche p1 Elemente hat.“
have card_units : Nat.card (ZMod p)ˣ = p - 1 := by
rw [Nat.card_eq_fintype_card, ZMod.card_units p]
-- „Nach Satz 17.2.4 («Satz von Lagrange») ist die
-- Ordnung von ā, also die Größe der von ā erzeugten
-- Untergruppe, ein Teiler von |𝔽_p^*| = p1.“
have lagrange :
Nat.card (Subgroup.zpowers u)
Nat.card (ZMod p)ˣ :=
Subgroup.card_subgroup_dvd_card (Subgroup.zpowers u)
have ord_dvd : orderOf u p - 1 := by
rw [ Nat.card_zpowers, card_units]
exact lagrange
-- „Es gilt also ā^(p1) = 1 ∈ 𝔽_p^* …“
have pow_eq_one : u ^ (p - 1) = 1 :=
orderOf_dvd_iff_pow_eq_one.mp ord_dvd
-- „… oder äquivalent a^p ≡ a (mod p).“
have key : u ^ p = u := by
calc u ^ p
= u ^ (p - 1 + 1) := by
rw [Nat.sub_add_cancel hp.one_lt.le]
_ = u ^ (p - 1) * u := pow_succ u (p - 1)
_ = u := by rw [pow_eq_one, one_mul]
exact_mod_cast congrArg Units.val key
```
Man beachte, wie treu die Übersetzung ist. Die Fallunterscheidung
Falls ist die Sache klar / Ansonsten …“ wird zu `by_cases`; das
Zitat des Satzes von Lagrange wird zum Bibliothekslemma
`Subgroup.card_subgroup_dvd_card`; und die Formulierung die Ordnung
von `ā`, also die Größe der von `ā` erzeugten Untergruppe ist genau
das Umschreiben mit `Nat.card_zpowers`, das `orderOf u` mit der
Mächtigkeit der von `u` erzeugten Untergruppe `Subgroup.zpowers u`
identifiziert.
# Bemerkungen
Mathlib enthält den kleinen Satz von Fermat natürlich längst; die
Aussage über Restklassen heißt `ZMod.pow_card`. Solche Lemmata findet
man selbst mit der Taktik `exact?` oder über die Suchmaschinen
[leansearch.net](https://leansearch.net) und
[loogle.lean-lang.org](https://loogle.lean-lang.org).
```lean
example (p : ) [Fact p.Prime] (a : ZMod p) : a ^ p = a :=
ZMod.pow_card a
```
# Übungsaufgabe
Das ist die Bemerkung nach dem Satz im Skript: In Anwendungen
verwendet man häufig die äquivalente Formulierung
$`a^{p-1} \equiv 1 \pmod{p}` für nicht durch $`p` teilbare $`a`. Leiten Sie
sie aus `little_fermat` ab oder geben Sie einen direkten Beweis nach
den Ideen oben. Öffnen Sie `AlgebraInLean/LittleFermat.lean` im
Übungs-Repository und ersetzen Sie das `sorry` durch einen Beweis.
```lean
theorem little_fermat' (p : ) (hp : p.Prime) (a : )
(ha : ¬ (p : ) a) :
a ^ (p - 1) 1 [ZMOD p] := by
sorry
```