I have a finite set represented as a vector V::Vector{T} and I am trying to compute the power of this set V^d=V\times V\times \cdots \times V. That is, the Cartesian product of V with itself d-times, which is a finite set of vectors. At the end, I would like to store the result as an array with d rows.
Typically, I would use Iterators.product, which is fast, but returns tuples instead of vectors:
function cartesian_power_tuples(V::Vector{T},d) where T
X=fill(V,d)
iterable=Iterators.product(X...)
return collect(iterable)[:]
end
I want to modify the code above and obtain an array instead of tuples. Here’s my naive implementation:
function cartesian_power_array(V::Vector{T},d) where T
n=size(V,1)
X=fill(V,d)
iterable=Iterators.product(X...)
A=Matrix{T}(undef,d,n^d)
i=1
for x in iterable
for j=1:d A[j,i]=x[j] end
i+=1
end
return A
end
However, the second function is significantly more expensive than the first one:
function cartesian_power_matrix(V::Vector{T},d) where T
X=fill(V,d)
iterable=Iterators.product(X...)
a = collect(iterable)
return reshape(reinterpret(T, a), d, length(a))
end
function cartesian_power_matrix(V::Vector{T}, ::Val{d}) where {T,d}
X = ntuple(_ -> V, Val{d}())
iterable=Iterators.product(X...)
a = collect(iterable)
return reshape(reinterpret(T, a), d, length(a))
end
Another way to write this is stack(Iterators.product(V,V,V); dims=2), or to accept d something like stack(Iterators.product(ntuple(Returns(V),3)...); dims=2). This isn’t quite as fast as collect+reinterpret, although I’m not sure why.