I have done more digging.  If I am not mistaken, what governs the coercion 
is the function `pushout` in `categories/pushout.py`.  For each 
construction functor there is a hardcoded rank, such as 9.5 for the 
InfinitePolynomialFunctor, 10 for the MatrixFunctor, or 9 for the 
PolynomialFunctor and the MultiPolynomialFunctor.  SymmetricFunctions do 
not have a construction functor.

First the two parents are decomposed into their construction tower - a list 
of (functor, object) pairs, for example

[(None,
  Univariate Polynomial Ring in z over Infinite polynomial ring in a over 
Integer Ring),
 (Poly[z], Infinite polynomial ring in a over Integer Ring),
 (InfPoly{[a], "lex", "dense"}, Integer Ring)]

or 

[(None, Univariate Polynomial Ring in z over Integer Ring),
 (Poly[z], Integer Ring)]
 
Next (in this case), these two towers are merged, essentially by preferring 
lower rank construction functors.  In the case at hand, we obtain the 
construction tower
[(None,
  Univariate Polynomial Ring in z over Infinite polynomial ring in a over 
Univariate Polynomial Ring in z over Integer Ring),
 (Poly[z],
  Infinite polynomial ring in a over Univariate Polynomial Ring in z over 
Integer Ring),
 (InfPoly{[a], "lex", "dense"},
  Univariate Polynomial Ring in z over Integer Ring),
 (Poly[z], Integer Ring)]

However, if the ranks of two construction functors are equal, such as the 
PolynomialFunctor and the MultiPolynomialFunctor, a look ahead is done, 
whether one of the two functors to be applied next appears later in the 
other tower anyway.  If so, application of this functor is postponed.

Now it is unclear to me, why this look ahead is only done when the ranks 
are equal.  In any case, it does not look like a quick andd easy project to 
me.

Might it be easier to create a copy of the InfinitePolynomialRing, so that 
I can guarantee that the common parent of anything with base ring R and 
anything with base ring InfinitePolynomialRing(R) is simply the latter?

Help still greatly appreciated.

Martin

On Saturday 13 January 2024 at 12:00:54 UTC+1 Martin R wrote:

