In Julia, Transpose operator - julia

I am trying to use a transpose operator over a vector in order to perform am element-wise addition.
For example, I want to add a column vector a = [a1;a2;a3] to a row vector b = [b1,b2] I should get matrix
M = a+b = [a1+b1, a1+b2; a2+b1, a2+b2; a3+b1, a3+b2].
In MATLAB it is equivalent (if both vectors are row vectors) M = a.'+b
I am trying to get the same in Julia but here is the problem, there is no .' operator in Julia starting from 1.0 version. There is the transpose operator which does not work in broadcasting mode. The adjoint operator is not Valid for me because I work with complex numbers.
a = Vector{ComplexF64}([1+3im,2])
b = Vector{ComplexF64}([0,0,0])
Z = zeros(ComplexF64,3,2)
G = zeros(ComplexF64,3,2)
#. Z = b + a' # Works but takes the complex conjugate
#. Z = b + transpose(a) # DOES NOT WORK!!!! The error is " DimensionMismatch("array could not be broadcast to match destination") "
Z = b .+ transpose(a) # Works but not efficient
#. Z = b + conj(a')
The third case Z = b .+ transpose(a) is not efficient because it makes 2 loops first one for addition b .+ transpose(a), than it runs the second loop one for the assignment of b .+ transpose(a) to Z. While the other 3 cases do it within one loop.
So which is the fastest way?
And why transpose doesn't within Broadcasting?
Thank you in advance

For Hermitian You can just type:
a' .+ b
Example
julia> a = ComplexF64.([1+3im,2])
2-element Array{Complex{Float64},1}:
1.0 + 3.0im
2.0 + 0.0im
julia> b = ComplexF64.([10,20,30])
3-element Array{Complex{Float64},1}:
10.0 + 0.0im
20.0 + 0.0im
30.0 + 0.0im
julia> a' .+ b
3×2 Array{Complex{Float64},2}:
11.0-3.0im 12.0+0.0im
21.0-3.0im 22.0+0.0im
31.0-3.0im 32.0+0.0im
If you want to have just transposition you could define your own unary operator (perhaps from the list of unused unary operators):
¬(a) = permutedims(a)
Now you could do
julia> ¬a
1×2 Matrix{ComplexF64}:
1.0+3.0im 2.0+0.0im

Related

upsample complex matrix in julia

I have a complex matrix (i.e. Array{Complex{Float64},2}) in julia that I would like to upsample in one dimension.
My equivalent python code is:
data_package['time_series'] = sp.signal.resample(data_package['time_series'] .astype('complex64'), data_package['time_series'].shape[1]*upsample_factor, axis=1)
A resample() function can be found in DSP.jl. But it only works on Vectors, so one has to apply it manually along the desired dimension. One possible way looks like this (resampling along the second dimension, with a new rate of 2):
julia> using DSP
julia> test = reshape([1.0im, 2.0im, 3.0im, 4., 5., 6.], 3, 2)
3×2 Matrix{ComplexF64}:
0.0+1.0im 4.0+0.0im
0.0+2.0im 5.0+0.0im
0.0+3.0im 6.0+0.0im
julia> newRate = 2
2
julia> up = [resample(test[:, i], newRate) for i in 1:size(test, 2)] # gives a vector of vectors
2-element Vector{Vector{ComplexF64}}:
[0.0 + 0.9999042566881922im, 0.0 + 1.2801955476665785im, 0.0 + 1.9998085133763843im, 0.0 + 2.968204475861045im, 0.0 + 2.9997127700645763im]
[3.9996170267527686 + 0.0im, 4.466495565312296 + 0.0im, 4.999521283440961 + 0.0im, 6.154504493506763 + 0.0im, 5.9994255401291525 + 0.0im]
julia> cat(up..., dims = 2) # fuse to matrix
5×2 Matrix{ComplexF64}:
0.0+0.999904im 3.99962+0.0im
0.0+1.2802im 4.4665+0.0im
0.0+1.99981im 4.99952+0.0im
0.0+2.9682im 6.1545+0.0im
0.0+2.99971im 5.99943+0.0im
Please consider the package FFTResampling.jl
The method is based on the FFT, assuming periodic and band-limited input.

Element-wise compound assignment operator in Julia

Consider the following two functions,
function f(x)
x = x .+ 1
end
function g(x)
x .+= 1
end
My understanding is that they should behave identically, since a .+= b is just syntactic sugar for a = a .+ b. However f does not mutate a global variable passed to it as an argument, while g does.
Can anyone explain to me what is going on here?
Thanks.
This is almost right: x .+= 1 is syntactic sugar for x .= x .+ 1 which does in-place elementwise assignment whereas x = x .+ 1 rebinds x to the new array produced by doing elementwise addition.

Creating matrix of draws from vector of distributions

