如何在Elizia中使用带有equality_constraint的NLopt

问题描述 投票:1回答:1

我正在努力修改Julia-specific tutorial on NLopt以满足我的需求,如果有人能解释我做错了什么或者不理解,我将不胜感激。

我希望:

  • 最小化某些目标函数myfunc(x)的值;哪里
  • x必须位于单元超立方体中(下例中仅为2维);和
  • x元素的总和必须是1。

下面我让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

我已经阅读了this similar question和文档herehere,但仍然无法弄清楚出了什么问题。令人担忧的是,每次我运行testNLopt时,我都会看到不同的行为,as in this screenshot包括解算器多次无用地评估myfunc([NaN,NaN])的情况。

julia nlopt
1个回答
1
投票

当你在评论中写道时,你实际上并没有就地写入grad参数;

grad = 2 .* (x .- origin)

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

grad .= 2 .* (x .- origin)

等等。你可以阅读有关herehere的行为。

© www.soinside.com 2019 - 2024. All rights reserved.