no method matching setindex : trying to change matrix values - julia

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]

Related

Error plotting array with exponential operation

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.)

Values of ket vectors in Julia

I can't figure out how to get specific elements/ values of a ket vector in Julia language. I tried to call a specific index of the ket vector using [index], like one does with a regular vector, but that does not seem to work with kets.
Kets are available in the QuantumOptics.jl package. So for a simple example, if I would define a ket myself:
basis = FockBasis(2)
x = Ket(basis, [1,3,2])
which gives output:
Ket(dim=3)
basis: Fock(cutoff=2)
1.0
3.0
2.0
If I then try to get an element of the ket, I would try it like this:
x[1]
which gives an error:
MethodError: no method matching getindex(::Ket{FockBasis{Int64},Array{Int64,1}}, ::Int64)
and I can't access the seperate elements of the ket.
Maybe the easiest way to get the j coefficient for a ket is just to access the j value for the data property of the ket. For your example you can just do
j = 1
j_coeff = x.data[j]

Problem with asigning non-irrational values to irrational arrays using broadcast .=

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

Creating an array of `nothing` of any size in Julia

In Julia it is possible to create arrays of any size using the functions zeros(.) or ones(.). Is there a similar function to create an array that is filled with nothing at initialization but also accepts floats? I mean a function like in this example:
a = array_of_nothing(3)
# a = [nothing,nothing,nothing]
a[1] = 3.14
# a = [3.14,nothing,nothing]
I tried to find information on internet, but without success... Sorry, I am a beginner in Julia.
The fill function can be used to create arrays of arbitrary values, but it's not so easy to use here, since you want a Vector{Union{Float64, Nothing}}. Two options come to mind:
A comprehension:
a = Union{Float64, Nothing}[nothing for _ in 1:3];
a[2] = 3.14;
>> a
3-element Array{Union{Nothing, Float64},1}:
nothing
3.14
nothing
Or ordinary array initialization:
a = Vector{Union{Float64, Nothing}}(undef, 3)
fill!(a, nothing)
a[2] = 3.14
It seems that when you do Vector{Union{Float64, Nothing}}(undef, 3) the vector automatically contains nothing, but I wouldn't rely on that, so fill! may be necessary.
I think you are looking for the Base.fill — Function.
fill(x, dims)
This creates an array filled with value x.
println(fill("nothing", (1,3)))
You can also pass a function Foo() like fill(Foo(), dims) which will return an array filled with the result of evaluating Foo() once.

Julia: append to an empty vector

I would like to create an empty vector and append to it an array in Julia. How do I do that?
x = Vector{Float64}
append!(x, rand(10))
results in
`append!` has no method matching append!(::Type{Array{Float64,1}}, ::Array{Float64,1})
Thanks.
Your variable x does not contain an array but a type.
x = Vector{Float64}
typeof(x) # DataType
You can create an array as Array(Float64, n)
(but beware, it is uninitialized: it contains arbitrary values) or zeros(Float64, n),
where n is the desired size.
Since Float64 is the default, we can leave it out.
Your example becomes:
x = zeros(0)
append!( x, rand(10) )
I am somewhat new to Julia and came across this question after getting a similar error. To answer the original question for Julia version 1.2.0, all that is missing are ():
x = Vector{Float64}()
append!(x, rand(10))
This solution (unlike x=zeros(0)) works for other data types, too. For example, to create an empty vector to store dictionaries use:
d = Vector{Dict}()
push!(d, Dict("a"=>1, "b"=>2))
A note regarding use of push! and append!:
According to the Julia help, push! is used to add individual items to a collection, while append! adds an collection of items to a collection. So, the following pieces of code create the same array:
Push individual items:
a = Vector{Float64}()
push!(a, 1.0)
push!(a, 2.0)
Append items contained in an array:
a = Vector{Float64}()
append!(a, [1.0, 2.0])
You can initialize an empty Vector of any type by typing the type in front of []. Like:
Float64[] # Returns what you want
Array{Float64, 2}[] # Vector of Array{Float64,2}
Any[] # Can contain anything
New answer, for Julia 1. append! is deprecated, you now need to use push!(array, element) to add elements to an array
my_stuff = zeros()
push!(my_stuff, "new element")

Resources