9. Grup dan Gelanggang

Dalam Bab 2.2, kita telah melihat cara menalar tentang operasi pada grup dan gelanggang. Kemudian, dalam Bab 7.2, kita melihat cara mendefinisikan struktur aljabar abstrak, seperti struktur grup, beserta instans konkret seperti struktur gelanggang pada bilangan bulat Gauss. Bab 8 menjelaskan cara hierarki struktur abstrak ditangani dalam Mathlib.

Dalam bab ini, kita akan mempelajari grup dan gelanggang secara lebih terperinci. Kita tidak akan dapat membahas setiap aspek penanganan topik-topik tersebut dalam Mathlib, terlebih karena Mathlib terus berkembang. Namun, kita akan menyediakan titik masuk ke pustaka dan menunjukkan cara menggunakan konsep-konsep esensial. Ada sedikit tumpang tindih dengan pembahasan dalam Bab 8, tetapi di sini kita akan berfokus pada cara menggunakan Mathlib, bukan pada keputusan desain yang mendasari penanganan topik-topik tersebut. Karena itu, memahami sebagian contoh mungkin memerlukan peninjauan kembali latar belakang dari Bab 8.

9.1. Monoid dan Grup

9.1.1. Monoid dan morfismenya

Kuliah aljabar abstrak sering dimulai dengan grup, lalu berlanjut ke gelanggang, medan, dan ruang vektor. Hal ini menuntut beberapa penyesuaian ketika membahas perkalian pada gelanggang, sebab operasi perkalian tersebut tidak berasal dari struktur grup, tetapi banyak buktinya dapat dipindahkan kata demi kata dari teori grup ke konteks baru ini. Solusi yang paling lazim ketika mengerjakan matematika dengan pena dan kertas adalah menyerahkan bukti tersebut sebagai latihan. Cara yang kurang efisien, tetapi lebih aman dan lebih ramah formalisasi, adalah menggunakan monoid. Struktur monoid pada tipe M merupakan hukum komposisi internal yang asosiatif dan memiliki elemen netral.

Monoid terutama digunakan untuk mencakup grup sekaligus struktur multiplikatif gelanggang. Namun, ada pula sejumlah contoh alami; misalnya, himpunan bilangan asli yang dilengkapi penjumlahan membentuk monoid.

Dari sudut pandang praktis, Anda dapat mengabaikan monoid hampir sepenuhnya ketika menggunakan Mathlib. Namun, Anda perlu mengetahui keberadaannya ketika mencari lemma dengan menelusuri berkas Mathlib. Jika tidak, Anda mungkin mencari suatu pernyataan dalam berkas teori grup, padahal pernyataan tersebut terdapat pada bagian monoid karena tidak memerlukan elemen yang dapat dibalik.

Tipe struktur monoid pada tipe M ditulis Monoid M. Monoid merupakan kelas tipe, sehingga hampir selalu muncul sebagai argumen instans implisit (dengan kata lain, di dalam tanda kurung siku). Secara baku, Monoid menggunakan notasi multiplikatif bagi operasinya; untuk notasi aditif, gunakan AddMonoid. Versi komutatif struktur tersebut menambahkan prefiks Comm sebelum Monoid.

example {M : Type*} [Monoid M] (x : M) : x * 1 = x := mul_one x

example {M : Type*} [AddCommMonoid M] (x y : M) : x + y = y + x := add_comm x y

Perhatikan bahwa meskipun AddMonoid tersedia di pustaka, penggunaan notasi aditif untuk operasi nonkomutatif umumnya membingungkan.

Tipe morfisme di antara monoid M dan N disebut MonoidHom M N dan ditulis M →* N. Lean secara otomatis memandang morfisme semacam itu sebagai fungsi dari M ke N ketika kita menerapkannya pada elemen M. Versi aditifnya disebut AddMonoidHom dan ditulis M →+ N.

example {M N : Type*} [Monoid M] [Monoid N] (x y : M) (f : M →* N) : f (x * y) = f x * f y :=
  f.map_mul x y

example {M N : Type*} [AddMonoid M] [AddMonoid N] (f : M →+ N) : f 0 = 0 :=
  f.map_zero

Morfisme tersebut merupakan pemetaan terbundel, yakni mengemas sebuah pemetaan beserta beberapa sifatnya. Ingat bahwa Bab 8.2 menjelaskan pemetaan terbundel. Di sini, kita hanya mencatat konsekuensi yang sedikit disayangkan: komposisi fungsi biasa tidak dapat digunakan untuk mengomposisikan pemetaan ini. Sebagai gantinya, kita perlu menggunakan MonoidHom.comp dan AddMonoidHom.comp.

example {M N P : Type*} [AddMonoid M] [AddMonoid N] [AddMonoid P]
    (f : M →+ N) (g : N →+ P) : M →+ P := g.comp f

9.1.2. Grup dan morfismenya

Kita akan membahas grup jauh lebih banyak. Grup merupakan monoid dengan sifat tambahan bahwa setiap elemennya memiliki invers.

example {G : Type*} [Group G] (x : G) : x * x⁻¹ = 1 := mul_inv_cancel x

Serupa dengan taktik ring yang telah kita lihat, terdapat taktik group yang membuktikan setiap identitas yang berlaku dalam sembarang grup. (Secara ekuivalen, taktik ini membuktikan identitas yang berlaku dalam grup bebas.)

example {G : Type*} [Group G] (x y z : G) : x * (y * z) * (x * z)⁻¹ * (x * y * x⁻¹)⁻¹ = 1 := by
  group

Terdapat pula taktik bernama abel untuk identitas dalam grup aditif komutatif.

example {G : Type*} [AddCommGroup G] (x y z : G) : z + x + (y - z - x) = y := by
  abel

Menariknya, morfisme grup tidak lebih dari morfisme monoid di antara grup. Karena itu, kita dapat menyalin salah satu contoh terdahulu dan mengganti Monoid dengan Group.

example {G H : Type*} [Group G] [Group H] (x y : G) (f : G →* H) : f (x * y) = f x * f y :=
  f.map_mul x y

Tentu saja, kita memperoleh beberapa sifat baru, seperti berikut:

example {G H : Type*} [Group G] [Group H] (x : G) (f : G →* H) : f (x⁻¹) = (f x)⁻¹ :=
  f.map_inv x

Anda mungkin khawatir bahwa pembangunan morfisme grup mengharuskan kita melakukan pekerjaan yang tidak perlu. Definisi morfisme monoid mewajibkan elemen netral dipetakan ke elemen netral, padahal hal tersebut berlaku otomatis bagi morfisme grup. Dalam praktiknya pekerjaan tambahan ini tidak sulit, tetapi untuk menghindarinya tersedia fungsi yang membangun morfisme grup dari fungsi di antara grup yang kompatibel dengan hukum komposisi.

example {G H : Type*} [Group G] [Group H] (f : G  H) (h :  x y, f (x * y) = f x * f y) :
    G →* H :=
  MonoidHom.mk' f h

