How to create SymBandedMatrix with chosen values? - julia

With the BandedMatrices package, is there a way to created a SymBandedMatrix with chosen values? There are a variety of constructors in docs, but none seem to accept input values. And indexing isn't implemented. Is that on purpose or just not done yet?
julia> using BandedMatrices
julia> a = BandedMatrices.SymBandedMatrix(Float64,5,1)
5×5 BandedMatrices.SymBandedMatrix{Float64}:
6.90681e-310 6.90681e-310
6.90681e-310 6.90682e-310 6.90682e-310
6.90682e-310 6.90682e-310 6.90681e-310
6.90681e-310 6.90681e-310 6.90681e-310
6.90681e-310 6.90684e-310
julia> a[1,1]=1
ERROR: indexing not defined for BandedMatrices.SymBandedMatrix{Float64}
Stacktrace:
[1] setindex!(::BandedMatrices.SymBandedMatrix{Float64}, ::Int64, ::Int64, ::Int64) at ./abstractarray.jl:966

The following could be an unpolished solution:
Base.setindex!(M::SymBandedMatrix,val,r,c) =
( (a,b) = minmax(r,c) ; M.data[M.k+a-b+1,b-a+1]=val )
Giving for the code in the question:
julia> a = BandedMatrices.SymBandedMatrix(Float64,5,1)
5×5 BandedMatrices.SymBandedMatrix{Float64}:
6.36578e-310 6.36578e-310
6.36578e-310 6.36578e-310 6.36577e-310
6.36577e-310 6.36577e-310 6.36577e-310
6.36577e-310 6.36577e-310 6.36578e-310
6.36578e-310 6.36577e-310
julia> Base.setindex!(M::SymBandedMatrix,val,r,c) =
( (a,b) = minmax(r,c) ; M.data[M.k+a-b+1,b-a+1]=val )
julia> a[1,1]=1
1
julia> a
5×5 BandedMatrices.SymBandedMatrix{Float64}:
1.0 6.36578e-310
6.36578e-310 6.36578e-310 6.36577e-310
6.36577e-310 6.36577e-310 6.36577e-310
6.36577e-310 6.36577e-310 6.36578e-310
6.36578e-310 6.36577e-310

Related

How to run parallel function in julia?

