filippo
filippo

Reputation: 5294

Fast ndarray boolean intersection

I have two 3D boolean arrays of the same shape (let's say (512,512,512)). I'd like to check if the True region of one array is completely included in the second.

Right now the best I've come up with is:

np.all((A * B) == A)

Is there a faster way to do this? Unfortunately this goes inside an inner loop I'm not able to optimize further, so the more I shave from this the better.

Upvotes: 2

Views: 209

Answers (1)

Divakar
Divakar

Reputation: 221514

Approach #1 : If they are boolean arrays, AND-ing might be better than multiplication -

((A & B) == A).all()

Approach #2 : Another with counting of True values -

np.count_nonzero(A & B) == np.count_nonzero(A)

Runtime test -

In [225]: A = np.random.rand(512,512,512)>0.5
     ...: B = np.random.rand(512,512,512)>0.5

In [226]: %timeit np.all((A * B) == A)
     ...: %timeit ((A & B) == A).all()
     ...: %timeit np.count_nonzero(A & B) == np.count_nonzero(A)
10 loops, best of 3: 170 ms per loop
10 loops, best of 3: 169 ms per loop
10 loops, best of 3: 57.7 ms per loop

Approach #3 : Short-circuiting at numba level basically looking for if there's any A True, for which the corresponding B isn't -

from numba import njit 

@njit
def numba_app(a, b):
    l = len(a)
    out = True
    for i in range(l):
        if a[i] & ~b[i]:
            out = False
            break
    return out

out = numba_app(A.ravel(), B.ravel())

The timings with this Short-circuiting method would depend on the data.

Upvotes: 2

Related Questions