# differentiation in InfinitePolynomialRing

49 views

### Max Alekseyev

Sep 8, 2021, 3:35:10 AMSep 8
to sage-support
I've found a couple of issues with differentiation in InfinitePolynomialRing

(ISSUE #1) Differentiation fails in InfinitePolynomialRing(QQ), e.g. the following code

R.<x> = InfinitePolynomialRing(QQ)
f = x[0] + x[1]
derivative(f,x[1])

gives an error
TypeError: Argument 'var' has incorrect type (expected sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular, got InfinitePolynomial_dense)

However, if we replace QQ with something more sophisticated, differentiation starts suddenly work:

K.<u> = PolynomialRing(QQ)
R.<x> = InfinitePolynomialRing(K)
f = x[0] + x[1]
derivative(f,x[1])

gives 1 as expected.

(ISSUE #2) Slightly modifying the second example above:

K.<u> = PolynomialRing(QQ)
R.<x> = InfinitePolynomialRing(K)
f = x[0] + x[1]
derivative(f,x[2])

we get an error
ValueError: cannot differentiate with respect to x_2

However, if we try to execute the same 'derivative(f,x[2])' command again in the same Sage session, it will succeed.
So, it appears that if we differentiate with respect to a new variable, which was not accessed before, then differentiation would fail. I hope this is not an intended behavior and can be easily fixed.

Thanks,
Max

### Simon King

Sep 8, 2021, 10:30:21 AMSep 8
Hi Max,

On 2021-09-08, Max Alekseyev <max...@gmail.com> wrote:
> I've found a couple of issues with differentiation in InfinitePolynomialRing
>
> (ISSUE #1) Differentiation fails in InfinitePolynomialRing(QQ), e.g. the
> following code
>
> R.<x> = InfinitePolynomialRing(QQ)
> f = x[0] + x[1]
> derivative(f,x[1])
>
> gives an error
> TypeError: Argument 'var' has incorrect type (expected
> sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular,
> got InfinitePolynomial_dense)

Sure, that's not supposed to work. InfinitePolynomialRing knows nothing
about symbolic calculus. That would be the job of symbolic expressions.

> However, if we replace QQ with something more sophisticated,
> differentiation starts suddenly work:
>
> K.<u> = PolynomialRing(QQ)
> R.<x> = InfinitePolynomialRing(K)
> f = x[0] + x[1]
> derivative(f,x[1])
>
> gives 1 as expected.

Interesting. That's not supposed to work either.

A possible explanation: InfinitePolynomialRing uses a *finite*
polynomial ring under the hood, which is extended when a generator
is requested with a higher index.

If I recall correctly, methods that aren't explicitly implemented for
elements of InfinitePolynomialRing are forwarded to the underlying finite
polynomials. That could explain why it works at all. But I don't know
why it only works if the base ring is a polynomial ring.

> (ISSUE #2) Slightly modifying the second example above:
>
> K.<u> = PolynomialRing(QQ)
> R.<x> = InfinitePolynomialRing(K)
> f = x[0] + x[1]
> derivative(f,x[2])
>
> we get an error
> ValueError: cannot differentiate with respect to x_2
>
> However, if we try to execute the same 'derivative(f,x[2])' command again
> in the same Sage session, it will succeed.

> So, it appears that if we differentiate with respect to a new variable,
> which was not accessed before, then differentiation would fail. I hope this
> is not an intended behavior and can be easily fixed.

When you create f, then it is implemented based on a ring with two variables
x0 and x1. Thus, a method of an element of K['x0','x1'] is called, on
x[2], which K['x0','x1'] doesn't know about. But by calling x[2], the
underlying finite ring in the meantime is extended to K['x0', 'x1',
'x2'], thus, when you try to differentiate a second time, it is done in
a ring in which x2 is known.

At least that's my guess.

As I said, differentiation is not supposed to work. But I (as original
author) don't fully understand *why* it sometimes works and how to fix
that (by "fix", I mean "make it not work and, in the best case, suggest
to convert to a symbolic expression").

InfinitePolynomialRing was created for a very narrow purpose, namely
computing symmetric Gröbner bases. In particular, calculus was not in
the scope. If someone wants to extend its functionality, I wouldn't
mind though.

Best regards,
Simon

### Nils Bruin

Sep 8, 2021, 11:05:30 AMSep 8
to sage-support
On Wednesday, 8 September 2021 at 07:30:21 UTC-7 Simon King wrote:

As I said, differentiation is not supposed to work. But I (as original
author) don't fully understand *why* it sometimes works and how to fix
that (by "fix", I mean "make it not work and, in the best case, suggest
to convert to a symbolic expression").

InfinitePolynomialRing was created for a very narrow purpose, namely
computing symmetric Gröbner bases. In particular, calculus was not in
the scope. If someone wants to extend its functionality, I wouldn't
mind though.

Hm, I wouldn't say derivatives of polynomials are "calculus". Differentiation is perfectly valid formal algebraic operation with well-studied properties and many applications in algebraic settings that are not covered by "calculus". That doesn't change that the original designer of InfinitePolynomialRing didn't put it in the scope, but I think we can be a little more enthusiastic about potential attempts at remedying that lack in functionality:

From what Simon describes, differentiation in InfinitePolynomialRing only works "by chance". The function "derivative" goes out of its way to make sense of its arguments, mainly by putting them into SR (with variable degree of success). This is its implementation:

try:
return f.derivative(*args, **kwds)
except AttributeError:
pass
if not isinstance(f, Expression):
f = SR(f)
return f.derivative(*args, **kwds)

so, if one would simply implement a derivative method on infinitepolynomialring elements, then things would work.

### Max Alekseyev

Sep 8, 2021, 12:24:15 PMSep 8
to sage-support
Hi Simon,

Thank you for your insight, and let me state that I find InfinitePolynomialRing useful in combinatorics to deal with (truncated) multivariate generating functions with apriori unknown number of variables, and so basic operations (such as differentiation) on polynomials would be very welcome here. Btw, is there InfinitePowerSeriesRing or alike available by any chance?

From what you said, I think it should be easy to fix (making it work) at least ISSUE#2 -- one just needs to extend the underlying finite PolynomialRing with the differentiating variable(s) before delegating the actual differentiation to it.
I think as a temporary fix for ISSUE#2, one can create an polynomial being a sum of all variables that may ever appear later to make sure that the underlying PolynomialRing knows about them all upfront.

Regards,
Max

### Nils Bruin

Sep 8, 2021, 4:59:07 PMSep 8
to sage-support
On Wednesday, 8 September 2021 at 09:24:15 UTC-7 max...@gmail.com wrote:
Hi Simon,

Thank you for your insight, and let me state that I find InfinitePolynomialRing useful in combinatorics to deal with (truncated) multivariate generating functions with apriori unknown number of variables, and so basic operations (such as differentiation) on polynomials would be very welcome here. Btw, is there InfinitePowerSeriesRing or alike available by any chance?

From what you said, I think it should be easy to fix (making it work) at least ISSUE#2 -- one just needs to extend the underlying finite PolynomialRing with the differentiating variable(s) before delegating the actual differentiation to it.

I don't think any extending is required: if the differentiation variables do no lie in the parent of the representing finite polynomial ring for the actual element then the answer is 0.

def derivative(self, *args):
R=self._p.parent()
try:
L=[R(c) for c in args]
except TypeError:  #perhaps test a little more here
return self.parent().zero()
return R(self._p.derivative(*L))

### Simon King

Sep 9, 2021, 2:15:48 AMSep 9
Hi Nils,

can you open a ticket for it?

Best regards,
Simon

### Max Alekseyev

Sep 9, 2021, 11:01:01 AMSep 9
to sage-support
That would be nice to fix. Btw, there is also the same issue with formal integration - like in the example below:

K.<u> = PolynomialRing(QQ)
R.<x> = InfinitePolynomialRing(K)
f = x[0] + x[1]
integrate(f,x[2])

which fails while integrate(f,x[1]) works fine.

Regards,
Max