There are some inconsistencies in the way `gens`, `gens_dict`, and 
`gens_dict_recursive` work in rings.

There's some old questions on `gens` in 
https://groups.google.com/forum/#!msg/sage-devel/BRE2F90oezU/xmKC86SRllEJ;context-place=forum/sage-devel,
 
and some more discussion in trac 22514.

The old question and answer suggests that if `R.base_ring()` is not `R`, 
then `gens` should return the generators for R over its base ring.  I hope 
this means that the smallest subring of `R` containing the base ring and 
the generators is `R` itself.  It is possible that when `R.base_ring()` is 
`R`, then instead we get generators for `R` in the same sense: the smallest 
subring of `R` containing the generators is `R` itself.

tscrim observed an interesting corner case

sage: R = PolynomialRing(QQ, 0, 'x')
sage: R.gens()
()

Here, R is isomorphic, but not identical (according to Sage), to its base 
ring.  We can argue that `()` is indeed the correct answer, but also argue 
that we should get the same answer as for `QQ.gens()`.

For InfinitePolynomialRings, the set of generators is infinite.  The 
current implementation returns a special object as the generator:

sage: R = InfinitePolynomialRing(GaussianIntegers(), 'x')
sage: R.gens()
(x_*,)

The returned object is not even an element of the ring, but instead can be 
indexed to get generators:

sage: g = R.gens()[0]
sage: g in R
False
sage: g[4]
x_4
sage: g[100]
x_100

Admittedly, gens() cannot return an infinite tuple, although it could 
return something that acted very much like one---which is exactly the value 
`g` above. It also seems clear than `ngens` should be `+Infinity` rather 
than 1 as it is now.


Method `gens_dict` is apparently meant to return a dictionary that names 
all the generators.
sage: QQ.gens_dict()
{'1': 1}
sage: GaussianIntegers().gens_dict()
{'I': I}
sage: ZZ['x', 'y', 'z'].gens_dict()
{'x': x, 'y': y, 'z': z}

with `R.gens_dict_recursive()` adding the `gens_dict` of `R`, 
`R.base_ring()`, `R.base_ring().base_ring()`, and so on.

sage: QQ['x']['y'].gens_dict()
{'y': y}
sage: QQ['x']['y'].gens_dict_recursive()
{'x': x, 'y': y}
sage: GaussianIntegers()['x']['y'].gens_dict()
{'y': y}
sage: GaussianIntegers()['x']['y'].gens_dict_recursive()
{'I': I, 'x': x, 'y': y}

The difference between the results for `QQ` and `GaussianIntegers` is odd.  
In the latter case, the smallest subring of `GaussianIntegers()['x']['y']` 
containing
these three elements is indeed the whole ring, whereas in the former case, 
`ZZ['x']['y']` contains the returned generators of `QQ['x']['y']`.  In part 
I think this is due to `QQ` being a field; `QQ.gens()` does *not* give a 
set of generators with respect to just being a ring.

The situation for fields is different:

sage: K.<cuberoot2> = NumberField(x^3 - 2)
sage: L.<cuberoot3> = K.extension(x^3 - 3)
sage: S.<sqrt2> = L.extension(x^2 - 2)
sage: S
Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
sage: S.gens()
(sqrt2, cuberoot3, cuberoot2)
sage: S.base_field()
Number Field in cuberoot3 with defining polynomial x^3 - 3 over its base 
field
sage: S.base_ring()
Number Field in cuberoot3 with defining polynomial x^3 - 3 over its base 
field
sage: S.gens_dict()
{'cuberoot2': cuberoot2, 'cuberoot3': cuberoot3, 'sqrt2': sqrt2}
sage: S.gens_dict_recursive()
{'cuberoot2': cuberoot2, 'cuberoot3': cuberoot3, 'sqrt2': sqrt2}

Orders behave a bit differently, too:

sage: K = NumberField(z^5-z-1, 'a'); K
Number Field in a with defining polynomial z^5 - z - 1
sage: O = K.maximal_order(); O
Maximal Order in Number Field in a with defining polynomial z^5 - z - 1
sage: O.gens()
(1, a, a^2, a^3, a^4)
Clearly not a minimal set with respect to being a ring, and indeed 
`O.ring_generators()` returns just `[a]`.

sage: O.gens_dict()
{'a': a}
Why does the `gens_dict` disagree with `gens`?

All of this leaves the intended results of `gens` rather fuzzy.  If nothing 
else, the documentation could be clearer on just how these elements are 
meant to generate:
sage: S.gens?
Signature:      S.gens()
Docstring:     
   Return the generators of this relative number field.

   EXAMPLES:

      sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
      Number Field in a with defining polynomial x^4 + 3 over its base field
      sage: K.gens()
      (a, b)

sage: Q
Univariate Polynomial Ring in x over Eisenstein Integers in Number Field in 
omega with defining polynomial x^2 + x + 1
sage: Q.gens?
Docstring:     
   Return a tuple whose entries are the generators for this object, in
   order.

sage: O.gens?
Docstring:     
   Return a tuple whose entries are the generators for this object, in
   order.


-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-devel@googlegroups.com.
Visit this group at https://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to