Boolean matrix multiplication in Julia
Following Oscar's comment of adding two for
loops around your code, but without the LoopVectorization improvement, although with not allocating the full array inside the any
call (so that the any
stops on the first occurrence), this is decently fast (edit: replaced standard AND &
with short-circuit &&
):
function bool_mul2(A, B)
mA, nA = size(A)
mB, nB = size(B)
nA ≠ mB && error()
AB = BitArray(undef, mA, nB)
for i in 1:mA, j in 1:nB
AB[i,j] = any(A[i,k] && B[k,j] for k in 1:nA)
end
AB
end
(Note I removed the [
and ]
inside the any
to not allocate there.
E.g., with A
and B
of size 1000×1000, I get
julia> @btime bool_mul2($A, $B) ;
16.128 ms (3 allocations: 122.25 KiB)
compared to
julia> @btime bool_mul($A, $B) ;
346.374 ms (12 allocations: 7.75 MiB)
EDIT: For squaring the matrix, maybe try
function bool_square(A)
m, n = size(A)
m ≠ n && error()
A² = BitArray(undef, n, n)
for i in 1:n, j in 1:n
A²[i,j] = any(A[i,k] && A[k,j] for k in 1:n)
end
A²
end
for which I get
julia> A = rand(Bool, 500, 500) ;
julia> @btime $A * $A .!= 0 ;
42.483 ms (12 allocations: 1.94 MiB)
julia> @btime bool_square($A) ;
4.653 ms (3 allocations: 30.69 KiB)
One very simple solution is
function bool_mul(A,B)
return A*B .!= 0
end
This won't be the most efficient since it will allocate a matrix for A*B
, but might end up being one of the fastest solutions available.