Terdapat pula tipe MulEquiv bagi isomorfisme grup (atau monoid), yang dinyatakan dengan ≃* (serta AddEquiv, yang dinyatakan dengan ≃+ dalam notasi aditif). Invers dari f : G ≃* H adalah MulEquiv.symm f : H ≃* G, komposisi f dan g adalah MulEquiv.trans f g, dan isomorfisme identitas pada G adalah MulEquiv.refl G. Dengan notasi proyektor anonim, dua yang pertama masing-masing dapat ditulis f.symm dan f.trans g. Elemen tipe ini secara otomatis dikoersikan menjadi morfisme dan fungsi apabila diperlukan.

example {G H : Type*} [Group G] [Group H] (f : G ≃* H) :
    f.trans f.symm = MulEquiv.refl G :=
  f.self_trans_symm

Kita dapat menggunakan MulEquiv.ofBijective untuk membangun isomorfisme dari morfisme bijektif. Cara ini membuat fungsi inversnya tidak dapat dihitung.

noncomputable example {G H : Type*} [Group G] [Group H]
    (f : G →* H) (h : Function.Bijective f) :
    G ≃* H :=
  MulEquiv.ofBijective f h

9.1.3. Subgrup

Sebagaimana morfisme grup dibundel, subgrup dari G juga merupakan struktur terbundel yang terdiri atas himpunan di G beserta sifat-sifat ketertutupan yang relevan.

example {G : Type*} [Group G] (H : Subgroup G) {x y : G} (hx : x  H) (hy : y  H) :
    x * y  H :=
  H.mul_mem hx hy

example {G : Type*} [Group G] (H : Subgroup G) {x : G} (hx : x  H) :
    x⁻¹  H :=
  H.inv_mem hx

Dalam contoh di atas, penting untuk dipahami bahwa Subgroup G merupakan tipe subgrup dari G, bukan predikat IsSubgroup H dengan H sebagai elemen Set G. Subgroup G dilengkapi koersi ke Set G dan predikat keanggotaan pada G. Lihat Bab 8.3 untuk penjelasan mengenai cara dan alasan hal ini dilakukan.

Tentu saja, dua subgrup sama jika dan hanya jika keduanya memiliki elemen yang sama. Fakta ini didaftarkan untuk digunakan bersama taktik ext. Taktik tersebut dapat membuktikan kesamaan dua subgrup dengan cara yang sama seperti ketika membuktikan kesamaan dua himpunan.

Sebagai contoh, untuk menyatakan dan membuktikan bahwa merupakan subgrup aditif dari , sebenarnya kita ingin mengonstruksi term bertipe AddSubgroup yang proyeksinya ke Set adalah , atau secara lebih tepat, citra di .

example : AddSubgroup  where
  carrier := Set.range (() :   )
  add_mem' := by
    rintro _ _ n, rfl m, rfl
    use n + m
    simp
  zero_mem' := by
    use 0
    simp
  neg_mem' := by
    rintro _ n, rfl
    use -n
    simp

Dengan menggunakan kelas tipe, Mathlib mengetahui bahwa subgrup dari suatu grup mewarisi struktur grup.

example {G : Type*} [Group G] (H : Subgroup G) : Group H := inferInstance

Contoh ini memiliki seluk-beluk. Objek H bukanlah tipe, tetapi Lean secara otomatis mengkoersikannya menjadi tipe dengan menafsirkannya sebagai subtipe dari G. Karena itu, contoh di atas dapat dinyatakan ulang secara lebih eksplisit sebagai berikut:

