Python YALV(又一个循环矢量化)

Python YALV(又一个循环矢量化),python,numpy,vectorization,Python,Numpy,Vectorization,我可以沿着这些线写一些代码,来计算不同频率下,在给定初始条件下的谐波函数 from numpy import * ... for i in range(n_freqs): # A, B so that X(t) = A cos(w t) + B sin(w t) # and X(t0) = x, dX/dt(t0) = v w = ws[i] # use a frequency solver = array(((+cos(w*t0), -sin(w*t0)),

我可以沿着这些线写一些代码,来计算不同频率下,在给定初始条件下的谐波函数

from numpy import *
...
for i in range(n_freqs):
    # A, B so that X(t) = A cos(w t) + B sin(w t)
    # and X(t0) = x, dX/dt(t0) = v
    w = ws[i] # use a frequency
    solver = array(((+cos(w*t0), -sin(w*t0)),
                    (+sin(w*t0), +cos(w*t0)))) 
    AB = solver @ array((x[i], v[i]/w)) # and store somewhere the result
但我想写些更像

Solver = array(((+cos(ws*t0), -sin(ws*t0)),
                (+sin(ws*t0), +cos(ws*t0))))
AB = Solver @ vstack((x,v/ws)
姆诺特韦

from numpy import *

ws = array((1., 2., 3., 4.))
x = array((3., 6., 2., 1.))
v = x
t0 = 10.0
Solver = array(((+cos(ws*t0), -sin(ws*t0)),
                (+sin(ws*t0), +cos(ws*t0))))
AB = Solver @ vstack((x,v/ws)
这给了我以下的线索

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: shapes (2,2,4) and (2,4) not aligned: 4 (dim 2) != 2 (dim 0)
当我想要一个2,4或4,2,我不是太挑剔的形状

是否可以编写一个无循环表达式,立即计算不同三角函数的系数?

1 假设:我们希望得到解算器@b[0],解算器@b[1]等等,即对解算器和b的第一个轴进行迭代,并使用@操作符

给定:b=np.vstackx,v/ws,我们可以使用einsum或matmul/@或tensordot/dot

方法1:采用-

方法2:采用-

现在@operator,我相信,作为Python3.5上np.matmul的替代品,我们只需要将:np.matmulSolver,b.T替换为Solver@b.T

方法3:采用-

方法4:我们也可以使用更流行的方法,在将其输入函数之前进行一些整形,如-

b.dot(Solver.reshape(4,-1).T).reshape(-1,2)
W = ws*t0
cS = np.cos(W)
sS = np.sin(W)
vws = v/ws
out = np.array((cS*x - sS*vws, sS*x + cS*vws))
样本运行-

1设置输入:

In [7]: ws = np.array((1., 2., 3., 4.))
   ...: x = np.array((3., 6., 2., 1.))
   ...: v = x
   ...: t0 = 10.0
   ...: Solver = np.array(((+np.cos(ws*t0), -np.sin(ws*t0)), \
   ...:                     (np.sin(ws*t0), +np.cos(ws*t0))))
    ...: b = np.vstack((x,v/ws))
    ...: 
2以迭代方式获取输出:

In [8]: Solver @ b[0]
Out[8]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738]])

