Problem with Array in struct in Julia language - julia

I've a problem with the following struct:
struct OdeSol{typ, rng, n}
t::rng
x::Array{typ}
v::Array{typ}
end
OdeSol(typ, rng, n) = OdeSol(rng, Array{typ}(undef, n, length(rng)), Array{typ}(undef, n, length(rng)))
where t_range=tlim[1]:Δt:tlim[2], typeof(x0[1]) is Float64 and size(x0)[1] is an integer (size(x0)[1]=2).
When I launch sol = OdeSol(typeof(x0[1]), t_range, size(x0)[1]) I got the following error:
MethodError: no method matching Array{0.0:0.01:10.0,N} where N(::UndefInitializer, ::Array{Float64,2}, ::Int64)
Closest candidates are:
Array{0.0:0.01:10.0,N} where N(::UndefInitializer, !Matched::Int64, ::Int64) where T at boot.jl:421
Array{0.0:0.01:10.0,N} where N(::UndefInitializer, !Matched::Int64, ::Int64, !Matched::Int64) where T at boot.jl:422
Array{0.0:0.01:10.0,N} where N(::UndefInitializer, !Matched::Integer, ::Integer) where T at baseext.jl:17
...
Stacktrace:
[1] OdeSol(::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Array{Float64,2}, ::Array{Float64,2}) at ./In[10]:8 (repeats 2 times)
[2] top-level scope at In[11]:1
[3] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091
Anyone can help me?

You seem to be mixing the parametric types with the field values within the struct.
On top of that it is worth to use capital letters for type names.
Looking at the parameters it also seems that you are looking for matrices (that is 2-dimensional arrays)/
Perhaps you mean the following thing:
struct OdeSol{T, R}
t::R
x::Matrix{T}
v::Matrix{T}
end
OdeSol{T,R}(rng::R, n) where {T,R} = OdeSol{T,R}(rng, Matrix{T}(undef, n, length(rng)), Matrix{T}(undef, n, length(rng)))
And now sample usage:
julia> OdeSol{Int, Vector{Int}}([1,2,3],4)
OdeSol{Int64,Array{Int64,1}}([1, 2, 3], [0 0 0; 0 0 0; 0 0 0; 0 0 0], [0 0 0; 0 0 0; 0 0 0; 0 0 0])

Related

Julia not accepting this constraint. No method matching cartesian index

