【问题标题】:How to evaluate a symbolic expression in different ways?如何以不同的方式评估符号表达式?
【发布时间】:2019-05-26 23:23:57
【问题描述】:

我有一个符号表达式列表,如下所示:

import numpy as np
import sympy
s = sympy.Symbol('s')
x = [ s, s+1, 10*s**2, 5]

使用“sum”添加元素后:

y = sum (x)

我会得到:10*s**2 + 2*s + 6 我想为下面列表中的每个元素评估这个表达式:

s = [1, 2 , 3 , 4 , 5]

我知道我可以定义如下函数:

def F (s):

    F = 10*s**2 + 2*s + 6
    return F
f_dis = [F(value )for value in s]

它会给出我正在寻找的结果:[18, 50, 102, 174, 266] 但是,我的问题是我必须定义 F 并在我的代码中编写表达式。有没有其他方法可以评估sum (x) 而无需在我的代码中编写F = 10*s**2 + 2*s + 6? 我无法将sum (x) 的结果复制并粘贴到我的代码中。

【问题讨论】:

标签: python list sum sympy evaluation


【解决方案1】:

你可以试试这个

import numpy as np
import sympy
s = sympy.Symbol('s')
x = [ s, s+1, 10*s**2, 5]

a = [1, 2 , 3 , 4 , 5]

evals = [sum(x).subs(s, el) for el in a]

输出

[18, 50, 102, 174, 266]

复数

a = [1, 2 , 3 , 4 , 5, 1+1j]

evals = [sum(x).subs(s, el).as_real_imag() for el in a]

您可以轻松解析元组以获取第一个元素。

def re_(tpl: tuple) -> float:
    return tpl[0]

def img_(tpl: tuple) -> float:
    return tpl[-1]

或者

a = [1, 2 , 3 , 4 , 5, 1+1j]

evals = [sum(x).subs(s, el).evalf() for el in a]

输出

[18.0000000000000, 50.0000000000000,
102.000000000000, 174.000000000000,
266.000000000000, 8.0 + 22.0*I]

但最后一个必须转换为复数。

【讨论】:

  • 谢谢,它也可以。但唯一的问题是,如果我将 list 的一个元素更改为复数,则代码不会为我的复数返回简化值。例如,在列表中插入 1+1j 而不是 1,您将得到 8.0 + 2.0*I + 10*(1.0 + 1.0*I)**2 而不是 8.0 + 22.0*I。 eval 函数可以处理这个问题,但速度很慢。
  • 嗨@AmirRezaJalali。也许我对答案的新编辑会有所帮助
【解决方案2】:

另一种解决方案是使用fun.evalf 来评估您的功能。您可以通过使用Add、SymPy 的Advanced Expression Manipulation 添加所有术语来创建函数

import numpy as np
from sympy import Symbol, Add

s = Symbol('s')
x = [s, s+1, 10*s**2, 5]
s_values = [1, 2 , 3 , 4 , 5]
fun = Add(*x) # Create a function by adding all terms. * is to unpack all the values

def F(fun, v):
    return fun.evalf(subs={s: v}) # Evaluate the function at s=v

f_dis = [F(fun, v) for v in s_values]   

# [18.0000000000000,
#  50.0000000000000,
#  102.000000000000,
#  174.000000000000,
#  266.000000000000]

【讨论】:

    【解决方案3】:

    或者计算一次总和并在 lambda 中使用:

    >>> x = [ s, s+1, 10*s**2, 5]
    >>> sumx = sum(x)
    >>> do = lambda si: sumx.subs(s, si)
    >>> list(map(do, range(1, 6)))
    [18, 50, 102, 174, 266]
    

    【讨论】:

    • 谢谢,它也有效。但唯一的问题是,如果我将 list 的一个元素更改为复数,则代码不会为我的复数返回简化值。例如,在列表中插入 1+1j 而不是 1,您将得到 8.0 + 2.0*I + 10*(1.0 + 1.0*I)**2 而不是 8.0 + 22.0*I。 eval 函数可以处理这个问题,但速度很慢。
    • 您可以更改do = lambda si: sumx.subs(s, si).expand(),然后它也适用于这种情况。
    猜你喜欢
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多