用sympy代替函数调用

时间:2016-09-16 16:50:01

标签: python sympy

我希望从用户接收输入,解析它,然后对结果表达式执行一些替换。我知道我可以使用SyntaxError: invalid syntax来解析用户的任意输入。但是,我在函数定义中替换时遇到了麻烦。是否有可能以这种方式进行替换,如果是这样,我该怎么办呢?

总体目标是允许用户提供sympy.parsing.sympy_parser.parse_expr的函数,然后将其用于拟合数据。 x让我获得了95%的合作,但我想提供一些方便的扩展,如下所示。

parse_expr

这是使用python 2.7.9,sympy 0.7.5。

完成的

2 个答案:

答案 0 :(得分:2)

您可以使用replace方法。例如

gaus = Function("gaus") # gaus is parsed as a Function
expr.replace(gaus, Lambda((height, mean, sigma), height*sympy.exp(-((x-mean)/sigma)**2 / 2)))

replace还有其他选项,例如模式匹配。

答案 1 :(得分:0)

经过一些实验,虽然我没有找到内置解决方案,但构建一个满足简单案例的解决方案并不困难。我不是一位专家,所以可能会有一些我没有考虑的优势案例。

import sympy
from sympy.core.function import AppliedUndef

def func_sub_single(expr, func_def, func_body):
    """
    Given an expression and a function definition,
    find/expand an instance of that function.

    Ex:
        linear, m, x, b = sympy.symbols('linear m x b')
        func_sub_single(linear(2, 1), linear(m, b), m*x+b) # returns 2*x+1
    """
    # Find the expression to be replaced, return if not there
    for unknown_func in expr.atoms(AppliedUndef):
        if unknown_func.func == func_def.func:
            replacing_func = unknown_func
            break
    else:
        return expr

    # Map of argument name to argument passed in
    arg_sub = {from_arg:to_arg for from_arg,to_arg in
               zip(func_def.args, replacing_func.args)}

    # The function body, now with the arguments included
    func_body_subst = func_body.subs(arg_sub)

    # Finally, replace the function call in the original expression.
    return expr.subs(replacing_func, func_body_subst)


def func_sub(expr, func_def, func_body):
    """
    Given an expression and a function definition,
    find/expand all instances of that function.

    Ex:
        linear, m, x, b = sympy.symbols('linear m x b')
        func_sub(linear(linear(2,1), linear(3,4)),
                 linear(m, b), m*x+b)               # returns x*(2*x+1) + 3*x + 4
    """
    if any(func_def.func==body_func.func for body_func in func_body.atoms(AppliedUndef)):
        raise ValueError('Function may not be recursively defined')

    while True:
        prev = expr
        expr = func_sub_single(expr, func_def, func_body)
        if prev == expr:
            return expr