Utilizing ndgrid/meshgrid functionality in Julia - julia

I'm trying to find functionality in Julia similar to MATLAB's meshgrid or ndgrid. I know Julia has defined ndgrid in the examples but when I try to use it I get the following error.
UndefVarError: ndgrid not defined
Anyone know either how to get the builtin ndgrid function to work or possibly another function I haven't found or library that provides these methods (the builtin function would be preferred)? I'd rather not write my own in this case.
Thanks!

We prefer to avoid these functions, since they allocate arrays that usually aren't necessary. The values in these arrays have such a regular structure that they don't need to be stored; they can just be computed during iteration. For example, one alternative approach is to write an array comprehension:
julia> [ 10i + j for i=1:5, j=1:5 ]
5×5 Array{Int64,2}:
11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
41 42 43 44 45
51 52 53 54 55
Or, you can write for loops, or iterate over a product iterator:
julia> collect(Iterators.product(1:2, 3:4))
2×2 Array{Tuple{Int64,Int64},2}:
(1, 3) (1, 4)
(2, 3) (2, 4)

I do find sometimes it's convenient to use some function like meshgrid in numpy. It's easy to do it with list comprehension:
function meshgrid(x, y)
X = [i for i in x, j in 1:length(y)]
Y = [j for i in 1:length(x), j in y]
return X, Y
end
e.g.
x = 1:4
y = 1:3
X, Y = meshgrid(x, y)
now
julia> X
4×3 Array{Int64,2}:
1 1 1
2 2 2
3 3 3
4 4 4
julia> Y
4×3 Array{Int64,2}:
1 2 3
1 2 3
1 2 3
1 2 3
However, I did not find this makes the code run faster than using iteration. Here's what I mean:
After defining
x = 1:1000
y = x
X, Y = meshgrid(x, y)
I did benchmark on the following two functions
using Statistics
function fun1()
return mean(sqrt.(X.*X + Y.*Y))
end
function fun2()
sum = 0.0
for i in 1:1000
for j in 1:1000
sum += sqrt(i*i + j*j)
end
end
return sum / (1000*1000)
end
Here are the benchmark results:
julia> #btime fun1()
8.310 ms (19 allocations: 30.52 MiB)
julia> #btime run2()
1.671 ms (0 allocations: 0 bytes)
The meshgrid method is both significantly slower and taking more memory. Any Julia expert knows why? I understand Julia is a compiling language unlike Python so iterations won't be slower than vectorization, but I don't understand why vector(array) calculation is many times slower than iteration. (For bigger N this difference is even larger.)
Edit: After reading this post, I have the following updated version of the 'meshgrid' method. The idea is to not create a meshgrid beforehand, but to do it in the calculation via Julia's powerful elementwise array operation:
x = collect(1:1000)
y = x'
function fun1v2()
mean(sqrt.(x .* x .+ y .* y))
end
The trick here is the .+ between a size-M column array and a size-N row array which returns a M-by-N array. It does the 'meshgrid' for you. This function is nearly 3 times faster then fun1, albeit not as fast as fun2.
julia> #btime fun1v2()
3.189 ms (24 allocations: 7.63 MiB)
765.8435104896155

Above, #ChrisRackauckas suggests that the "proper way" to do this is with a lazy operator but he hadn't gotten around to it.
There is now a registered packaged with lazy ndgrid in it:
https://github.com/JuliaArrays/LazyGrids.jl
It is more general than the version in
VectorizedRoutines.jl
because it can handle vectors with different types, e.g.,
ndgrid(1:3, Float16[0:2], ["x", "y", "z"]).
There are Literate.jl examples in the docs that show the lazy performance is pretty good.
Of course lazy meshgrid is just one step away:
meshgrid(y,x) = (ndgrid_lazy(x,y)[[2,1]]...,)

Related

Fast Fourier Transform for tensor product spaces in Julia

