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.

Reply via email to