In [9]: Solver @ b[1]
Out[9]: 
array([[-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
3使用einsum并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
4使用matmul并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
5使用@运算符并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
6使用tensordot并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
运行时测试-

In [123]: ws = np.random.randint(1,9,(10000))

In [124]: x = np.random.randint(1,9,(10000))

In [125]: v = x
     ...: t0 = 10.0
     ...: Solver = np.array(((+np.cos(ws*t0), -np.sin(ws*t0)), \
     ...:                     (np.sin(ws*t0), +np.cos(ws*t0))))
     ...: b = np.vstack((x,v/ws))
     ...: 

In [126]: %timeit np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
     ...: %timeit np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
     ...: %timeit np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
     ...: %timeit b.dot(Solver.reshape(4,-1).T).reshape(-1,2)
     ...: 
10000 loops, best of 3: 147 µs per loop
10000 loops, best of 3: 75.1 µs per loop
10000 loops, best of 3: 67.5 µs per loop
10000 loops, best of 3: 60 µs per loop
解释2 假设:我们有这样的东西-

for i in range(len(x)):
    v = x    
    w = ws[i]
    solver = np.array(((+np.cos(w*t0), -np.sin(w*t0)),
                        (+np.sin(w*t0), +np.cos(w*t0))))
    p = np.array((x[i], v[i]/w))
    p0 = np.matmul(solver, p) # output at each iteration
一种避免任何叠加操作并直接使用正弦、余弦项的方法如下-

b.dot(Solver.reshape(4,-1).T).reshape(-1,2)
W = ws*t0
cS = np.cos(W)
sS = np.sin(W)
vws = v/ws
out = np.array((cS*x - sS*vws, sS*x + cS*vws))
解释1 假设:我们希望得到解算器@b[0],解算器@b[1]等等,即对解算器和b的第一个轴进行迭代,并使用@操作符

给定:b=np.vstackx,v/ws,我们可以使用einsum或matmul/@或tensordot/dot

方法1:采用-

方法2:采用-

现在@operator,我相信,作为Python3.5上np.matmul的替代品,我们只需要将:np.matmulSolver,b.T替换为Solver@b.T

方法3:采用-

方法4:我们也可以使用更流行的方法,在将其输入函数之前进行一些整形,如-

b.dot(Solver.reshape(4,-1).T).reshape(-1,2)
W = ws*t0
cS = np.cos(W)
sS = np.sin(W)
vws = v/ws
out = np.array((cS*x - sS*vws, sS*x + cS*vws))
样本运行-

1设置输入:

In [7]: ws = np.array((1., 2., 3., 4.))
   ...: x = np.array((3., 6., 2., 1.))
   ...: v = x
   ...: t0 = 10.0
   ...: Solver = np.array(((+np.cos(ws*t0), -np.sin(ws*t0)), \
   ...:                     (np.sin(ws*t0), +np.cos(ws*t0))))
    ...: b = np.vstack((x,v/ws))
    ...: 
2以迭代方式获取输出:

In [8]: Solver @ b[0]
Out[8]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738]])

