将 Mathematica 代码重新编写为 Python。用矩阵求解函数

问题描述 投票:0回答:1

我正在尝试将一段代码从 Mathematica 重写为 Python。在 Mathematica 中我有:

求解[(K - w*M) 。 a == 0]

其中 K 和 M 是方阵,a = {x1, x2, x3, x4, x5, x6, x7};在这种情况下,w 将给出系统正常振动模式的 7 个频率的值。然后,对于 w 的每个值,我得到每个 x_i 的相对位置。

编辑:我正在插入完整的代码:

from sympy.solvers import solve
from sympy import *
import numpy as np

m=3.0
k=1.50


w,x1,x2,x3,x4,x5,x6,x7 = symbols("w,x1,x2,x3,x4,x5,x6,x7")

M = Matrix([[m,0,0,0,0,0,0], [0,m,0,0,0,0,0],[0,0,m,0,0,0,0],[0,0,0,m,0,0,0],[0,0,0,0,m,0,0],[0,0,0,0,0,m,0],[0,0,0,0,0,0,m]])
K = Matrix([[2*k,-k,0,0,0,0,0], [-k,2*k,-k,0,0,0,0],[0,-k,2*k,-k,0,0,0],[0,0,-k,2*k,-k,0,0],[0,0,0,-k,2*k,-k,0],[0,0,0,0,-k,2*k,-k],[0,0,0,0,0,-k,2*k]])
xn = Matrix([x1,x2,x3,x4,x5,x6,x7])

D1=K-w*M


print("omega squared")
A=solve(D1.det(), w)
print(A)

res =(np.array(A))**0.5


for i in range(7):
  omegan=float(res[i])
  wn=round(omegan**2,5)
  D1=K-wn*M
  print(D1*xn)
  print("\n** Positions x_i ", i+1, "for omega= ", np.sqrt(wn), " son; ",solve(D1*xn,xn))


我确实得到了与在 Mathematica 中得到的 w 相同的数值,尽管对于矩阵 K 和 M 中的某些数值,计算未完成或两分钟后我没有得到任何响应。对于其他数值,我确实在不到 10 秒的时间内得到了答案。

现在,当我尝试使用以下几行获取 w 的每个数值的 x_i 的位置时:

.
.
.
wn=omegan**2
D1=K-wn*M
solve(D1*xn,xn)

我得到了所有 wn 的情况 {x1:0.0,x2:0.0,x3:0.0,x4:0.0,x5:0.0,x6:0.0,x7:0.0}

但是使用 Mathematica,我确实得到了 x1 -> 0.541196 x2、x3 -> 1.30656 x2、x4 -> 1.41421 x2、x5 -> 1.30656 x2、x6 -> x2、x7 -> 0.541196 x2。

我想我使用的方法在Python中是不可取的。

python sympy wolfram-mathematica
1个回答
0
投票

现在问题已更新为完整的代码,让我们首先看看这些矩阵是什么样的:

In [2]: K
Out[2]: 
⎡3.0   -1.5   0     0     0     0     0  ⎤
⎢                                        ⎥
⎢-1.5  3.0   -1.5   0     0     0     0  ⎥
⎢                                        ⎥
⎢ 0    -1.5  3.0   -1.5   0     0     0  ⎥
⎢                                        ⎥
⎢ 0     0    -1.5  3.0   -1.5   0     0  ⎥
⎢                                        ⎥
⎢ 0     0     0    -1.5  3.0   -1.5   0  ⎥
⎢                                        ⎥
⎢ 0     0     0     0    -1.5  3.0   -1.5⎥
⎢                                        ⎥
⎣ 0     0     0     0     0    -1.5  3.0 ⎦

In [3]: M
Out[3]: 
⎡3.0   0    0    0    0    0    0 ⎤
⎢                                 ⎥
⎢ 0   3.0   0    0    0    0    0 ⎥
⎢                                 ⎥
⎢ 0    0   3.0   0    0    0    0 ⎥
⎢                                 ⎥
⎢ 0    0    0   3.0   0    0    0 ⎥
⎢                                 ⎥
⎢ 0    0    0    0   3.0   0    0 ⎥
⎢                                 ⎥
⎢ 0    0    0    0    0   3.0   0 ⎥
⎢                                 ⎥
⎣ 0    0    0    0    0    0   3.0⎦

