带嵌套数组的Numpy Dot产品

时间:2018-07-11 05:10:02

标签: python numpy

试图为结构/土木工程应用提供一种执行载荷组合和瞬态载荷模式的方法。

没有模式就很简单:

list of load results = [[d],[t1],...,[ti]], where [ti] = transient load result as a numpy array = A

list of combos = [[1,0,....,0],[0,1,....,1], [dfi, tf1,.....,tfi]] , where tfi = code load factor for transient load = B

在python中,其作用为numpy.dot(A,B)

所以我的问题出现在哪里:

`list of load results = [[d],[t1],.....[ti]]`, where [t1] = [[t11]......[t1i]] for i pattern possibilities and [t1i] = numpy array

所以我在另一个数组中有一个嵌套数组,并想乘以负载组合矩阵。有没有一种方法可以在一个矩阵运算中实现这一点,我可以想出一种方法:先将模式的可能性循环,然后将点乘积与负载组合组合起来,但这在计算上是昂贵的。有什么想法吗?

谢谢

有关不考虑图案化的示例,请参见:https://github.com/buddyd16/Structural-Engineering/blob/master/Analysis/load_combo_test.py

基本,我需要一种给出类似结果的方法,假设loads = np.array([[D],[Ex],[Ey],[F],[H],[L],[Lr],[R],[S],[Wx],[Wy]])-> [L],[Lr],[R],[S]实际上是嵌套数组,即如果D = 1x500数组/矢量,则L,Lr,R或S可以= 100x500阵列。

我的简单解决方案是:

combined_pattern = []
for pattern in load_patterns:
    loads = np.array([[D],[Ex],[Ey],[F],[H],[L[pattern]],[Lr[pattern]],[R[pattern]],[S[pattern]],[Wx],[Wy]])
    combined_pattern.append(np.dot(basic_factors, loads))

简单示例:

import numpy as np

#Simple

A = np.array([1,0,0])
B = np.array([0,1,0])
C = np.array([0,0,1])

Loads = np.array([A,B,C])

Factors = np.array([[1,1,1],[0.5,0.5,0.5],[0.25,0.25,0.25]])

result = np.dot(Factors, Loads)

# Looking for a faster way to accomplish the below operation   
# this works but will be slow for large data sets
# bi can be up to 1x5000 in size and i can be up to 500

A = np.array([1,0,0])
b1 = np.array([1,0,0])
b2 = np.array([0,1,0])
b3 = np.array([0,0,1])
B = np.array([b1,b2,b3])
C = np.array([0,0,1])

result_list = []

for load in B:
    Loads = np.array([A,load,C])

    Factors = np.array([[1,1,1],[0.5,0.5,0.5],[0.25,0.25,0.25]])

    result = np.dot(Factors, Loads)

    result_list.append(result)

edit:在np.dot()中具有相反的因子和负载。

1 个答案:

答案 0 :(得分:1)

在您的简单示例中,数组形状为:

In [2]: A.shape
Out[2]: (3,)
In [3]: Loads.shape
Out[3]: (3, 3)
In [4]: Factors.shape
Out[4]: (3, 3)
In [5]: result.shape
Out[5]: (3, 3)

dot中的规则是Loads的最后一个维度与Factors的第二个到最后一个配对

result = np.dot(Loads,Factors)
(3,3) dot (3,3) => (3,3)    # 3's in common
(m,n) dot (n,l) => (m,l)    # n's in common

在迭代中,AloadC都是(3,),而Loads是(3,3)。

result_list是3(3,3)个数组的列表,而np.array(result_list)将是(3,3,3)。

让我们对所有Loads进行3d排列:

In [16]: Bloads = np.array([np.array([A,load,C]) for load in B])
In [17]: Bloads.shape
Out[17]: (3, 3, 3)
In [18]: Bloads
Out[18]: 
array([[[1, 0, 0],
        [1, 0, 0],
        [0, 0, 1]],

       [[1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]],

       [[1, 0, 0],
        [0, 0, 1],
        [0, 0, 1]]])

我可以轻松地用dot来完成BloadsFactors中的einsum

In [19]: np.einsum('lkm,mn->lkn', Bloads, Factors)
Out[19]: 
array([[[1.  , 1.  , 1.  ],
        [1.  , 1.  , 1.  ],
        [0.25, 0.25, 0.25]],

       [[1.  , 1.  , 1.  ],
        [0.5 , 0.5 , 0.5 ],
        [0.25, 0.25, 0.25]],

       [[1.  , 1.  , 1.  ],
        [0.25, 0.25, 0.25],
        [0.25, 0.25, 0.25]]])

einsum不是唯一的方法,但是(对我来说)这是跟踪尺寸的最简单方法。

如果尺寸不同,则保持直线更容易。它们都是3,因此很难将它们分开。但是,如果B为(5,4)和Factors(4,2),则Bloads为(5,3,4),而einsum的结果为( 5,3,2)(尺寸4在dot中消失)。

无循环地构造Bloads有点棘手,因为B的行与AC交错。

In [38]: np.stack((A[None,:].repeat(3,0),B,C[None,:].repeat(3,0)),1)
Out[38]: 
array([[[1, 0, 0],
        [1, 0, 0],
        [0, 0, 1]],

       [[1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]],

       [[1, 0, 0],
        [0, 0, 1],
        [0, 0, 1]]])

要了解此测试的子表达式,例如A[None,:]repeat等。

等效地:

np.array((A[None,:].repeat(3,0),B,C[None,:].repeat(3,0))).transpose(1,0,2)