I would like to run the function f() on all my 4 processors (intel i7) and fetch the rands sum, as follows:
using Distributed;
#everywhere function f()
return sum(rand(10000))
end
#sync for w in workers()
#async begin
res = #spawnat w f()
values[w-1] = fetch(res)
end
end
But, getting the following error:
ERROR: TaskFailedException
nested task error: MethodError: no method matching setindex!(::typeof(values), ::Float64, ::Int64)
Stacktrace:
[1] macro expansion
# ./REPL[58]:4 [inlined]
[2] (::var"#68#70"{Channel{Any}, Int64})()
# Main ./task.jl:411
Stacktrace:
[1] sync_end(c::Channel{Any})
# Base ./task.jl:369
[2] top-level scope
# task.jl:388
Please guide me in resolving the issue!
For your code the easiest way would be (assuming Julia has been run with -p 4 command line parameter or you have run addprocs(4):
julia> values = #distributed (append!) for i in 1:4
[f()]
end
4-element Vector{Float64}:
5001.232864826896
4999.244031827526
4966.883114472259
5014.022690758762
If you want to do #spawns yourself this code works:
julia> values = Vector{Float64}(undef, 4);
julia> #sync for w in workers()
#async values[w-1] = fetch(#spawnat w f())
end
julia> values
4-element Vector{Float64}:
5029.967318172736
4993.1064528029
5016.491407076979
5062.0706219606345
However your code mostly didn't work because the type of your values was not Vector{Float64}. Here is how to replicate your error:
julia> vv()=0
vv (generic function with 1 method)
julia> vv[1]=11
ERROR: MethodError: no method matching setindex!(::typeof(vv), ::Int64, ::Int64)

Assign atoms in the Earth to a variable in Julia

In Python 3.6, the following works to assign a variable an estimate of the atoms in the Earth:
In[6]: atoms_in_earth = 10**50
In[7]: atoms_in_earth
Out[7]: 100000000000000000000000000000000000000000000000000
However, the following does not work in Julia 1.0.0:
julia> atoms_in_earth = 10^50
-5376172055173529600
julia> atoms_in_earth = BigInt(10^50)
-5376172055173529600
julia> atoms_in_earth = BigFloat(10^50)
-5.3761720551735296e+18
julia> atoms_in_earth = big(10^50)
-5376172055173529600
julia> atoms_in_earth = big"10^50"
ERROR: ArgumentError: invalid number format 10^50 for BigInt or BigFloat
Stacktrace:
[1] top-level scope at none:0
I was able to get these methods to work:
julia> atoms_in_earth = big"1_0000000000_0000000000_0000000000_0000000000_0000000000"
100000000000000000000000000000000000000000000000000
julia> float(ans)
1.0e+50
julia> atoms_in_earth = parse(BigInt, '1' * '0'^50)
100000000000000000000000000000000000000000000000000
julia> float(ans)
1.0e+50
I am hoping there is an easier way to do this in Julia.
What am I missing?
Julia uses native integers by default, and these can overflow. Python uses big integers by default (of arbitrary precision, it's size limit depend of the amount of available memory) and does not overflow (but is slower because of this).
Your first example overflows for Int64:
julia> atoms_in_earth = 10^50
-5376172055173529600
Your second, third and fourth examples, have already overflown, before you converted them to bigs:
julia> atoms_in_earth = BigInt(10^50)
-5376172055173529600
julia> atoms_in_earth = BigFloat(10^50)
-5.3761720551735296e+18
julia> atoms_in_earth = big(10^50)
-5376172055173529600
Your fifth example is not a valid big literal:
julia> atoms_in_earth = big"10^50"
ERROR: ArgumentError: invalid number format 10^50 for BigInt or BigFloat
But you can create a small number as a BigInt, in your example 10 and any further operations will be promoted to big arithmetic, form then on:
julia> x = 10
10
julia> typeof(x)
Int64
julia> x = BigInt(10)
10
julia> typeof(x)
BigInt
julia> big(10) == big"10" == big(10)
true
julia> y = x^50
100000000000000000000000000000000000000000000000000
julia> typeof(y)
BigInt
In this case 50 gets promoted to a BigInt as well, before computing x^50 and thus yielding a BigInt in the end.
julia> BigInt(10)^50 == big"10"^50 == big(10)^50
true
This works:
julia> atoms_in_earth = big"1e50"
1.0e+50
julia> typeof(ans)
BigFloat

Julia - save workspace

Is there an official way to save all variables in the workspace? If not, is there a way to display all variables? Right now I use whos() but that displays all modules and functions aswell
I think what you want is #save and #load pair of JLD.jl.
julia> n = 10
10
julia> x = randn(n, n)
10×10 Array{Float64,2}:
-0.0197367 -0.176776 0.25441 1.27037 … 0.922747 -1.62709 -1.00135
-0.926221 0.0511172 0.616038 -0.876974 -1.38141 -0.663528 0.0851561
-1.16956 1.33495 -0.192604 0.986576 1.20383 -1.11466 0.654329
-0.0358511 -2.18456 -0.253529 1.12241 -0.558712 -0.29862 1.52749
-0.228209 0.21741 0.79077 0.104083 -0.109346 0.206167 1.6082
-0.255945 0.185782 0.650366 -1.43969 … 0.367013 -1.20504 -3.03426
0.801956 -1.03232 -0.13117 0.0241593 -0.0129462 2.2469 0.208836
-1.09213 -0.723174 0.609008 0.175357 0.487224 0.97294 0.770932
-1.12841 0.249794 0.134091 0.0268805 -0.832201 -1.0924 -1.08669
0.0170944 0.945585 -0.915999 0.96237 2.03081 -0.800125 -0.584156
julia> using JLD
julia> #save "data.jld"
# restart Julia REPL
julia> using JLD
julia> #load "data.jld"
3-element Array{Symbol,1}:
:ans
:n
:x
julia> n
10
julia> x
10×10 Array{Float64,2}:
-0.0197367 -0.176776 0.25441 1.27037 … 0.922747 -1.62709 -1.00135
-0.926221 0.0511172 0.616038 -0.876974 -1.38141 -0.663528 0.0851561
-1.16956 1.33495 -0.192604 0.986576 1.20383 -1.11466 0.654329
-0.0358511 -2.18456 -0.253529 1.12241 -0.558712 -0.29862 1.52749
-0.228209 0.21741 0.79077 0.104083 -0.109346 0.206167 1.6082
-0.255945 0.185782 0.650366 -1.43969 … 0.367013 -1.20504 -3.03426
0.801956 -1.03232 -0.13117 0.0241593 -0.0129462 2.2469 0.208836
-1.09213 -0.723174 0.609008 0.175357 0.487224 0.97294 0.770932
-1.12841 0.249794 0.134091 0.0268805 -0.832201 -1.0924 -1.08669
0.0170944 0.945585 -0.915999 0.96237 2.03081 -0.800125 -0.584156

Julia: Assignment in Arrays

When indexing more than one level for an array, it works fine. But when I used it to assign values, it did not. Does anyone know why A does not change below?
In [4]: A = rand(6)
Out [4]: 6-element Array{Float64,1}:
0.111552
0.155126
0.78485
0.147477
0.362078
0.959022
In [5]: A[3:5][[true,false,true]]
Out [5]: 2-element Array{Float64,1}:
0.78485
0.362078
In [6]: A[3:5][[true,false,true]] = [99, 999]
Out [6]: 2-element Array{Int64,1}:
99
999
In [7]: A
Out [7]: 6-element Array{Float64,1}:
0.111552
0.155126
0.78485
0.147477
0.362078
0.959022
This is because indexing arrays by ranges and vectors returns a new array with the output (instead of a view into the original array). Your statement is equivalent to the following:
julia> A = rand(6)
6-element Array{Float64,1}:
0.806919
0.445286
0.882625
0.556251
0.719156
0.276755
julia> B = A[3:5]
3-element Array{Float64,1}:
0.882625
0.556251
0.719156
julia> B[[true,false,true]] = [99, 999]
2-element Array{Int64,1}:
99
999
julia> A'
1x6 Array{Float64,2}:
0.806919 0.445286 0.882625 0.556251 0.719156 0.276755
julia> B'
1x3 Array{Float64,2}:
99.0 0.556251 999.0
You can actually see that this is what Julia is doing through some of its expression utilities. Note the explicit parentheses — it's calling setindex! on the result of indexing, which has made a copy. (GenSym() is an internal way of specifying a temporary variable):
julia> :(A[3:5][[true,false,true]] = [99, 999])
:((A[3:5])[[true,false,true]] = [99,999])
julia> expand(:(A[3:5][[true,false,true]] = [99, 999]))
:(begin
GenSym(0) = (top(vect))(99,999)
setindex!(getindex(A,colon(3,5)),GenSym(0),(top(vect))(true,false,true))
return GenSym(0)
end)
The goal is to eventually have all array indexing return views instead of copies, but that's still a work-in-progress.

Julia: check whether array entry is undef

What is the best way in Julia to check whether an array entry is #undef?
Example:
julia> a = Array(Vector,2)
julia> isdefined(a[1]) # fails
julia> isempty(a[1]) # fails
You can push the access into isdefined by using isdefined(a, 1) instead of isdefined(a[1]):
julia> a = Array(Vector,2);
julia> a[2] = {10}
1-element Array{Any,1}:
10
julia> a
2-element Array{Array{T,1},1}:
#undef
{10}
julia> isdefined(a[1])
ERROR: access to undefined reference
in getindex at array.jl:246
julia> isdefined(a, 1)
false
julia> isdefined(a, 2)
true

Resources