如何在 SymPy 中识别 exp 或 trig polynomials/fractions
How to recognize exp or trig polynomials/fractions in SymPy
让我将 指数多项式 定义为项 exp(a*X)
的线性组合,其中 a
是不同的复数。通过只取虚数 a
s,我们得到一个三角多项式。但是请注意,exp(X*X)
或 cos(X*X)
形式的项是 而不是 一个 exp/trig 多项式。
我们以相同的方式定义 exp/trig 有理分数 作为前面描述的相应类型的两个“多项式”的商。
我的问题:给定一个 sympy 表达式,如何识别它是一个 exp/trig poly/frac?
我的目标是编写一个函数 is_exp_poly(expr)
返回一个布尔值。
到目前为止,我已经尝试了以下代码,它以一种有前途的方式重写了我的起始表达式:
X= Symbol('X')
expr= cos(2*X) * sin(pi*X)
trans= powsimp(expand(expr.rewrite(exp).subs(X : log(X)).rewrite(sympy.Pow)))
# results in: -I*X**(-2*I + I*pi)/4 - I*X**(2*I + I*pi)/4 + I*X**(-I*pi - 2*I)/4 + I*X**(-I*pi + 2*I)/4
从这里我觉得我应该可以回答我的问题了。但我不太清楚如何识别一个表达式,它是(非整数)幂(或其一部分)的线性组合。就此而言,我的意思是使用高级 sympy 函数而不是直接分析公式结构。
有好心人帮我解决问题吗?不知何故,我偶然发现了可能相关的 this question,尽管 Laurent Polynomials 的功能仍未实现(据我了解 git 问题的线程)。看来我正在处理更复杂的表达式(尽管我不打算做任何像分解它们那样花哨的事情)。
你可以这样做:
In [9]: X= Symbol('X')
...: expr= cos(2*X) * sin(pi*X)
In [10]: expr.atoms(sin, cos, exp)
Out[10]: {sin(π⋅X), cos(2⋅X)}
In [11]: expr.as_poly(*expr.atoms(sin, cos, exp))
Out[11]: Poly((cos(2*X))*(sin(pi*X)), cos(2*X), sin(pi*X), domain='ZZ')
对于有理函数,您应该可以只使用 ratsimp
、together
、as_numer_denom
等来分别获取分子和分母。
以下收集不同的指数并为它们分配一个变量,在表达式中替换它们,然后可以测试它是否满足您的要求:
>>> x = numbered_symbols('x')
>>> reps={}
>>> powsimp(expr.rewrite(exp).expand()).replace(lambda x: x.func is exp,
... lambda e: reps.setdefault(e, next(x)))
-I*x0/4 - I*x1/4 + I*x2/4 + I*x3/4
所以你给出的表达式是指数的线性组合。 reps
.
中的符号和指数之间的映射
根据@smichr 的回答,这就是我解决识别 exp poly 问题的方法。进一步明显的修改完全回答了我的问题。
x = numbered_symbols('x')
reps={}
trans=cancel(expr.rewrite(exp).expand().replace(lambda e: e.func is exp, lambda e: reps.setdefault(e, next(x))))
if trans.is_polynomial():
result=all([diff(e.args[0],X,2).is_zero and not "_rec_replace" in str(e) for e in reps.keys()])
else:
result=False
让我将 指数多项式 定义为项 exp(a*X)
的线性组合,其中 a
是不同的复数。通过只取虚数 a
s,我们得到一个三角多项式。但是请注意,exp(X*X)
或 cos(X*X)
形式的项是 而不是 一个 exp/trig 多项式。
我们以相同的方式定义 exp/trig 有理分数 作为前面描述的相应类型的两个“多项式”的商。
我的问题:给定一个 sympy 表达式,如何识别它是一个 exp/trig poly/frac?
我的目标是编写一个函数 is_exp_poly(expr)
返回一个布尔值。
到目前为止,我已经尝试了以下代码,它以一种有前途的方式重写了我的起始表达式:
X= Symbol('X')
expr= cos(2*X) * sin(pi*X)
trans= powsimp(expand(expr.rewrite(exp).subs(X : log(X)).rewrite(sympy.Pow)))
# results in: -I*X**(-2*I + I*pi)/4 - I*X**(2*I + I*pi)/4 + I*X**(-I*pi - 2*I)/4 + I*X**(-I*pi + 2*I)/4
从这里我觉得我应该可以回答我的问题了。但我不太清楚如何识别一个表达式,它是(非整数)幂(或其一部分)的线性组合。就此而言,我的意思是使用高级 sympy 函数而不是直接分析公式结构。
有好心人帮我解决问题吗?不知何故,我偶然发现了可能相关的 this question,尽管 Laurent Polynomials 的功能仍未实现(据我了解 git 问题的线程)。看来我正在处理更复杂的表达式(尽管我不打算做任何像分解它们那样花哨的事情)。
你可以这样做:
In [9]: X= Symbol('X')
...: expr= cos(2*X) * sin(pi*X)
In [10]: expr.atoms(sin, cos, exp)
Out[10]: {sin(π⋅X), cos(2⋅X)}
In [11]: expr.as_poly(*expr.atoms(sin, cos, exp))
Out[11]: Poly((cos(2*X))*(sin(pi*X)), cos(2*X), sin(pi*X), domain='ZZ')
对于有理函数,您应该可以只使用 ratsimp
、together
、as_numer_denom
等来分别获取分子和分母。
以下收集不同的指数并为它们分配一个变量,在表达式中替换它们,然后可以测试它是否满足您的要求:
>>> x = numbered_symbols('x')
>>> reps={}
>>> powsimp(expr.rewrite(exp).expand()).replace(lambda x: x.func is exp,
... lambda e: reps.setdefault(e, next(x)))
-I*x0/4 - I*x1/4 + I*x2/4 + I*x3/4
所以你给出的表达式是指数的线性组合。 reps
.
根据@smichr 的回答,这就是我解决识别 exp poly 问题的方法。进一步明显的修改完全回答了我的问题。
x = numbered_symbols('x')
reps={}
trans=cancel(expr.rewrite(exp).expand().replace(lambda e: e.func is exp, lambda e: reps.setdefault(e, next(x))))
if trans.is_polynomial():
result=all([diff(e.args[0],X,2).is_zero and not "_rec_replace" in str(e) for e in reps.keys()])
else:
result=False