在PYTHON中求解矩阵耦合微分方程时,如何绘制特征值?

在PYTHON中求解矩阵耦合微分方程时,如何绘制特征值?,python,numpy,matrix,scipy,odeint,Python,Numpy,Matrix,Scipy,Odeint,假设我们有三个复矩阵和一个由这些矩阵组成的耦合微分方程组 import numpy, scipy from numpy import (real,imag,matrix,linspace,array) from scipy.integrate import odeint import matplotlib.pyplot as plt def system(x,t): a1= x[0];a3= x[1];a5= x[2];a7= x[3]; a2= x[4];a4= x[5]

假设我们有三个复矩阵和一个由这些矩阵组成的耦合微分方程组

import numpy, scipy
from numpy import (real,imag,matrix,linspace,array)
from scipy.integrate import odeint
import matplotlib.pyplot as plt


def system(x,t):

    a1= x[0];a3= x[1];a5= x[2];a7= x[3];
    a2= x[4];a4= x[5];a6= x[6];a8= x[7];
    b1= x[8];b3= x[9];b5= x[10];b7= x[11];
    b2= x[12];b4= x[13];b6= x[14];b8= x[15];
    c1= x[16];c3= x[17];c5= x[18];c7= x[19];
    c2= x[20];c4= x[21];c6= x[22];c8= x[23];

    A= matrix([ [a1+1j*a2,a3+1j*a4],[a5+1j*a6,a7+1j*a8] ])  
    B= matrix([ [b1+1j*b2,b3+1j*b4],[b5+1j*b6,b7+1j*b8] ])
    C= matrix([ [c1+1j*c2,c3+1j*c4],[c5+1j*c6,c7+1j*c8] ])

    dA_dt= A*C+B*C
    dB_dt= B*C
    dC_dt= C

    list_A_real= [dA_dt[0,0].real,dA_dt[0,1].real,dA_dt[1,0].real,dA_dt[1,1].real]
    list_A_imaginary= [dA_dt[0,0].imag,dA_dt[0,1].imag,dA_dt[1,0].imag,dA_dt[1,1].imag]

    list_B_real= [dB_dt[0,0].real,dB_dt[0,1].real,dB_dt[1,0].real,dB_dt[1,1].real]
    list_B_imaginary= [dB_dt[0,0].imag,dB_dt[0,1].imag,dB_dt[1,0].imag,dB_dt[1,1].imag]

    list_C_real= [dC_dt[0,0].real,dC_dt[0,1].real,dC_dt[1,0].real,dC_dt[1,1].real]
    list_C_imaginary= [dC_dt[0,0].imag,dC_dt[0,1].imag,dC_dt[1,0].imag,dC_dt[1,1].imag]

    return list_A_real+list_A_imaginary+list_B_real+list_B_imaginary+list_C_real+list_C_imaginary



t= linspace(0,1.5,1000)
A_initial= [1,2,2.3,4.3,2.1,5.2,2.13,3.43]
B_initial= [7,2.7,1.23,3.3,3.1,5.12,1.13,3]
C_initial= [0.5,0.9,0.63,0.43,0.21,0.5,0.11,0.3]
x_initial= array( A_initial+B_initial+C_initial )
x= odeint(system,x_initial,t)

