Reputation: 599
I have a function f(t,u,v)
in string format; for example 't^2 * sint + u*(20 + t) + v*t'
.
How can I solve this function?
I tried to do:
t = Symbol('t')
u = mu
v = mv
sol = eval(f)
But I get error saying name 'sint' is not defined
Upvotes: 1
Views: 435
Reputation: 2289
This is rather ugly, but you could use regular expressions to (somewhat) format the expression before evaluating it. You'll probably have to hack around to adapt the below code to your needs.
import re
import textwrap
import math
functionBaseCode = textwrap.dedent("""
def f({variables}):
return {mathExpr}
""")
def generateFunctionFromExpression(expression, variables):
expression = expression.replace("^", "**")
for fname in ["sin", "cos", "exp", "log", "sqrt"]:
pattern = r"{fname} ?([a-zA-Z0-9]*)".format(fname = fname)
replacement = r"math.{fname}(\1)".format(fname = fname)
expression = re.sub(pattern, replacement, expression)
variables = ", ".join(variables)
mathExpr = expression
funCode = functionBaseCode.format(
variables = variables,
mathExpr = mathExpr)
# print(funCode)
definitions = {}
eval(compile(funCode, "<string>", "exec"), globals(), definitions)
f = definitions["f"]
return f
f = generateFunctionFromExpression("t^2 * sint + u*(20 + t) + v*t", "t u v".split())
g = generateFunctionFromExpression("x^2 + y^2", ["x", "y"])
# h = generateFunctionFromExpression("sqrt(x^2 + y^2)")
# l = generateFunctionFromExpression("log(sqrt(x)) - log(x) / 2", ["x"])
# h and l would fail because of the parenthesis after sqrt and log.
print(f(1, 1, 1)) # 22.8414
print(g(2, 3)) # 13
Upvotes: 0
Reputation:
Using eval
is not the best approach.
SymPy parser has options that allow for parsing strings with things like t^2
(called convert_xor
) and sin t
(called implicit_application
). Here is an example:
from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_application, convert_xor
transformations = standard_transformations + (implicit_application, convert_xor)
f = parse_expr('t^2 * sin t + u*(20 + t) + v*t', transformations=transformations)
Now f
is t**2*sin(t) + t*v + u*(t + 20)
and you can work with it normally, for example
solve(f.subs({Symbol('u'): 4}), Symbol('v')) # returns [-t*sin(t) - 4 - 80/t]
You may want to introduce u, v, t = symbols('u v t')
to have easier access to those symbols.
Unfortunately sint
will not be recognized as sin(t)
; the lack of space is fatal. This will have to be preprocessed, probably with regular expressions. For example,
import re
s = re.sub(r'\bsin', 'sin ', 't^2 * sint + u*(20 + t) + v*t')
leaves a space after each "sin" (extra space will not hurt).
Upvotes: 1