Julia: "Method error" while calling a parametric function - julia

In a file named "func.jl", I defined the following function:
function testXYZ(xi::Array{T, 1}, yi::Array{T, 1}) where {T<:Float64}
println("Success")
end
In "main.jl" I did build a minimum example:
include("func.jl");
xs = [0.0, 1.2, 2.0, 5.0, 10.0, 11.0]
ys = [2.0, 2.1, 1.0, 0.0, 0.0, 3.0]
testXYZ(xs, ys)
Checking with the console the types of xs and ys, I obtain as expected:
julia> ys = [2.0, 2.1, 1.0, 0.0, 0.0, 3.0];
julia> typeof(ys)
Array{Float64,1}
While exectuting the minimum example in main I obtain a method error:
ERROR: LoadError: MethodError: no method matching
+(::Array{Float64,1}, ::String)
In Julia manual, I found lots of similar errors, but no one solved my problem.

From #tamasgal comment, the correct answer is:
"The error hasnothing to do with the code above. It says that it cannot perform + with two arrays of floats which is fine, however there is no call of + in your example."

Related

How do I declare a matrix in a struct?

In my code
mutable struct frame
Lx::Float64
Ly::Float64
T::Matrix{Float64} #I think the error is here
function frame(
Lx::Float64,
Ly::Float64,
T::Matrix{Float64}
)
return new(Lx, Ly, T)
end
end
frames = frame[]
push!(frames, frame(1.0, 1.0, undef)) #ERROR here I try nothing, undef, any
push!(frames, frame(2.0, 1.0, undef)) #ERROR here I try nothing, undef, any
frames[1].T = [1 1 2]
frames[2].T = [[2 4 5 6] [7 6 1 8]]
I got the following error in ::Matrix
ERROR: MethodError: no method matching frame(::Float64, ::Float64, ::UndefInitializer)
Closest candidates are:
frame(::Float64, ::Float64, ::Matrix)
I need to define the dimensionless matrix inside the structure and then pass the matrices with different dimensions, but I'm having an error when I push!
The error is because there is no method for the types you call:
julia> methods(frame)
# 1 method for type constructor:
[1] frame(Lx::Float64, Ly::Float64, T::Matrix{Float64})
julia> typeof(undef)
UndefInitializer
It is possible to make mutable structs with undefined fields, by calling new with fewer arguments:
julia> mutable struct Frame2
Lx::Float64
Ly::Float64
T::Matrix{Float64}
Frame2(x,y) = new(x,y)
Frame2(x,y,z) = new(x,y,z)
end
julia> a = Frame2(1,2)
Frame2(1.0, 2.0, #undef)
julia> b = Frame2(3,4,[5 6])
Frame2(3.0, 4.0, [5.0 6.0])
julia> a.T = b.T;
julia> a
Frame2(1.0, 2.0, [5.0 6.0])
You want frame(1.0, 1.0, Matrix{Float64}(undef, 0, 0))

Julia LinearAlgebra.LAPACK.geev! does not return lvector

In Julia 1.5.0, a call to LinearAlgebra.LAPACK.geev! like
W, lv, rv = LinearAlgebra.LAPACK.geev!('V','V', tMatrix)
is supposed to return the three items: the matrix W, the right vector rv and the left vector lv. The function in Julia returns in rv what GoLang and Python return on lv. In Julia, the lv is returned empty, like lv = [0.0, 0.0, 0.0., 0.0, 0.0, 0.0]

Restricting function signatures while using ForwardDiff in Julia

I am trying to use ForwardDiff in a library where almost all functions are restricted to only take in Floats. I want to generalise these function signatures so that ForwardDiff can be used while still being restrictive enough so functions only take numeric values and not things like Dates. I have alot of functions with the same name but different types (ie functions that take in "time" as either a float or a Date with the same function name) and do not want to remove the type qualifiers throughout.
Minimal Working Example
using ForwardDiff
x = [1.0, 2.0, 3.0, 4.0 ,5.0]
typeof(x) # Array{Float64,1}
function G(x::Array{Real,1})
return sum(exp.(x))
end
function grad_F(x::Array)
return ForwardDiff.gradient(G, x)
end
G(x) # Method Error
grad_F(x) # Method error
function G(x::Array{Float64,1})
return sum(exp.(x))
end
G(x) # This works
grad_F(x) # This has a method error
function G(x)
return sum(exp.(x))
end
G(x) # This works
grad_F(x) # This works
# But now I cannot restrict the function G to only take numeric arrays and not for instance arrays of Dates.
Is there are a way to restict functions to only take numeric values (Ints and Floats) and whatever dual number structs that ForwardDiff uses but not allow Symbols, Dates, etc.
ForwardDiff.Dual is a subtype of the abstract type Real. The issue you have, however, is that Julia's type parameters are invariant, not covariant. The following, then, returns false.
# check if `Array{Float64, 1}` is a subtype of `Array{Real, 1}`
julia> Array{Float64, 1} <: Array{Real, 1}
false
That makes your function definition
function G(x::Array{Real,1})
return sum(exp.(x))
end
incorrect (not suitable for your use). That's why you get the following error.
julia> G(x)
ERROR: MethodError: no method matching G(::Array{Float64,1})
The correct definition should rather be
function G(x::Array{<:Real,1})
return sum(exp.(x))
end
or if you somehow need an easy access to the concrete element type of the array
function G(x::Array{T,1}) where {T<:Real}
return sum(exp.(x))
end
The same goes for your grad_F function.
You might find it useful to read the relevant section of the Julia documentation for types.
You might also want to type annotate your functions for AbstractArray{<:Real,1} type rather than Array{<:Real, 1} so that your functions can work other types of arrays, like StaticArrays, OffsetArrays etc., without a need for redefinitions.
This would accept any kind of array parameterized by any kind of number:
function foo(xs::AbstractArray{<:Number})
#show typeof(xs)
end
or:
function foo(xs::AbstractArray{T}) where T<:Number
#show typeof(xs)
end
In case you need to refer to the type parameter T inside the body function.
x1 = [1.0, 2.0, 3.0, 4.0 ,5.0]
x2 = [1, 2, 3,4, 5]
x3 = 1:5
x4 = 1.0:5.0
x5 = [1//2, 1//4, 1//8]
xss = [x1, x2, x3, x4, x5]
function foo(xs::AbstractArray{T}) where T<:Number
#show xs typeof(xs) T
println()
end
for xs in xss
foo(xs)
end
Outputs:
xs = [1.0, 2.0, 3.0, 4.0, 5.0]
typeof(xs) = Array{Float64,1}
T = Float64
xs = [1, 2, 3, 4, 5]
typeof(xs) = Array{Int64,1}
T = Int64
xs = 1:5
typeof(xs) = UnitRange{Int64}
T = Int64
xs = 1.0:1.0:5.0
typeof(xs) = StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}
T = Float64
xs = Rational{Int64}[1//2, 1//4, 1//8]
typeof(xs) = Array{Rational{Int64},1}
T = Rational{Int64}
You can run the example code here: https://repl.it/#SalchiPapa/Restricting-function-signatures-in-Julia

Julia: LoadError: MethodError: `call` has no method matching call(::Array{Float64,1}, ::Int64)

I want to use Julia to calculate the Euclidean distance between points (x(i), y(i)) and (x(j),y(j)), and I use the following codes
C = zeros(Float64,10,10)
x = [0.0, 20.0, 18.0, 30.0, 35.0, 33.0, 5.0, 5.0, 11.0, 2.0]
y = [0.0, 20.0, 10.0 ,12.0 ,0.0 ,25.0 ,27.0 ,10.0 ,0.0 ,15.0]
Required = [10.0, 6.0 ,8.0 ,11.0 ,9.0 ,7.0 ,15.0 ,7.0 ,9.0 ,12.0]
Present = [8.0, 13.0, 4.0, 8.0, 12.0, 2.0, 14.0, 11.0, 15.0, 7.0]
for i in 1:10
for j in 1:10
C[i,j] = 1.3*sqrt((x(i) - x(j))^2.0 + (y(i) - y(j))^2.0)
end
end
And the Julia gives me the following result
eLoadError: MethodError: `call` has no method matching call(::Array{Float64,1}, ::Int64)
Closest candidates are:
BoundsError()
BoundsError(!Matched::Any...)
DivideError()
...
while loading In[17], in expression starting on line 7
[inlined code] from In[17]:9
in anonymous at no file:0
Can anyone solve my problem? Thanks!
Use x[i] in stead of x(i) etc.
The latter is Matlab syntax, it does not work in Julia.
Rakesh is correct. Additionally, the reason the error message looks like that is that it's possible to overload the f( ... ) function call syntax, so it thinks you're trying to "call" the array and says there is no matching definition of call.

How to print text with a specified RGB value in Julia?

For example, say I want to print text using the following color:
R: 0.5
G: 0.8
B: 0.1
I know about print_with_color() but as far as I know it has to use a Symbol to print, and I do not know how to create one for any arbitrary color, or if that is actually possible.
Possibly:
julia> function print_rgb(r, g, b, t)
print("\e[1m\e[38;2;$r;$g;$b;249m",t)
end
print_rgb (generic function with 1 method)
julia> for i in 0:100
print_rgb(rand(0:255), rand(0:255), rand(0:255), "hello!")
end
You might try Crayons.jl. Your specification is float, and Crayons expects specification of 0-255, so some conversion is necessary:
julia> import Pkg; Pkg.add("Crayons")
julia> using Crayons
julia> a = (0.5, 0.8, 0.1)
(0.5, 0.8, 0.1)
julia> b = round.(Int, a .* 255)
(128, 204, 26)
julia> print(Crayon(foreground = b) , "My color string.")
Crayons.jl also supports hex RGB specification in string macros:
julia> print(crayon"#80cc1a", "My color string.")
You might try 'printstyled' from 'Base' package, it require at least julia 1.7.
printstyled("pouet pouet"; color = :blue, blink = true)

Resources