Right now I use the package FFTW in order to get some Fourier Transforms I am interested in. However, I'm wondering if there is already a package of FFT that can do the transformation in a vector space which is of the form kron(C2, Rn), where C2 means a 2x2 system and Rn represents the "spatial" subspace in which one is interested in getting the Fourier Transform. In other words, does it exist a routine that implements:
kron(Id2x2, FFT)[kron(C2, Rn)] = kron(C2, FFT(Rn))
Of course the real problem I am interested is in the "two particle case" where the vector space (Hilbert space) is kron(kron(C2, Rn),kron(C2, Rn)), so in this case the routine would need an operator like kron(kron(Id2x2, FFT), kron(Id2x2, FFT)).
Note 1: I haven't tried to do the problem taking partial traces, but in my case this option simply may not work because the states are sparse, i.e. it might be ineficient.
Note 2: Note that (unless I'm mistaken) for kron(C2, Rn) one could do "twice" the fft (one in each sector of C2). However this might also be ineficient for large vector spaces.
Here's an example of what I think you are asking. res is computed by FFT from mat = kron(C2, Rn), and this is (as you say) a wasteful way of doing kron(C2, fft(Rn)) since it the FFT along the k dimension is re-done for each of the 2×2 other dimensions. But the point, presumably, is to do this for "entangled" states in the product space -- a generic likemat = rand(8,2) cannot be decomposed into factors kron(likeC2, likeRn).
(If instead you are really only interested in "un-entangled" product states, then you should probably just work with their components. Combining with kron will then always be wasteful. The package Kronecker.jl may help for some things, but I don't think it knows about fft.)
This uses my package to handle kron-like operations; you could just write out the necessary reshapes yourself, too.
julia> C2 = [1 2; 3 4]; Rn = [1,10,0,0];
julia> mat = kron(C2,Rn)
8×2 Matrix{Int64}:
1 2
10 20
0 0
0 0
3 4
30 40
0 0
0 0
julia> using TensorCast, FFTW
# notation: kron is a reshape of a tensor product, to combine i & k
julia> kron(C2,Rn) == #cast out[(k,i),j] := C2[i,j] * Rn[k]
true
# reshape mat to put the index from Rn in its own dimension:
julia> #cast tri[k,i,j] := mat[(k,i),j] (i in 1:2);
julia> summary(tri)
"4×2×2 Array{Int64, 3}"
# then fft(tri, 1) is the FFT along only that, reshape back:
julia> #cast res[(ktil,i),j] := fft(tri, 1)[ktil,i,j]
8×2 Matrix{ComplexF64}:
11.0+0.0im 22.0+0.0im
1.0-10.0im 2.0-20.0im
-9.0+0.0im -18.0+0.0im
1.0+10.0im 2.0+20.0im
33.0+0.0im 44.0+0.0im
3.0-30.0im 4.0-40.0im
-27.0+0.0im -36.0+0.0im
3.0+30.0im 4.0+40.0im
julia> res ≈ kron(C2, fft(Rn))
true
julia> res ≈ fft(mat, 1)
false
julia> fft(Rn)
4-element Vector{ComplexF64}:
11.0 + 0.0im
1.0 - 10.0im
-9.0 + 0.0im
1.0 + 10.0im
# if fft() understood the dims keyword, it could be tidier:
julia> _fft(x; dims) = fft(x, dims);
julia> #cast _res[(k,i),j] := _fft(k) mat[(k,i),j] (i in 1:2);
julia> _res ≈ res
true

Julia - combining vectors into the matrix

Let's assume I have two vectors x = [1, 2] and y = [3, 4]. How to best combine them to get a matrix m = [1 2; 3 4] in Julia Programming language? Thanks in advance for your support.
Note that in vcat(x', y') the operation x' is adjoint so it should not be used if you are working with complex numbers or vector elements that do not have adjoint defined (e.g. strings). Therefore then permutedims should be used but it will be slower as it allocates. A third way to do it is (admittedly it is more cumbersome to type):
julia> [reshape(x, 1, :); reshape(y, 1, :)]
2×2 Array{Int64,2}:
1 2
3 4
It is non allocating like [x'; y'] but does not do a recursive adjoint.
EDIT:
Note for Cameron:
julia> x = repeat(string.('a':'z'), 10^6);
julia> #btime $x';
1.199 ns (0 allocations: 0 bytes)
julia> #btime reshape($x, 1, :);
36.455 ns (2 allocations: 96 bytes)
so reshape allocates but only minimally (it needs to create an array object, while x' creates an immutable struct which does not require allocation).
Also I think it was a design decision to allocate. As for isbitsunion types actually reshape returns a struct so it does not allocate (similarly like for ranges):
julia> #btime reshape($x, 1, :)
12.211 ns (0 allocations: 0 bytes)
1×2 reshape(::Array{Union{Missing, Int64},1}, 1, 2) with eltype Union{Missing, Int64}:
1 missing
Two ways I know of:
julia> x = [1,2];
julia> y = [3,4];
julia> vcat(x', y')
2×2 Array{Int64,2}:
1 2
3 4
julia> permutedims(hcat(x, y))
2×2 Array{Int64,2}:
1 2
3 4
One more option - this one works both with numbers and other objects as Strings:
julia> rotl90([y x])
2×2 Array{Int64,2}:
1 2
3 4
What about
vcat(transpose(x), transpose(y))
or
[transpose(x); transpose(y)]

What is the correct way to select rows from matrix by a boolean array?

I have a boolean array (from previous computations) and I would like to select the related rows from several matrices. That is why I need the proper index array (to be reused later). This is easy in Matlab and python but I do not crock the correct julian way of doing it...
I am aware of DataFrames, but would like to find an orthodox matrix and array way of doing this.
In Matlab I would say:
n= 9; temp= 1:n; A= 1.0 + temp;
someTest= mod(temp,2) == 0; % just a substitute of a more complex case
% now I have both someTest and A!
inds= find(someTest); Anew= A(inds,:);
% I got inds (which I need)!
What I have got working is this:
n= 10; data= Array(1:n); A= 1.0 .+ data;
someTest= rem.(data,2) .== 0;
inds= [xy[2] for xy in zip(someTest,1:length(someTest)) if xy[1]]; # (*)
Anew= A[inds,:];
What I assumed is that there is some shorter way to express the above phrase. in v. 0.6 there was find() function, but I have not gotten good sense of the julia documentation yet (I am a very very newbie in this).
You can use the BitArray just directly to select the elements:
julia> A[someTest]
5-element Array{Float64,1}:
3.0
5.0
7.0
9.0
11.0
Fot your case:
julia> A[someTest,:] == A[inds,:]
true
find in 0.6 was renamed to findall in Julia 1.0.
To get inds, you can simply do the following:
inds = findall(someTest)
You do not have to compute the intermediate someTest first, which would allocate an array you do not intend to use. Instead, you can do the test with findall directly passing a predicate function.
inds = findall(x -> rem(x,2) == 0, data)
This will return indices of data for which the predicate rem(x,2) == 0 returns true. This will not allocate an intermediate array to find the indices, and should be faster.
As a side note, most of the time you do not need to materialize a range in Julia. Ranges are already iterable and indexable. They will automatically be converted to an Array when there is a need. Array(1:n) or collect(1:n) are usually redundant, and allocates more memory.
Your Matlab code doesn't work. A is just a row-vector (1x9 matrix), so when you try to do A(inds, :) you get an error:
>> Anew= A(inds,:)
Index in position 1 exceeds array bounds
(must not exceed 1).
But if you just fix that, you can solve the problem in exactly the same way in both Matlab and Julia, using either logical indices or regular ones:
Matlab (I'm making sure it's a matrix this time):
n = 9;
temp = (1:n).';
A = temp * (1:4);
inds = mod(temp,2) == 0;
>> A(inds, :) % using logical indices
ans =
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
>> A(find(inds), :) % using regular indices
ans =
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
And now, Julia:
n = 9;
temp = 1:n;
A = temp .* (1:4)'; # notice that we're transposing the opposite vector from Matlab
inds = mod.(temp, 2) .== 0; # you can use iseven.(temp) instead
julia> A[inds, :] # logical indices (BitArray)
4×4 Array{Int64,2}:
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
julia> A[findall(inds), :] # regular integer indices
4×4 Array{Int64,2}:
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
In this case, I would use the logical indices in both Julia and Matlab. In fact, the Matlab linter (in the editor) will tell that you should use logical indices here because it's faster. In Julia, however, there might be cases where it's more efficient to use inds = findall(iseven, temp), and just skip the logical BitArray, like #hckr says.

Location of minimum in Julia

Does Julia have a build in command to find the index of the minimum of a vector? R, for example, has a which.min command (and a which.max, of course).
Obviously, I could write the following myself, but it would be nice not to have to.
function whichmin( x::Vector )
i = 1
min_x=minimum(x)
while( x[i] > min_x )
i+=1
end
return i
end
Apologies if this has been asked before, but I couldn't find it. Thanks!
Since 0.7-alpha, indmin and indmax are deprecated.
Use argmin and argmax instead.
For a vector it just returns the linear index
julia> x = rand(1:9, 4)
4-element Array{Int64,1}:
9
5
8
5
julia> argmin(x)
2
julia> argmax(x)
1
If looking for both the index and the value, use findmin and findmax.
For multidimensional array, all these functions return the CartesianIndex.
I believe indmax(itr) does what you want. From the julia documentation:
indmax(itr) → Integer
Returns the index of the maximum element in a collection.
And here's an example of it in use:
julia> x = [8, -4, 3.5]
julia> indmax(x)
1
There's also findmax, that returns both the maximum value and its position.
For multidim array, you'll have to switch between linear indexes et multidim indexes:
x = rand(1:9, 2,3)
# 2×3 Array{Int64,2}:
# 5 1 9
# 3 3 8
indmin(x)
# 3
# => third element in the column-major ordered array (value=1)
ind2sub(size(x),indmin(x))
# (1, 2)
# => (row,col) indexes: what you are looking for.
-- Maurice

Check size in bytes of variable using Julia

Question: How do I check the size in bytes of a variable using Julia?
What I've tried: In Matlab, the whos() function provided this information, but in Julia that just provides the variable names and module. Browsing the standard library in the Julia manual, sizeof() looked promising, but it only appears to provide the size of the canonical binary representation, rather than the current variable.
sizeof works on variables too
sizeof(a::Array{T,N})
returns the size of the array times the element size.
julia> x = [1 2 3 4]
1x4 Array{Int64,2}:
1 2 3 4
julia> sizeof(x)
32
julia> x = Int8[1 2 3 4]
1x4 Array{Int8,2}:
1 2 3 4
julia> sizeof(x)
4
sizeof(B::BitArray{N})
returns chunks; each chunk is 8 bytes so can represent up to 64 bits
julia> x = BitArray(36);
julia> sizeof(x)
8
julia> x = BitArray(65);
julia> sizeof(x)
16
sizeof(s::ASCIIString) and sizeof(s::UTF8String)
return the number of characters in the string (1 byte/char).
julia> sizeof("hello world")
11
sizeof(s::UTF16String) and sizeof(s::UTF32String)
Same as above but with 2 and 4 bytes/character respectively.
julia> x = utf32("abcd");
julia> sizeof(x)
16
Accordingly other strings
sizeof(s::SubString{ASCIIString}) at string.jl:590
sizeof(s::SubString{UTF8String}) at string.jl:591
sizeof(s::RepString) at string.jl:690
sizeof(s::RevString{T<:AbstractString}) at string.jl:737
sizeof(s::RopeString) at string.jl:802
sizeof(s::AbstractString) at string.jl:71
core values
returns the number of bytes each variable uses
julia> x = Int64(0);
julia> sizeof(x)
8
julia> x = Int8(0);
julia> sizeof(x)
1
julia> x = Float16(0);
julia> sizeof(x)
2
julia> x = sizeof(Float64)
8
one would expect, but note that Julia characters are wide characters
julia> sizeof('a')
4
getBytes
For cases where the layout is more complex and/or not contiguous. Here's a function that will iterate over the fields of a variable (if any) and return of sum of all of the sizeof results which should be the total number of bytes allocated.
getBytes(x::DataType) = sizeof(x);
function getBytes(x)
total = 0;
fieldNames = fieldnames(typeof(x));
if fieldNames == []
return sizeof(x);
else
for fieldName in fieldNames
total += getBytes(getfield(x,fieldName));
end
return total;
end
end
using it
create an instance of a random-ish type...
julia> type X a::Vector{Int64}; b::Date end
julia> x = X([i for i = 1:50],now())
X([1,2,3,4,5,6,7,8,9,10 … 41,42,43,44,45,46,47,48,49,50],2015-02-09)
julia> getBytes(x)
408
The function Base.summarysize provides exactly that
It also includes the overhead from the struct as seen in the examples.
julia> struct Foo a; b end
julia> Base.summarysize(ones(10000))
80040
julia> Base.summarysize(Foo(ones(10000), 1))
80064
julia> Base.summarysize(Foo(ones(10000), Foo(ones(10, 10), 1)))
80920
However, care should be taken as the function is non-exported and might not be future proof
In julia 1.6, varinfo() shows sizes:
julia> a = 1;
julia> v = ones(10000);
julia> varinfo()
name size summary
–––––––––––––––– ––––––––––– –––––––––––––––––––––––––––––
Base Module
Core Module
InteractiveUtils 250.022 KiB Module
Main Module
ans 78.164 KiB 10000-element Vector{Float64}
v 78.164 KiB 10000-element Vector{Float64}
a 8 bytes Int64
For specific variables, either use pattern matching (r"..." is a regular expression):
julia> varinfo(r"^v$")
name size summary
–––– –––––––––– –––––––––––––––––––––––––––––
v 78.164 KiB 10000-element Vector{Float64}
or combine the Base.summarysize from Korbinian answer with Base.format_bytes:
julia> pretty_summarysize(x) = Base.format_bytes(Base.summarysize(x))
pretty_summarysize (generic function with 1 method)
julia> pretty_summarysize(v)
"78.164 KiB"
Edit: beware that summarysize had a bug, at least in 1.5.3 and 1.6.1. varinfo was affected as well. It is fixed (tested with 1.7.3).

Resources