1

Is there a way in JuMP to define a function that returns for example a tuple containing the objective function and the gradient, which you can pass to register?

In the documentation : https://jump.dev/JuMP.jl/stable/manual/nlp/#Register-a-function-and-gradient

I see you can do this

f(x) = x^2
∇f(x) = 2x
∇²f(x) = 2
model = Model()
register(model, :my_square, 1, f, ∇f, ∇²f)
@variable(model, x >= 0)
@NLobjective(model, Min, my_square(x))

i.e define the functions seperatley. In my context I'm solving an optimal control problem where in one fuction I can get the objective and gradient in one go. Is there a way when I set autodiff=false that I can just make a function that returns the objective and gradient and do gradient based optimization, or returns all three to do hessian optimization based on my needs?

Also, how do you make the symbols like the nabla and nabla squared? Do you need to use a special editor?

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Eigenvalue
  • 1,093
  • 1
  • 14
  • 35

2 Answers2

1

You could have those functions as a tuple of lambdas such as:

funcs = ((x) -> x^2, (x) -> 2x, (x) -> 2 )

And now you could register as

register(model, :my_square_2, 1, funcs...)

Or you could directly do:

register(model, :my_square_2, 1, (x) -> x^2, (x) -> 2x, (x) -> 2 )

However, as you can see the only outcome is a reduced code readibility.

Regarding lambdas - in Julia (IDE such as VS Code, Jupyter, REPL) any unicode character can be entered using LaTex notation and pressing tab, try:

\Delta   <PRESS TAB>

or

\nabla <PRESS TAB>

or

\^2 <PRESS TAB>
Przemyslaw Szufel
  • 40,002
  • 3
  • 32
  • 62
0

Use a closure:

julia> function fg()
           last_g = zeros(2)
           last_x = nothing
           last_fx = 0.0
           function update(x...)
               if x != last_x
                   @info "Updating $x"
                   last_fx = x[1]^2 + x[2]^2
                   last_g[1] = 2x[1]
                   last_g[2] = 2x[2]
                   last_x = x
               end
               return
           end
           function f(x...)
               update(x...)
               return last_fx
           end
           function ∇f(g, x...)
               update(x...)
               copy!(g, last_g)
               return
           end
           return f, ∇f
       end
fg (generic function with 1 method)

julia> f, ∇f = fg()
(f, ∇f)

julia> f(1, 2)
[ Info: Updating (1, 2)
5

julia> f(1, 2)
5

julia> f(1, 2)
5

julia> f(1, 3)
[ Info: Updating (1, 3)
10

julia> f(1, 3)
10

julia> g = zeros(2)
2-element Vector{Float64}:
 0.0
 0.0

julia> ∇f(g, 1, 2)
[ Info: Updating (1, 2)

julia> ∇f(g, 1, 2)

julia> f(1, 2)
5

julia> g
2-element Vector{Float64}:
 2.0
 4.0
Oscar Dowson
  • 2,395
  • 1
  • 5
  • 13