Tadhg McDonald-Jensen
Tadhg McDonald-Jensen

Reputation: 21474

evaluate sympy expression with python equivalent operations

I would like to generate equations symbolically, then sub in values with types from libraries like uncertainties (but could be any library with custom types) however it seems that using .evalf(subs={...}) method fails with a rather odd error message:

>>> from uncertainties import ufloat
>>> from sympy.abc import x
>>> (x**2).evalf(subs={x: ufloat(5,1)})
Traceback (most recent call last):
  ...
  File "<string>", line 1
    Float ('5.0' )+/-Float ('1.0' )
                   ^
SyntaxError: invalid syntax

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#116>", line 1, in <module>
    (x**2).evalf(subs={x: ufloat(5,1)})
  ...
sympy.core.sympify.SympifyError: Sympify of expression 'could not parse '5.0+/-1.0'' failed, because of exception being raised:
SyntaxError: invalid syntax (<string>, line 1)

I know that many sympy operations (like differentiation) wouldn't be possible to support this and it would only be possible if all free symbols were substituted since the two types don't play nice:

>>> x + ufloat(5,1)
Traceback (most recent call last):
  File "<pyshell#117>", line 1, in <module>
    x + ufloat(5,1)
TypeError: unsupported operand type(s) for +: 'Symbol' and 'Variable'

But assuming I leave no symbolic operations/variables is it possible to simply evaluate a sympy expression with the python equivalent operations?

Upvotes: 0

Views: 721

Answers (2)

f5r5e5d
f5r5e5d

Reputation: 3741

maybe you want more, but you can just create ordinary functions from sympy expressions and then use uncertainties

from uncertainties import ufloat
from sympy.abc import x
from sympy.utilities.lambdify import lambdify
expr = x**2
f = lambdify(x, expr)
f(ufloat(5,1))
Out[5]: 25.0+/-10.0

Upvotes: 2

Tadhg McDonald-Jensen
Tadhg McDonald-Jensen

Reputation: 21474

My current solution is just using a loose call to eval which does not seem like a good idea, especially since Sympy is fine with Basic.__str__ method being monkey patched.

import math, operator
eval_globals = {"Mod":operator.mod}
eval_globals.update(vars(math))

def eval_sympy_expr(expr, **subs):
    return eval(str(expr), eval_globals, subs)

and for uncertainties support I'd just do import uncertainties.umath as math instead of the default math module.

Upvotes: 0

Related Questions