How to add / accumulate a matrix product (dot)?

Using the numpy python library, you can use the cumprod function to evaluate aggregate products, for example.

a = np.array([1,2,3,4,2])
np.cumprod(a)

gives

array([ 1,  2,  6, 24, 48])

Indeed, this function can be applied only along one axis.

I would like to do the same with matrices (represented as numpy arrays), for example. if I have

S0 = np.array([[1, 0], [0, 1]])
Sx = np.array([[0, 1], [1, 0]])
Sy = np.array([[0, -1j], [1j, 0]])
Sz = np.array([[1, 0], [0, -1]])

and

b = np.array([S0, Sx, Sy, Sz])

then I would like to have a function cumprodthat gives

np.array([S0, S0.dot(Sx), S0.dot(Sx).dot(Sy), S0.dot(Sx).dot(Sy).dot(Sz)])

(This is a simple example, in fact I have potentially large matrices scored over n-dimensional grids, so I'm looking for the easiest and most efficient way to evaluate this thing.)

In particular. Mathematica I would use

FoldList[Dot, IdentityMatrix[2], {S0, Sx, Sy, Sz}]

, , , - accumulate numpy.ufunc s. , , , , ,

np.core.umath_tests.matrix_multiply.accumulate(np.array([pauli_0, pauli_x, pauli_y, pauli_z]))

numpy,

Reduction not defined on ufunc with signature

, () ?

.

+4
1

, 3 :

Python ( )

In [118]: reduce(np.dot,[S0,Sx,Sy,Sz])
array([[ 0.+1.j,  0.+0.j],
       [ 0.+0.j,  0.+1.j]])

einsum

In [119]: np.einsum('ij,jk,kl,lm',S0,Sx,Sy,Sz)

einsum , 5d 3 . C nditer , :

In [120]: np.sum(S0[:,:,None,None,None] * Sx[None,:,:,None,None] *
    Sy[None,None,:,:,None] * Sz[None,None,None,:,:],(1,2,3))

In [127]: np.prod([S0[:,:,None,None,None], Sx[None,:,:,None,None],
    Sy[None,None,:,:,None], Sz[None,None,None,:,:]]).sum((1,2,3))

A , np.einsum, C Python, (-) Cython. github

https://github.com/hpaulj/numpy-einsum

einsum_py.py - einsum Python,

sop.pyx - Cython, sop.so.

. Sy, sop ( ).

import numpy as np
import sop
import einsum_py    

S0 = np.array([[1., 0], [0, 1]])
Sx = np.array([[0., 1], [1, 0]])
Sz = np.array([[1., 0], [0, -1]])

print np.einsum('ij,jk,kl', S0, Sx, Sz)
# [[ 0. -1.] [ 1.  0.]]
# same thing, but with parsing information
einsum_py.myeinsum('ij,jk,kl', S0, Sx, Sz, debug=True)
"""
{'max_label': 108, 'min_label': 105, 'nop': 3, 
 'shapes': [(2, 2), (2, 2), (2, 2)], 
 'strides': [(16, 8), (16, 8), (16, 8)], 
 'ndim_broadcast': 0, 'ndims': [2, 2, 2], 'num_labels': 4,
 ....
 op_axes [[0, -1, 1, -1], [-1, -1, 0, 1], [-1, 1, -1, 0], [0, 1, -1, -1]]
"""    

# take op_axes (for np.nditer) from this debug output
op_axes = [[0, -1, 1, -1], [-1, -1, 0, 1], [-1, 1, -1, 0], [0, 1, -1, -1]]
w = sop.sum_product_cy3([S0,Sx,Sz], op_axes)
print w

sum_product_cy3 ops. . , Cython, Python. , , repeat(dot...) .

Cython:

def sum_product_cy3(ops, op_axes, order='K'):
    #(arr, axis=None, out=None):
    cdef np.ndarray[double] x, y, z, w
    cdef int size, nop
    nop = len(ops)
    ops.append(None)
    flags = ['reduce_ok','buffered', 'external_loop'...]
    op_flags = [['readonly']]*nop + [['allocate','readwrite']]

    it = np.nditer(ops, flags, op_flags, op_axes=op_axes, order=order)
    it.operands[nop][...] = 0
    it.reset()
    for x, y, z, w in it:
        for i in range(x.shape[0]):
           w[i] = w[i] + x[i] * y[i] * z[i]
    return it.operands[nop]
+4

All Articles