In [9]: Solver @ b[1]
Out[9]: 
array([[-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
3使用einsum并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
4使用matmul并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
5使用@运算符并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
6使用tensordot并验证输出:

In [10]: np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
Out[10]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [11]: np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
Out[11]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [14]: (Solver @ b.T).transpose(2,0,1).reshape(-1,2)
Out[14]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
In [15]: np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
Out[15]: 
array([[-0.42715738, -2.61465808],
       [ 2.61465808, -0.42715738],
       [-1.35686862, -0.63436296],
       [ 0.63436296, -1.35686862]])
运行时测试-

In [123]: ws = np.random.randint(1,9,(10000))

In [124]: x = np.random.randint(1,9,(10000))

In [125]: v = x
     ...: t0 = 10.0
     ...: Solver = np.array(((+np.cos(ws*t0), -np.sin(ws*t0)), \
     ...:                     (np.sin(ws*t0), +np.cos(ws*t0))))
     ...: b = np.vstack((x,v/ws))
     ...: 

In [126]: %timeit np.einsum('ijk,lk->lij',Solver, b).reshape(-1,2)
     ...: %timeit np.matmul(Solver, b.T).transpose(2,0,1).reshape(-1,2)
     ...: %timeit np.tensordot(b, Solver, axes=((-1),(-1))).reshape(-1,2)
     ...: %timeit b.dot(Solver.reshape(4,-1).T).reshape(-1,2)
     ...: 
10000 loops, best of 3: 147 µs per loop
10000 loops, best of 3: 75.1 µs per loop
10000 loops, best of 3: 67.5 µs per loop
10000 loops, best of 3: 60 µs per loop
解释2 假设:我们有这样的东西-

for i in range(len(x)):
    v = x    
    w = ws[i]
    solver = np.array(((+np.cos(w*t0), -np.sin(w*t0)),
                        (+np.sin(w*t0), +np.cos(w*t0))))
    p = np.array((x[i], v[i]/w))
    p0 = np.matmul(solver, p) # output at each iteration
一种避免任何叠加操作并直接使用正弦、余弦项的方法如下-

b.dot(Solver.reshape(4,-1).T).reshape(-1,2)
W = ws*t0
cS = np.cos(W)
sS = np.sin(W)
vws = v/ws
out = np.array((cS*x - sS*vws, sS*x + cS*vws))
w是n,所以cosw*t0也有这个形状。解算器的布局为2,2,但有n个元素,因此它是2,2,n。你在用一个2,n“打点”。但在哪个维度上,n还是2中的一个

表示您希望最后一个尺寸标注“随车行驶”,并在解算器的最后2个上点。在Einsum符号中:

np.einsum('ijk,jk->ik', Solver, arr)

In [99]: Solver = np.array(((np.cos(wst),-np.sin(wst)),(np.sin(wst),np.cos(wst))))

In [101]: b = np.vstack((x,v/ws))
In [102]: b.shape
Out[102]: (2, 4)
In [103]: for i in range(4):
     ...:     print(Solver[:,:,i]@b[:,i])
     ...:     
[-0.88515125 -4.14927792]
[-0.29034338  6.70191769]
[ 0.96719065 -1.87322895]
[-0.85321635  0.57837865]
In [104]: np.einsum('ijk,jk->ik',Solver,b)
Out[104]: 
array([[-0.88515125, -0.29034338,  0.96719065, -0.85321635],
       [-4.14927792,  6.70191769, -1.87322895,  0.57837865]])
对于@来说,这不是一个简单的例子,因为它假设数组堆叠在第一维上。e、 g解算器应为n,2,2和b n,2,1`

如果我的推论是正确的,您的“点”维度的大小为2,那么在该维度上的迭代速度将几乎相同,尤其是对于大n:

res = np.zeros((2,n))
for i in range(2):
    res += Solver[:,i,:] * b[i,:]
w是n,所以cosw*t0也有这个形状。解算器的布局为2,2,但有n个元素,因此它是2,2,n。你在用一个2,n“打点”。但在哪个维度上,n还是2中的一个

表示您希望最后一个尺寸标注“随车行驶”,并在解算器的最后2个上点。在Einsum符号中:

np.einsum('ijk,jk->ik', Solver, arr)

In [99]: Solver = np.array(((np.cos(wst),-np.sin(wst)),(np.sin(wst),np.cos(wst))))

In [101]: b = np.vstack((x,v/ws))
In [102]: b.shape
Out[102]: (2, 4)
In [103]: for i in range(4):
     ...:     print(Solver[:,:,i]@b[:,i])
     ...:     
[-0.88515125 -4.14927792]
[-0.29034338  6.70191769]
[ 0.96719065 -1.87322895]
[-0.85321635  0.57837865]
In [104]: np.einsum('ijk,jk->ik',Solver,b)
Out[104]: 
array([[-0.88515125, -0.29034338,  0.96719065, -0.85321635],
       [-4.14927792,  6.70191769, -1.87322895,  0.57837865]])
对于@来说,这不是一个简单的例子,因为它假设数组堆叠在第一维上。e、 g解算器应为n,2,2和b n,2,1`

如果我的推论是正确的,您的“点”维度的大小为2,那么在该维度上的迭代速度将几乎相同,尤其是对于大n:

res = np.zeros((2,n))
for i in range(2):
    res += Solver[:,i,:] * b[i,:]

这里有一点形状模糊,2*2=4。如果示例使用了5个数组,则会更清晰。旁白:从numpy import*执行操作只会给您带来麻烦。使用np。无论什么都更好。这里有一点形状模糊,2*2=4。如果示例使用了5个数组,则会更清晰。旁白:从numpy import*执行操作只会给您带来麻烦。使用np。无论什么都好。奇怪的是,根据你的解释,即使在测试用例中,他也想要一个4,2的结果,而我认为他想要一个210000的结果。@hpaulj你可能是对的。所以,为这种情况添加了其他解决方案。奇怪的是,根据您的解释,即使在测试用例中,他也希望得到4,2的结果,而我认为他希望得到210000个结果。@hpaulj您可能是对的。所以,为这种情况添加了其他解决方案。最后我将使用np.einsum'ijk,jk->jk',Solver,arr。点积方法太复杂了,不是吗?einsum是强大的,但我还没有把我的头缠在它周围。。。我应该更加努力。。。谢谢。最后我将使用np.einsum'ijk,jk->jk',Solver,arr。点积方法太复杂了 很复杂,不是吗?einsum是强大的,但我还没有把我的头缠在它周围。。。我应该更加努力。。。非常感谢。