0

Suppose I have a 2d image, with associated coordinates (x,y) at every point. I want to find the inner product of the position vector at every point $i$ with every other point $j$. Essentially, the Cartesian product of two 2d arrays.

What would be the fastest way to accomplish this, in Python?

My current implementation looks something like this:

def cartesian_product(arrays):
    broadcastable = np.ix_(*arrays)
    broadcasted = np.broadcast_arrays(*broadcastable)
    rows, cols = reduce(np.multiply, broadcasted[0].shape), len(broadcasted)
    out = np.empty(rows * cols, dtype=broadcasted[0].dtype)
    start, end = 0, rows
    for a in broadcasted:
        out[start:end] = a.reshape(-1)
        start, end = end, end + rows
    return out.reshape(cols, rows).T

def inner_product():
    x, y = np.meshgrid(np.arange(4),np.arange(4))

    cart_x = cartesian_product([x.flatten(),x.flatten()])
    cart_y = cartesian_product([y.flatten(),y.flatten()])

    Nx = x.shape[0]    

    xx = (cart_x[:,0]*cart_x[:,1]).reshape((Nx**2,Nx,Nx))
    yy = (cart_y[:,0]*cart_y[:,1]).reshape((Nx**2,Nx,Nx))

    inner_products = xx+yy
    return inner_products

(Credit where credit is due: cartesian_product is taken from Using numpy to build an array of all combinations of two arrays)

But this doesn't work. For larger arrays (say, 256x256), this gives me a memory error.

Community
  • 1
  • 1
user1991
  • 584
  • 1
  • 4
  • 18

1 Answers1

0

You're probably storing the generated cartesian product.
You're taking product of 2 dimensional arrays. Product of mxm and nxn matrices would produce (mmn*n) values.
For 256*256 matrices it's going to generate 2^32=4,294,967,296 elements. If you don't need all the values at the same time, you could try storing a few and processing them and disposing them off before generating next values.

Simpler way of taking cartesian product, would be like :

import itertools

xMax = 2
yMax = 2
m1 = [ [ (x + y*xMax) for x in range(xMax)] for y in range(yMax)]
print("m1=" + `m1`)
m2 = [ [ chr(ord('a') + (x + y*xMax)) for x in range(xMax)] for y in range(yMax)]
print("m2=" + `m2`)
for x in m1 :
    for y in m2:
        for e in itertools.product(x,y): #generating xMax *xMax at at time, process one by one or in batch
            print e

Above code will generate following output

m1=[[0, 1], [2, 3]]
m2=[['a', 'b'], ['c', 'd']]
(0, 'a')
(0, 'b')
(1, 'a')
(1, 'b')
(0, 'c')
(0, 'd')
(1, 'c')
(1, 'd')
(2, 'b')
(2, 'a')
(3, 'a')
(3, 'b')
(2, 'c')
(2, 'd')
(3, 'c')
(3, 'd')
11thdimension
  • 10,333
  • 4
  • 33
  • 71