看起来您正在尝试解决广义特征值问题,即找到标量

w_i^2
和非零向量
x_i
,这样

K x_i = w_i * M * x_i

SymPy 没有专门的求解器来解决此类广义特征值问题,但 SciPy 的 eig 函数可以用于浮点数矩阵:

https://docs.scipy.org/doc/scipy/reference/ generated/scipy.linalg.eig.html

In [5]: from scipy.linalg import eig

In [11]: import numpy as np

In [12]: Kn = np.array(K, dtype=float)

In [13]: Mn = np.array(M, dtype=float)

In [14]: type(Kn), type(Mn)
Out[14]: (numpy.ndarray, numpy.ndarray)

In [15]: Kn
Out[15]: 
array([[ 3. , -1.5,  0. ,  0. ,  0. ,  0. ,  0. ],
       [-1.5,  3. , -1.5,  0. ,  0. ,  0. ,  0. ],
       [ 0. , -1.5,  3. , -1.5,  0. ,  0. ,  0. ],
       [ 0. ,  0. , -1.5,  3. , -1.5,  0. ,  0. ],
       [ 0. ,  0. ,  0. , -1.5,  3. , -1.5,  0. ],
       [ 0. ,  0. ,  0. ,  0. , -1.5,  3. , -1.5],
       [ 0. ,  0. ,  0. ,  0. ,  0. , -1.5,  3. ]])

In [16]: Mn
Out[16]: 
array([[3., 0., 0., 0., 0., 0., 0.],
       [0., 3., 0., 0., 0., 0., 0.],
       [0., 0., 3., 0., 0., 0., 0.],
       [0., 0., 0., 3., 0., 0., 0.],
       [0., 0., 0., 0., 3., 0., 0.],
       [0., 0., 0., 0., 0., 3., 0.],
       [0., 0., 0., 0., 0., 0., 3.]])

In [17]: eig(Kn, Mn)
Out[17]: 
(array([0.07612047+0.j, 0.29289322+0.j, 0.61731657+0.j, 1.        +0.j,
        1.92387953+0.j, 1.70710678+0.j, 1.38268343+0.j]),
 array([[ 1.91341716e-01,  3.53553391e-01, -4.61939766e-01,
          5.00000000e-01, -1.91341716e-01,  3.53553391e-01,
          4.61939766e-01],
        [ 3.53553391e-01,  5.00000000e-01, -3.53553391e-01,
         -1.93816282e-16,  3.53553391e-01, -5.00000000e-01,
         -3.53553391e-01],
        [ 4.61939766e-01,  3.53553391e-01,  1.91341716e-01,
         -5.00000000e-01, -4.61939766e-01,  3.53553391e-01,
         -1.91341716e-01],
        [ 5.00000000e-01, -7.68527201e-16,  5.00000000e-01,
         -1.91221591e-16,  5.00000000e-01, -4.23414829e-16,
          5.00000000e-01],
        [ 4.61939766e-01, -3.53553391e-01,  1.91341716e-01,
          5.00000000e-01, -4.61939766e-01, -3.53553391e-01,
         -1.91341716e-01],
        [ 3.53553391e-01, -5.00000000e-01, -3.53553391e-01,
         -3.60198282e-16,  3.53553391e-01,  5.00000000e-01,
         -3.53553391e-01],
        [ 1.91341716e-01, -3.53553391e-01, -4.61939766e-01,
         -5.00000000e-01, -1.91341716e-01, -3.53553391e-01,
          4.61939766e-01]]))

或者,由于矩阵 M 是可逆的,我们可以简单地将其转化为普通的特征值问题:

(M**-1 * K) x_i = w_i * x_i

然后我们可以用 SymPy 来做:

In [22]: evs = (M.inv() * K).eigenvects()

