Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test if an array is broadcastable to a shape?

What is the best way to test whether an array can be broadcast to a given shape?

The "pythonic" approach of trying doesn't work for my case, because the intent is to have lazy evaluation of the operation.

I'm asking how to implement is_broadcastable below:

>>> x = np.ones([2,2,2])
>>> y = np.ones([2,2])
>>> is_broadcastable(x,y)
True
>>> y = np.ones([2,3])
>>> is_broadcastable(x,y)
False

or better yet:

>>> is_broadcastable(x.shape, y.shape)
like image 984
keflavich Avatar asked Jul 14 '14 18:07

keflavich


People also ask

What is a Broadcastable shape?

A set of arrays is called “broadcastable” to the same shape if the above rules produce a valid result. For example, if a.shape is (5,1), b.shape is (1,6), c.shape is (6,) and d.shape is () so that d is a scalar, then a, b, c, and d are all broadcastable to dimension (5,6); and.

What is the relationship between rank and shape of an array?

The rank of the array is the number of dimensions. The shape of the array is a tuple of integers giving the size of the array along each dimension.

What happens if you try to add two arrays with incompatible dimensions?

Broadcasting with Two Three-dimensional Arrays And, for the other dimension, one of the dimensions is one. So an arithmetic operation is possible. But if you try to add two arrays which cannot be broadcasted due to incompatible shapes, you will get an error.


2 Answers

I really think you guys are over thinking this, why not just keep it simple?

def is_broadcastable(shp1, shp2):
    for a, b in zip(shp1[::-1], shp2[::-1]):
        if a == 1 or b == 1 or a == b:
            pass
        else:
            return False
    return True
like image 116
Bi Rico Avatar answered Sep 28 '22 07:09

Bi Rico


If you just want to avoid materializing an array with a given shape, you can use as_strided:

import numpy as np
from numpy.lib.stride_tricks import as_strided

def is_broadcastable(shp1, shp2):
    x = np.array([1])
    a = as_strided(x, shape=shp1, strides=[0] * len(shp1))
    b = as_strided(x, shape=shp2, strides=[0] * len(shp2))
    try:
        c = np.broadcast_arrays(a, b)
        return True
    except ValueError:
        return False

is_broadcastable((1000, 1000, 1000), (1000, 1, 1000))  # True
is_broadcastable((1000, 1000, 1000), (3,))  # False

This is memory efficient, since a and b are both backed by a single record

like image 26
ChrisB Avatar answered Sep 28 '22 09:09

ChrisB