I have the following code in which the JuMP constraint is throwing an error.
using JuMP
using MosekTools
K = 3
N = 2
penalties = [1.0, 3.9, 8.7]
function A_tau(r::Number, n::Number, tau::Float64)
fac = 1
for m in 1:r
fac *= (n - (m - 1))
end
if n >= r
return fac * tau ^ (n - r)
else
return 0.0
end
end
function A_tau_mat(tau::Float64)
mat = Array{Float64, 2}(undef, N+1, N+1)
for i in 1:N+1
for j in 1:N+1
mat[i, j] = A_tau(i, j, tau)
end
end
return mat
end
m = Model(optimizer_with_attributes(Mosek.Optimizer, "QUIET" => false, "INTPNT_CO_TOL_DFEAS" => 1e-7))
#variable(m, p[1:1:K,1:1:N+1])
#variable(m, A[1:1:K+1,1:1:K,1:1:N+1,1:1:N+1])
#constraint(m, -A_tau_mat(0.0) * p[1, :] == [0.0, 0.0, 0.0])
optimize!(m)
println("p value is ", value.(p[1, :]))
println(A_tau_mat(0.0))
The error happens when the #constraint line is added and there's no error without it. The error is as follows. The error shows no method matching CartesianIndex ::Int64.
ERROR: LoadError: MethodError: no method matching -(::CartesianIndex{1}, ::Int64)
Closest candidates are:
-(!Matched::Complex{Bool}, ::Real) at complex.jl:307
-(!Matched::Missing, ::Number) at missing.jl:115
-(!Matched::MutableArithmetics.Zero, ::Any) at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/rewrite.jl:55
...
Stacktrace:
[1] _add_mul_array(::Array{GenericAffExpr{Float64,VariableRef},1}, ::Array{Float64,2}, ::JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{StepRange{Int64,Int64}},Tuple{Dict{Int64,Int64}}}) at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/linear_algebra.jl:166
[2] mutable_operate! at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/linear_algebra.jl:196 [inlined]
[3] mutable_operate_to!(::Array{GenericAffExpr{Float64,VariableRef},1}, ::typeof(*), ::Array{Float64,2}, ::JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{StepRange{Int64,Int64}},Tuple{Dict{Int64,Int64}}}) at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/linear_algebra.jl:208
[4] operate at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/linear_algebra.jl:221 [inlined]
[5] operate at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/rewrite.jl:43 [inlined]
[6] operate_fallback! at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/interface.jl:275 [inlined]
[7] operate!(::typeof(MutableArithmetics.sub_mul), ::MutableArithmetics.Zero, ::Array{Float64,2}, ::JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{StepRange{Int64,Int64}},Tuple{Dict{Int64,Int64}}}) at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/rewrite.jl:70
[8] top-level scope at /Users/prikshetsharma/.julia/packages/MutableArithmetics/0tlz5/src/rewrite.jl:227
[9] top-level scope at /Users/prikshetsharma/.julia/packages/JuMP/qhoVb/src/macros.jl:440
[10] top-level scope at /Users/prikshetsharma/Documents/clotorch/src/clotorch/flight/trajectory.jl:72
[11] include(::Function, ::Module, ::String) at ./Base.jl:380
[12] include(::Module, ::String) at ./Base.jl:368
[13] exec_options(::Base.JLOptions) at ./client.jl:296
[14] _start() at ./client.jl:506
in expression starting at /Users/prikshetsharma/Documents/clotorch/src/clotorch/flight/trajectory.jl:72
How to fix this error and use the constraint like I want to? What's wrong with this constraint?
You can try this
#variable(m, p[1:K,1:N+1])
#variable(m, A[1:K+1,1:K,1:N+1,1:N+1])
#constraint(m, -A_tau_mat(0.0) * p[1, :] .== [0.0, 0.0, 0.0])
There are two problems. First, the p's type in your original is DenseAxisArray rather than the normal Array because a StepRange (1:1:3) rather than a UnitRange (1:3) is provided. Though having the same elements, their types are different and the matrix multiplication implementation for it is somewhat problematic. I think it is a bug that should be fixed on the JuMP side. The other change is the dot . before the ==, which indicates broadcasting.

How to overload Base.show for custom array types?

