TL;DR One of the biggest questions for me is should gens for a polynomial ring with 0 variables return (1,) or ()? IMO, it should be (1,) in line with ZZ/QQ/etc. as otherwise it suggests too much that it is the trivial ring.
IMO, gens can return an infinite object, but of course, it would not be a tuple. Instead something like a Family is a good enough approximation. Best, Travis On Wednesday, July 26, 2017 at 3:58:23 PM UTC-5, Mark S wrote: > > 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 [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
