如何在具有等式约束的Julia中使用NLopt

如何在具有等式约束的Julia中使用NLopt,julia,nlopt,Julia,Nlopt,我正在努力修改这本书以满足我的需要,如果有人能解释我做错了什么或不理解什么,我将不胜感激 我希望: 最小化某些目标函数的值myfunc(x);在哪里 x必须位于单位超立方体中(在下面的示例中只有2维);及 x的元素之和必须为一 下面我将myfunc变得非常简单-从x到[2.0,0.0]的距离的平方,因此问题的明显正确解决方案是x=[1.0,0.0],其中myfunc(x)=1.0。我还添加了println语句,以便查看解算器正在执行的操作 testNLopt = function()

我正在努力修改这本书以满足我的需要,如果有人能解释我做错了什么或不理解什么,我将不胜感激

我希望:

  • 最小化某些目标函数的值
    myfunc(x)
    ;在哪里
  • x
    必须位于单位超立方体中(在下面的示例中只有2维);及
  • x
    的元素之和必须为一
下面我将
myfunc
变得非常简单-从
x
[2.0,0.0]
的距离的平方,因此问题的明显正确解决方案是
x=[1.0,0.0]
,其中
myfunc(x)=1.0
。我还添加了
println
语句,以便查看解算器正在执行的操作

testNLopt = function()

    origin = [2.0,0.0]
    n = length(origin)

    #Returns square of the distance between x and "origin", and amends grad in-place
    myfunc = function(x::Vector{Float64}, grad::Vector{Float64})
        if length(grad) > 0 
            grad = 2 .* (x .- origin)
        end
        xOut = sum((x .- origin).^2)
        println("myfunc: x = $x; myfunc(x) = $xOut; ∂myfunc/∂x = $grad")
        return(xOut)
    end

    #Constrain the sums of the x's to be 1...
    sumconstraint =function(x::Vector{Float64}, grad::Vector{Float64})
        if length(grad) > 0
            grad = ones(length(x)) 
        end
        xOut = sum(x) - 1
        println("sumconstraint: x = $x; constraint = $xOut; ∂constraint/∂x = $grad")
        return(xOut)
    end

    opt = Opt(:LD_SLSQP,n)

    lower_bounds!(opt, zeros(n))
    upper_bounds!(opt,ones(n))
    equality_constraint!(opt,sumconstraint,0)
    #xtol_rel!(opt,1e-4)
    xtol_abs!(opt,1e-8)

    min_objective!(opt, myfunc)
    maxeval!(opt,20)#to ensure code always terminates, remove this line when code working correctly?
    optimize(opt,ones(n)./n)
end

我已经阅读了相关的文档和资料,但仍然无法找出问题所在。令人担忧的是,每次我运行
testNLopt
时,我都会看到不同的行为,包括求解器多次无效地计算
myfunc([NaN,NaN])

在注释中写入时,您实际上并没有写入到位的
grad
参数

grad = 2 .* (x .- origin)
只覆盖局部变量,而不是数组内容——我想这就是为什么到处都可以看到这些
df/dx=[NaN,NaN]
。解决这个问题的最简单方法是广播分配(注意点):


等等。你可以读到关于这种行为的信息。

我没有答案,但是
grad
在这里没有改变。你必须使用
=
来实现这一点。太好了!使用
=
在两个函数
myfunc
sumconstraint
中指定grad,修复了我发布的示例以及我正在处理的更复杂的实际问题。非常感谢。这就是问题的实际解决方案?是的。我是否需要以某种方式将问题标记为已回答?我将发布一个答案,这被认为比在评论中留下这个更好。然后,您可以将答案标记为已接受(一段时间后,当系统允许时)。谢谢你的关心!
grad .= 2 .* (x .- origin)