> OK, possibly I now understand Matthias Köppe's comment on the PR.  He said 
> that the pushout of R and S looks suspicious (this is indeed computed in 
> ModuleAction.__init__ and seems to govern the process):
>
> sage: R
>
> Univariate Polynomial Ring in z over Rational Field
> sage: S
>
> Univariate Polynomial Ring in z over Full MatrixSpace of 1 by 1 dense 
> matrices over Rational Field
> sage: pushout(R, S)
>
> Univariate Polynomial Ring in z over Full MatrixSpace of 1 by 1 dense 
> matrices over Univariate Polynomial Ring in z over Rational Field
>
> I have not yet understood the documentation.  It says:
>
>     try to construct a reasonable object `Y` and return maps such that 
> canonically `R <- Y -> S`.
>
> I would have thought that the most reasonable object in the case above 
> would be S itself (I find the arrows are surprising, shouldn't they be the 
> other way round?).
>
> Martin
> On Saturday 13 January 2024 at 11:47:20 UTC+1 Martin R wrote:
>
>> I find the MatrixSpace example interesting:
>>
>> sage: R = MatrixSpace(QQ, 1)
>> sage: P = PolynomialRing(R, names="z")
>> sage: Q = PolynomialRing(QQ, names="z")
>> sage: Q.gen() * P.gen()
>> [z]*z
>> sage: P.gen() * Q.gen()
>> [z]*z
>> sage: coercion_model.analyse(P.gen(), Q.gen(), operator.mul)
>> (['Action discovered.',
>>   Right scalar multiplication by Univariate Polynomial Ring in z over 
>> Rational Field on Univariate Polynomial Ring in z over Full MatrixSpace of 
>> 1 by 1 dense matrices over Rational Field],
>>  Univariate Polynomial Ring in z over Full MatrixSpace of 1 by 1 dense 
>> matrices over Univariate Polynomial Ring in z over Rational Field)
>>
>> So, the action of QQ[z] on Mat_n(QQ) [z]  returns something in 
>> Mat_n(QQ[z]) [z].
>>
>> Where are these actions are actually coded?
>>
>> I am currently trying to figure out what ModuleAction.__init__ is doing.
>>
>> Martin
>> On Saturday 13 January 2024 at 10:13:03 UTC+1 Martin R wrote:
>>
>>> How can I find out what causes this?  How can I find out where this 
>>> action is defined?
>>>
>>> I played around a little, but without any insights.  It seems that most 
>>> of the time, the coercion tries to do the embedding in the base ring, but 
>>> not always.  The MatrixSpace seems to be another exception.
>>>
>>> I admit, it does look odd to me, because we usually treat variable names 
>>> as the distinguishing feature of polynomial rings, don't we?
>>>
>>> Martin
>>>
>>> def test(R):
>>>     """
>>>     sage: test(QQ)
>>>     z^2
>>>     sage: test(ZZ)
>>>     z^2
>>>     sage: test(PolynomialRing(ZZ, "a"))
>>>     z^2
>>>     sage: test(PolynomialRing(ZZ, "a, b"))
>>>     z^2
>>>     sage: test(SymmetricFunctions(QQ).s())
>>>     s[]*z^2
>>>
>>>     sage: test(MatrixSpace(QQ, 2))
>>>     [z 0]
>>>     [0 z]*z
>>>     sage: test(PolynomialRing(ZZ, "z"))
>>>     z*z
>>>     sage: test(InfinitePolynomialRing(QQ, "a"))
>>>     z*z
>>>
>>>     """
>>>     P = PolynomialRing(R, names="z")
>>>     p = P.gen()
>>>     Q = PolynomialRing(QQ, names="z")
>>>     q = Q.gen()
>>>     return p*q
>>>
>>> On Saturday 13 January 2024 at 00:30:02 UTC+1 Nils Bruin wrote:
>>>
>>>> This might be at fault:
>>>>
>>>> sage: coercion_model.analyse(q,e)
>>>> (['Action discovered.',
>>>>   Left scalar multiplication by Multivariate Polynomial Ring in z, q 
>>>> over Rational Field on Multivariate Polynomial Ring in z, q over Infinite 
>>>> polynomial ring in F over Rational Field],
>>>>  Multivariate Polynomial Ring in z, q over Infinite polynomial ring in 
>>>> F over Multivariate Polynomial Ring in z, q over Rational Field)
>>>>
>>>> it looks like somehow an action is found before "common parent" 
>>>> multiplication is used.
>>>>
>>>>
>>>>
>>>> On Friday 12 January 2024 at 17:24:00 UTC-5 Martin R wrote:
>>>>
>>>> I am not quite sure I understand how this works / what is used:
>>>>
>>>> sage: pushout(e.parent(), z.parent())
>>>> Multivariate Polynomial Ring in z, q over Infinite polynomial ring in F 
>>>> over Multivariate Polynomial Ring in z, q over Rational Field
>>>> sage: coercion_model.common_parent(z, e)
>>>> Multivariate Polynomial Ring in z, q over Infinite polynomial ring in F 
>>>> over Rational Field
>>>>
>>>> Martin
>>>> On Friday 12 January 2024 at 22:47:49 UTC+1 Martin R wrote:
>>>>
>>>> Hm, that's somewhat unfortunate - I don't see how to work around it.  I 
>>>> guess I would have to force all elements to be in P (using the notation of 
>>>> the example), but this is, I think, not possible.
>>>>
>>>> Do you know where this behaviour is determined?
>>>>
>>>> On Friday 12 January 2024 at 22:09:41 UTC+1 Nils Bruin wrote:
>>>>
>>>> On Friday 12 January 2024 at 14:30:06 UTC-5 Martin R wrote:
>>>>
>>>> I made a tiny bit of progress, and now face the following problem:
>>>>
>>>> sage: I.<F> = InfinitePolynomialRing(QQ) 
>>>> sage: P.<z, q> = I[] 
>>>> sage: e = z*q 
>>>> sage: Q.<z, q> = QQ[] 
>>>> sage: z*e
>>>> z*z*q 
>>>>
>>>> Is this correct behaviour?
>>>>
>>>> I don't think it's desperately wrong. To sage, these structures look 
>>>> like:
>>>>
>>>> sage: P.construction()
>>>> (MPoly[z,q], Infinite polynomial ring in F over Rational Field)
>>>> sage: Q.construction()
>>>> (MPoly[z,q], Rational Field)
>>>> sage: parent(z*e).construction()
>>>> (MPoly[z,q],
>>>>  Infinite polynomial ring in F over Multivariate Polynomial Ring in z, 
>>>> q over Rational Field)
>>>>
>>>> Note that an "infinite polynomial ring" is a different object than an 
>>>> MPoly, and obviously it has different rules/priorities for finding common 
>>>> overstructures.
>>>>  
>>>>
>>>>

-- 
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 sage-devel+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sage-devel/3d9c5a00-2cf7-4377-90ef-b91bd15cfe5cn%40googlegroups.com.

Reply via email to