Skip to content

Commit 057bd86

Browse files
author
Release Manager
committed
gh-36390: add simple function to count irreducible polynomials over 𝔽q There is a well-known formula for counting irreducible polynomials of given degree $n$ over a finite field $\mathbb F_q$, using Möbius inversion. In this patch we add a simple function to evaluate this formula. URL: #36390 Reported by: Lorenz Panny Reviewer(s): Giacomo Pope, grhkm21, Matthias Köppe, Max Alekseyev
2 parents 1cd4990 + d952887 commit 057bd86

File tree

3 files changed

+100
-1
lines changed

3 files changed

+100
-1
lines changed

src/doc/en/reference/references/index.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ REFERENCES:
4747
*Quantum compution with anyons: an F-matrix and braid calculator*
4848
(2022). https://arxiv.org/abs/2212.00831
4949
50+
.. [Alekseyev2006] \M. Alekseyev:
51+
(Forum post on counting irreducible multivariate polynomials),
52+
2006.
53+
https://dxdy.ru/post7034.html
54+
5055
.. [AB2007] \M. Aschenbrenner, C. Hillar,
5156
*Finite generation of symmetric ideals*.
5257
Trans. Amer. Math. Soc. 359 (2007), no. 11, 5171--5192.
@@ -503,6 +508,11 @@ REFERENCES:
503508
*A new construction for Hadamard matrices*.
504509
Bulletin of the American Mathematical Society 71(1):169-170, 1965.
505510
511+
.. [Bodin2007] \A. Bodin:
512+
Number of irreducible polynomials in several variables over finite fields,
513+
The American Mathematical Monthly 115(7), pp. 653-660, 2008.
514+
https://arxiv.org/abs/0706.0157
515+
506516
.. [BH2012] \A. Brouwer and W. Haemers,
507517
Spectra of graphs,
508518
Springer, 2012,

src/sage/combinat/all.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@
247247
from .integer_vector_weighted import WeightedIntegerVectors
248248
from .integer_vectors_mod_permgroup import IntegerVectorsModPermutationGroup
249249

250-
lazy_import('sage.combinat.q_analogues', ['gaussian_binomial', 'q_binomial'])
250+
lazy_import('sage.combinat.q_analogues', ['gaussian_binomial', 'q_binomial', 'number_of_irreducible_polynomials'])
251251

252252
from .species.all import *
253253

src/sage/combinat/q_analogues.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,3 +988,92 @@ def q_stirling_number2(n, k, q=None):
988988
return parent(q)(0)
989989
return (q**(k-1)*q_stirling_number2(n - 1, k - 1, q=q) +
990990
q_int(k, q=q) * q_stirling_number2(n - 1, k, q=q))
991+
992+
993+
def number_of_irreducible_polynomials(n, q=None, m=1):
994+
r"""
995+
Return the number of monic irreducible polynomials of degree ``n``
996+
in ``m`` variables over the finite field with ``q`` elements.
997+
998+
If ``q`` is not given, the result is returned as an integer-valued
999+
polynomial in `\QQ[q]`.
1000+
1001+
INPUT:
1002+
1003+
- ``n`` -- positive integer
1004+
- ``q`` -- ``None`` (default) or a prime power
1005+
- ``m`` -- positive integer (default `1`)
1006+
1007+
OUTPUT: integer or integer-valued polynomial over `\QQ`
1008+
1009+
EXAMPLES::
1010+
1011+
sage: number_of_irreducible_polynomials(8, q=2)
1012+
30
1013+
sage: number_of_irreducible_polynomials(9, q=9)
1014+
43046640
1015+
sage: number_of_irreducible_polynomials(5, q=11, m=3)
1016+
2079650567184059145647246367401741345157369643207055703168
1017+
1018+
::
1019+
1020+
sage: poly = number_of_irreducible_polynomials(12); poly
1021+
1/12*q^12 - 1/12*q^6 - 1/12*q^4 + 1/12*q^2
1022+
sage: poly(5) == number_of_irreducible_polynomials(12, q=5)
1023+
True
1024+
sage: poly = number_of_irreducible_polynomials(5, m=3); poly
1025+
q^55 + q^54 + q^53 + q^52 + q^51 + q^50 + ... + 1/5*q^5 - 1/5*q^3 - 1/5*q^2 - 1/5*q
1026+
sage: poly(11) == number_of_irreducible_polynomials(5, q=11, m=3)
1027+
True
1028+
1029+
This function is *much* faster than enumerating the polynomials::
1030+
1031+
sage: num = number_of_irreducible_polynomials(99, q=101)
1032+
sage: num.bit_length()
1033+
653
1034+
1035+
ALGORITHM:
1036+
1037+
In the univariate case, classical formula
1038+
`\frac1n \sum_{d\mid n} \mu(n/d) q^d`
1039+
using the Möbius function `\mu`;
1040+
see :func:`moebius`.
1041+
1042+
In the multivariate case, formula from [Bodin2007]_,
1043+
independently [Alekseyev2006]_.
1044+
"""
1045+
n = ZZ(n)
1046+
if n <= 0:
1047+
raise ValueError('n must be positive')
1048+
if m <= 0:
1049+
raise ValueError('m must be positive')
1050+
1051+
if q is None:
1052+
from sage.rings.rational_field import QQ
1053+
q = QQ['q'].gen() # we produce an integer-valued polynomial in q, but it does not necessarily have integer coefficients
1054+
1055+
if m == 1:
1056+
from sage.arith.misc import moebius
1057+
r = sum((moebius(n//d) * q**d for d in n.divisors()), parent(q).zero())
1058+
return r // n
1059+
1060+
from sage.functions.other import binomial
1061+
from sage.combinat.partition import Partitions
1062+
1063+
def monic_reducible(irreducible, d):
1064+
"""
1065+
Compute the number of monic reducible polynomials of degree `d`
1066+
given the numbers of irreducible polynomials up to degree `d-1`.
1067+
"""
1068+
res = 0
1069+
for p in Partitions(d+1, max_part=d):
1070+
res += prod(binomial(r+t-1, t) for r, t in zip(irreducible, p.to_exp(d)))
1071+
return res
1072+
1073+
r = []
1074+
for d in range(n):
1075+
monic = (q**binomial(d + m, m - 1) - 1) * q**binomial(d + m, m) // (q - 1)
1076+
reducible = monic_reducible(r, d)
1077+
r.append(monic - reducible)
1078+
1079+
return r[-1]

0 commit comments

Comments
 (0)