Suppose I make my own custom vector type with it's own custom show method:
struct MyVector{T} <: AbstractVector{T}
v::Vector{T}
end
function Base.show(io::IO, v::MyVector{T}) where {T}
println(io, "My custom vector with eltype $T with elements")
for i in eachindex(v)
println(io, " ", v.v[i])
end
end
If I try making one of these objects at the REPL I get unexpected errors related to functions I never intended to call:
julia> MyVector([1, 2, 3])
Error showing value of type MyVector{Int64}:
ERROR: MethodError: no method matching size(::MyVector{Int64})
Closest candidates are:
size(::AbstractArray{T,N}, ::Any) where {T, N} at abstractarray.jl:38
size(::BitArray{1}) at bitarray.jl:77
size(::BitArray{1}, ::Integer) at bitarray.jl:81
...
Stacktrace:
[1] axes at ./abstractarray.jl:75 [inlined]
[2] summary(::IOContext{REPL.Terminals.TTYTerminal}, ::MyVector{Int64}) at ./show.jl:1877
[3] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::MyVector{Int64}) at ./arrayshow.jl:316
[4] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:132
[5] display(::REPL.REPLDisplay, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:136
[6] display(::Any) at ./multimedia.jl:323
...
Okay, whatever so I'll implement Base.size so it'll leave me alone:
julia> Base.size(v::MyVector) = size(v.v)
julia> MyVector([1, 2, 3])
3-element MyVector{Int64}:
Error showing value of type MyVector{Int64}:
ERROR: getindex not defined for MyVector{Int64}
Stacktrace:
[1] error(::String, ::Type) at ./error.jl:42
[2] error_if_canonical_getindex(::IndexCartesian, ::MyVector{Int64}, ::Int64) at ./abstractarray.jl:991
[3] _getindex at ./abstractarray.jl:980 [inlined]
[4] getindex at ./abstractarray.jl:981 [inlined]
[5] isassigned(::MyVector{Int64}, ::Int64, ::Int64) at ./abstractarray.jl:405
[6] alignment(::IOContext{REPL.Terminals.TTYTerminal}, ::MyVector{Int64}, ::UnitRange{Int64}, ::UnitRange{Int64}, ::Int64, ::Int64, ::Int64) at ./arrayshow.jl:67
[7] print_matrix(::IOContext{REPL.Terminals.TTYTerminal}, ::MyVector{Int64}, ::String, ::String, ::String, ::String, ::String, ::String, ::Int64, ::Int64) at ./arrayshow.jl:186
[8] print_matrix at ./arrayshow.jl:159 [inlined]
[9] print_array at ./arrayshow.jl:308 [inlined]
[10] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::MyVector{Int64}) at ./arrayshow.jl:345
[11] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:132
[12] display(::REPL.REPLDisplay, ::Any) at /Users/mason/julia/usr/share/julia/stdlib/v1.3/REPL/src/REPL.jl:136
[13] display(::Any) at ./multimedia.jl:323
...
Hmm, now it wants getindex
julia> Base.getindex(v::MyVector, args...) = getindex(v.v, args...)
julia> MyVector([1, 2, 3])
3-element MyVector{Int64}:
1
2
3
What? That wasn't the print formatting I told it to do! what's going on here?
The problem is that in julia, Base defines a method Base.show(io::IO ::MIME"text/plain", X::AbstractArray) which is actually more specific than the Base.show(io::IO, v::MyVector) for the purposes of display. This section of the julia manual describes the sort of custom printing that AbstractArray uses. So if we want to use our custom show method, we instead need to do
julia> function Base.show(io::IO, ::MIME"text/plain", v::MyVector{T}) where {T}
println(io, "My custom vector with eltype $T and elements")
for i in eachindex(v)
println(io, " ", v.v[i])
end
end
julia> MyVector([1, 2, 3])
My custom vector with eltype Int64 and elements
1
2
3
See also: https://discourse.julialang.org/t/extending-base-show-for-array-of-types/31289

How to assign value to a column while iterating over a DataFrame using for eachrow

I have the following code. It basically iterates over rows in a dataframe and tries to assign a value to column C.
I have tried to locate how to achieve this without success. I know that this sentence r.C = i*100 is not correct, which would be the right one to assign a value to column C for each iterated row?
Note that the question is a simplified example, in my real code I need to actually iterate over each row because the calculations are far more complex.
File main2.jl:
struct MyStruct
a::Int32
b::Int32
c::String
end
df = DataFrame( A=Int[], B=Int[] )
push!(df, [1, 10])
push!(df, [2, 20])
push!(df, [3, 30])
insertcols!(df, 3, :C => Int)
println(df)
i = 1
for r in eachrow(df)
global i
r.C = i*100
i = i + 1
end
And I get:
julia> include("main2.jl")
| A | B | C |
| Int64 | Int64 | DataType |
|-------|-------|----------|
| 1 | 10 | Int64 |
| 2 | 20 | Int64 |
| 3 | 30 | Int64 |
ERROR: LoadError: MethodError: Cannot `convert` an object of type Int64 to an object of type DataType
Closest candidates are:
convert(::Type{S}, ::T<:(Union{CategoricalString{R}, CategoricalValue{T,R} where T} where R)) where {S, T<:(Union{CategoricalString{R}, CategoricalValue{T,R} where T} where R)} at /home/.../.julia/packages/CategoricalArrays/qcwgl/src/value.jl:91
convert(::Type{T}, ::T) where T at essentials.jl:167
Stacktrace:
[1] setindex!(::Array{DataType,1}, ::Int64, ::Int64) at ./array.jl:766
[2] insert_single_entry!(::DataFrame, ::Int64, ::Int64, ::Int64) at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:458
[3] setindex! at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:497 [inlined]
[4] setindex! at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframerow/dataframerow.jl:106 [inlined]
[5] setproperty!(::DataFrameRow{DataFrame,DataFrames.Index}, ::Symbol, ::Int64) at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframerow/dataframerow.jl:129
[6] top-level scope at /usr/home/.../main2.jl:23
[7] include at ./boot.jl:328 [inlined]
[8] include_relative(::Module, ::String) at ./loading.jl:1094
[9] include(::Module, ::String) at ./Base.jl:31
[10] include(::String) at ./client.jl:431
[11] top-level scope at REPL[1]:1
in expression starting at /usr/home/.../main2.jl:21
The standard way to add a column with a sentinel value to a DataFrame is just:
df[!, :C] .= 0
insertcols! is OK to use but typically it is employed when you want to insert a column in the middle of the DataFrame (not as the last column, what my example does).
Now the loop you have written at the end of your question can be stated as:
for (i, r) in enumerate(eachrow(df))
r.C = i*100
end
which I would say is a more typical way to do it.
Finally you could have simply written:
df.C = 100 .* axes(df, 1)
to get the same effect. Note that the last statement could have been much more complex like:
df.C = #. 100 * $axes(df, 1) + df.A + sin(df.B)
or equivalently in this case
df.C = 100 * axes(df, 1) + df.A + sin.(df.B)
(in general - you can freely use broadcasting when working with data frames instead of loops)
The problem is in
insertcols!(df, 3, :C => Int)
where you initialize the :C column with a type (Int) instead of an Int value, like 0. Changing this to
insertcols!(df, 3, :C => 0)
works.

