如何使用缓存来减少符号计算问题?


import sympy as sp
from fuanctools import lru_cache
s = []
for i in range(4):
s.append(sp.Symbol('s%s'%i)
@lru_cache
def some_calculation(input1, input2):
'''
some calculation code
'''
return calculation_result
#First calculation
some_calculation(sp.sin(s[0]),sp.sin(s[1]))
#Second calculation
some_calculation(sp.sin(s[2]),sp.sin(s[3]))

在第二次计算中,它与第一次计算只有变量不同。实际计算过程相同。在当前的方法中,它有一个不同的因变量,因此需要重新计算。如何使用缓存的方法,使计算过程不必重复,而不改变计算结果。

注:这里的计算是为了保留变量的原始形式,而不是替换后的数值解。下面是一些例子:

def example_calculation(input1, input2):
return sp.simplify(input1(input1+input2) + input2(input1-input2))     

我想要一个更通用的方法。input1和input2是随机输入。在使用缓存之前,有必要首先判断input1和input2是否出现了相同的结构。在利用缓存的直接输出之前,请确保对相同的结构进行了计算。

我建议通过将符号xy传递给计算来获得符号结果,然后该结果,在某种意义上,您的缓存。只需将您想要的值替换为xy

def f(x,y):
return x + y
from sympy.abc import x, y
from sympy import symbols
s = symbols('s:4')
v = f(x, y)
>>> v
x + y
>>> v.subs(dict(zip((x,y),(s[0],s[1]))))
s0 + s1

或更复杂的f:

def f(x,y):
g, h = map(Function, 'gh')
return g(x + y) + h(x - y)
s=symbols('s:5')
C=lambda i,j: cos(s[i])*cos(s[j]);S=lambda i,j: sin(s[i])*sin(s[j])
>>> eq = f(x, y); eq
g(x + y) + h(x - y)
>>> eq.subs(x,S(0,1)).subs(y,C(2,4))
g(sin(s0)*sin(s1) + cos(s2)*cos(s4)) + h(sin(s0)*sin(s1) - cos(s2)*cos(s4))
>>> eq.subs(x,S(1,2)).subs(y,C(3,4))
g(sin(s1)*sin(s2) + cos(s3)*cos(s4)) + h(sin(s1)*sin(s2) - cos(s3)*cos(s4))

如果使用subs不方便,请继续修改您的方程,为您执行subs/xreplace:

>>> from sympy.abc import a, b
>>> EQ = lambdify((a,b), eq.xreplace(dict(zip((x,y),(a,b)))))
>>> EQ(S(1,2), C(3,4))
g(sin(s1)*sin(s2) + cos(s3)*cos(s4)) + h(sin(s1)*sin(s2) - cos(s3)*cos(s4))