example {G : Type*} [Group G] (H : Subgroup G) : Group {x : G // x  H} := inferInstance

Manfaat penting dari penggunaan tipe Subgroup G alih-alih predikat IsSubgroup : Set G Prop adalah bahwa Subgroup G dapat dengan mudah dilengkapi struktur tambahan. Secara khusus, tipe tersebut memiliki struktur kekisi lengkap terhadap inklusi. Sebagai contoh, alih-alih memiliki lemma yang menyatakan bahwa irisan dua subgrup dari G kembali merupakan subgrup, kita menggunakan operasi kekisi untuk mengonstruksi irisannya. Selanjutnya, kita dapat menerapkan sembarang lemma tentang kekisi pada konstruksi tersebut.

Mari kita periksa bahwa himpunan yang mendasari infimum dua subgrup memang, berdasarkan definisi, merupakan irisan keduanya.

example {G : Type*} [Group G] (H H' : Subgroup G) :
    ((H  H' : Subgroup G) : Set G) = (H : Set G)  (H' : Set G) := rfl

Mungkin tampak aneh menggunakan notasi yang berbeda bagi sesuatu yang pada dasarnya merupakan irisan himpunan-himpunan yang mendasarinya. Namun, korespondensi tersebut tidak berlaku bagi operasi supremum dan gabungan himpunan, sebab gabungan subgrup pada umumnya bukan subgrup. Sebagai gantinya, kita perlu menggunakan subgrup yang dibangkitkan oleh gabungan tersebut, yang dilakukan dengan Subgroup.closure.

example {G : Type*} [Group G] (H H' : Subgroup G) :
    ((H  H' : Subgroup G) : Set G) = Subgroup.closure ((H : Set G)  (H' : Set G)) := by
  rw [Subgroup.sup_eq_closure]

Seluk-beluk lainnya adalah bahwa G itu sendiri tidak bertipe Subgroup G. Karena itu, kita memerlukan cara untuk membicarakan G sebagai subgrup dari G. Hal ini juga disediakan oleh struktur kekisi: subgrup penuh merupakan elemen teratas kekisi tersebut.

example {G : Type*} [Group G] (x : G) : x  ( : Subgroup G) := trivial

Serupa dengan itu, elemen terbawah kekisi ini adalah subgrup yang satu-satunya elemen adalah elemen netral.

example {G : Type*} [Group G] (x : G) : x  ( : Subgroup G)  x = 1 := Subgroup.mem_bot

Sebagai latihan memanipulasi grup dan subgrup, Anda dapat mendefinisikan konjugat suatu subgrup oleh elemen grup induknya.

def conjugate {G : Type*} [Group G] (x : G) (H : Subgroup G) : Subgroup G where
  carrier := {a : G |  h, h  H  a = x * h * x⁻¹}
  one_mem' := by
    dsimp
    sorry
  inv_mem' := by
    dsimp
    sorry
  mul_mem' := by
    dsimp
    sorry

Dengan menghubungkan dua topik sebelumnya, kita dapat mengambil citra langsung dan prapeta subgrup menggunakan morfisme grup. Konvensi penamaan dalam Mathlib menyebut kedua operasi tersebut map dan comap. Nama-nama ini bukan istilah matematika yang lazim, tetapi lebih singkat daripada "citra langsung" dan "prapeta".

example {G H : Type*} [Group G] [Group H] (G' : Subgroup G) (f : G →* H) : Subgroup H :=
  Subgroup.map f G'

example {G H : Type*} [Group G] [Group H] (H' : Subgroup H) (f : G →* H) : Subgroup G :=
  Subgroup.comap f H'

#check Subgroup.mem_map
#check Subgroup.mem_comap

Secara khusus, prapeta subgrup terbawah di bawah morfisme f merupakan subgrup yang disebut kernel dari f, dan citra f juga merupakan subgrup.

example {G H : Type*} [Group G] [Group H] (f : G →* H) (g : G) :
    g  MonoidHom.ker f  f g = 1 :=
  f.mem_ker

example {G H : Type*} [Group G] [Group H] (f : G →* H) (h : H) :
    h  MonoidHom.range f   g : G, f g = h :=
  f.mem_range

Sebagai latihan memanipulasi morfisme grup dan subgrup, mari kita buktikan beberapa sifat elementer. Sifat-sifat ini sudah dibuktikan dalam Mathlib, jadi jangan terlalu cepat menggunakan exact? jika ingin memperoleh manfaat dari latihan ini.

section exercises
variable {G H : Type*} [Group G] [Group H]

open Subgroup

example (φ : G →* H) (S T : Subgroup H) (hST : S  T) : comap φ S  comap φ T := by
  sorry

example (φ : G →* H) (S T : Subgroup G) (hST : S  T) : map φ S  map φ T := by
  sorry

variable {K : Type*} [Group K]

-- Ingat bahwa Anda dapat memakai taktik `ext` untuk membuktikan kesamaan subgrup.
example (φ : G →* H) (ψ : H →* K) (U : Subgroup K) :
    comap (ψ.comp φ) U = comap φ (comap ψ U) := by
  sorry

-- Mengambil citra langsung subgrup melalui satu homomorfisme lalu homomorfisme lain
-- sama dengan mengambil citra langsungnya melalui komposisi kedua homomorfisme.
example (φ : G →* H) (ψ : H →* K) (S : Subgroup G) :
    map (ψ.comp φ) S = map ψ (S.map φ) := by
  sorry

end exercises

Mari kita akhiri pengantar tentang subgrup dalam Mathlib ini dengan dua hasil klasik. Teorema Lagrange menyatakan bahwa kardinalitas subgrup dari suatu grup hingga membagi kardinalitas grup tersebut. Teorema pertama Sylow merupakan konvers parsial yang terkenal dari teorema Lagrange.

Walaupun bagian Mathlib ini sebagian disiapkan untuk memungkinkan penghitungan, kita tetap dapat meminta Lean menggunakan logika nonkonstruktif melalui perintah open scoped berikut.

open scoped Classical


example {G : Type*} [Group G] (G' : Subgroup G) : Nat.card G'  Nat.card G :=
  G'.index, mul_comm G'.index _  G'.index_mul_card.symm

open Subgroup

example {G : Type*} [Group G] [Finite G] (p : ) {n : } [Fact p.Prime]
    (hdvd : p ^ n  Nat.card G) :  K : Subgroup G, Nat.card K = p ^ n :=
  Sylow.exists_subgroup_card_pow_prime p hdvd

Dua latihan berikut menurunkan sebuah korolari dari lemma Lagrange. (Hasil ini juga sudah tersedia di Mathlib, jadi jangan terlalu cepat menggunakan exact?.)

lemma eq_bot_iff_card {G : Type*} [Group G] {H : Subgroup G} :
    H =   Nat.card H = 1 := by
  suffices ( x  H, x = 1)   x  H,  a  H, a = x by
    simpa [eq_bot_iff_forall, Nat.card_eq_one_iff_exists]
  sorry

#check card_dvd_of_le

lemma inf_bot_of_coprime {G : Type*} [Group G] (H K : Subgroup G)
    (h : (Nat.card H).Coprime (Nat.card K)) : H  K =  := by
  sorry

9.1.4. Grup konkret

Kita juga dapat memanipulasi grup konkret dalam Mathlib, walaupun hal ini biasanya lebih rumit daripada bekerja dengan teori abstrak. Sebagai contoh, untuk sembarang tipe X, grup permutasi dari X adalah Equiv.Perm X. Secara khusus, grup simetris \(\mathfrak{S}_n\) adalah Equiv.Perm (Fin n). Kita dapat menyatakan hasil abstrak mengenai grup ini, misalnya bahwa Equiv.Perm X dibangkitkan oleh siklus apabila X hingga.

open Equiv

example {X : Type*} [Finite X] : Subgroup.closure {σ : Perm X | Perm.IsCycle σ} =  :=
  Perm.closure_isCycle

Kita dapat bekerja sepenuhnya secara konkret dan menghitung hasil kali siklus yang sebenarnya. Di bawah ini kita menggunakan perintah #simp, yang memanggil taktik simp pada ekspresi yang diberikan. Notasi c[] digunakan untuk mendefinisikan permutasi siklik. Dalam contoh tersebut, hasilnya merupakan permutasi dari . Kita dapat memberikan penetapan tipe seperti (1 : Fin 5) pada bilangan pertama agar penghitungan berlangsung dalam Perm (Fin 5).

#simp [mul_assoc] c[1, 2, 3] * c[2, 3, 4]

Cara lain untuk bekerja dengan grup konkret adalah menggunakan grup bebas dan presentasi grup. Grup bebas pada tipe α adalah FreeGroup α, dan pemetaan inklusinya adalah FreeGroup.of : α FreeGroup α. Sebagai contoh, mari kita definisikan tipe S dengan tiga elemen yang dilambangkan a, b, dan c, serta elemen ab⁻¹ dari grup bebas yang bersesuaian.

section FreeGroup

inductive S | a | b | c

open S

def myElement : FreeGroup S := (.of a) * (.of b)⁻¹

Perhatikan bahwa kita memberikan tipe yang diharapkan bagi definisi tersebut agar Lean mengetahui bahwa .of berarti FreeGroup.of.

Sifat universal grup bebas diwujudkan oleh ekuivalensi FreeGroup.lift. Sebagai contoh, mari kita definisikan morfisme grup dari FreeGroup S ke Perm (Fin 5) yang memetakan a ke c[1, 2, 3], b ke c[2, 3, 1], dan c ke c[2, 3].

def myMorphism : FreeGroup S →* Perm (Fin 5) :=
  FreeGroup.lift fun | .a => c[1, 2, 3]
                     | .b => c[2, 3, 1]
                     | .c => c[2, 3]

Sebagai contoh konkret terakhir, mari kita lihat cara mendefinisikan grup yang dibangkitkan oleh satu elemen dengan pangkat tiga sama dengan satu (sehingga grup tersebut isomorfik dengan \(\mathbb{Z}/3\)), lalu membangun morfisme dari grup tersebut ke Perm (Fin 5).

Sebagai tipe yang memiliki tepat satu elemen, kita akan menggunakan Unit, yang satu-satunya elemennya dilambangkan dengan (). Fungsi PresentedGroup menerima himpunan relasi, yakni himpunan elemen dari suatu grup bebas, dan menghasilkan hasil bagi grup bebas tersebut oleh subgrup normal yang dibangkitkan oleh relasi-relasi itu. (Kita akan melihat cara menangani hasil bagi yang lebih umum dalam Bab 9.1.6.) Karena detail ini kita sembunyikan di balik sebuah definisi, kita menggunakan deriving Group untuk memaksa pembuatan instans grup pada myGroup.

def myGroup := PresentedGroup {.of () ^ 3} deriving Group

Sifat universal grup berpresentasi memastikan bahwa morfisme dari grup ini dapat dibangun dari fungsi yang memetakan relasi ke elemen netral grup sasaran. Karena itu, kita memerlukan fungsi semacam itu beserta bukti bahwa syaratnya terpenuhi. Selanjutnya, bukti tersebut dapat diberikan kepada PresentedGroup.toGroup untuk memperoleh morfisme grup yang diinginkan.

def myMap : Unit  Perm (Fin 5)
| () => c[1, 2, 3]

lemma compat_myMap :
     r  ({.of () ^ 3} : Set (FreeGroup Unit)), FreeGroup.lift myMap r = 1 := by
  rintro _ rfl
  simp
  decide

def myNewMorphism : myGroup →* Perm (Fin 5) := PresentedGroup.toGroup compat_myMap

end FreeGroup

9.1.5. Aksi grup

Salah satu cara penting teori grup berinteraksi dengan bidang matematika lainnya adalah melalui aksi grup. Aksi suatu grup G pada tipe X tidak lebih dari morfisme dari G ke Equiv.Perm X. Jadi, dalam arti tertentu, aksi grup sudah tercakup oleh pembahasan sebelumnya. Namun, kita tidak ingin terus membawa morfisme tersebut; sebisa mungkin, kita ingin Lean menyimpulkannya secara otomatis. Karena itu, tersedia kelas tipe MulAction G X.

Kekurangan pengaturan ini adalah bahwa beberapa aksi dari grup yang sama pada tipe yang sama memerlukan sejumlah penyesuaian, misalnya dengan mendefinisikan sinonim tipe yang masing-masing membawa instans kelas tipe berbeda.

Secara khusus, pengaturan ini memungkinkan kita menggunakan g x untuk menyatakan aksi elemen grup g pada titik x.

noncomputable section GroupActions

example {G X : Type*} [Group G] [MulAction G X] (g g': G) (x : X) :
    g  (g'  x) = (g * g')  x :=
  (mul_smul g g' x).symm

Terdapat pula versi bagi grup aditif bernama AddAction, dengan aksinya dinyatakan oleh +ᵥ. Versi ini antara lain digunakan dalam definisi ruang afin.

example {G X : Type*} [AddGroup G] [AddAction G X] (g g' : G) (x : X) :
    g +ᵥ (g' +ᵥ x) = (g + g') +ᵥ x :=
  (add_vadd g g' x).symm

Morfisme grup yang mendasarinya disebut MulAction.toPermHom.

open MulAction

example {G X : Type*} [Group G] [MulAction G X] : G →* Equiv.Perm X :=
  toPermHom G X

Sebagai ilustrasi, mari kita lihat cara mendefinisikan isomorfisme Cayley yang menyematkan sembarang grup G ke grup permutasi, yaitu Perm G. Untuk membuat instans [MulAction G G], Lean menemukan aksi grup baku yang diberikan oleh perkalian kiri, tepat seperti yang kita inginkan.

def CayleyIsoMorphism (G : Type*) [Group G] : G ≃* (toPermHom G G).range :=
  Equiv.Perm.subgroupOfMulAction G G

Perhatikan bahwa sebelum definisi di atas, tidak ada sesuatu pun yang mengharuskan kita memiliki grup alih-alih monoid (atau, sebenarnya, sembarang tipe yang dilengkapi operasi perkalian).

Syarat grup baru benar-benar berperan ketika kita ingin mempartisi X menjadi orbit. Relasi ekuivalensi yang bersesuaian pada X disebut MulAction.orbitRel. Relasi tersebut tidak dideklarasikan sebagai instans global.

example {G X : Type*} [Group G] [MulAction G X] : Setoid X := orbitRel G X

Dengan menggunakan relasi ini, kita dapat menyatakan bahwa X dipartisi menjadi orbit-orbit di bawah aksi G. Secara lebih tepat, kita memperoleh bijeksi antara X dan produk dependen : orbitRel.Quotient G X) × (orbit G (Quotient.out ω)), dengan Quotient.out ω sekadar memilih elemen yang diproyeksikan ke ω. Ingat bahwa elemen produk dependen ini merupakan pasangan ⟨ω, x⟩, dengan tipe orbit G (Quotient.out ω) dari x bergantung pada ω.

example {G X : Type*} [Group G] [MulAction G X] :
    X  (ω : orbitRel.Quotient G X) × (orbit G (Quotient.out ω)) :=
  MulAction.selfEquivSigmaOrbits G X

Secara khusus, ketika X hingga, hasil ini dapat digabungkan dengan Fintype.card_congr dan Fintype.card_sigma untuk menyimpulkan bahwa kardinalitas X merupakan jumlah kardinalitas orbit-orbitnya. Selain itu, orbit-orbit tersebut berkorespondensi bijektif dengan hasil bagi G di bawah aksi stabilisator melalui translasi kiri. Aksi suatu subgrup melalui translasi kiri ini digunakan untuk mendefinisikan hasil bagi grup oleh subgrup dengan notasi /, sehingga kita dapat memakai pernyataan ringkas berikut.

example {G X : Type*} [Group G] [MulAction G X] (x : X) :
    orbit G x  G  stabilizer G x :=
  MulAction.orbitEquivQuotientStabilizer G x

Kasus khusus penting dari penggabungan dua hasil di atas terjadi ketika X adalah grup G yang dilengkapi aksi subgrup H melalui translasi. Dalam kasus ini, semua stabilisator trivial, sehingga setiap orbit berkorespondensi bijektif dengan H dan kita memperoleh:

example {G : Type*} [Group G] (H : Subgroup G) : G  (G  H) × H :=
  groupEquivQuotientProdSubgroup

Ini merupakan varian konseptual dari versi teorema Lagrange yang telah kita lihat. Perhatikan bahwa versi ini tidak membuat asumsi keterhinggaan.

Sebagai latihan untuk bagian ini, mari kita bangun aksi suatu grup pada subgrupnya melalui konjugasi, dengan menggunakan definisi conjugate dari latihan sebelumnya.

variable {G : Type*} [Group G]

lemma conjugate_one (H : Subgroup G) : conjugate 1 H = H := by
  sorry

instance : MulAction G (Subgroup G) where
  smul := conjugate
  one_smul := by
    sorry
  mul_smul := by
    sorry

end GroupActions

9.1.6. Grup hasil bagi

Dalam pembahasan di atas mengenai subgrup yang beraksi pada grup, kita melihat kemunculan hasil bagi G H. Secara umum, hasil ini hanyalah sebuah tipe. Tipe tersebut dapat dilengkapi struktur grup sedemikian sehingga pemetaan hasil baginya merupakan morfisme grup jika dan hanya jika H merupakan subgrup normal (dan struktur grup tersebut kemudian unik).

Asumsi kenormalan berupa kelas tipe Subgroup.Normal, sehingga inferensi kelas tipe dapat menggunakannya untuk menurunkan struktur grup pada hasil bagi.

noncomputable section QuotientGroup

example {G : Type*} [Group G] (H : Subgroup G) [H.Normal] : Group (G  H) := inferInstance

example {G : Type*} [Group G] (H : Subgroup G) [H.Normal] : G →* G  H :=
  QuotientGroup.mk' H

Sifat universal grup hasil bagi diakses melalui QuotientGroup.lift: morfisme grup φ menginduksi morfisme pada G N segera setelah kernelnya memuat N.

example {G : Type*} [Group G] (N : Subgroup G) [N.Normal] {M : Type*}
    [Group M] (φ : G →* M) (h : N  MonoidHom.ker φ) : G  N →* M :=
  QuotientGroup.lift N φ h

Fakta bahwa grup sasaran dinamai M dalam cuplikan di atas memberi petunjuk bahwa struktur monoid pada M sebenarnya sudah cukup.

Kasus khusus yang penting adalah ketika N = ker φ. Dalam kasus tersebut, morfisme yang diturunkan bersifat injektif dan kita memperoleh isomorfisme grup ke citranya. Hasil ini sering disebut teorema isomorfisme pertama.

example {G : Type*} [Group G] {M : Type*} [Group M] (φ : G →* M) :
    G  MonoidHom.ker φ →* MonoidHom.range φ :=
  QuotientGroup.quotientKerEquivRange φ

Dengan menerapkan sifat universal pada komposisi morfisme φ : G →* G' dengan proyeksi grup hasil bagi Quotient.mk' N', kita juga dapat membangun morfisme dari G N ke G' N'. Syarat yang diperlukan pada φ biasanya dirumuskan dengan mengatakan "φ harus memetakan N ke dalam N'". Namun, hal ini ekuivalen dengan meminta agar prapeta N' di bawah φ memuat N. Syarat terakhir lebih mudah digunakan karena definisi prapeta tidak melibatkan kuantor eksistensial.

example {G G': Type*} [Group G] [Group G']
    {N : Subgroup G} [N.Normal] {N' : Subgroup G'} [N'.Normal]
    {φ : G →* G'} (h : N  Subgroup.comap φ N') : G  N →* G'  N':=
  QuotientGroup.map N N' φ h

Satu hal yang perlu diperhatikan adalah bahwa tipe G N benar-benar bergantung pada N (hingga kesamaan definisional). Karena itu, bukti bahwa dua subgrup normal N dan M sama belum cukup untuk membuat tipe hasil bagi yang bersesuaian sama secara definisional. Namun, sifat-sifat universal memang memberikan isomorfisme dalam kasus ini.

example {G : Type*} [Group G] {M N : Subgroup G} [M.Normal]
    [N.Normal] (h : M = N) : G  M ≃* G  N := QuotientGroup.quotientMulEquivOfEq h

Sebagai rangkaian latihan terakhir untuk bagian ini, kita akan membuktikan bahwa jika H dan K merupakan subgrup normal yang saling lepas dari grup hingga G, dan hasil kali kardinalitas keduanya sama dengan kardinalitas G, maka G isomorfik dengan H × K. Ingat bahwa saling lepas dalam konteks ini berarti H K = .

Kita mulai dengan sedikit bermain menggunakan lemma Lagrange, tanpa mengasumsikan bahwa subgrup-subgrup tersebut normal atau saling lepas.

section
variable {G : Type*} [Group G] {H K : Subgroup G}

open MonoidHom

#check Nat.card_pos -- Argumen tak kosong akan disimpulkan secara otomatis untuk subgrup
#check Subgroup.index_eq_card
#check Subgroup.index_mul_card
#check Nat.eq_of_mul_eq_mul_right

lemma aux_card_eq [Finite G] (h' : Nat.card G = Nat.card H * Nat.card K) :
    Nat.card (G  H) = Nat.card K := by
  sorry

Mulai sekarang, kita mengasumsikan bahwa subgrup-subgrup kita normal dan saling lepas, serta mengasumsikan syarat kardinalitas. Sekarang kita mengonstruksi blok pembangun pertama bagi isomorfisme yang diinginkan.

variable [H.Normal] [K.Normal] [Fintype G] (h : Disjoint H K)
  (h' : Nat.card G = Nat.card H * Nat.card K)

#check Nat.bijective_iff_injective_and_card
#check ker_eq_bot_iff
#check restrict
#check ker_restrict

def iso₁ : K ≃* G  H := by
  sorry

Sekarang kita dapat mendefinisikan blok pembangun kedua. Kita akan memerlukan MonoidHom.prod, yang membangun morfisme dari G₀ ke G₁ × G₂ dari dua morfisme yang masing-masing memetakan G₀ ke G₁ dan ke G₂.

def iso₂ : G ≃* (G  K) × (G  H) := by
  sorry

Kita siap merangkai semua bagiannya.

#check MulEquiv.prodCongr

def finalIso : G ≃* H × K :=
  sorry

9.2. Gelanggang

9.2.1. Gelanggang, unit, morfisme, dan subgelanggangnya

Tipe struktur gelanggang pada tipe R adalah Ring R. Variannya yang mengasumsikan perkalian komutatif adalah CommRing R. Kita telah melihat bahwa taktik ring akan membuktikan setiap kesamaan yang mengikuti aksioma gelanggang komutatif.

example {R : Type*} [CommRing R] (x y : R) : (x + y) ^ 2 = x ^ 2 + y ^ 2 + 2 * x * y := by ring

Varian yang lebih eksotis tidak mengharuskan penjumlahan pada R membentuk grup, melainkan cukup monoid aditif. Kelas tipe yang bersesuaian adalah Semiring R dan CommSemiring R. Tipe bilangan asli merupakan instans penting dari CommSemiring ; demikian pula setiap tipe fungsi yang nilainya berupa bilangan asli. Contoh penting lainnya adalah tipe ideal dalam gelanggang, yang akan dibahas di bawah. Nama taktik ring menyesatkan dalam dua hal: taktik ini mengasumsikan komutativitas, tetapi juga bekerja pada semigelanggang. Dengan kata lain, taktik tersebut berlaku bagi setiap CommSemiring.

example (x y : ) : (x + y) ^ 2 = x ^ 2 + y ^ 2 + 2 * x * y := by ring

Ada pula versi kelas gelanggang dan semigelanggang yang tidak mengasumsikan adanya unit multiplikatif atau sifat asosiatif perkalian. Kita tidak akan membahasnya di sini.

Sebagian konsep yang biasanya diajarkan dalam pengantar teori gelanggang sebenarnya menyangkut monoid multiplikatif yang mendasarinya. Contoh utamanya ialah definisi unit suatu gelanggang. Setiap monoid (multiplikatif) M memiliki predikat IsUnit : M Prop yang menyatakan keberadaan invers dua sisi, tipe unit Units M dengan notasi , serta koersi ke M. Tipe Units M membundel elemen yang dapat dibalik bersama inversnya dan sifat-sifat yang memastikan bahwa keduanya benar-benar saling invers.

Perincian implementasi ini terutama relevan ketika mendefinisikan fungsi yang dapat dihitung. Dalam kebanyakan keadaan, kita dapat menggunakan IsUnit.unit {x : M} : IsUnit x untuk membangun sebuah unit. Dalam kasus komutatif, tersedia pula Units.mkOfMulEqOne (x y : M) : x * y = 1 , yang membangun x sebagai sebuah unit.

example (x : ˣ) : x = 1  x = -1 := Int.units_eq_one_or x

example {M : Type*} [Monoid M] (x : Mˣ) : (x : M) * x⁻¹ = 1 := Units.mul_inv x

example {M : Type*} [Monoid M] : Group Mˣ := inferInstance

Tipe morfisme gelanggang di antara dua (semi)gelanggang R dan S adalah RingHom R S, dengan notasi R →+* S.

example {R S : Type*} [Ring R] [Ring S] (f : R →+* S) (x y : R) :
    f (x + y) = f x + f y := f.map_add x y

example {R S : Type*} [Ring R] [Ring S] (f : R →+* S) : Rˣ →* Sˣ :=
  Units.map f

Varian isomorfismenya adalah RingEquiv, dengan notasi ≃+*.

Seperti pada submonoid dan subgrup, terdapat tipe Subring R untuk subgelanggang dari gelanggang R. Namun, tipe ini jauh kurang berguna daripada tipe subgrup karena kita tidak dapat mengambil hasil bagi gelanggang terhadap subgelanggang.

example {R : Type*} [Ring R] (S : Subring R) : Ring S := inferInstance

Perhatikan pula bahwa RingHom.range menghasilkan subgelanggang.

9.2.2. Ideal dan hasil bagi

Karena alasan historis, Mathlib hanya memiliki teori ideal untuk gelanggang komutatif. (Pustaka gelanggang semula dikembangkan untuk mempercepat pembangunan landasan geometri aljabar modern.) Oleh sebab itu, pada bagian ini kita akan bekerja dengan (semi)gelanggang komutatif. Ideal dari R didefinisikan sebagai submodul dari R yang dipandang sebagai modul-R. Modul akan dibahas kelak dalam bab aljabar linear. Perincian implementasi ini sebagian besar dapat diabaikan dengan aman karena kebanyakan—meski tidak semua—lemma yang relevan dinyatakan ulang dalam konteks khusus ideal.

Namun, notasi proyeksi anonim tidak selalu bekerja sebagaimana yang diharapkan. Misalnya, Ideal.Quotient.mk I tidak dapat diganti dengan I.Quotient.mk dalam cuplikan berikut. Karena terdapat dua tanda . dalam ekspresi tersebut, Lean akan mengurainya sebagai (Ideal.Quotient I).mk; padahal Ideal.Quotient sendiri tidak ada.

example {R : Type*} [CommRing R] (I : Ideal R) : R →+* R  I :=
  Ideal.Quotient.mk I

example {R : Type*} [CommRing R] {a : R} {I : Ideal R} :
    Ideal.Quotient.mk I a = 0  a  I :=
  Ideal.Quotient.eq_zero_iff_mem

Sifat universal gelanggang hasil bagi diwujudkan oleh Ideal.Quotient.lift.

example {R S : Type*} [CommRing R] [CommRing S] (I : Ideal R) (f : R →+* S)
    (H : I  RingHom.ker f) : R  I →+* S :=
  Ideal.Quotient.lift I f H

Secara khusus, sifat ini menghasilkan teorema isomorfisme pertama untuk gelanggang.

example {R S : Type*} [CommRing R] [CommRing S](f : R →+* S) :
    R  RingHom.ker f ≃+* f.range :=
  RingHom.quotientKerEquivRange f

Dengan relasi inklusi, ideal-ideal membentuk kekisi lengkap sekaligus struktur semigelanggang. Kedua struktur ini berinteraksi dengan baik.

variable {R : Type*} [CommRing R] {I J : Ideal R}

example : I + J = I  J := rfl

example {x : R} : x  I + J   a  I,  b  J, a + b = x := by
  simp [Submodule.mem_sup]

example : I * J  J := Ideal.mul_le_left

example : I * J  I := Ideal.mul_le_right

example : I * J  I  J := Ideal.mul_le_inf

Morfisme gelanggang dapat digunakan untuk mengambil citra langsung dan prapeta ideal melalui Ideal.map dan Ideal.comap. Seperti biasa, operasi kedua lebih nyaman digunakan karena tidak melibatkan kuantor eksistensial. Itulah sebabnya operasi tersebut dipakai untuk menyatakan syarat yang memungkinkan kita membangun morfisme di antara gelanggang hasil bagi.

example {R S : Type*} [CommRing R] [CommRing S] (I : Ideal R) (J : Ideal S) (f : R →+* S)
    (H : I  Ideal.comap f J) : R  I →+* S  J :=
  Ideal.quotientMap J f H

Satu hal yang perlu diperhatikan ialah bahwa tipe R I benar-benar bergantung pada I (hingga kesamaan definisional). Karena itu, bukti bahwa dua ideal I dan J sama belum cukup untuk membuat tipe hasil bagi yang bersesuaian sama secara definisional. Meskipun demikian, sifat universal memang memberikan isomorfisme dalam kasus ini.

example {R : Type*} [CommRing R] {I J : Ideal R} (h : I = J) : R  I ≃+* R  J :=
  Ideal.quotEquivOfEq h

Sekarang kita dapat menyajikan isomorfisme sisa Tionghoa sebagai contoh. Perhatikan perbedaan antara simbol infimum terindeks dan simbol produk besar tipe Π. Bergantung pada fon yang digunakan, keduanya dapat sangat sulit dibedakan.

example {R : Type*} [CommRing R] {ι : Type*} [Fintype ι] (f : ι  Ideal R)
    (hf :  i j, i  j  IsCoprime (f i) (f j)) : (R   i, f i) ≃+* Π i, R  f i :=
  Ideal.quotientInfRingEquivPiQuotient f hf

Versi elementer teorema sisa Tionghoa, yakni pernyataan tentang ZMod, dapat dengan mudah diturunkan dari hasil sebelumnya:

open BigOperators PiNotation

example {ι : Type*} [Fintype ι] (a : ι  ) (coprime :  i j, i  j  (a i).Coprime (a j)) :
    ZMod ( i, a i) ≃+* Π i, ZMod (a i) :=
  ZMod.prodEquivPi a coprime

Sebagai rangkaian latihan, kita akan membuktikan kembali teorema sisa Tionghoa dalam kasus umum.

Pertama-tama, dengan sifat universal gelanggang hasil bagi, kita perlu mendefinisikan pemetaan yang muncul dalam teorema tersebut sebagai morfisme gelanggang.

variable {ι R : Type*} [CommRing R]
open Ideal Quotient Function

#check Pi.ringHom
#check ker_Pi_Quotient_mk

/-- Homomorfisme dari ``R ⧸ ⨅ i, I i`` ke ``Π i, R ⧸ I i`` yang tampil dalam
  teorema sisa Tionghoa. -/
def chineseMap (I : ι  Ideal R) : (R   i, I i) →+* Π i, R  I i :=
  sorry

Pastikan dua lemma berikut dapat dibuktikan dengan rfl.

lemma chineseMap_mk (I : ι  Ideal R) (x : R) :
    chineseMap I (Quotient.mk _ x) = fun i : ι  Ideal.Quotient.mk (I i) x :=
  sorry

lemma chineseMap_mk' (I : ι  Ideal R) (x : R) (i : ι) :
    chineseMap I (mk _ x) i = mk (I i) x :=
  sorry

Lemma berikut membuktikan separuh yang mudah dari teorema sisa Tionghoa tanpa asumsi apa pun mengenai keluarga idealnya. Panjang buktinya kurang dari satu baris.

#check injective_lift_iff

lemma chineseMap_inj (I : ι  Ideal R) : Injective (chineseMap I) := by
  sorry

Sekarang kita siap menghadapi inti teorema, yaitu menunjukkan surjektivitas chineseMap. Pertama-tama, kita perlu mengetahui berbagai cara untuk menyatakan asumsi koprimalitas (juga disebut asumsi komaksimalitas). Hanya dua cara pertama yang akan diperlukan di bawah.

#check IsCoprime
#check isCoprime_iff_add
#check isCoprime_iff_exists
#check isCoprime_iff_sup_eq
#check isCoprime_iff_codisjoint

Kita menggunakan kesempatan ini untuk menerapkan induksi pada Finset. Lemma yang relevan mengenai Finset diberikan di bawah. Ingat bahwa taktik ring bekerja pada semigelanggang dan bahwa ideal-ideal suatu gelanggang membentuk semigelanggang.

#check Finset.mem_insert_of_mem
#check Finset.mem_insert_self

theorem isCoprime_Inf {I : Ideal R} {J : ι  Ideal R} {s : Finset ι}
    (hf :  j  s, IsCoprime I (J j)) : IsCoprime I ( j  s, J j) := by
  classical
  simp_rw [isCoprime_iff_add] at *
  induction s using Finset.induction with
  | empty =>
      simp
  | @insert i s _ hs =>
      rw [Finset.iInf_insert, inf_comm, one_eq_top, eq_top_iff,  one_eq_top]
      set K :=  j  s, J j
      calc
        1 = I + K                  := sorry
        _ = I + K * (I + J i)      := sorry
        _ = (1 + K) * I + K * J i  := sorry
        _  I + K  J i            := sorry

Sekarang kita dapat membuktikan surjektivitas pemetaan yang muncul dalam teorema sisa Tionghoa.

lemma chineseMap_surj [Fintype ι] {I : ι  Ideal R}
    (hI :  i j, i  j  IsCoprime (I i) (I j)) : Surjective (chineseMap I) := by
  classical
  intro g
  choose f hf using fun i  Ideal.Quotient.mk_surjective (g i)
  have key :  i,  e : R, mk (I i) e = 1   j, j  i  mk (I j) e = 0 := by
    intro i
    have hI' :  j  ({i} : Finset ι), IsCoprime (I i) (I j) := by
      sorry
    sorry
  choose e he using key
  use mk _ ( i, f i * e i)
  sorry

Sekarang semua bagian tersebut berpadu dalam definisi berikut:

noncomputable def chineseIso [Fintype ι] (f : ι  Ideal R)
    (hf :  i j, i  j  IsCoprime (f i) (f j)) : (R   i, f i) ≃+* Π i, R  f i :=
  { Equiv.ofBijective _ chineseMap_inj f, chineseMap_surj hf⟩,
    chineseMap f with }

9.2.3. Aljabar dan polinomial

Jika diberikan (semi)gelanggang komutatif R, sebuah aljabar atas R adalah semigelanggang A yang dilengkapi morfisme gelanggang dari R ke A dan setiap elemen dalam citra morfisme tersebut berkomutasi dengan setiap elemen A. Hal ini dikodekan sebagai kelas tipe Algebra R A. Morfisme dari R ke A disebut pemetaan struktur dan dinotasikan sebagai algebraMap R A : R →+* A dalam Lean. Perkalian a : A dengan algebraMap R A r untuk suatu r : R disebut perkalian skalar a oleh r dan dinotasikan sebagai r a. Perhatikan bahwa pengertian aljabar ini kadang-kadang disebut aljabar unital asosiatif untuk menekankan adanya pengertian aljabar yang lebih umum.

Fakta bahwa algebraMap R A merupakan morfisme gelanggang mengemas banyak sifat perkalian skalar, seperti berikut ini:

example {R A : Type*} [CommRing R] [Ring A] [Algebra R A] (r r' : R) (a : A) :
    (r + r')  a = r  a + r'  a :=
  add_smul r r' a

example {R A : Type*} [CommRing R] [Ring A] [Algebra R A] (r r' : R) (a : A) :
    (r * r')  a = r  r'  a :=
  mul_smul r r' a

Morfisme di antara dua aljabar-R, A dan B, adalah morfisme gelanggang yang menghormati perkalian skalar oleh elemen R. Morfisme tersebut terbundel dalam tipe AlgHom R A B, yang dinotasikan sebagai A →ₐ[R] B.

Contoh penting aljabar nonkomutatif mencakup aljabar endomorfisme dan aljabar matriks persegi; keduanya akan dibahas dalam bab aljabar linear. Dalam bab ini, kita akan membahas salah satu contoh terpenting aljabar komutatif, yaitu aljabar polinomial.

Aljabar polinomial satu peubah dengan koefisien dalam R disebut Polynomial R dan dapat ditulis sebagai R[X] setelah namespace Polynomial dibuka. Pemetaan struktur aljabar dari R ke R[X] dinotasikan sebagai C. Huruf ini berarti "konstan" karena fungsi polinomial yang bersesuaian selalu konstan. Peubah tak tentunya dinotasikan sebagai X.

open Polynomial

example {R : Type*} [CommRing R] : R[X] := X

example {R : Type*} [CommRing R] (r : R) := X - C r

Dalam contoh pertama di atas, kita harus memberikan tipe yang diharapkan kepada Lean karena tipe tersebut tidak dapat ditentukan dari badan definisi. Dalam contoh kedua, aljabar polinomial sasaran dapat disimpulkan dari penggunaan C r karena tipe r diketahui.

Karena C merupakan morfisme gelanggang dari R ke R[X], kita dapat menggunakan semua lemma morfisme gelanggang, seperti map_zero, map_one, map_mul, dan map_pow, sebelum menghitung dalam gelanggang R[X]. Sebagai contoh:

example {R : Type*} [CommRing R] (r : R) : (X + C r) * (X - C r) = X ^ 2 - C (r ^ 2) := by
  rw [C.map_pow]
  ring

Koefisien dapat diakses menggunakan Polynomial.coeff.

example {R : Type*} [CommRing R] (r:R) : (C r).coeff 0 = r := by simp

example {R : Type*} [CommRing R] : (X ^ 2 + 2 * X + C 3 : R[X]).coeff 1 = 2 := by simp

Mendefinisikan derajat polinomial selalu rumit karena kasus khusus polinomial nol. Mathlib memiliki dua varian: Polynomial.natDegree : R[X] memberikan derajat 0 kepada polinomial nol, sedangkan Polynomial.degree : R[X] WithBot memberikan . Pada varian kedua, WithBot dapat dipandang sebagai {-∞}, hanya saja -∞ dinotasikan sebagai , yakni simbol yang sama dengan elemen terbawah dalam kekisi lengkap. Nilai khusus ini digunakan sebagai derajat polinomial nol dan bersifat menyerap terhadap penjumlahan. (Nilai ini hampir menyerap terhadap perkalian, kecuali bahwa * 0 = 0.)

Secara konseptual, versi degree merupakan versi yang tepat. Sebagai contoh, versi ini memungkinkan kita menyatakan rumus yang diharapkan bagi derajat hasil kali (dengan asumsi gelanggang dasar tidak memiliki pembagi nol).

example {R : Type*} [Semiring R] [NoZeroDivisors R] {p q : R[X]} :
    degree (p * q) = degree p + degree q :=
  Polynomial.degree_mul

Sebaliknya, versi untuk natDegree perlu mengasumsikan bahwa kedua polinomial tidak nol.

example {R : Type*} [Semiring R] [NoZeroDivisors R] {p q : R[X]} (hp : p  0) (hq : q  0) :
    natDegree (p * q) = natDegree p + natDegree q :=
  Polynomial.natDegree_mul hp hq

Namun, jauh lebih nyaman digunakan daripada WithBot . Karena itu, Mathlib menyediakan kedua versi beserta lemma untuk mengonversi di antara keduanya. Selain itu, natDegree merupakan definisi yang lebih nyaman ketika menghitung derajat komposisi. Komposisi polinomial diberikan oleh Polynomial.comp, dan kita memiliki:

example {R : Type*} [Semiring R] [NoZeroDivisors R] {p q : R[X]} :
    natDegree (comp p q) = natDegree p * natDegree q :=
  Polynomial.natDegree_comp

Polinomial menghasilkan fungsi polinomial: setiap polinomial dapat dievaluasi pada R menggunakan Polynomial.eval.

example {R : Type*} [CommRing R] (P: R[X]) (x : R) := P.eval x

example {R : Type*} [CommRing R] (r : R) : (X - C r).eval r = 0 := by simp

Secara khusus, terdapat predikat IsRoot yang berlaku bagi elemen r dalam R yang membuat suatu polinomial bernilai nol.

example {R : Type*} [CommRing R] (P : R[X]) (r : R) : IsRoot P r  P.eval r = 0 := Iff.rfl

Dengan asumsi R tidak memiliki pembagi nol, kita ingin mengatakan bahwa jumlah akar suatu polinomial tidak melebihi derajatnya, dengan memperhitungkan multiplisitas akar. Namun, sekali lagi kasus polinomial nol menyulitkan. Karena itu, Mathlib mendefinisikan Polynomial.roots yang memetakan polinomial P ke sebuah multihimpunan: multihimpunan ini didefinisikan kosong apabila P nol, dan selain itu memuat akar-akar P beserta multiplisitasnya. Definisi ini hanya tersedia ketika gelanggang yang mendasari merupakan domain, sebab tanpa syarat tersebut definisinya tidak memiliki sifat yang baik.

example {R : Type*} [CommRing R] [IsDomain R] (r : R) : (X - C r).roots = {r} :=
  roots_X_sub_C r

example {R : Type*} [CommRing R] [IsDomain R] (r : R) (n : ):
    ((X - C r) ^ n).roots = n  {r} :=
  by simp

Baik Polynomial.eval maupun Polynomial.roots hanya mempertimbangkan gelanggang koefisien. Keduanya tidak memungkinkan kita mengatakan bahwa X ^ 2 - 2 : ℚ[X] memiliki akar dalam atau bahwa X ^ 2 + 1 : ℝ[X] memiliki akar dalam . Untuk itu, kita memerlukan Polynomial.aeval, yang mengevaluasi P : R[X] dalam sembarang aljabar-R. Lebih tepatnya, jika diberikan semigelanggang A dan instans Algebra R A, Polynomial.aeval memetakan setiap elemen a : A ke morfisme aljabar-R R[X] A yang mengevaluasi X pada a. Karena AlgHom memiliki koersi ke fungsi, morfisme tersebut dapat diterapkan pada polinomial. Namun, aeval tidak menerima polinomial sebagai argumen langsung, sehingga notasi titik seperti pada P.eval di atas tidak dapat digunakan.

example : aeval Complex.I (X ^ 2 + 1 : [X]) = 0 := by simp

Fungsi yang bersesuaian dengan roots dalam konteks ini adalah aroots. Fungsi tersebut menerima sebuah polinomial lalu sebuah aljabar dan menghasilkan multihimpunan (dengan catatan yang sama mengenai polinomial nol seperti pada roots).

open Complex Polynomial

example : aroots (X ^ 2 + 1 : [X])  = {Complex.I, -I} := by
  suffices roots (X ^ 2 + 1 : [X]) = {I, -I} by simpa [aroots_def]
  have factored : (X ^ 2 + 1 : [X]) = (X - C I) * (X - C (-I)) := by
    have key : (C I * C I : [X]) = -1 := by simp [ C_mul]
    rw [C_neg]
    linear_combination key
  have p_ne_zero : (X - C I) * (X - C (-I))  0 := by
    intro H
    apply_fun eval 0 at H
    simp [eval] at H
  simp only [factored, roots_mul p_ne_zero, roots_X_sub_C]
  rfl

-- Mathlib mengetahui teorema d'Alembert–Gauss: ``ℂ`` tertutup secara aljabar.
example : IsAlgClosed  := inferInstance

Secara lebih umum, jika diberikan morfisme gelanggang f : R →+* S, kita dapat mengevaluasi P : R[X] pada suatu titik dalam S menggunakan Polynomial.eval₂. Fungsi ini benar-benar menghasilkan fungsi dari R[X] ke S karena tidak mengasumsikan adanya instans Algebra R S; oleh sebab itu, notasi titik bekerja sebagaimana yang diharapkan.

#check (Complex.ofRealHom :  →+* )

example : (X ^ 2 + 1 : [X]).eval₂ Complex.ofRealHom Complex.I = 0 := by simp

Mari kita akhiri dengan membahas polinomial multipeubah secara singkat. Jika diberikan semigelanggang komutatif R, aljabar-R dari polinomial berkoefisien dalam R dengan peubah tak tentu yang diindeks oleh tipe σ adalah MvPolynomial σ R. Jika diberikan i : σ, polinomial yang bersesuaian adalah MvPolynomial.X i. (Seperti biasa, namespace MvPolynomial dapat dibuka agar penulisannya dipersingkat menjadi X i.) Misalnya, jika kita menginginkan dua peubah tak tentu, kita dapat memakai Fin 2 sebagai σ dan menulis polinomial yang mendefinisikan lingkaran satuan dalam \(\mathbb{R}^2\) sebagai berikut:

open MvPolynomial

def circleEquation : MvPolynomial (Fin 2)  := X 0 ^ 2 + X 1 ^ 2 - 1

Ingat bahwa penerapan fungsi memiliki prioritas sangat tinggi, sehingga ekspresi di atas dibaca sebagai (X 0) ^ 2 + (X 1) ^ 2 - 1. Kita dapat mengevaluasinya untuk memastikan bahwa titik berkoordinat \((1, 0)\) terletak pada lingkaran. Ingat bahwa notasi ![...] menyatakan elemen Fin n X untuk suatu bilangan asli n yang ditentukan oleh banyaknya argumen dan suatu tipe X yang ditentukan oleh tipe argumen-argumennya.

example : MvPolynomial.eval ![1, 0] circleEquation = 0 := by simp [circleEquation]