I have a vector of n distributions and I am trying to create a n x t matrix of t draws from each of the n distributions.
using Distributions
d = [Uniform(0,1), Uniform(1,2), Uniform(3,4)]
r = [rand(i, 2) for i in d] # Want a 3x2 matrix, but get an array of arrays
Expected:
[0.674744 0.781853; 1.70171 1.56444; 3.65103 3.76522]
Actual:
[[0.674744, 0.781853], [1.70171, 1.56444], [3.65103, 3.76522]]
Try double indexing of a comprehension:
julia> using Distributions
julia> d = [Uniform(0,1), Uniform(1,2), Uniform(3,4)]
3-element Array{Uniform{Float64},1}:
Uniform{Float64}(a=0.0, b=1.0)
Uniform{Float64}(a=1.0, b=2.0)
Uniform{Float64}(a=3.0, b=4.0)
julia> r = [rand(i) for i in d, _ in 1:2]
3×2 Array{Float64,2}:
0.687725 0.433771
1.28782 1.00533
3.37017 3.88304
Another interesting option is to use broadcasting assignment:
julia> out = Matrix{Float64}(undef, 3, 2)
3×2 Array{Float64,2}:
1.0735e-313 7.30082e-316
7.30082e-316 7.30082e-316
7.30082e-316 6.11918e-316
julia> out .= rand.(d)
3×2 Array{Float64,2}:
0.803554 0.457955
1.4354 1.41107
3.31749 3.2684
This is shorter and might be useful if you need to sample many times and want an in-place operation (which is often the case in simulation modeling).

indices of unique elements of vector in Julia

How to get indexes of unique elements of a vector?
For instance if you have a vector v = [1,2,1,3,5,3], the unique elements are [1,2,3,5] (output of unique) and their indexes are ind = [1,2,4,5]. What function allows me to compute ind so that v[ind] = unique(v) ?
This is a solution for Julia 0.7:
findfirst.(isequal.(unique(x)), [x])
or similar working under Julia 0.6.3 and Julia 0.7:
findfirst.(map(a -> (y -> isequal(a, y)), unique(x)), [x])
and a shorter version (but it will not work under Julia 0.7):
findfirst.([x], unique(x))
It will probably not be the fastest.
If you need speed you can write something like (should work both under Julia 0.7 and 0.6.3):
function uniqueidx(x::AbstractArray{T}) where T
uniqueset = Set{T}()
ex = eachindex(x)
idxs = Vector{eltype(ex)}()
for i in ex
xi = x[i]
if !(xi in uniqueset)
push!(idxs, i)
push!(uniqueset, xi)
end
end
idxs
end
Another suggestion is
unique(i -> x[i], 1:length(x))
which is about as fast as the function in the accepted answer (in Julia 1.1), but a bit briefer.
If you don't care about finding the first index for each unique element, then you can use a combination of the unique and indexin functions:
julia> indexin(unique(v), v)
4-element Array{Int64,1}:
3
2
6
5
Which gets one index for each unique element of v in v. These are all in base and works in 0.6. This is about 2.5 times slower than #Bogumil's function, but it's a simple alternative.
A mix between mattswon and Bogumił Kamiński answers (thanks !):
uniqueidx(v) = unique(i -> v[i], eachindex(v))
eachindex allows to work with any kind of array, even views.
julia> v = [1,2,1,3,5,3];
julia> uniqueidx(v)
4-element Vector{Int64}:
1
2
4
5
julia> v2 = reshape(v, 2, 3)
2×3 Matrix{Int64}:
1 1 5
2 3 3
julia> subv2 = view(v2, 1:2, 1:2)
2×2 view(::Matrix{Int64}, 1:2, 1:2) with eltype Int64:
1 1
2 3
julia> uniqueidx(subv2)
3-element Vector{CartesianIndex{2}}:
CartesianIndex(1, 1)
CartesianIndex(2, 1)
CartesianIndex(2, 2)

For-loop with the dimension flexibility of broadcasting

With the aid of broadcasting, the following code will work whether x, y, and z are scalars, vectors of size n, or any combination thereof.
b = zeros(n)
b .= x.*y.*z .+ x
However, I'd like a for-loop. The following for-loop only works when x is a vector of size n, y is a scalar, and z is a scalar.
for i = 1:n
b[i] = x[i]*y*z + x[i]
end
To write the equivalent of b .= x.*y.*z .+ x as a for-loop for any case, I can only think of writing a for-loop for every combination of x, y, and z within if-statements. This can get messy with more variables in more complicated math expressions.
Is there a more elegant way to do what I'd like than using many if-statements?
You could define a wrapper type that indexing into it will give array indexing if wrapped variable is array and repeats the same value for all indices for scalars. I have an example below but it probably is not as efficient as using broadcast. And it is not checking if array lengths are consistent. However, a custom wrapper type would alleviate the situation.
julia> function f(x,y,z)
lx,ly,lz = length(x),length(y),length(z)
maxlen = max(lx,ly,lz)
cx = cycle(x)
cy = cycle(y)
cz = cycle(z)
b = zeros(maxlen)
#inbounds for (xi,yi,zi,i) in zip(cx,cy,cz,1:maxlen)
b[i] = xi*yi*zi+xi
end
return b
end
f (generic function with 1 method)
julia> f(1:3,21,2)
3-element Array{Float64,1}:
43.0
86.0
129.0

Resources