matrix of sparse complex numbers in Julia - matrix

In Julia, I can create a sparse matrix of zeros:
julia> a = spzeros(2,2)
2x2 sparse matrix with 0 Float64 entries:
julia> a[1,1] = 1
1
julia> full(a)
2x2 Array{Float64,2}:
1.0 0.0
0.0 0.0
and I can create a complex matrix:
julia> b = [ 1 ; im ]
2-element Array{Complex{Int64},1}:
1+0im
0+1im
If I try assigning a complex value to a sparse matrix of zeros I get an error:
julia> a[1,1] = im
ERROR: InexactError()
in setindex! at sparse/sparsematrix.jl:1095
which is consistent with the spzeros() returned type being parametrized by Float64:
julia> typeof(a)
SparseMatrixCSC{Float64,Int64} (constructor with 1 method)
How can I create a sparse matrix of complex-typed zeros in Julia?

Looking at what we can pass to spzeros:
julia> methods(spzeros)
# 5 methods for generic function "spzeros":
spzeros(m::Integer,n::Integer) at sparse/sparsematrix.jl:406
spzeros(Tv::Type{T<:Top},m::Integer,n::Integer) at sparse/sparsematrix.jl:407
spzeros(Tv::Type{T<:Top},Ti::Type{T<:Top},m::Integer,n::Integer) at sparse/sparsematrix.jl:409
spzeros(m::Integer) at deprecated.jl:28
spzeros(Tv::Type{T<:Top},m::Integer) at deprecated.jl:28
We see we should be able to pass a type as the first argument:
julia> a = spzeros(Complex{Float64}, 2,2)
2x2 sparse matrix with 0 Complex{Float64} entries:
julia> full(a)
2x2 Array{Complex{Float64},2}:
0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im
julia> a[1,1] = 2+3.4im
2.0 + 3.4im
julia> a
2x2 sparse matrix with 1 Complex{Float64} entries:
[1, 1] = 2.0+3.4im

Related

Pivoted QR in Julia?

In Julia, the function qr(A) will perform a QR decomposition on a given matrix A. However, is there any function/way in Julia to do a "pivoted" QR decomposition on a given matrix?
Just pass in the magic option:
julia> A = 10*log.(1 .- rand(4,3));
julia> qr(A, ColumnNorm())
QRPivoted{Float64, Matrix{Float64}}
Q factor:
4×4 LinearAlgebra.QRPackedQ{Float64, Matrix{Float64}}:
-0.0101543 -0.218633 0.804736 -0.551812
-0.118832 -0.376628 0.446673 0.802816
-0.118236 -0.88692 -0.390704 -0.216204
-0.985797 0.154029 -0.0152722 -0.0651594
R factor:
3×3 Matrix{Float64}:
26.4193 4.80784 8.92215
0.0 18.7537 15.1792
0.0 0.0 -9.77702
permutation:
3-element Vector{Int64}:
2
3
1
Note that the docs are a little off.

let indexing return a matrix instead of a vector in julia

When you index a matrix in Julia, and your selection is a single column or row the result will be represented as a vector. similarly, when you index a single point you get the value of that point, not a 1x1 matrix.
However, for my use case I want my answer to be a matrix as well, because the orientation of the vector has meaning, that I don't want to lose.
So given the following example matrix:
julia> A = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
I get:
julia> A[:, 1]
2-element Vector{Int64}:
1
3
julia> A[1, :]
2-element Vector{Int64}:
1
2
julia> A[1, 1]
1
but I want:
julia> A[:, 1]
2×1 Matrix{Int64}:
1
3
julia> A[1, :]
1×2 Matrix{Int64}:
1 2
julia> A[1, 1]
1×1 Matrix{Int64}:
1
Is there an easy way to achieve this?
Right now I do something like:
function getindex_asmatrix(A::Matrix, i, j)
# If i & j are Integers convert point to 1x1 Matrix
# If only j == Integer make a nx1 Matrix
# If only i == Integer make a 1xm Matrix
# else do A[i, j]
end
But I feel there might be an more elegant solution.
Just use 1:1 (range) instead of 1, e.g.:
julia> A[:, 1:1]
2×1 Matrix{Int64}:
1
3
julia> A[1:1, :]
1×2 Matrix{Int64}:
1 2
julia> A[1:1, 1:1]
1×1 Matrix{Int64}:
1
You could also use [1] instead, but it will allocate, while 1:1 does not allocate.

Define a custom sortperm function