In [23]: print(evs[0])
(0.0761204674887132, 1, [Matrix([
[-0.191341716182545],
[-0.353553390593274],
[-0.461939766255643],
[              -0.5],
[-0.461939766255643],
[-0.353553390593274],
[-0.191341716182545]])])

这只是显示第一个(

evs[0]
)特征向量和特征值,并且
1
存在特征值的重数。

在此计算中使用 SymPy 而不是 SciPy 的优点是如果您想精确计算结果。要做到这一点,首先将你的浮点数变成有理数:

In [24]: Mr = M.applyfunc(nsimplify)

In [25]: Kr = K.applyfunc(nsimplify)

In [26]: Mr
Out[26]: 
⎡3  0  0  0  0  0  0⎤
⎢                   ⎥
⎢0  3  0  0  0  0  0⎥
⎢                   ⎥
⎢0  0  3  0  0  0  0⎥
⎢                   ⎥
⎢0  0  0  3  0  0  0⎥
⎢                   ⎥
⎢0  0  0  0  3  0  0⎥
⎢                   ⎥
⎢0  0  0  0  0  3  0⎥
⎢                   ⎥
⎣0  0  0  0  0  0  3⎦

In [27]: Kr
Out[27]: 
⎡ 3    -3/2   0     0     0     0     0  ⎤
⎢                                        ⎥
⎢-3/2   3    -3/2   0     0     0     0  ⎥
⎢                                        ⎥
⎢ 0    -3/2   3    -3/2   0     0     0  ⎥
⎢                                        ⎥
⎢ 0     0    -3/2   3    -3/2   0     0  ⎥
⎢                                        ⎥
⎢ 0     0     0    -3/2   3    -3/2   0  ⎥
⎢                                        ⎥
⎢ 0     0     0     0    -3/2   3    -3/2⎥
⎢                                        ⎥
⎣ 0     0     0     0     0    -3/2   3  ⎦

In [28]: evs = (Mr.inv() * Kr).eigenvects()

In [29]: evs[0]
Out[29]: 
⎛      ⎡⎡-1⎤⎤⎞
⎜      ⎢⎢  ⎥⎥⎟
⎜      ⎢⎢0 ⎥⎥⎟
⎜      ⎢⎢  ⎥⎥⎟
⎜      ⎢⎢1 ⎥⎥⎟
⎜      ⎢⎢  ⎥⎥⎟
⎜1, 1, ⎢⎢0 ⎥⎥⎟
⎜      ⎢⎢  ⎥⎥⎟
⎜      ⎢⎢-1⎥⎥⎟
⎜      ⎢⎢  ⎥⎥⎟
⎜      ⎢⎢0 ⎥⎥⎟
⎜      ⎢⎢  ⎥⎥⎟
⎝      ⎣⎣1 ⎦⎦⎠

In [30]: evs[1]
Out[30]: 
⎛           ⎡⎡-1 ⎤⎤⎞
⎜           ⎢⎢   ⎥⎥⎟
⎜           ⎢⎢-√2⎥⎥⎟
⎜           ⎢⎢   ⎥⎥⎟
⎜           ⎢⎢-1 ⎥⎥⎟
⎜    √2     ⎢⎢   ⎥⎥⎟
⎜1 - ──, 1, ⎢⎢ 0 ⎥⎥⎟
⎜    2      ⎢⎢   ⎥⎥⎟
⎜           ⎢⎢ 1 ⎥⎥⎟
⎜           ⎢⎢   ⎥⎥⎟
⎜           ⎢⎢√2 ⎥⎥⎟
⎜           ⎢⎢   ⎥⎥⎟
⎝           ⎣⎣ 1 ⎦⎦⎠

