矢量化和标量的矩阵乘法

时间:2018-02-05 22:12:05

标签: python numpy numpy-broadcasting

我是python / numpy的新手。 我需要做以下计算: 对于一系列离散时间t,计算$ e ^ {At} $ $ 2 \次2 $矩阵$ A $

我做了什么:

def calculate(t_,x_0,v_0,omega_0,c):

    # define A
    a_11,a_12, a_21, a_22=0,1,-omega_0^2,-c
    A =np.matrix([[a_11,a_12], [a_21, a_22]]) 
    print A
    # use vectorization 
    temps = np.array(t_)
    A_ = np.array([A  for k in  range (1,n+1,1)])
    temps*A_
    x_=scipy.linalg.expm(temps*A)
    v_=A*scipy.linalg.expm(temps*A)
    return x_,v_

n=10
omega_0=1
c=1
x_0=1
v_0=1
t_ = [float(5*k*np.pi/n)  for k in  range (1,n+1,1)]
x_, v_ = calculate(t_,x_0,v_0,omega_0,c)

但是,在将A_(包含n次A的数组)与temps(包含我想要计算exp(At)的时间相乘时,我得到此错误:

ValueError:操作数无法与形状(10,)(10,2,2)

一起广播

据我了解矢量化,A_中的每个元素都会乘以与temps相同的索引处的元素;但我想我做对了。 任何帮助/评论非常感谢

2 个答案:

答案 0 :(得分:2)

t_的纯In [254]: t = 5*np.arange(1,n+1)*np.pi/n In [255]: t Out[255]: array([ 1.57079633, 3.14159265, 4.71238898, 6.28318531, 7.85398163, 9.42477796, 10.99557429, 12.56637061, 14.13716694, 15.70796327]) In [256]: a_11,a_12, a_21, a_22=0,1,-omega_0^2,-c In [257]: a_11 Out[257]: 0 In [258]: A = np.array([[a_11,a_12], [a_21, a_22]]) In [259]: A Out[259]: array([[ 0, 1], [-3, -1]]) In [260]: t.shape Out[260]: (10,) In [261]: A.shape Out[261]: (2, 2) In [262]: A_ = np.array([A for k in range (1,n+1,1)]) In [263]: A_.shape Out[263]: (10, 2, 2) 计算是(创建数组而不是列表):

A_

np.ndarrayA。我也np.ndarray np.matrix了;你的A_np.ndarray,但np.matrix仍为A_t * A只能是2d,而(10,) (10,2,2)是3d。

所以In [264]: result = t[:,None,None]*A[None,:,:] In [265]: result.shape Out[265]: (10, 2, 2) 将是数组元素乘法,因此广播错误为einsum

要进行元素乘法,你需要像

这样的东西
In [266]: result1 = np.einsum('i,ijk', t, A_)
In [267]: result1
Out[267]: 
array([[   0.        ,   86.39379797],
       [-259.18139392,  -86.39379797]])

但是如果你想要(10,)与(10,2,2)的矩阵乘法,那么np.dot很容易做到:

tensordot

einsum不能这样做,因为它的规则是'倒数第二个'。 einsum可以,但我对In [268]: (t[:,None,None]*A[None,:,:]).sum(axis=0) Out[268]: array([[ 0. , 86.39379797], [-259.18139392, -86.39379797]]) 感到满意。

但是(t[:,None,None]*A[None,:,:]).cumsum(axis=0)表达式(对我来说)显而易见的是,我可以通过在第一轴上求和来从元素*得到相同的东西:

DECLARE @TAB TABLE(ID INT,NAME VARCHAR(20),DTE DATETIME)

INSERT INTO @TAB
SELECT 1,'RAJIV',GETDATE()
UNION ALL
SELECT 2,'RAJIV',GETDATE()
UNION ALL
SELECT 3,'RAVI',GETDATE()
UNION ALL
SELECT 4,'RAVI',GETDATE()
UNION ALL
SELECT 5,'AJAY',GETDATE()

SELECT A.ID ,CASE WHEN A.R = 1 THEN A.NAME ELSE '' END AS NAME ,A.DTE FROM ( SELECT ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY ID) AS R,* FROM @TAB) A ORDER BY A.ID 每次获得2x2。

答案 1 :(得分:0)

这就是我要做的。

import numpy as np
from scipy.linalg import expm
A = np.array([[1, 2], [3, 4]])
for t in np.linspace(0, 5*np.pi, 20):
    print(expm(t*A))

此处不尝试矢量化。 expm函数一次应用于一个矩阵,它肯定需要大量的计算时间。无需担心将A乘以标量的成本。