plt.plot(t,x[:,0])
plt.show()
我基本上有两个问题:

  • 如何减少我的代码?我的意思是,有没有一种方法可以做到这一点,即不单独写下所有组件,而是在解决ODE系统时处理矩阵

  • 与绘制关于t(我代码的最后两行)的矩阵元素不同,我如何绘制特征值(绝对值)(比如,矩阵A的特征值的abs作为t的函数)?


  • 今年早些时候,我为
    scipy.integrate.odeint
    创建了一个包装器,使求解复杂数组微分方程变得简单:

    您可以使用git签出整个软件包,并使用脚本
    setup.py
    安装它,或者您可以获取一个基本文件,将其重命名为
    odeintw.py
    ,然后将其复制到需要的任何位置。下面的脚本使用函数
    odeintw.odeintw
    来解决系统问题。它通过将三个矩阵
    A
    B
    C
    堆叠成具有形状(3、2、2)的三维数组
    M
    ,使用
    odeintw

    您可以使用
    numpy.linalg.eigvals
    计算
    A(t)
    的特征值。脚本显示了一个示例和一个绘图。特征值是复杂的,因此您可能需要进行一些实验,以找到一种可视化它们的好方法

    import numpy as np
    from numpy import linspace, array
    from odeintw import odeintw
    import matplotlib.pyplot as plt
    
    
    def system(M, t):
        A, B, C = M
        dA_dt = A.dot(C) + B.dot(C)
        dB_dt = B.dot(C)
        dC_dt = C
        return array([dA_dt, dB_dt, dC_dt])
    
    
    t = np.linspace(0, 1.5, 1000)
    
    #A_initial= [1, 2, 2.3, 4.3, 2.1, 5.2, 2.13, 3.43]
    A_initial = np.array([[1 + 2.1j, 2 + 5.2j], [2.3 + 2.13j, 4.3 + 3.43j]])
    
    # B_initial= [7, 2.7, 1.23, 3.3, 3.1, 5.12, 1.13, 3]
    B_initial = np.array([[7 + 3.1j, 2.7 + 5.12j], [1.23 + 1.13j, 3.3 + 3j]])
    
    # C_initial= [0.5, 0.9, 0.63, 0.43, 0.21, 0.5, 0.11, 0.3]
    C_initial = np.array([[0.5 + 0.21j, 0.9 + 0.5j], [0.63 + 0.11j, 0.43 + 0.3j]])
    
    M_initial = np.array([A_initial, B_initial, C_initial])
    sol = odeintw(system, M_initial, t)
    
    A = sol[:, 0, :, :]
    B = sol[:, 1, :, :]
    C = sol[:, 2, :, :]
    
    plt.figure(1)
    plt.plot(t, A[:, 0, 0].real, label='A(t)[0,0].real')
    plt.plot(t, A[:, 0, 0].imag, label='A(t)[0,0].imag')
    plt.legend(loc='best')
    plt.grid(True)
    plt.xlabel('t')
    
    A_evals = np.linalg.eigvals(A)
    
    plt.figure(2)
    plt.plot(t, A_evals[:,0].real, 'b.', markersize=3, mec='b')
    plt.plot(t, A_evals[:,0].imag, 'r.', markersize=3, mec='r')
    plt.plot(t, A_evals[:,1].real, 'b.', markersize=3, mec='b')
    plt.plot(t, A_evals[:,1].imag, 'r.', markersize=3, mec='r')
    plt.ylim(-200, 1200)
    plt.grid(True)
    plt.title('Real and imaginary parts of the eigenvalues of A(t)')
    plt.xlabel('t')
    plt.show()
    
    以下是脚本生成的绘图:

    [0,0]“>


    你确定你的代码是正确的吗?行
    a1=x[0];a2=x[1];a3=x[2];a4=x[3];…
    A=matrix([[a1+1j*a2,a3+1j*a4],…
    表示
    A
    的实部和虚部在
    x
    中交错,但是当你组装
    系统(x,t)的返回值时
    ,你列出了dA_dt的所有实部,然后是所有虚部。你的意思是交错这些吗?微分方程是:dA(t)/dt=A(t)*C(t)+B(t)*C(t);dB(t)/dt=B(t)*C(t)和dC(t)/dt=C(t)。每个元素(每个元素的实部和虚部)任何一个矩阵的值都是t的函数。顺便说一句,除了我提到的两个问题外,我给出的代码对我来说都是完美的。我理解这些等式;我的问题是关于
    a
    B
    C
    中的实数和imag.值是如何存储在
    x
    中的。当你在
    系统(x,t)开始解包
    x
    ,很明显,例如,
    x[1]
    A[0,0]
    的imag.部分。因此
    系统(x,t)
    返回的列表的第二个元素应该是
    A[0,0]
    的虚部的时间导数。也就是说,它应该是
    dA_dt[0,0].imag
    。返回
    list\u real+…
    ,这意味着返回
    list\u real[1]
    作为
    A[0,0]
    的虚部的时间导数。但是
    list\u real[1]
    dA\u dt[0,1]。real
    ,而不是
    dA\u dt[0,0].imag
    @WarrenWeckesser,我明白了!你的意思是我在返回颂歌结果时没有正确地维护顺序。但是如果我将我的新的/返回的“A矩阵”定义为A=矩阵([[x[:,0]+1jx[:,4],x[:,1]+1jx[:,5],[x[:,2]+1jx[:,6],x[:,3]+1jx[:,7])?它能完成任务吗,还是我必须坚持我的第一次分配顺序?我复制了文件并将其命名为odeintw.py到同一个文件夹中。现在,当我运行上面您写下的代码时,我得到了以下错误:回溯(最近一次调用):file“/home/…”,第27行,在sol=odeintw(system,M_initial,t)file中“/home/../odeintw.py”,第180行,在odeintw y0=y0.astype(np.complex128,copy=False)TypeError:astype()不接受关键字参数您使用的是哪个版本的numpy?我猜
    astype
    方法的
    copy
    参数是在更高版本的numpy中添加的。您可以从
    astype的调用中删除该参数(…)
    ,代码应该仍然可以正常工作。文件中有两个对
    astype
    的调用——将它们都更改。(我将在我的待办事项列表中添加“使odeintw对旧版本的numpy更宽容”。)
    astype
    copy
    参数是在numpy 1.7中添加的。@string:我在github上更新了文件
    \u odeintw.py
    ,以处理1.7之前的numpy。它在numpy 1.6.2中对我有效。感谢您的辛勤工作,但不幸的是,现在我又遇到了另一个错误。我的numpy版本是1.6.1,现在我正在使用您更新的_odeint.w pac错误是:回溯(最后一次调用):文件“/home/name.py”,第40行,在A_evals=np.linalg.eigvals(A)文件“/usr/lib/python2.7/dist-packages/numpy/linalg/linalg.py”,第765行,在eigvals\u assertRank2(A)文件“/usr/lib/python2.7/dist-packages/numpy/linalg/linalg.py”中“,第155行,在_assertRank2二维“%len(a.shape)LINALGER:给定了三维数组。数组必须是二维的。”