如何在 SymPy 中识别 exp 或 trig polynomials/fractions

How to recognize exp or trig polynomials/fractions in SymPy

让我将 指数多项式 定义为项 exp(a*X) 的线性组合,其中 a 是不同的复数。通过只取虚数 as,我们得到一个三角多项式。但是请注意,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')

对于有理函数,您应该可以只使用 ratsimptogetheras_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