Closed dibernstein closed 3 months ago
The function GF creates an explicit description of the field by defining the polynomial ring ZZ/p[a], then taking the quotient by an irreducible polynomial of the right degree. You can change the variable it uses to do this with the Variable option:
K = GF(500009, Variable => x)
I discovered this while rewriting the documentation for flattenRing, which (among other uses) will give the explicit description of your finite field that's being used internally.
flattenRing(K, Result => 1)
This is now explained in the new documentation for flattenRing, which is on the master branch (the web version is the old one), but it looks like the doc for GF doesn't explain this and needs a rewrite as well! I can't assign myself issues on here, but anyone with the right permissions should feel free to assign it to me. That is, if we agree that it's a doc issue rather than an issue of changing the scope of the variable used to construct the quotient ring.
Okay, I just actually tried this and it is definitely a problem beyond just needing to be documented. GF overwrites "a" even if it's already defined!
If we change
GF = method (
Options => {
PrimitiveElement => FindOne,
Variable => null,
SizeLimit => 10000,
Strategy => null
to
GF = method (
Options => {
PrimitiveElement => FindOne,
Variable => getSymbol "a",
SizeLimit => 10000,
Strategy => null
then the documentation would say
* Inputs:
* p, a prime number
* n
* Variable => a symbol, default value a, the name to use for the generator of the field
* SizeLimit => an integer, default value 10000, the limit on the size of a Galois field whose elements will be represented internally as powers of the primitive element
, so that might be enough to make it visible what the default variable is.
I don't see overwriting as a problem, because R=QQ[a] also overwrites a.
It seems there are two possible philosophies here:
Thinking of it this way, I am in total agreement that philosophy 2 makes sense for a Galois field. Being able to work with elements of the field is the right priority. The difference is that defining and describing a polynomial ring makes the variable very clear:
i1 : QQ[a]
o1 = QQ[a]
o1 : PolynomialRing
i2 : describe oo
o2 = QQ[a, Degrees => {1}, Heft => {1}, MonomialOrder => {MonomialSize => 32}, DegreeRank => 1]
{GRevLex => {1} }
{Position => Up }
whereas defining and describing a Galois field does not at all:
i3 : GF(3^5)
o3 = GF 243
o3 : GaloisField
i4 : describe oo
o4 = GF 243
In addition to information in the documentation, it could be helpful to have the GF object or the result of "describe" display something about the construction. I am imagining something like the following
i3 = GF(3^5)
o3 = GF 243
o3 : GaloisField
o3 : (ZZ/3)[a]/(a^5-a+1)
(Where the last expression is the output of flattenRing.) I don't know whether implementing something like this is practical or straightforward, but it would be a very nice addition!
By the way, the "T" in hilbertSeries is exposed to the user, in the sense that "use" makes the symbol available:
i4 : R=QQ[x]
o4 = R
o4 : PolynomialRing
i7 : hilbertSeries R
1
o7 = -------
(1 - T)
o7 : Expression of class Divide
i8 : numerator oo
o8 = 1
o8 : ZZ[T]
i9 : T
o9 = T
o9 : Symbol
i10 : use ring o8
o10 = ZZ[T]
o10 : PolynomialRing
i11 : T
o11 = T
o11 : ZZ[T]
This was addressed by #3259, as now the GF
docs mention the variable a
. Is this okay to close?
The GF command seems to set the symbol "a" to some random value of the field created. For example, when I run the following block of code:
restart
a
GF(500009);
a
the first line "a" tells me that a is a symbol. However, after the GF command, it then tells me that a is an element of GF(500009).