I am new to Julia and need some help.
I have a list of 1D Arrays, I want to produce a matrix like this
g = [ 2.0 -1.0 0.0 0.0;
-1.0 2.0 -1.0 0.0;
0.0 -1.0 2.0 -1.0;
0.0 0.0 -1.0 3.0]
I am able to follow simple examples given on docs, but how do I achieve this using loops?
Cheers,
Ayush
with loops you can create a matrix and then fill it.
with loops
horizontally:
julia> arr = [[2.0,-1.0,0.0,0.0],[-1.0,2.0,-1.0,0.0],[0.0,-1.0,2.0,-1.0],[0.0,0.0,-1.0,3.0],[1.,1.,1.,1.]]
5-element Array{Array{Float64,1},1}:
[2.0, -1.0, 0.0, 0.0]
[-1.0, 2.0, -1.0, 0.0]
[0.0, -1.0, 2.0, -1.0]
[0.0, 0.0, -1.0, 3.0]
[1.0, 1.0, 1.0, 1.0]
julia> function make_matrix(input::Vector{<:Vector})
element_type = eltype(eltype(input))
if (length(input) == 0)
return Array{element_type,2}(undef,0,0)
end
height,width = length(input[1]), length(input)
for col in input
(height == length(col)) ? nothing : throw("inconsistent array size")
end
output = Array{element_type}(undef,height,width)
for i in 1:width
output[:,i] = input[i]
end
return output
end
make_matrix (generic function with 1 method)
julia> make_matrix(arr)
4×5 Array{Float64,2}:
2.0 -1.0 0.0 0.0 1.0
-1.0 2.0 -1.0 0.0 1.0
0.0 -1.0 2.0 -1.0 1.0
0.0 0.0 -1.0 3.0 1.0
vertically:
julia> function vmake_matrix(input::Vector{<:Vector})
element_type = eltype(eltype(input))
if (length(input) == 0)
return Array{element_type,2}(undef,0,0)
end
height,width = length(input),length(input[1])
for col in input
(width == length(col)) ? nothing : throw("inconsistent array size")
end
output = Array{element_type}(undef,height,width)
for i in 1:height
output[i,:] = input[i]
end
return output
end
vmake_matrix (generic function with 1 method)
julia> vmake_matrix(arr)
5×4 Array{Float64,2}:
2.0 -1.0 0.0 0.0
-1.0 2.0 -1.0 0.0
0.0 -1.0 2.0 -1.0
0.0 0.0 -1.0 3.0
1.0 1.0 1.0 1.0
without loops
without loops you can use vcat or hcat depending on the direction you want to concatenate the arrays in.
julia> H_arr = [ [ 2.0 -1.0 0.0 0.0],[-1.0 2.0 -1.0 0.0],[0.0 -1.0 2.0 -1.0],[0.0 0.0 -1.0 3.0] ]
4-element Array{Array{Float64,2},1}:
[2.0 -1.0 0.0 0.0]
[-1.0 2.0 -1.0 0.0]
[0.0 -1.0 2.0 -1.0]
[0.0 0.0 -1.0 3.0]
julia> vcat(H_arr...)
4×4 Array{Float64,2}:
2.0 -1.0 0.0 0.0
-1.0 2.0 -1.0 0.0
0.0 -1.0 2.0 -1.0
0.0 0.0 -1.0 3.0
julia> V_arr = [[2.0,-1.0,0.0,0.0],[-1.0,2.0,-1.0,0.0],[0.0,-1.0,2.0,-1.0],[0.0,0.0,-1.0,3.0]]
4-element Array{Array{Float64,1},1}:
[2.0, -1.0, 0.0, 0.0]
[-1.0, 2.0, -1.0, 0.0]
[0.0, -1.0, 2.0, -1.0]
[0.0, 0.0, -1.0, 3.0]
julia> hcat(V_arr...)
4×4 Array{Float64,2}:
2.0 -1.0 0.0 0.0
-1.0 2.0 -1.0 0.0
0.0 -1.0 2.0 -1.0
0.0 0.0 -1.0 3.0
Related
As mentioned I have a vector of 1D matrice, such as:
P_predefined = [[.3 .4 .2 .1], [.2 .3 .5 0.], [.1 0. .8 .1], [.4 0. 0. .6]]
I would like to turn it into a matrix of 2D, I tried to use vcat, for which I expected to behave like vstack in Python, but it doesn't work.
vcat(algorithm.predefinedP)
It still returns a vector
[[0.3 0.4 0.2 0.1], [0.2 0.3 0.5 0.0], [0.1 0.0 0.8 0.1], [0.4 0.0 0.0 0.6]] #Vector{Matrix{Float64}}
How should I do it in the right way?
Julia 1.9 has stack, which can be used on earlier Julia versions via the package Compat.
julia> using Compat
julia> P_predefined = vec.([[.3 .4 .2 .1], [.2 .3 .5 0.], [.1 0. .8 .1], [.4 0. 0. .6]])
4-element Vector{Vector{Float64}}:
[0.3, 0.4, 0.2, 0.1]
[0.2, 0.3, 0.5, 0.0]
[0.1, 0.0, 0.8, 0.1]
[0.4, 0.0, 0.0, 0.6]
julia> stack(P_predefined)
4×4 Matrix{Float64}:
0.3 0.2 0.1 0.4
0.4 0.3 0.0 0.0
0.2 0.5 0.8 0.0
0.1 0.0 0.1 0.6
julia> stack(P_predefined; dims=1)
4×4 Matrix{Float64}:
0.3 0.4 0.2 0.1
0.2 0.3 0.5 0.0
0.1 0.0 0.8 0.1
0.4 0.0 0.0 0.6
Note: your P_predefined is a vector of 1xn matrices, instead of vectors. I've used vec here to convert them to vectors.
vcat(A...)
Concatenate along dimension 1. To efficiently concatenate a large
vector of arrays, use reduce(vcat, x).
julia> reduce(vcat, P_predefined)
4×4 Matrix{Float64}:
0.3 0.4 0.2 0.1
0.2 0.3 0.5 0.0
0.1 0.0 0.8 0.1
0.4 0.0 0.0 0.6
Since you mention efficiency, a comprehension will be 2X faster than vcat.
m, n = length(P_predefined), length(P_predefined[1])
#btime mat = [$P_predefined[i][j] for i=1:$m, j=1:$n]
#btime mat = reduce(vcat, $P_predefined)
# 29.347 ns (1 allocation: 192 bytes)
# 72.131 ns (1 allocation: 192 bytes)
I've been doing some exercises in julia, and I am currently trying to #assert a vector that has been diagonalized into a matrix against a "solution matrix" given in the exercise notebook. However, I get an AssertionError when asserting my code against the provided solution. Example of my code:
julia> using LinearAlgebra
julia> A =
[
140 97 74 168 131
97 106 89 131 36
74 89 152 144 71
168 131 144 54 142
131 36 71 142 36
]
5×5 Matrix{Int64}:
140 97 74 168 131
97 106 89 131 36
74 89 152 144 71
168 131 144 54 142
131 36 71 142 36
julia> A_eigv = eigen(A).values
5-element Vector{Float64}:
-128.49322764802145
-55.887784553057
42.752167279318854
87.16111477514494
542.4677301466137
julia> A_diag = Diagonal(A_eigv)
5×5 Diagonal{Float64, Vector{Float64}}:
-128.493 ⋅ ⋅ ⋅ ⋅
⋅ -55.8878 ⋅ ⋅ ⋅
⋅ ⋅ 42.7522 ⋅ ⋅
⋅ ⋅ ⋅ 87.1611 ⋅
⋅ ⋅ ⋅ ⋅ 542.468
julia> #assert A_diag == [-128.493 0.0 0.0 0.0 0.0;
0.0 -55.8878 0.0 0.0 0.0;
0.0 0.0 42.7522 0.0 0.0;
0.0 0.0 0.0 87.1611 0.0;
0.0 0.0 0.0 0.0 542.468]
AssertionError: A_diag == [-128.493 0.0 0.0 0.0 0.0; 0.0 -55.8878 0.0 0.0 0.0; 0.0 0.0 42.7522 0.0 0.0; 0.0 0.0 0.0 87.1611 0.0; 0.0 0.0 0.0 0.0 542.468]
Stacktrace:
[1] top-level scope
# In[90]:1
[2] eval
# ./boot.jl:360 [inlined]
[3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
# Base ./loading.jl:1094
My inital assumption was that a difference in number of decimals was the cause of the error. I therefore replaced == with ≈ (\approx). However, as the code example below shows, the error persists:
julia> #assert A_diag ≈ #\approx
[-128.493 0.0 0.0 0.0 0.0;
0.0 -55.8878 0.0 0.0 0.0;
0.0 0.0 42.7522 0.0 0.0;
0.0 0.0 0.0 87.1611 0.0;
0.0 0.0 0.0 0.0 542.468]
AssertionError: A_diag ≈ [-128.493 0.0 0.0 0.0 0.0; 0.0 -55.8878 0.0 0.0 0.0; 0.0 0.0 42.7522 0.0 0.0; 0.0 0.0 0.0 87.1611 0.0; 0.0 0.0 0.0 0.0 542.468]
Stacktrace:
[1] top-level scope
# In[97]:1
[2] eval
# ./boot.jl:360 [inlined]
[3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
# Base ./loading.jl:1094
I've been reading through my code multiple times now, and I am at a loss. The values in my diagonal matrix (A_diag) are seemingly identical to the solution matrix. Furthermore, setting the statement to approximately equal (\approx) renders the same error, so I assume I can count out decimal error.
My main question is: What causes the AssertionError?
No, the dots are treated as 0 for the purpose of testing equality.
julia> Diagonal(1:2) == [1 0; 0 2]
true
Your problem is that your arrays are actually not equal; -128.49322764802145 is not the same as -128.493. (The pretty-printed version of the array truncates floats for display, but that's not the true underlying value!).
[Edit:]
Using ≈ (\approx) will also fail in this case. The reason for this is explained in the documentation for isapprox()
The binary operator ≈ is equivalent to isapprox with the default arguments,
if an atol > 0 is not specified, rtol defaults to the square root of eps of the type of x or y, whichever is bigger (least precise).
Essentially, what this means is that ≈ will test for approximate equality with a relative tolerance of √eps() which is approximately equal to 1.5e-8, or 0.0000015%. This tolerance is waaay too low, and increasing the tolerance will resolve the issue. E.g.:
# Option 1: Absolute tolerance. Set to a reasonable max deviation:
julia> isapprox(A_diag, sol_mat, atol = 1e-3)
true
# Option 2: Relative tolerance. Setting rtol = 1e-n, n is the number of significant digits in either matrices will work in most cases.
julia> isapprox(A_diag, sol_mat, rtol = 1e-6)
true
Since the solution matrix provides the values in six significant digits, another alternative is to round the values in A_diag to this number og digits and test for equality. E.g.:
julia> round.(A_diag, RoundNearestTiesUp, sigdigits=6) ==
[-128.493 0.0 0.0 0.0 0.0;
0.0 -55.8878 0.0 0.0 0.0;
0.0 0.0 42.7522 0.0 0.0;
0.0 0.0 0.0 87.1611 0.0;
0.0 0.0 0.0 0.0 542.468]
true
How to sum under the main diagonal without using main diagonal in matrix, in julia?
I was using sum=tril(a)-1 but it doesn't work in julia.
I know I need a mask but I don't know how to use it.
You're looking for the LinearAlgebra module, which is part of the standard library and contains a tril function:
julia> using LinearAlgebra
julia> A = ones(5, 5)
5×5 Array{Float64,2}:
1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0
julia> tril(A, -1)
5×5 Array{Float64,2}:
0.0 0.0 0.0 0.0 0.0
1.0 0.0 0.0 0.0 0.0
1.0 1.0 0.0 0.0 0.0
1.0 1.0 1.0 0.0 0.0
1.0 1.0 1.0 1.0 0.0
julia> sum(tril(A, -1))
10.0
tril function is in the Linear Algebra standard library. To use it, you need to import the LinearAlgebra module. tril takes a second optional argument to specify where you want to start the lower triangular part. You can set it to -1 in order not to take the main diagonal.
using LinearAlgebra
A = rand(5, 5)
lowerA = tril(A, -1)
println(sum(lowerA))
You might also want to take a look at lazy lower triangular view constructors such as LowerTriangular or OneUnitLowerTriangular.
Given a list of columns and rows, I want to produce a submatrix of a cholesky factorization. Example:
julia> A = rand(10,10)
julia> R = chol(A'*A)
julia> ind = [1,3,6,8,9]
julia> R[ind,ind]
However, this results in an error:
ERROR: BoundsError: attempt to access 5x5
UpperTriangular{Float64,Array{Float64,2}}:
1.28259 0.0 0.0 0.0 0.0
0.0 6.51646e-314 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
at index [2,1]
in _unsafe_getindex at multidimensional.jl:197
in getindex at abstractarray.jl:483
I understand that this would work for a typical matrix, but the UpperTriangular type obviously requires something different... I can't find documentation on this.
Looks like Triangular matrices haven't been updated to take advantage of fallback non-scalar indexing in 0.4 (this was a missing method error in 0.3).
Easiest ways around this for now are conversion to a full array before you index:
julia> full(R)[ind,ind]
5x5 Array{Float64,2}:
2.2261 1.28096 1.69087 1.26135 1.50703
0.0 1.03681 0.115735 0.559855 0.70766
0.0 0.0 0.702936 -0.111155 -0.61263
0.0 0.0 0.0 0.661491 0.33661
0.0 0.0 0.0 0.0 0.159691
Or by using a SubArray, which creates a view into the original data (so modifications will propagate):
julia> sub(R, ind, ind)
5x5 SubArray{Float64,2,UpperTriangular{Float64,Array{Float64,2}},Tuple{Array{Int64,1},Array{Int64,1}},0}:
2.2261 1.28096 1.69087 1.26135 1.50703
0.0 1.03681 0.115735 0.559855 0.70766
0.0 0.0 0.702936 -0.111155 -0.61263
0.0 0.0 0.0 0.661491 0.33661
0.0 0.0 0.0 0.0 0.159691
I'd coded a Julia function with an array bounds error:
function wrong()
alphas = [ 0.5, 1, 1.25, 2.0 ] ;
theta = 0:0.02:1 * pi ;
U = zeros( length(theta), 4 ) ;
i = 1 ;
j = 1 ;
for a = alphas
kd = pi * a ;
for t = theta
v = (cos( kd * cos( t ) ) - cos( kd ))/sin( t ) ;
U[i, j] = v ;
i = i + 1 ;
end
j = j + 1 ;
end
end
Here i=1 should be in the loop. I get:
julia> wrong()
ERROR: BoundsError()
in setindex! at array.jl:308 (repeats 2 times)
Is there any way to get the julia interpreter to give more detailed information about exceptions when they are hit, or ways to debug into the failing statement and see what's going on? For example, knowing what the index values that were caused the bounds error when this occurred would have been helpful to debug this.
Bounds error reporting has improved in julia v0.4 via this pull request https://github.com/JuliaLang/julia/pull/9534. In julia 0.4 the array as well as the index you were trying to access get printed by default:
julia> wrong()
ERROR: BoundsError: attempt to access 158x4 Array{Float64,2}:
NaN 0.0 0.0 0.0
0.0157085 0.0 0.0 0.0
0.0314201 0.0 0.0 0.0
0.047138 0.0 0.0 0.0
0.0628651 0.0 0.0 0.0
0.0786045 0.0 0.0 0.0
0.094359 0.0 0.0 0.0
0.110131 0.0 0.0 0.0
0.125924 0.0 0.0 0.0
0.141739 0.0 0.0 0.0
⋮
0.127183 0.0 0.0 0.0
0.111388 0.0 0.0 0.0
0.0956143 0.0 0.0 0.0
0.0798585 0.0 0.0 0.0
0.064118 0.0 0.0 0.0
0.04839 0.0 0.0 0.0
0.0326715 0.0 0.0 0.0
0.0169595 0.0 0.0 0.0
0.00125087 0.0 0.0 0.0
at index [159,2]
in wrong at none:15
I don't know if you can backport the changes to your julia version, but switching to 0.4 should solve your problem.