不是单独定义一个 objective 函数、梯度和 hessian 函数,你可以只定义一个函数 return 吗?

Instead of defining an objective function, gradient, and hessian function seperatley, can you have one function return all?

在 JuMP 中有没有一种方法可以定义一个 returns 函数,例如一个包含 objective 函数和梯度的元组,您可以将其传递给寄存器?

在文档中:https://jump.dev/JuMP.jl/stable/manual/nlp/#Register-a-function-and-gradient

我知道你可以做到这一点

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))

即单独定义函数。在我的上下文中,我正在解决一个最优控制问题,在这个问题中,我可以一次获得 objective 和梯度。有没有一种方法,当我设置 autodiff=false 时,我可以只创建一个 returns objective 和梯度的函数并进行基于梯度的优化,或者 returns 所有三个都进行基于 hessian 的优化根据我的需要?

另外,像 nabla 和 nabla 平方这样的符号是如何制作的?您需要使用特殊的编辑器吗?

您可以将这些函数作为 lambda 元组,例如:

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

现在您可以注册为

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

或者你可以直接做:

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

但是,如您所见,唯一的结果是代码可读性降低。

关于 lambdas - 在 Julia 中(IDE 例如 VS Code、Jupyter、REPL)任何 unicode 字符都可以使用 LaTex 表示法并按 Tab 键输入,试试:

\Delta   <PRESS TAB>

\nabla <PRESS TAB>

\^2 <PRESS TAB>

使用闭包:

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