In [31]: evs[2]
Out[31]: 
⎛                   ⎡⎡                               1                                ⎤⎤⎞
⎜                   ⎢⎢                                                                ⎥⎥⎟
⎜                   ⎢⎢                             ________                           ⎥⎥⎟
⎜                   ⎢⎢                           ╲╱ 2 - √2                            ⎥⎥⎟
⎜                   ⎢⎢                                                                ⎥⎥⎟
⎜                   ⎢⎢                                   2                            ⎥⎥⎟
⎜                   ⎢⎢                   ⎛      ________⎞                             ⎥⎥⎟
⎜                   ⎢⎢                   ⎜    ╲╱ 2 - √2 ⎟        ________             ⎥⎥⎟
⎜                   ⎢⎢            -5 + 4⋅⎜1 - ──────────⎟  + 4⋅╲╱ 2 - √2              ⎥⎥⎟
⎜                   ⎢⎢                   ⎝        2     ⎠                             ⎥⎥⎟
⎜                   ⎢⎢                                                                ⎥⎥⎟
⎜      ________     ⎢⎢                        3                                      2⎥⎥⎟
⎜    ╲╱ 2 - √2      ⎢⎢        ⎛      ________⎞                       ⎛      ________⎞ ⎥⎥⎟
⎜1 - ──────────, 1, ⎢⎢        ⎜    ╲╱ 2 - √2 ⎟         ________      ⎜    ╲╱ 2 - √2 ⎟ ⎥⎥⎟
⎜        2          ⎢⎢-16 - 8⋅⎜1 - ──────────⎟  + 10⋅╲╱ 2 - √2  + 24⋅⎜1 - ──────────⎟ ⎥⎥⎟
⎜                   ⎢⎢        ⎝        2     ⎠                       ⎝        2     ⎠ ⎥⎥⎟
⎜                   ⎢⎢                                                                ⎥⎥⎟
⎜                   ⎢⎢                                   2                            ⎥⎥⎟
⎜                   ⎢⎢                   ⎛      ________⎞                             ⎥⎥⎟
⎜                   ⎢⎢                   ⎜    ╲╱ 2 - √2 ⎟        ________             ⎥⎥⎟
⎜                   ⎢⎢            -5 + 4⋅⎜1 - ──────────⎟  + 4⋅╲╱ 2 - √2              ⎥⎥⎟
⎜                   ⎢⎢                   ⎝        2     ⎠                             ⎥⎥⎟
⎜                   ⎢⎢                                                                ⎥⎥⎟
⎜                   ⎢⎢                             ________                           ⎥⎥⎟
⎜                   ⎢⎢                           ╲╱ 2 - √2                            ⎥⎥⎟
⎜                   ⎢⎢                                                                ⎥⎥⎟
⎝                   ⎣⎣                               1                                ⎦⎦⎠

我不会显示其余部分,因为它很长,但为了完整性,这些是由 SymPy 计算的近似和精确特征值:

In [34]: (M.inv() * K).eigenvals()
Out[34]: 
{0.0761204674887132: 1, 0.292893218813452: 1, 0.61731656763491: 1, 1.0: 1, 1.38268343236509: 1, 1.7 ↪

↪ 0710678118655: 1, 1.92387953251129: 1}

In [35]: (Mr.inv() * Kr).eigenvals()
Out[35]: 
⎧                         ________             ________                    ________             ___ ↪
⎪          √2            ╱ 1   √2             ╱ √2   1      √2            ╱ 1   √2             ╱ √2 ↪
⎨1: 1, 1 - ──: 1, 1 -   ╱  ─ - ── : 1, 1 -   ╱  ── + ─ : 1, ── + 1: 1,   ╱  ─ - ──  + 1: 1,   ╱  ── ↪
⎪          2          ╲╱   2   4           ╲╱   4    2      2          ╲╱   2   4           ╲╱   4  ↪
⎩                                                                                                   ↪

↪ _____       ⎫
↪    1        ⎪
↪  + ─  + 1: 1⎬
↪    2        ⎪
↪             ⎭

这些是由 SciPy 计算的特征值:

In [36]: from scipy.linalg import eigvals

In [37]: eigvals(Kn, Mn)
Out[37]: 
array([0.07612047+0.j, 0.29289322+0.j, 0.61731657+0.j, 1.        +0.j,
       1.92387953+0.j, 1.70710678+0.j, 1.38268343+0.j])
© www.soinside.com 2019 - 2024. All rights reserved.