Francesco
Francesco

Reputation: 23

Unexpected behaviour when parsing string with sympy

I'm trying to perform the derivative of an equation with sympy, but, while if I write the equation by hand the derivative is correct; when I pass the equation as a string, the output is wrong. Can anyone explain me how to solve this issue? I'm using python 3.6 and sympy 1.5.1.

>>>from sympy import *

>>>from operator import *

>>> x1 = symbols('x1')

>>> f = add(sin(x1), mul(x1, x1))

>>> diff(f, x1)

2*x1 + cos(x1)   ## Correct output

>>>> f = 'add(sin(x1), mul(x1, x1))'  ## Equation provided as string

>>>> diff(f, x1)

(Subs(Derivative(mul(_xi_1, x1), _xi_1), _xi_1, x1) + Subs(Derivative(mul(x1, _xi_2), _xi_2), _xi_2, x1))*Subs(Derivative(add(sin(x1), _xi_2), _xi_2), _xi_2, mul(x1, x1)) + cos(x1)*Subs(Derivative(add(_xi_1, mul(x1, x1)), _xi_1), _xi_1, sin(x1))  ## Wrong output

Upvotes: 2

Views: 316

Answers (4)

cards
cards

Reputation: 4975

Sympy provides parser functions to turn string into sympy object, see doc parse_expr.

For custom functions translation you can make a mapping with those provide by sympy and pass it as argument, local_dict, to the parser.

from sympy import Add, Mul, sin
from sympy.parsing.sympy_parser import parse_expr

f = parse_expr('add(sin(x1), mul(x1, x1))', local_dict={'add': Add, 'mul': Mul})
f.diff('x1')

Output

2x1 + cos(x1)

Upvotes: 0

asmeurer
asmeurer

Reputation: 91550

You shouldn't pass strings directly to SymPy functions. Rather, first parse them with sympify (which is the same as S). You can pass a dictionary of names as the second argument to sympify if you want non-standard names like add to map to existing SymPy ones, like

sympify('add(x, y)', {'add': Add}) # Gives x + y

Otherwise sympify will assume that any unknown functions are undefined functions like f(x).

Upvotes: 0

smichr
smichr

Reputation: 19057

If you want to write it in this fashion, be sure to use the actual SymPy object names (which are capitalized). I use S(...) to interpret the expression and that is the same thing that any function would do, too:

>>> S('Add(sin(x1), Mul(x1, x1))')
x1**2 + sin(x1)

But you can also use the mathematical operators + and *:

>>> S('sin(x1) + x1*x1')
x1**2 + sin(x1)

Upvotes: 1

CDJB
CDJB

Reputation: 14516

This is happening because f = 'add(sin(x1), mul(x1, x1))' is not a valid mathematical equation that can be parsed by parse_expr. This function is designed to parse equations written in mathematical syntax, not in terms of Sympy functions. To get this function in particular to be parsed correctly, you would need to use, for example:

>>> f = 'sin(x1) +  x1^2'
>>> diff(f, x1)
2*x1 + cos(x1)

If you really need to use that specific string, you could use eval():

>>> f = 'add(sin(x1), mul(x1, x1))'
>>> diff(eval(f), x1)
2*x1 + cos(x1)

Upvotes: 1

Related Questions