Macaulay2 / M2

The primary source code repository for Macaulay2, a system for computing in commutative algebra, algebraic geometry and related fields.
https://macaulay2.com
347 stars 231 forks source link

GF command sets the symbol "a" to a random element of the field #897

Closed dibernstein closed 3 months ago

dibernstein commented 5 years ago

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).

lilysilverstein commented 5 years 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.

lilysilverstein commented 5 years ago

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!

DanGrayson commented 5 years ago

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.

lilysilverstein commented 5 years ago

It seems there are two possible philosophies here:

  1. Make "a" like the "T" in a Hilbert series---used to construct and represent something algebraic, but not exposed to the user and doesn't overwrite user symbols. The expression is more important than the ability to access the symbol.
  2. Make "a" like the "a" in QQ[a], which overwrites any user symbol, but it is immediately easy to do computations in the new ring instead of merely represent them symbolically.

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!

DanGrayson commented 5 years ago

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]
d-torrance commented 5 months ago

This was addressed by #3259, as now the GF docs mention the variable a. Is this okay to close?