In Julia, let's suppose I have the following matrix:
julia> rank = [[1.0,2.0,NaN] [5.0,3.0,1.0]]
3×2 Array{Float64,2}:
1.0 5.0
2.0 3.0
NaN 1.0
Using mapslices and sortperm to get a ranking on each column gives:
r = mapslices(sortperm, rank; dims=1)
3×2 Array{Int64,2}:
1 3
2 2
3 1
The problem being that NaN are considered as "worst" elements instead of being kept in final matrix. What I finally want is:
3×2 Array{Int64,2}:
1 3
2 2
NaN 1
My current workaround is to compare each element of r with those of rank. But I'm quite sure Julia has a classier way of doing it :p.
Current workaround: not enough because requires extra computation after mapslices as well as creating another array new_r.
nrow, ncol = size(r)
new_r = [Float64(ifelse(isnan(rank[i,j]), NaN, r[i,j])) for i in 1:nrow, j in 1:ncol]
NaN is not "special" in Julia. It is just a floating point value. If you want NaN to be treated as missing value you should first convert it to missing and then use ordinalrank function from StatsBase.jl:
julia> rank = [[1.0,2.0,NaN] [5.0,3.0,1.0]]
3×2 Array{Float64,2}:
1.0 5.0
2.0 3.0
NaN 1.0
julia> using StatsBase
julia> mapslices(rank; dims=1) do x
ordinalrank(replace(x, NaN=>missing))
end
3×2 Array{Union{Missing, Int64},2}:
1 3
2 2
missing 1

Extract lower triangle portion of a matrix

I was wondering if there is a command or a package in Julia that permits us to extract directly the lower triangle portion of a matrix, excluding the diagonal. I can call R commands for that (like lowerTriangle of the gdata package), obviously, but I'd like to know if Julia has something similar. For example, imagine I have the matrix
1.0 0.751 0.734
0.751 1.0 0.948
0.734 0.948 1.0
I don't want to create a lower triangular matrix like
NA NA NA
0.751 NA NA
0.734 0.948 NA
but extract the lower portion of the matrix as an array: 0.751 0.734 0.948
If you're OK with creating a lower triangular matrix as an intermediate step, you can use logical indexing and tril! with an extra argument to get what you need.
julia> M = [1.0 0.751 0.734
0.751 1.0 0.948
0.734 0.948 1.0];
julia> v = M[tril!(trues(size(M)), -1)]
3-element Array{Float64, 1}:
0.751
0.734
0.948
The trues call returns an array of M's shape filled with boolean true values. tril! then prunes this down to just the part of the matrix that we want. The second argument to tril! tells it which superdiagonal to start from, which we use here to avoid the values in the leading diagonal.
We use the result of that for indexing into M, and that returns an array with the required values.
Using comprehensions:
julia> [M[m, n] for m in 2:size(M, 1) for n in 1:m-1]
3-element Array{Float64,1}:
0.751
0.734
0.948
But it is much slower than the sundar/Matt B. solution:
lower_triangular_1(M) = [M[m, n] for m in 2:size(M, 1) for n in 1:m-1]
lower_triangular_2(M) = [M[m, n] for n in 1:size(M, 2) for m in n+1:size(M, 1)]
lower_triangular_3(M) = M[tril!(trues(size(M)), -1)]
using BenchmarkTools
using LinearAlgebra # avoid warning in 0.7
M=rand(100, 100)
Testing with Julia Version 0.7.0-alpha.0:
julia> #btime lower_triangular_1(M);
73.179 μs (10115 allocations: 444.34 KiB)
julia> #btime lower_triangular_2(M);
71.157 μs (10117 allocations: 444.41 KiB)
julia> #btime lower_triangular_3(M);
16.325 μs (6 allocations: 40.19 KiB)
Not elegant, but faster (with #views):
function lower_triangular_4(M)
# works only for square matrices
res = similar(M, ((size(M, 1)-1) * size(M, 2)) ÷ 2)
start_idx = 1
for n = 1:size(M, 2)-1
#views column = M[n+1:end, n]
last_idx = start_idx -1 + length(column)
#views res[start_idx:last_idx] = column[:]
start_idx = last_idx + 1
end
end
julia> #btime lower_triangular_4(M);
4.272 μs (101 allocations: 44.95 KiB)

Function or operator for matrix exponential in Julia

I am looking for a function or operator
that computes the n-th matrix exponential in Julia
where n is a non-negative integer.
For example, in MATLAB I would write expm(A, 3) for A * A * A.
I could just call the product using * multiple times,
but is there a way to compute the matrix exponential
without doing this?
julia> A = [1 -1; 0 2]
2x2 Array{Int64,2}:
1 -1
0 2
julia> A * A
2x2 Array{Int64,2}:
1 -3
0 4
julia> A * A * A
2x2 Array{Int64,2}:
1 -7
0 8
Simply use the exponentiation operator.
julia> A = [1 -1; 0 2]
2x2 Array{Int64,2}:
1 -1
0 2
julia> A^2
2x2 Array{Int64,2}:
1 -3
0 4
julia> A^3
2x2 Array{Int64,2}:
1 -7
0 8
To find out where it's implemented, you can use the function methods
julia> methods(^)
# 45 methods for generic function "^":
...
^(A::Array{T,2}, p::Integer) at linalg/dense.jl:170
^(x, p::Integer) at intfuncs.jl:108
^(A::Array{T,2}, p::Number) at linalg/dense.jl:173
Given that information, you can find it in the Julia repository.

Resources