Where should polynomial substitution live?

51 views
Skip to first unread message

Andrey Novoseltsev

unread,
May 23, 2021, 1:18:09 PM5/23/21
to sage-devel
Consider the following:

sage: R.<x,y> = QQ[]
....: p = x + y
....: print(parent(p.subs(x=1)))
....: print(parent(p.subs(x=1, y=2)))
....: print(parent(p(x=1)))
....: print(parent(p(x=1, y=2)))
....: print(parent(p(1, 2)))
....: print()
....: R.<x,y> = QQ["a"][]
....: p = x + y
....: print(parent(p.subs(x=1)))
....: print(parent(p.subs(x=1, y=2)))
....: print(parent(p(x=1)))
....: print(parent(p(x=1, y=2)))
....: print(parent(p(1, 2)))
Multivariate Polynomial Ring in x, y over Rational Field
Multivariate Polynomial Ring in x, y over Rational Field
Multivariate Polynomial Ring in x, y over Rational Field
Multivariate Polynomial Ring in x, y over Rational Field
Rational Field

Multivariate Polynomial Ring in x, y over Univariate Polynomial Ring in a over Rational Field
Univariate Polynomial Ring in a over Rational Field
Multivariate Polynomial Ring in x, y over Univariate Polynomial Ring in a over Rational Field
Univariate Polynomial Ring in a over Rational Field
Univariate Polynomial Ring in a over Rational Field

It seems to me that when a tuple of values is provided for all variables, the result is expected to be the polynomial evaluation and should live in the base ring. But if named substitutions are used, the result is going to be a polynomial of the same ring, even if it happens to be a constant for some reason. If that is not the case, one has to write different code to treat evaluations. So I'd say that the first ring here behaves well and the second one does not. What do you think?

Thank you!
Andrey

Nils Bruin

unread,
May 24, 2021, 11:30:34 AM5/24/21
to sage-devel
On Sunday, 23 May 2021 at 10:18:09 UTC-7... wrote:

It seems to me that when a tuple of values is provided for all variables, the result is expected to be the polynomial evaluation and should live in the base ring. But if named substitutions are used, the result is going to be a polynomial of the same ring, even if it happens to be a constant for some reason. If that is not the case, one has to write different code to treat evaluations. So I'd say that the first ring here behaves well and the second one does not. What do you think?

This was raised recently,:
Apologies if you're already aware of the link.

I think it's desirable to try and make evaluation of polynomials consistent with other operations, particularly what coercion would do with the expression describing the particular evaluation. Where that leads to parents dependent on special values of the polynomial, we should probably round up to parents that can deal with evaluation of all polynomials from the ring.

Partial evaluation should probably just be a shorthand notation for full evaluation, where the unmentioned variables are taken to be evaluated at themselves and the coercion framework is left to construct a common parent that can deal with the heterogeneous list.

Furthermore, I think that in keeping with python conventions, when arguments can be specified both positionally and by naming them, then there should not be a semantic difference. So basically, evaluation would be a call that allows positional arguments to be specified by name, and these arguments have default values equal to the corresponding variable in the ring.

According to these rules, I think the second ring behaves correctly and the first one does not. In particular, I don't see a desirable, meaningful semantic difference between .subs and .__call__ here.

(the code that does these evaluations should probably have a lot of shortcuts around the coercion framework for efficiency, and ring homomorphisms should probably avoid using evaluation code explicitly, for efficiency reasons: by the time a homomorphism is called, all the coercions involved in its evaluation should already be determined)
Reply all
Reply to author
Forward
0 new messages