Let us give names to the rings and the variables. The one-liners are mixing stuff.
First of all, let us introduce some rings that live longer that in that line, and see what happens with the tacit coercion.
We introduce a ring $R=\Bbb Q[x,y,z]$, and use the lexicographic term order in it as part of the structure.
The following works:
sage: R = PolynomialRing(QQ, 3, names='x,y,z', order=TermOrder('lex', [1, 1, 1]))
sage: R
Multivariate Polynomial Ring in x, y, z over Rational Field
sage: R('x')
x
sage: R('y')
y
sage: R('z')
z
sage: R('x').parent()
Multivariate Polynomial Ring in x, y, z over Rational Field
sage: R('x').parent() == R
True
So $R$ (in the code R
) is a ring and its variables are accessed via R('x')
and so on. I would want to inject them when dealing with the situation, but since two rings live together in the question and the question depends on them this is postponed. (The last injection of y
would win and the variable y
would live in the corresponding "injected ring".)
Note that the type of R
is:
sage: type(R)
<class 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
Also, R
has a term order,
sage: R.term_order()
Lexicographic term order with weights (1, 1, 1)
which is needed e.g. when "typing" the polynomial $x+y$.
Let us do the same for the other ring, $S=\Bbb Q[y]$, with "an other $y$".
sage: S = PolynomialRing(QQ, names='y')
sage: S('y')
y
sage: S('y').parent()
Univariate Polynomial Ring in y over Rational Field
sage: S('y').parent() == S
True
The type of S
is...
sage: type(S)
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category'>
And there is no term order.
Now the line
sage: R('x') + S('y')
leads to an error. The error has something to do with the coercion, and finally we have mentioned:
ValueError: impossible to use the original term order (most likely because it was a block order). Please specify the term order for the subring
In such cases it is a bad idea to let the machine guess too much.
Here are some solutions:
(1) To start with the $y$ from $S$, and see it as an element of $R$, we can simply type
sage: R(S('y'))
y
And this works. The coercion is done in a controlled manner. Now we can also ask for
sage: ( R('x') + R(S('y')) )^3
x^3 + 3*x^2*y + 3*x*y^2 + y^3
and the computations are done in $R$.
sage: _.parent() == R
True
(2) We can use explicitly a morphism between the two rings, $S\to R$, which maps $y\to y$. In this case, to have a piece of code that is better suited for the mathematician (arguably...), i will use $R=\Bbb Q[x,y,z]$, and $S=\Bbb Q[Y]$, with the morphism $f:S\to R$, $f(Y)=y$.
Then we can introduce the rings, inject variables, and compute $(x+f(Y))^3=(x+y)^3$ in $R$ using the code:
R = PolynomialRing(QQ, 3, names='x,y,z', order=TermOrder('lex', [1, 1, 1]))
S = PolynomialRing(QQ, names='Y')
R.inject_variables()
S.inject_variables()
f = S.Hom(R)(y) # map the ring generator of $S$ to $y$ from $R$.
print( (x + f(Y))^3 )
And the above delivers:
Defining x, y, z
Defining Y
x^3 + 3*x^2*y + 3*x*y^2 + y^3
(3) This is (2) made shorter, the preparser works for us:
R.<x,y,z> = PolynomialRing(QQ, order=TermOrder('lex', [1, 1, 1]))
S.<Y> = PolynomialRing(QQ)
f = S.Hom(R)(y) # map the ring generator of $S$ to $y$ from $R$.
print( (x + f(Y))^3 )
And we get the print we wanted.
Arguably, the above $f$ is an "explicit coercion", and as such it was excluded as a valid solution from the OP. But it is a "cheap coercion", mathematically we also have it, and it is always a good idea to mention in code morphisms when passing from one structure to an other one... If this is not wanted, then use R(S('y'))
, but for my taste, using $f$ makes the code readable.