"Natural" embeddings of polynomial rings
Yesterday I talked to @fieker and @fingolfin about the issues with #2192 where I introduced a new embed function which embeds a multivariate polynomial into a multivariate polynomial ring with potentially more variables by mapping the $i$-th variable of the polynomial to the $i$-th variable of the ring. As @thofma pointed out, this embedding may not be as natural to everyone.
@fieker suggested that such a functionality can be useful in many situations where one needs to add a temporary variable to a multivariate polynomial ring which is only used inside some algorithm. So, neither the input nor the output depend on this variable, it is only used while performing the algorithm.
@fingolfin suggested that this could be solved by a function which takes a multivariate polynomial ring and a vector of new symbols and returns a new multivariate polynomial ring with the new symbols added to the generators and a map which maps polynomials of the old ring into the new ring by mapping the $i$-th variable to the $i$-th variable. This map could even be a homomorphism in the OSCAR sense.
My problem is slightly different though. I would need to have a function which can map any multivariate polynomial to any multivariate polynomial ring with potentially more variables (over the same coefficient ring or perhaps a "compatible" one). So, a simple homomorphism wouldn't be enough for this.
How do we want to solve this problem? Apart from #2192 I could even imagine being able to write things like this:
julia> R, (x,y) = ZZ[:x,:y]
(Multivariate polynomial ring in 2 variables over ZZ, ZZMPolyRingElem[x, y])
julia> S, (z,w,v) = QQ[:z,:w,:v]
(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[z, w, v])
julia> S(x^2-y)
z^2-w
I know that this is controversial (for example I'm completely ignoring monomial orderings here) but we also allow multiplying polynomials with elements in their coefficient ring. One could argue that this is justified since QQ[:z,:w,:v] is a QQ-algebra (and thus also a ZZ-algebra) but modulo variable names QQ[:z,:w,:v] is also a ZZ[:x,:y]-algebra by identifying the $i$-th variable with the $i$-th variable.
In the case of univariate polynomials I'd also support things like this:
julia> R,x=ZZ[:x]
(Univariate polynomial ring in x over ZZ, x)
julia> S,y=ZZ[:y]
(Univariate polynomial ring in y over ZZ, y)
julia> S(x)
y
Interestingly, AbstractAlgebra and OSCAR behave differently here, while AbstractAlgebra errors OSCAR returns:
julia> S(x)
x
julia> S(x) == x
true
I'm not sure if this is intended.
In addition to this I'd also think mapping the other way around could be very useful, e.g. in the case where some result of an algorithm can be represented in a ring with less variable. So, things like this:
julia> R, (x,y) = ZZ[:x,:y]
(Multivariate polynomial ring in 2 variables over ZZ, ZZMPolyRingElem[x, y])
julia> S, (z,w,v) = ZZ[:z,:w,:v]
(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[z, w, v])
julia> R(z^2-w)
x^2-y
julia> R(v)
# Error of some kind
Maybe even allow a shorthand for to_univariate like this:
julia> R, (x,y) = ZZ[:x,:y]
(Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
julia> S, z = ZZ[:z]
(Univariate polynomial ring in z over integers, z)
julia> to_univariate(S, x^2+2*x)
z^2 + 2*z
julia> S(x^2+2*x)
z^2 + 2*z
julia> S(x^2+2*x) == to_univariate(S, x^2+2*x)
true
What S(y^2+2*y) should return is debatable, but I'd say z^2 + 2*z as well wouldn't be unexpected.
I hope I've wrapped up the discussion so far accurately. Please let me know if I didn't.
My problem is slightly different though. I would need to have a function which can map any multivariate polynomial to any multivariate polynomial ring with potentially more variables (over the same coefficient ring or perhaps a "compatible" one). So, a simple homomorphism wouldn't be enough for this.
Since this seems to be quite different to the other applications from @fieker and @fingolfin , it sounds like you can just write your _special_embedding function, which does what you need for your application. I think this is basically #2192 with a different name.
How do we want to solve this problem? Apart from #2192 I could even imagine being able to write things like this:
julia> R, (x,y) = ZZ[:x,:y] (Multivariate polynomial ring in 2 variables over ZZ, ZZMPolyRingElem[x, y]) julia> S, (z,w,v) = QQ[:z,:w,:v] (Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[z, w, v]) julia> S(x^2-y) z^2-w
One of the design principles from the beginning was that we don't do any coercions unless they are canonical. We chose explicit conversions over (ambiguous) magic. So we probably won't add this.
Interestingly, AbstractAlgebra and OSCAR behave differently here, while AbstractAlgebra errors OSCAR returns:
julia> S(x) x julia> S(x) == x trueI'm not sure if this is intended.
This is a bug. There are a few of them where people wrote (::PolyRing)(x::PolyRingType) = x. In this case for ZZPolyRing.
In addition to this I'd also think mapping the other way around could be very useful, e.g. in the case where some result of an algorithm can be represented in a ring with less variable. So, things like this:
julia> R, (x,y) = ZZ[:x,:y] (Multivariate polynomial ring in 2 variables over ZZ, ZZMPolyRingElem[x, y]) julia> S, (z,w,v) = ZZ[:z,:w,:v] (Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[z, w, v]) julia> R(z^2-w) x^2-y julia> R(v) # Error of some kind
Same comment as above. This does not fit with the rest of the design principles.
Since this seems to be quite different to the other applications from @fieker and @fingolfin , it sounds like you can just write
your _special_embeddingfunction, which does what you need for your application. I think this is basically https://github.com/Nemocas/AbstractAlgebra.jl/pull/2192 with a different name.
I don't see the big difference. As far as I understood it my embed function would cover the other applications as well, it is just a bit more general.
One of the design principles from the beginning was that we don't do any coercions unless they are canonical. We chose explicit conversions over (ambiguous) magic. So we probably won't add this.
Ok, but I'd say canonical is a flexible term :-) Personally, I consider my embed method to be very canonical, but I know that people have different opinions about that. I definitely agree that there is some point where ambiguous magic begins and that this point, wherever it is, shouldn't be crossed. For example I think MAPLE as a whole is ambiguous magic which has stunned me in the past.
@fieker Talked to me again and the OSCAR function im_func generalized the idea of embed even further and is thus perfectly suitable for my usecase. It can even be used to make some performance improvements for universal rings.