问题
I need to accept user input in the form of a string, parse it into a sympy expression, and then solve for a variable. Most of the user's allowed functions match sympy functions except for log2(x) which is equivalent to sympy's log(x, 2).
I've tried the method of defining a python function that returns the sympy function as mentioned here. I've also tried using defining a sympy function using lambda. Both methods work for getting the value of the expression after substituting variables for numbers, but create errors if sympy.solve is called to solve for a variable. For example:
import sympy
from sympy.parsing.sympy_parser import parse_expr
def log2(x):
return sympy.log(x, 2)
t, k, y = sympy.symbols('t k y')
parsed = parse_expr("log2(t + k) + k - y")
sympy.solve(parsed, k)
raises a NotImplementedError. Using lambda returns similar results. The above code works if log2(t+k) is replaced with log(t+k,2). I assume this is because sympy functions are objects with many different methods and sympy.solve attempts to call a method not implemented in my python function. I'm looking for a solution that doesn't require creating a class for my function the same length as the implementation for log. Is there a way to have sympy recognize and work with log2 without creating a long class to handle every possible call? Can I somehow create a short class definition that passes any method calls along to log(x, 2)?
回答1:
The parser does not automatically match "log2" in the given string to the function you created. You have to tell it explicitly that's what is to be done, with local_dict={"log2": log2}.
Or just put lambda directly into local_dict:
import sympy
from sympy.parsing.sympy_parser import parse_expr
t, k, y = sympy.symbols('t k y')
parsed = parse_expr("log2(t + k) + k - y", local_dict={"log2": lambda x: sympy.log(x, 2)})
print(sympy.solve(parsed, k))
Output: [(-t*log(2) + LambertW(exp((t + y)*log(2))*log(2)))/log(2)]
来源:https://stackoverflow.com/questions/44223486/need-sympy-function-for-log2x-capable-of-being-used-in-sympy-solve