I am new to Julia. For my application I have an expensive operation to calculate a matrix based on two points. Calculated matrices will be used multiple times so I though I would cache them in a dictionary. However, I have encountered a strange behaviour in Julia. If I add a first (key, value) pair as part of the dictionary initialization it all works as expected. However, if I don't, and try and add my first (key, value) pair later, Julia bombs out.
p1 = [ 2.0, 1.0, 1.0]
p2 = [ 4.0, 2.0, 1.0]
# This works
my_dict = Dict{Tuple{Array{Float64,1}, Array{Float64,1}}, String}(
(p1, p2) => "hello world"
)
println(my_dict[(p1, p2)])
# This works
my_dict[ (p2, p1)] = "hello again"
println(my_dict[ (p2, p1)] )
# This doesn't
my_dict2 = Dict{Tuple{Array{Float64,1}, Array{Float64,1}}, String}
my_dict2[(p2, p1)] = "this fails with method dispatch error"
Output from Julia:
julia complex_key_for_dict.jl
hello world
hello again
ERROR: LoadError: MethodError: no method matching setindex!(::Type{Dict{Tuple{Array{Float64,1},Array{Float64,1}},String}}, ::String, ::Tuple{Array{Float64,1},Array{Float64,1}})
Stacktrace:
[1] top-level scope at none:0
[2] include at ./boot.jl:326 [inlined]
[3] include_relative(::Module, ::String) at ./loading.jl:1038
[4] include(::Module, ::String) at ./sysimg.jl:29
[5] exec_options(::Base.JLOptions) at ./client.jl:267
[6] _start() at ./client.jl:436
in expression starting at /home/peter/julia/gps_analysis/complex_key_for_dict.jl:16
For now, I will simply add a fictitious first entry into the dictionary, but would be grateful if someone can put me straight on my error.
Nothing like posting a question to StackOverflow to me make realise what the solution might be. This works:
# This works. Added an open/close bracket to the end of the Dict defintion
my_dict2 = Dict{Tuple{Array{Float64,1}, Array{Float64,1}}, String}()
my_dict2[ (p2, p1)] = "this now works"
println(my_dict2[ (p2, p1)])
Thought I would post the answer so that anyone else who has also banged their head against a brick wall on this may find it helpful.
Related
I am currently reading a book (BRML) which has a demo (earthquake demo, exercise 1.22), which is written in Julia. I have never used Julia (although used Python and other languages quite extensively) before so I'm a complete noob.
What exactly does the line plot(x,y,".") do in the following code:
Pkg.add("Pkg")
using Pkg
Pkg.add("PyPlot")
S=5000 # number of points on the spiral
x=zeros(S); y=zeros(S)
for s=1:S
theta=50*2*pi*s/S; r=s/S
x[s]=r*cos(theta); y[s]=r*sin(theta)
end
plot(x,y,".")
I understand everything that is done before that, however I'm not sure what that specific line does. The reason I can't see for myself is because when I'm trying to run it on an online Julia compiler, I get the following error:
INFO: Initializing package repository /home/cg/root/4655378/.julia/v0.6
INFO: Cloning METADATA from https://github.com/JuliaLang/METADATA.jl
ERROR: LoadError: GitError(Code:ERROR, Class:Net, curl error: Could not resolve host: github.com
)
Stacktrace:
[1] macro expansion at ./libgit2/error.jl:99 [inlined]
[2] clone(::String, ::String, ::Base.LibGit2.CloneOptions) at ./libgit2/repository.jl:276
[3] #clone#100(::String, ::Bool, ::Ptr{Void}, ::Nullable{Base.LibGit2.AbstractCredentials}, ::Function, ::String, ::String) at ./libgit2/libgit2.jl:562
[4] (::Base.LibGit2.#kw##clone)(::Array{Any,1}, ::Base.LibGit2.#clone, ::String, ::String) at ./<missing>:0
[5] (::Base.Pkg.Dir.##8#10{String,String})() at ./pkg/dir.jl:55
[6] cd(::Base.Pkg.Dir.##8#10{String,String}, ::String) at ./file.jl:70
[7] init(::String, ::String) at ./pkg/dir.jl:53
[8] #cd#1(::Array{Any,1}, ::Function, ::Function, ::String, ::Vararg{String,N} where N) at ./pkg/dir.jl:28
[9] add(::String) at ./pkg/pkg.jl:117
while loading /home/cg/root/4655378/main.jl, in expression starting on line 1
As the third line indicates, the book is using the PyPlot package, which is basically a Julia wrapper around Python's pyplot.
So, we could refer to pyplot's documentation to figure out how that line of code works. But as mentioned in that page, pyplot is trying to emulate MATLAB's plot function, and for this case their help page is easier to navigate. As mentioned there,
plot(X,Y) creates a 2-D line plot of the data in Y versus the corresponding values in X.
and plot(X,Y,LineSpec) in addition "creates the plot using the specified line style, marker, and color." Clicking on LineSpec, we can see in the second table that '.' is one of the markers, with description Point and the resulting marker a black filled dot. So plot(x,y,".") creates a plot with dots as markers at the points specified by the x- and y-coordinates.
We could also try one of the other markers, for eg. plot(x,y,"+") creates this instead:
where if you look carefully, you can see that the points are marked by + signs instead.
Just starting to use Julia, but I can't figure out how do you actually find the function signature in any of the docs...
For example, let's say I want to see what parameters the gradient function of the Flux package takes.
How can I find that? If I go to flux docs it's mostly english docs and not function signatures. Similar for julia docs.
Any tips appreciated.
Use the methods function to get a list of signatures of all methods of a given function. For example:
julia> methods(sin)
# 13 methods for generic function "sin":
[1] sin(x::BigFloat) in Base.MPFR at mpfr.jl:727
[2] sin(::Missing) in Base.Math at math.jl:1197
[3] sin(a::Complex{Float16}) in Base.Math at math.jl:1145
[4] sin(a::Float16) in Base.Math at math.jl:1144
[5] sin(z::Complex{T}) where T in Base at complex.jl:804
[6] sin(x::T) where T<:Union{Float32, Float64} in Base.Math at special/trig.jl:29
[7] sin(x::Real) in Base.Math at special/trig.jl:53
[8] sin(A::LinearAlgebra.Hermitian{var"#s827",S} where S<:(AbstractArray{var"#s828",2} where var"#s828"<:var"#s827") where var"#s827"<:Complex) in LinearAlgebra at /home/bkamins/julia/share/julia/stdlib/v1.5/LinearAlgebra/src/symmetric.jl:922
[9] sin(A::Union{LinearAlgebra.Hermitian{var"#s828",S}, LinearAlgebra.Symmetric{var"#s828",S}} where S where var"#s828"<:Real) in LinearAlgebra at /home/bkamins/julia/share/julia/stdlib/v1.5/LinearAlgebra/src/symmetric.jl:918
[10] sin(D::LinearAlgebra.Diagonal) in LinearAlgebra at /home/bkamins/julia/share/julia/stdlib/v1.5/LinearAlgebra/src/diagonal.jl:576
[11] sin(A::AbstractArray{var"#s828",2} where var"#s828"<:Real) in LinearAlgebra at /home/bkamins/julia/share/julia/stdlib/v1.5/LinearAlgebra/src/dense.jl:836
[12] sin(A::AbstractArray{var"#s828",2} where var"#s828"<:Complex) in LinearAlgebra at /home/bkamins/julia/share/julia/stdlib/v1.5/LinearAlgebra/src/dense.jl:843
[13] sin(J::LinearAlgebra.UniformScaling) in LinearAlgebra at /home/bkamins/julia/share/julia/stdlib/v1.5/LinearAlgebra/src/uniformscaling.jl:139
It seems that this function is lacking proper documentation and the standard approaches described in other answers (? for the help REPL or methods) will not be very useful.
What I normally do in such cases is to type something line:
#edit gradient(1,2)
This brings me to function definition (actually I can suspect the first parameter is a function but running methods did not indicate anything.
This will open the editor and you will see something like this:
function gradient(f, args...)
y, back = pullback(f, args...)
return back(sensitivity(y))
end
So at this stage you know what your function is doing. If not perhaps you can search for pullback typing ?pullback. When you do that you discover that there is no documentation for this neither but it is a part of Zygote.
However, typing into Google Zygote.pullback will forward you to the documentation you need: https://fluxml.ai/Zygote.jl/latest/adjoints/
So this is kind of hackish. Most of Julia libraries are nicely documented but if not I always start the job with #edit macro.
I wish to re-use this code:
https://github.com/FluxML/model-zoo/blob/master/vision/mnist/mlp.jl
but with my own set of images.
I think I need to define an object like imgs of type Array{Array{Gray{Normed{UInt8,8}},2},1}
How do I initialize an array of images to obtain something of the following type:
Array{Array{Gray{Normed{UInt8,8}},2},1}
I tried this, but it fails:
x = Array{Array{ColorTypes.Gray{FixedPointNumbers.Normed{UInt8,8}},2}}(10)
ERROR: MethodError: no method matching Array{Array{Gray{Normed{UInt8,8}},2},N} where N(::Int64)
Closest candidates are:
Array{Array{Gray{Normed{UInt8,8}},2},N} where N(::UndefInitializer, ::Int64) where T at boot.jl:416
Array{Array{Gray{Normed{UInt8,8}},2},N} where N(::UndefInitializer, ::Int64, ::Int64) where T at boot.jl:417
Array{Array{Gray{Normed{UInt8,8}},2},N} where N(::UndefInitializer, ::Int64, ::Int64, ::Int64) where T at boot.jl:418
...
Stacktrace:
[1] top-level scope at none:0
To create an empty vector use:
Array{Array{Gray{Normed{UInt8,8}},2},1}()
then you can use the push! function to add images to it. Alternatively you could write the same as:
Vector{Matrix{Gray{Normed{UInt8,8}}}}()
which is a bit easier to read.
Alternatively you can write:
Array{Array{Gray{Normed{UInt8,8}},2},1}(undef, 10)
To create an uninitialized vector with 10 entries. Then you can use normal index setting syntax to initialize it. Again you could write it also as:
Vector{Matrix{Gray{Normed{UInt8,8}}}}(undef, 10)
In the arrays section of the manual there is an example of using implicit broadcast on strings which is failing for me. I can work around it, but I just wanted to report it -
julia> string.(1:3, ". ", ["First", "Second", "Third"])
I get the following output -
ERROR: MethodError: no method matching size(::String)
Closest candidates are:
size{N}(::Any, ::Integer, ::Integer, ::Integer...) at abstractarray.jl:48
size(::BitArray{1}) at bitarray.jl:39
size(::BitArray{1}, ::Any) at bitarray.jl:43
...
in map(::Base.#indices, ::Tuple{String,Array{String,1}}) at
./tuple.jl:93
in broadcast_shape(::UnitRange{Int64}, ::String, ::Array{String,1},
::Vararg{Array{String,1},N}) at ./broadcast.jl:31
in broadcast_t(::Function, ::Type{T}, ::UnitRange{Int64},
::Vararg{Any,N}) at ./broadcast.jl:228
in broadcast(::Function, ::UnitRange{Int64}, ::String,
::Array{String,1}) at ./broadcast.jl:230
It is just a version issue. On v0.5 it doesn't work and from v0.6 it does.
The docs are also appropriately versioned:
version 0.5 Array broadcasting docs
version 0.6 Array broadcasting docs
So all is good.
I'm using julia 0.5 after run this code :
Freqsample = 100;
second = 4;
step = (Freqsample * second )-1
i get this Error :
MethodError: no method matching getindex(::Int64, ::Colon, ::UnitRange{Int64})
in -(::Int64, ::Int64) at main.jl:12
in include_string(::String, ::String) at loading.jl:441
in eval(::Module, ::Any) at boot.jl:234
in (::Atom.##65#68)() at eval.jl:40
in withpath(::Atom.##65#68, ::Void) at utils.jl:30
in withpath(::Function, ::Void) at eval.jl:46
in macro expansion at eval.jl:109 [inlined]
in (::Atom.##64#67{Dict{String,Any}})() at task.jl:60
Whats wrong with subtracting ? i'm pretty new to julia forgive if its a dumb question
You've redefined - for more types than you probably intended. The second line in the backtrace you posted is telling you that Julia called a - method in main.jl for two integers. And line one is saying that within there it's trying to do something like x[:, 1:5] at line 12, where x is an integer.
This tells me two things;
Your definition of - is probably typed too permissively. You probably didn't intend to accept integers.
You are probably shadowing the built in - definition instead of extending it. You need to import Base: - in order to add a new method to a function in the standard library.