不是单独定义一个 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
在 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