jmejia8 / Metaheuristics.jl

High-performance metaheuristics for optimization coded purely in Julia.
https://jmejia8.github.io/Metaheuristics.jl/stable/
Other
255 stars 26 forks source link

Callable objects are not supported by `optimize` #112

Open RoyCCWang opened 3 months ago

RoyCCWang commented 3 months ago

I modified the tutorial to use a callable object.

using Metaheuristics

f(x) = 10length(x) + sum( x.^2 - 10cos.(2π*x) )

struct CostFunc{T}
  a1::T
  a2::T
end

function (A::CostFunc)(x)
  return A.a1*length(x) + sum( x.^2 - A.a2*cos.(2π*x) )
end

f2 = CostFunc(10.0, 10.0)

# limits/bounds
bounds = BoxConstrainedSpace(lb = -5ones(10), ub = 5ones(10))

# information on the minimization problem
information = Information(f_optimum = 0.0)

# generic settings
options = Options(f_calls_limit = 9000*10, f_tol = 1e-5, seed = 5)

# metaheuristic used to optimize
algorithm = ECA(information = information, options = options)

# start the minimization process
#result = optimize(f, bounds, algorithm)
result = optimize(f2, bounds, algorithm)

fx = minimum(result)
x = minimizer(result)

I got:

ERROR: LoadError: MethodError: no method matching optimize(::CostFunc{Float64}, ::BoxConstrainedSpace{Float64}, ::Metaheuristics.Algorithm{ECA})
The function `optimize` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  optimize(::Function, ::Any, ::Metaheuristics.AbstractAlgorithm; logger)
   @ Metaheuristics ~/.julia/packages/Metaheuristics/KyWxd/src/optimize/optimize.jl:42
  optimize(::Function, ::Any, ::Type{T}; logger, kargs...) where T<:Metaheuristics.AbstractParameters
   @ Metaheuristics ~/.julia/packages/Metaheuristics/KyWxd/src/optimize/optimize.jl:137
  optimize(::Function, ::Any; ...)
   @ Metaheuristics ~/.julia/packages/Metaheuristics/KyWxd/src/optimize/optimize.jl:42

Stacktrace:
 [1] top-level scope
   @ ~/Documents/repos/examples/debug.jl:32
 [2] include(fname::String)
   @ Main ./sysimg.jl:38
 [3] top-level scope
   @ REPL[4]:1
in expression starting at /home/roy/Documents/repos/examples/debug.jl:32

The issue is the type annotation ::Function on the first input.

As a work-around, the user can wrap the callable object in an anonymous function, there are strange "boxing" behaviors with them. There are a lot of posts on the Julia Discourse (e.g. this and this). I often don't have time to do timing tests to see if my anonymous functions are fast, so I always explicitly pass callable structs instead of closures when I interface with library functions.

I'm using Metaheuristics v3.3.5. My versioninfo() is

Julia Version 1.11.0-rc1
Commit 3a35aec36d1 (2024-06-25 10:23 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 16 × AMD Ryzen 7 1700 Eight-Core Processor
  WORD_SIZE: 64
  LLVM: libLLVM-16.0.6 (ORCJIT, znver1)
Threads: 1 default, 0 interactive, 1 GC (on 16 virtual cores)