首页 > 解决方案 > sympy 和 lambda() 的区别

问题描述

我一直在尝试优化最初使用 Sympy 编写的一段代码(它是正确的,但速度很慢)。我用lambda()函数替换了方程(它要快得多)。但是,输出并不完全相同。这似乎是一个微小的偏差,但对我来说,它有所作为。我将非常感谢有关如何使两个结果相同的任何想法或建议。请看下面的代码:

# --------- Parameters ----------------
s_1_value = 0.9
s_2_value = 1.2
s_eq_pre = 11.628616990912533
history = 471.88639640808105

# --------- Sympy ----------------
t = sympy.Symbol('t', positive = True)
s_1, s_2 = sympy.symbols('s_1 s_2', real = True)
s_eq = + 6.11513442504139 * s_1 ** 3 + 0.764837815685049 * s_1 + 0.0319169512850692 * s_2 ** 3 + 0.00409678596174992 * s_2 + 0.0837906906442538
exponential = sympy.exp(1.73847894065589 * t) * sympy.exp(-1.74850463949595 * t)

s_eq_cur = s_eq.subs([(s_1, s_1_value), (s_2, s_2_value)])
DELTA = (s_eq_pre - s_eq_cur) * (1 / exponential.subs(t, history))

print("sympy: ", DELTA)


# --------- lambda ----------------
s_eq = lambda s_1, s_2: + 6.11513442504139 * s_1 ** 3 + 0.764837815685049 * s_1 + 0.0319169512850692 * s_2 ** 3 + 0.00409678596174992 * s_2 + 0.0837906906442538
exponential = lambda t: mpmath.exp(1.73847894065589 * t) * mpmath.exp(-1.74850463949595 * t)
DELTA_ = lambda s_eq_pre_, s_eq_cur_: (s_eq_pre_ - s_eq_cur_) * (1 / exponential(history))

s_eq_cur = s_eq(s_1_value, s_2_value)
DELTA = DELTA_(s_eq_pre, s_eq_cur)

print("lambda: ", DELTA)

和输出:

sympy:   718.832531350073
lambda:  718.83253135012

谢谢...

标签: lambdasympy

解决方案


不同之处在于 SymPy 在评估之前自动简化 lambda 表达式的能力:

>>> exp(1.73847894065589 * t) * exp(-1.74850463949595 * t)
exp(-0.01002569884006*t)
>>> 1/_.subs(t, history)
113.407882233341

该单个函数的计算结果与两个函数的乘积略有不同。如果您不希望发生这种情况,您要么必须对表达式使用 unevaluate-Mul,要么可以将 lambda 设置为 2-arg lambda 并在函数exp调用时提供要用于的函数:

>>> e1, e2 = sympy.exp(1.73847894065589 * t), sympy.exp(-1.74850463949595 * t)
>>> uneval = lambda x: Mul(e1, e2, evaluate=False).subs(t, x)
>>> two_args = lambda e, t: e(1.73847894065589 * t)*e(-1.74850463949595 * t)
>>> 1/uneval(history)
113.407882233349
>>> 1/two_args(sympy.exp, history)
113.407882233349
>>> 1/two_args(mpmath.exp, history)
113.407882233349

推荐阅读