2016-09-16 3 views
3

사용자로부터 입력을 받아서 구문 분석 한 다음 결과 표현식을 대체하려고합니다. 나는 sympy.parsing.sympy_parser.parse_expr을 사용하여 사용자의 임의 입력을 구문 분석 할 수 있음을 알고 있습니다. 그러나 함수 정의를 대체하는 데 문제가 있습니다. 이 방법으로 보충을 할 수 있습니까? 그렇다면 어떻게해야합니까?대용 함수 호출을 sympy로 대체

전체적인 목표는 사용자가 x의 기능을 제공 할 수 있도록 허용하는 것이며 데이터를 저장하는 데 사용됩니다. parse_expr은 저에게 방법의 95 %를 가져다줍니다. 그러나 아래에 나와있는 것과 같이 편리한 확장을 제공하고 싶습니다.

import sympy 
from sympy.parsing.sympy_parser import parse_expr 

x,height,mean,sigma = sympy.symbols('x height mean sigma') 
gaus = height*sympy.exp(-((x-mean)/sigma)**2/2) 

expr = parse_expr('gaus(100, 5, 0.2) + 5') 

print expr.subs('gaus',gaus)         # prints 'gaus(100, 5, 0.2) + 5' 
print expr.subs(sympy.Symbol('gaus'),gaus)     # prints 'gaus(100, 5, 0.2) + 5' 
print expr.subs(sympy.Symbol('gaus')(height,mean,sigma),gaus) # prints 'gaus(100, 5, 0.2) + 5' 

# Desired output: '100 * exp(-((x-5)/0.2)**2/2) + 5' 

이 작업은 python 2.7.9, sympy 0.7.5를 사용하여 수행됩니다.

답변

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 또한 패턴 매칭 등의 다른 옵션을 갖는다.

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