符号复杂表达式简化

时间:2021-06-01 10:18:24

标签: python sympy simplify

虽然我的问题与特定问题有关,但我想用更一般的术语来解决它。 我想简化通过使用 sympy 包将符号矩阵相乘获得的分数复数表达式。 我得到的是带有实参数和许多复杂指数项(相位项)的分数,例如 exp(-jd)、exp(-2jd) 和 exp(-4j*d)。我得到了正确的结果,但是当我尝试计算一个真正的表达式 ||**2 时,sympy.simplify() 无法管理相位项,我得到了一个巨大的表达式,我必须手动减少. 我的测试程序是 T、M、M_inv、F 和 T,2x2 符号矩阵是:

import simply as sym
Mf = T @ M_inv @ F @ T
Mf = sym.simplify(Mf)
eig = Mf.eigenvals() 
for key,value in eig.items():
    val = key
eig_cc = np.conj(val)
final = sym.simplify(val*eig_cc)

我想知道是否存在改进计算的特定工具。

经过快速研究,我在帖子中发现了两种可能性:

Exponential to trigonometric conversion in SymPy while simplifying - a stubborn expression

  1. a.trigsimp() for a in expr.rewrite(cos).expand().as_real_imag()

  2. expr.rewrite(cos).simplify().trigsimp()

虽然第一个为更简单的表达式提供了正确的结果(不是我想要解决的那个),但在我的情况下它们都不起作用。

第二个问题,eig 输出有一个 dict 形状,所以为了取值,我使用了 for 循环。

for key,value in eig.items():
    val = key

是否有更好、更快的方法来达到相同的结果?

我使用的代码是:

import numpy as np
import sympy as sym
from sympy import *
t = sym.Symbol('t', real=True)
r = sym.Symbol('r', real=True)
u = sym.Symbol('u', real=True)
d = sym.Symbol('d', real=True)
a = sym.Symbol('a', real=True)


I = np.identity(2)

T = sym.Matrix ([[t,0],[0,t]])
R = sym.Matrix ([[r,0],[0,r]])
F = sym.Matrix ([[sym.sqrt(u)*sym.exp(-1j*d),0],[0,sym.sqrt(u)*sym.exp(-1j*d)]])



sym.init_printing()
M = (I - F @ R @ F @ R)
M_inv = M.inv() 

Mf = T @ M_inv @ F @ T

Mf = sym.simplify(Mf)

eig = Mf.eigenvals()



for key,value in eig.items():
    val = key

eig_cc = np.conj(val)
expr = finale = sym.simplify(val*eig_cc)

"""
Test1
"""

result = [a.trigsimp() for a in expr.rewrite(sin).expand().as_real_imag()]

"""
Test2
"""

result1 = expr.rewrite(sin).simplify().trigsimp()

提前致谢

1 个答案:

答案 0 :(得分:1)

几点:

  1. 不要把 numpy 和 sympy 这样混为一谈,除非你清楚地知道自己在做什么。这里根本不需要使用 numpy,所以使用例如sym.eye(2)sym.conjugate(val)

  2. 除非有充分的理由,否则不要使用浮点数 - 使用 sym.I 而不是 1j。使用 numpy 可能会引入浮点数,因此除非您知道自己在做什么,否则不要这样做。

  3. 虽然在这种情况下 eigenvals 返回一个 dict,但您只关心 dict 的值,因此您可以只执行 list(M.eigenvals())

  4. 虽然您将所有符号声明为实数,但您使用的 sqrt(u) 只有在 u 为正数时才是实数。除非您打算将 sqrt(u) 设为潜在的虚数,否则应将 u 声明为正数。

通过上述更改,您的代码如下所示:

import sympy as sym
from sympy import *
t = sym.Symbol('t', real=True)
r = sym.Symbol('r', real=True)
u = sym.Symbol('u', positive=True)
d = sym.Symbol('d', real=True)
a = sym.Symbol('a', real=True)

I = sym.eye(2)

T = sym.Matrix ([[t,0],[0,t]])
R = sym.Matrix ([[r,0],[0,r]])
F = sym.Matrix ([[sym.sqrt(u)*sym.exp(-sym.I*d),0],[0,sym.sqrt(u)*sym.exp(-sym.I*d)]])

sym.init_printing()
M = (I - F @ R @ F @ R)
M_inv = M.inv()

Mf = T @ M_inv @ F @ T

Mf = sym.simplify(Mf)

[eig] = Mf.eigenvals()

expr = eig * sym.conjugate(eig)

现在最终的表达式 expr 是这样的:

In [8]: expr
Out[8]: 
               4                
              t ⋅u              
────────────────────────────────
⎛ 2      -2⋅ⅈ⋅d⎞ ⎛ 2      2⋅ⅈ⋅d⎞
⎝r ⋅u - ℯ      ⎠⋅⎝r ⋅u - ℯ     ⎠

In [9]: expr.expand()
Out[9]: 
                  4                   
                 t ⋅u                 
──────────────────────────────────────
 4  2    2    2⋅ⅈ⋅d    2    -2⋅ⅈ⋅d    
r ⋅u  - r ⋅u⋅ℯ      - r ⋅u⋅ℯ       + 1

In [10]: expr.expand().rewrite(sin)
Out[10]: 
                                   4                                    
                                  t ⋅u                                  
────────────────────────────────────────────────────────────────────────
 4  2    2                               2                              
r ⋅u  - r ⋅u⋅(-ⅈ⋅sin(2⋅d) + cos(2⋅d)) - r ⋅u⋅(ⅈ⋅sin(2⋅d) + cos(2⋅d)) + 1

In [11]: expr.expand().rewrite(sin).expand()
Out[11]: 
             4             
            t ⋅u           
───────────────────────────
 4  2      2               
r ⋅u  - 2⋅r ⋅u⋅cos(2⋅d) + 1

我想最终的结果就是你想要的。

相关问题