I am new to Julia and I am trying to create a plot with the following:
xi2 = range(0,sqrt(6),step=1e-3)
collect(xi2)
plot(xi2, 1-xi2^2/6, label="n = 0")
When I try this though, I have the error:
MethodError: no method matching ^(::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, ::Int64)
Closest candidates are:
^(::Union{AbstractChar, AbstractString}, ::Integer) at C:\Users\Acer\AppData\Local\Programs\Julia-1.7.0\share\julia\base\strings\basic.jl:721
^(::Rational, ::Integer) at C:\Users\Acer\AppData\Local\Programs\Julia-1.7.0\share\julia\base\rational.jl:475
^(::Complex{<:AbstractFloat}, ::Integer) at C:\Users\Acer\AppData\Local\Programs\Julia-1.7.0\share\julia\base\complex.jl:839
...
What am I missing here?
You want the elements of xi2 raised to the power of two, so you want element-wise operations using the dot operator:
julia> xi2 = range(0,sqrt(6),step=1e-3);
julia> plot(xi2, 1 .- xi2.^2/6, label="n = 0")
(The collect step was unnecessary, since most array operations can be performed on a range directly. And in case you did want to collect - i.e. allocate memory and make it a full array - you have to assign the result of collect to some variable. In your original code, the elements were being collected into an array, but then thrown away since the result wasn't assigned to anything.)
Related
The methods function returns the method table of a function as also mentioned here. I am looking for an explanation on how the function works.
Consider the following example in Julia 1.7:
julia> f(a::Int64,b::Int64=1,c::Float64=1.0) = (a+b+c)
f (generic function with 3 methods)
julia> g(a::Int64,b::Int64=1;c::Float64=1.0) = (a+b+c)
g (generic function with 2 methods)
julia> methods(f)
# 3 methods for generic function "f":
[1] f(a::Int64) in Main at REPL[1]:1
[2] f(a::Int64, b::Int64) in Main at REPL[1]:1
[3] f(a::Int64, b::Int64, c::Float64) in Main at REPL[1]:1
julia> methods(g)
# 2 methods for generic function "g":
[1] g(a::Int64) in Main at REPL[1]:1
[2] g(a::Int64, b::Int64; c) in Main at REPL[1]:1
julia> f(1,1.0)
ERROR: MethodError: no method matching f(::Int64, ::Float64)
Closest candidates are:
f(::Int64) at REPL[1]:1
f(::Int64, ::Int64) at REPL[1]:1
f(::Int64, ::Int64, ::Float64) at REPL[1]:1
Stacktrace:
[1] top-level scope
# REPL[4]:1
julia> g(1,c=1.0)
3.0
julia>
It is not quite clear to me why there is no method f(::Int64, ::Float64) (hence the error). I am also wondering why there is no error for g(1,c=1.0) given that g(::Int64, ::Float64) or g(::Int64, c) are not listed as valid methods for g.
Ah, so to be a bit technical this is really more accurately a question about how type annotations, dispatch, optional arguments, and keyword arguments work in Julia; the methods function just gives you some insight into that process, but it's not the methods function that makes those decisions. To answer your individual questions
It is not quite clear to me why there is no method f(::Int64, ::Float64) (hence the error).
There is no method for this because you you can only omit optional normal (non-keyword) arguments contiguously from the last normal (non-keyword) argument. Consider the following case:
julia> f(a=1, b=1, c=1, d=1) = a + 2b +3c +4d
f (generic function with 8 methods)
julia> f(2,4)
If there were not a rule for this, the compiler would have no idea whether the 2 and 4 provided were supposed to be for a and b, or do I mean that actually I wanted the 2 to go to a and the 4 to go to d? or c? Or anything! This would be undecidable. So we have a rule, and the rule is that the first argument goes to a, the second to b, and the omitted ones are c and d. Even though you have specified defaults, you cannot omit middle arguments, you can only omit the last N optional arguments. This is just the rule, and it does not matter whether or not you have applied type annotations or not.
I am also wondering why there is no error for g(1,c=1.0) given that g(::Int64, ::Float64) or g(::Int64, c) are not listed as valid methods for g.
Firstly, there is no method for g(::Int64, ::Float64) or g(::Int64, c) because keyword arguments (in this example, c) do not participate in dispatch. There is no error for g(1,c=1.0) because when you write g(1,c=1.0), you the optional argument for b is falling back to its default, so you are actually calling g(1,1,c=1.0) When you write g(1,c=1.0), you have explicitly specified that the 1.0 is being assigned to c, so it cannot possibly be the value for b. The value for b has to fall back to it's default, 1.
Is there in Julia a Collection type from which both Set and Array derive ?
I have both:
julia> supertype(Array)
DenseArray{T,N} where N where T
julia> supertype(DenseArray)
AbstractArray{T,N} where N where T
julia> supertype(AbstractArray)
Any
And:
julia> supertype(Set)
AbstractSet{T} where T
julia> supertype(AbstractSet)
Any
What I try to achieve is to write function that can take both Array or Set as argument, because the type of collection doesn't matter as long as I can iterate over it.
function(Collection{SomeOtherType} myCollection)
for elem in myCollection
doSomeStuff(elem)
end
end
No, there is no Collection type, nor is there an Iterable one.
In theory, what you ask can be accomplished through traits, which you can read about elsewhere. However, I would argue that you should not use traits here, and instead simply refrain from restricting the type of your argument to the function. That is, instead of doing
foo(x::Container) = bar(x)
, do
foo(x) = bar(x)
There will be no performance difference.
If you want to restrict your argument types you could create a type union:
julia> ty = Union{AbstractArray,AbstractSet}
Union{AbstractSet, AbstractArray}
julia> f(aarg :: ty) = 5
f (generic function with 1 method)
This will work on both sets and arrays
julia> f(1:10)
5
julia> f(rand(10))
5
julia> f(Set([1,2,5]))
5
But not on numbers, for example
julia> f(5)
ERROR: MethodError: no method matching f(::Int64)
Closest candidates are:
f(::Union{AbstractSet, AbstractArray}) at REPL[2]:1
Take as example following (irrational) array
a = fill(pi, 10)
When trying to assign a different value to one element, for example
a[1] .= 0.0
Following error occurs:
ERROR: MethodError: no method matching copyto!(::Irrational{:π}, ::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{0},Tuple{},typeof(identity),Tuple{Int64}})
The reason for this is that the element type of a when you construct it like that is the special number typ Irrational{:π} as seen from the output:
julia> a = fill(pi, 2)
2-element Array{Irrational{:π},1}:
π
π
When you try to put another numeric type in this container (e.g. a Float64 with value 0.0 in your example) it is like trying to fit squares in circular holes -- they don't fit.
The solution is to construct the array with the desired element type to start with. For "regular" computations you probably want Float64, so you can convert pi to a float first:
julia> a = fill(float(pi), 2)
2-element Array{Float64,1}:
3.141592653589793
3.141592653589793
The two other answers suggest you to convert your pi to Float64. In Julia you do not have to do that.
v = fill!(Vector{Union{Float64,Irrational}}(undef,10), pi)
Now your vector v can store both Float64 and Irrational numbers. Note that the performance of such code will be worse than having just a Vector{Float64} but on the other hand you are not forced to loose precision (which might be desirable or not).
First of all, we use broadcast to vectorialize operation : if you want to change all the values of the array a, you write
a .= 0.0
And if you want to change only the first value, you write
a[1] = 0.0
wich gives now a different error
ERROR: MethodError: no method matching Irrational{:π}(::Float64)
The problem comes frome the type. As you can see here, https://julialang.org/blog/2017/03/piday/ irrational is some kind of weird type. Shortly, it's only used to stock some classical values ( pi, e, ...) wich can be converted to any floating type without any intermediate routine.
It's a bit strange to set an array of irrational, I think you would prefer to use Float64. If I take your original declation, write
a = fill( Float64(pi), 10 )
an then you can use
a[1] = 0.0
or
a .= 0.0
I try to compute the inverse fourier transform of a array of coefficients using ifft with Julia.
I have N complex numbers on an array organized as : Y=[Y_0,.., Y_(N-1)] representing my Fourier coefficients and by computing
ifft(Y)
I get the following error message :
MethodError: no method matching plan_bfft(::Array{Complex,1},
::UnitRange{Int64}) Closest candidates are:
plan_bfft{T<:Union{Complex{Float32},Complex{Float64}},N}(::Union{Base.ReshapedArray{T<:Union{Complex{Float32},Complex{Float64}},N,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N}}},DenseArray{T<:Union{Complex{Float32},Complex{Float64}},N},SubArray{T<:Union{Complex{Float32},Complex{Float64}},N,A<:Union{Base.ReshapedArray{T,N,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N}},L}},
::Any; flags, timelimit) at fft/FFTW.jl:601
plan_bfft{T<:Real}(::AbstractArray{T<:Real,N}, ::Any; kws...) at
dft.jl:205
plan_bfft{T<:Union{Integer,Rational{T<:Integer}}}(::AbstractArray{Complex{T<:Union{Integer,Rational}},N},
::Any; kws...) at dft.jl:207 ...
in #plan_ifft#15(::Array{Any,1}, ::Function, ::Array{Complex,1},
::UnitRange{Int64}) at ./dft.jl:268 in #plan_ifft#3(::Array{Any,1},
::Function, ::Array{Complex,1}) at ./dft.jl:58 in
ifft(::Array{Complex,1}) at ./dft.jl:56
Could anyone help with this?
when I ask typeof(Y) the answer is Array{Complex,1}.
Thank you
Just a guess here: ifft expects the array elements to be of type Complex{Float64}, not Complex. Furthermore,
julia> Complex<:Complex{Float64}
false
How did you get an array of Complex?
When using Complex{Float64} things work correctly:
julia> Y=complex([1.,2.,3.],[4.,3.,2.])
3-element Array{Complex{Float64},1}:
1.0+4.0im
2.0+3.0im
3.0+2.0im
julia> ifft(Y)
3-element Array{Complex{Float64},1}:
2.0+3.0im
-0.788675+0.211325im
-0.211325+0.788675im
Using Julia, I've defined a 9x10 matrix of zeros, and am trying to change a single entry , but I get the error 'setindex!' has no method matching setindex!(::Float64, ::Float64, ::Int64)
My code is:
m = zeros(9,10)
m[1][1] = 1.0
with the error pointing to the second line. typeof(m) is an Array{Float64,2}, which, as far as I can tell is mutable.
What am I doing wrong here?
To index 2-dimensional arrays, just use m[1,1].
The syntax m[1][1] would be valid for a 1-dimensional array of 1-dimensional arrays.
m = zeros(9,10)
m[1,1] = 1.0
m = Array[ [1,2], [3,4,5] ]
m[1][1]