# Functor usage for Optim.jl

**URL:** <https://discourse.julialang.org/t/functor-usage-for-optim-jl/45778>\
**Category:** General Usage\
**Tags:** question, optim, functors\
**Created:** [August 30, 2020, 3:12am UTC](https://discourse.julialang.org/t/functor-usage-for-optim-jl/45778 "2020-08-30T03:12:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![stevengogogo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengogogo/32/11947_2.png) [@stevengogogo](https://discourse.julialang.org/u/stevengogogo)\
**Post date:** [August 30, 2020, 3:12am UTC](https://discourse.julialang.org/t/functor-usage-for-optim-jl/45778/1 "2020-08-30T03:12:51Z")

</div>

Dear Community,

I got a question about **functor** usage with Optim.jl.

I’m currently writing a Julian package for biological modeling. To organize parameters of the biological process, I chose function-like object (functor) for development. However, I found functor type is somehow not supported with Optim.jl though it belongs to `Any` type and works like function.

Here is my sample code of Optim.optimize with the input of functor type. I got **MethodError** due to using the functor type with Optim.jl.

Is there a reason why functor can not work like a function in this situation?

## Code

```julia

# Code for finding the minimum of y-function within (0.1,0.2)
using Optim
using Test

struct y
    p
end

function (s::y)(x)
    return x*s.p
end

model = y(1.0)
model2(x;p=1.0) = x*p

@show model(2.0)
@show model2(2.0)

@test typeof(y) <: Any # Because Optim.jl accepts :Any object

Optim.optimize(model, 0.1, 0.2); # MethodError
Optim.optimize(model2, 0.1, 0.2); # Pass

```

## REPL result

However, it seems like functor is not supported in Optim.jl

```sh
julia> using Optim

julia> using Test

julia> struct y
           p
       end

julia> function (s::y)(x)
           return x*s.p
       end

julia> model = y(1.0)
y(1.0)

julia> model2(x;p=1.0) = x*p
model2 (generic function with 1 method)

julia> @show model(2.0)
model(2.0) = 2.0
2.0

julia> @show model2(2.0)
model2(2.0) = 2.0
2.0

julia> @test typeof(y) <: Any # Because Optim.jl accepts :Any object
Test Passed

julia> Optim.optimize(model, 0.1, 0.2);
ERROR: MethodError: no method matching optimize(::y, ::Float64, ::Float64)
Closest candidates are:
  optimize(::Any, ::Number, ::Number, ::AbstractArray{T,N} where N; kwargs...) where T at /Users/stevenchiu/.julia/packages/Optim/TNmSw/src/multivariate/solvers/constrained/fminbox.jl:156
  optimize(::Any, ::Number, ::Number, ::AbstractArray{T,N} where N, ::Optim.AbstractConstrainedOptimizer) where T at /Users/stevenchiu/.julia/packages/Optim/TNmSw/src/multivariate/solvers/constrained/fminbox.jl:160
  optimize(::Any, ::Number, ::Number, ::AbstractArray{T,N} where N, ::Optim.AbstractConstrainedOptimizer, ::Optim.Options; kwargs...) where T at /Users/stevenchiu/.julia/packages/Optim/TNmSw/src/multivariate/solvers/constrained/fminbox.jl:160
  ...
Stacktrace:
 [1] top-level scope at none:1

julia> Optim.optimize(model2, 0.1, 0.2);

julia> 

```

Thank you for reading this question.

---

<div class="post-metadata">

**Author:** ![liuyxpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/liuyxpp/32/9870_2.png) [@liuyxpp](https://discourse.julialang.org/u/liuyxpp)\
**Post date:** [August 30, 2020, 3:58am UTC](https://discourse.julialang.org/t/functor-usage-for-optim-jl/45778/2 "2020-08-30T03:58:03Z")

</div>

I wonder if this fits your purpose

```julia
# using anonymous function
Optim.optimize(x->model(x), 0.1, 0.2)

# or
m = x -> model(x)
Optim.optimize(m, 0.1, 0.2)

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 30, 2020, 5:33am UTC](https://discourse.julialang.org/t/functor-usage-for-optim-jl/45778/3 "2020-08-30T05:33:58Z")

</div>

It looks like that the multivariate interface does not restrict to `Function`, but the univariate one does. See

[https://github.com/JuliaNLSolvers/Optim.jl/blob/431a5f97f814f9df17b24fe429fcc7b9af3c9577/src/univariate/optimize/interface.jl#L2](https://github.com/JuliaNLSolvers/Optim.jl/blob/431a5f97f814f9df17b24fe429fcc7b9af3c9577/src/univariate/optimize/interface.jl#L2)

I don’t think this is necessary — please check if there is an existing issue and open one if there isn’t. In the meantime, @liuyxpp’s workaround using a closure should help.

---

<div class="post-metadata">

**Author:** ![pkofod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pkofod/32/2179_2.png) [@pkofod](https://discourse.julialang.org/u/pkofod)\
**Post date:** [August 30, 2020, 5:36am UTC](https://discourse.julialang.org/t/functor-usage-for-optim-jl/45778/4 "2020-08-30T05:36:28Z")

</div>

Yeah that’s not intended, it should have been removed a long time ago. I’ll remove it. You can you the solution above until I tag a new version. Thanks for bringing this up

---

<div class="post-metadata">

**Author:** ![stevengogogo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengogogo/32/11947_2.png) [@stevengogogo](https://discourse.julialang.org/u/stevengogogo)\
**Post date:** [August 31, 2020, 3:32pm UTC](https://discourse.julialang.org/t/functor-usage-for-optim-jl/45778/5 "2020-08-31T15:32:07Z")

</div>

This solved my question. The functor type is not supported in univariate analysis of Optim.jl  
I’ve extended my functor to multivariate input, and it works with Optim.jl now.  
Here is my code:

```julia
using Optim

"Model parameter"
struct y
  p
end

"Univariable Functor"
function (s::y)(x)
  return x*s.p
end

"Multivariable Functor with array input"
function (s::y)(x_v)
  return x_v[1]*s.p
end

model = y(1.0)

Optim.optimize(model, -1, 2, [1.]) #PASS
Optim.optimize(model, -1, 2, 1.) #ERROR

```

## REPL output

```sh
julia> using Optim

julia> "Model parameter"
       struct y
         p
       end
y

julia> "Univariable Functor"
       function (s::y)(x)
         return x*s.p
       end
y

julia> "Multivariable Functor with array input"
       function (s::y)(x_v)
         return x_v[1]*s.p
       end
y

julia> model = y(1.0);

julia> Optim.optimize(model, -1, 2, [1.]); #PASS

julia> Optim.optimize(model, -1, 2, 1.); #ERROR
ERROR: MethodError: no method matching optimize(::y, ::Int64, ::Int64, ::Float64)
Closest candidates are:
  optimize(::Any, ::Any, ::Number, ::Number, ::AbstractArray{T,N} where N, ::Optim.Options; kwargs...) where T at /Users/stevenchiu/.julia/packages/Optim/TNmSw/src/multivariate/solvers/constrained/fminbox.jl:164
  optimize(::Any, ::Number, ::Number, ::AbstractArray{T,N} where N; kwargs...) where T at /Users/stevenchiu/.julia/packages/Optim/TNmSw/src/multivariate/solvers/constrained/fminbox.jl:156
  optimize(::Any, ::Number, ::Number, ::AbstractArray{T,N} where N, ::Optim.AbstractConstrainedOptimizer) where T at /Users/stevenchiu/.julia/packages/Optim/TNmSw/src/multivariate/solvers/constrained/fminbox.jl:160
  ...
Stacktrace:
 [1] top-level scope at none:1

julia> 

```

Thank you! @Tamas_Papp and @liuyxpp