JuMP variable declaration: MethodError

I'm following the quickstart guide on JuMP.
My julia version is 0.7, the code is this:
using JuMP
m = Model()
l = zeros(10)
u = ones(10)
##variable(m, x)
##variable(m, 0 <= x[1:10] <= 1)
#variable(m, l<=x[1:10]<=u)
The first two variable macros (commented out) work fine, but the last one produces an error.
MethodError: no method matching constructvariable!(::Model, ::getfield(JuMP, Symbol("#_error#107")){Tuple{Symbol,Expr}}, ::Array{Float64,1}, ::Array{Float64,1}, ::Symbol, ::String, ::Float64)
Closest candidates are:
constructvariable!(::Model, ::Function, !Matched::Number, !Matched::Number, ::Symbol, ::AbstractString, ::Number; extra_kwargs...) at /home/lhk/.julia/packages/JuMP/Xvn0n/src/macros.jl:968
constructvariable!(::Model, ::Function, !Matched::Number, !Matched::Number, ::Symbol, !Matched::Number, !Matched::Array{T,1} where T, !Matched::Array{Float64,1}, !Matched::AbstractString, !Matched::Number; extra_kwargs...) at /home/lhk/.julia/packages/JuMP/Xvn0n/src/macros.jl:961
Stacktrace:
[1] top-level scope at /home/lhk/.julia/packages/JuMP/Xvn0n/src/macros.jl:1259
[2] top-level scope at In[18]:7
How can I have different bounds for each entry in a vector valued variable ?
Argh, this is actually really easy:
l = zeros(10)
u = ones(10)
#variable(m, l[idx] <= x[idx = 1:10] <= u[idx])

Avoid broadcasting on an argument in Julia

Consider this toy version of a very real-life problem:
julia> foo(a,b) = sum(a) + b
foo (generic function with 1 method)
julia> foo.([1,2],[3,4,5])
ERROR: DimensionMismatch("arrays could not be broadcast to a common size")
Stacktrace:
[1] _bcs1(::Base.OneTo{Int64}, ::Base.OneTo{Int64}) at ./broadcast.jl:70
[2] _bcs at ./broadcast.jl:63 [inlined]
[3] broadcast_shape at ./broadcast.jl:57 [inlined] (repeats 2 times)
[4] broadcast_indices at ./broadcast.jl:53 [inlined]
[5] broadcast_c at ./broadcast.jl:311 [inlined]
[6] broadcast(::Function, ::Array{Int64,1}, ::Array{Int64,1}) at ./broadcast.jl:434
I want the above code to return [6,7,8], but that's not happening because the broadcast implied by the dot tries to match up the input vectors of length 2 and 3 and feed scalars into both arguments of foo. How can I avoid this?
Simply wrap the arguments you don't want to broadcast on into a Ref:
julia> foo.(Ref([1,2]),[3,4,5])
3-element Array{Int64,1}:
6
7
8

Resources