Ask Your Question
2

Substitution of variable in polynomial not working as expected.

asked 2023-06-25 17:18:23 +0100

jllb gravatar image

updated 2023-06-25 18:50:30 +0100

slelievre gravatar image

The subs method behaves differently in two related settings:

  • univariate polynomials over SR
  • multivariate polynomials over SR

when trying to substitute a value for some variable involved as a coefficient.

In the univariate case:

R.<x> = SR[]
a = SR.var('a')
P = a*x
P.subs(a=1)

returns x, as expected.

But in the multivariate case:

R.<x, y> = SR[]
a = SR.var('a')
P = a*x
P.subs(a=1)

returns a*x.

edit retag flag offensive close merge delete

Comments

The implementations are different. to clarify :

sage: reset()
sage: a=SR.var("a")
sage: R1.<x>=SR[]
sage: R2.<y,z>=SR[]
sage: list(a*x^3)
[0, 0, 0, a]
sage: list(a*y^3)
[(a, y^3)]

You may have discovered that the subs method of polynomial rings is buggy. You may explore this a bot further an open an issue, possibly after a yelp on sage-support...

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2023-06-25 21:00:09 +0100 )edit

I take that back : subs is not supposed to do that in multivariate polynomials. I'll prepare an answer.

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2023-06-25 21:03:12 +0100 )edit

To start with, a is not a polynomial variable in your example.

Max Alekseyev gravatar imageMax Alekseyev ( 2023-06-25 22:34:41 +0100 )edit

Echoing @Max Alekseyev, I think that mixing symbolic variables with polynomials could be buggy. If you instead did R.<a,x,y> = SR[], then (a*x).subs(a=3) should return 3*x.

John Palmieri gravatar imageJohn Palmieri ( 2023-06-25 22:58:14 +0100 )edit

2 Answers

Sort by ยป oldest newest most voted
1

answered 2023-06-25 21:05:32 +0100

Emmanuel Charpentier gravatar image

updated 2023-06-25 21:15:59 +0100

The subs method for polynomials is not an analog of SR.subs !

sage: a=SR.var("a")
sage: R1.<x>=SR[]
sage: R2.<y,z>=SR[]
sage: x.subs?

prints

Docstring:     
   Identical to "self(*x)".

   See the docstring for "__call__()".

   EXAMPLES:

      sage: R.<x> = QQ[]
      sage: f = x^3 + x - 3
      sage: f.subs(x=5)
      127
      sage: f.subs(5)
      127
      sage: f.subs({x:2})
      7
      sage: f.subs({})
      x^3 + x - 3
      sage: f.subs({'x':2})
      Traceback (most recent call last):

etc... Compare with :

sage: y.subs?
Signature:      y.subs(fixed=None, **kw)
Docstring:     
   Fix some given variables in a given multivariate polynomial and
   return the changed multivariate polynomials. The polynomial itself
   is not affected. The variable, value pairs for fixing are to be
   provided as a dictionary of the form "{variable: value}".

   This is a special case of evaluating the polynomial with some of
   the variables constants and the others the original variables.

   INPUT:

   * "fixed" - (optional) dictionary of inputs

   * "**kw" - named parameters

   OUTPUT: new "MPolynomial"

   EXAMPLES:

      sage: R.<x,y> = QQbar[]                                                     # optional - sage.rings.number_field
      sage: f = x^2 + y + x^2*y^2 + 5                                             # optional - sage.rings.number_field
      sage: f((5, y))                                                             # optional - sage.rings.number_field
      25*y^2 + y + 30
      sage: f.subs({x: 5})                                                        # optional - sage.rings.number_field
      25*y^2 + y + 30

As far as I understand it, (a*x).subs(a=1) should have raised an error.

Consider yelping on sage-support...

HTH,

edit flag offensive delete link more
1

answered 2023-06-26 02:26:57 +0100

Max Alekseyev gravatar image

updated 2023-06-26 15:49:15 +0100

P.subs() should work only for the variables of the polynomials, ie. x and y. a is a not a polynomial variable but rather a parameter, which polynomial coefficients depend on. Hence, you need to perform symbolic substitution in each of the coefficients. For example, this will do the job:

R.<x, y> = SR[]
a = SR.var('a')
P = a*x
print( sum(map(lambda t: t[0].subs({a:1})*t[1], P)) )

or (as suggested by @achrzesz):

print( P.map_coefficients(lambda t: t.subs({a:1})) )
edit flag offensive delete link more

Comments

2

P.map_coefficients(lambda t:t.subs({a:1}))

achrzesz gravatar imageachrzesz ( 2023-06-26 08:27:22 +0100 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2023-06-25 17:18:23 +0100

Seen: 417 times

Last updated: Jun 26 '23