将MATLAB优化函数转换为julia

时间:2016-01-18 16:49:02

标签: matlab julia nlopt

我正在尝试将Matlab fmincon优化函数转换为julia。 但没有太多运气。

我认为可以使用NLopt或IPopt。 默认示例有效但当我尝试更改值时,它似乎不会迭代。

using NLopt
count = 0 # keep track of # function evaluations
function myfunc(x::Vector, grad::Vector)
    if length(grad) > 0
        grad[1] = 0
        grad[2] = 0.5/sqrt(x[2])
    end
    global count
    count::Int += 1
    println("f_$count($x)")

    sqrt(x[2])
end

function myconstraint(x::Vector, grad::Vector, a, b)
    if length(grad) > 0
        grad[1] = 3a * (a*x[1] + b)^2
        grad[2] = -1
    end
    (a*x[1] + b)^3 - x[2]
end

opt = Opt(:LD_MMA, 2)
lower_bounds!(opt, [-Inf, 0.])
xtol_rel!(opt,1e-4)

min_objective!(opt, myfunc)
inequality_constraint!(opt, (x,g) -> myconstraint(x,g,2,0), 1e-8)
inequality_constraint!(opt, (x,g) -> myconstraint(x,g,-1,1), 1e-8)

(minf,minx,ret) = optimize(opt, [1.234, 5.678])
println("got $minf at $minx after $count iterations (returned $ret)")

这个工作正常。它给出了2个结果和11个迭代

using NLopt
count = 0 # keep track of # function evaluations
function myfunc(x)
    x[1]^2 + 5*x[2] - 3
end
function myconstraint(x)
    100*x[1] + 2000*x[2] == 100
end

opt = Opt(:LD_MMA, 2)
lower_bounds!(opt, [0, 0])
upper_bounds!(opt,[10,5])
xtol_rel!(opt,1e-10)

min_objective!(opt, myfunc);
inequality_constraint!(opt, (x) -> myconstraint(x), 1e-10)

(minf,minx,ret) = optimize(opt, [0.1,0.1])

这不起作用,它只给出一个结果和0次迭代

using NLopt
count = 0 # keep track of # function evaluations
function myfunc(x::Vector, grad::Vector)
    x[1]^2 + 5*x[2] - 3
end
function myconstraint(result::Vector, x::Vector, grad::Vector)
    100*x[1] + 2000*x[2] == 100
end

opt = Opt(:LD_MMA, 2)
lower_bounds!(opt, [0., 0.])
upper_bounds!(opt, [10.,5.])
xtol_rel!(opt,1e-4)

min_objective!(opt, myfunc)
inequality_constraint!(opt, (x,g) -> myconstraint(x), 1e-8)

(minf,minx,ret) = optimize(opt, [0., 0.])#even with [5.,10.]

这只给了我一个结果和0次迭代。

任何人都知道我做错了什么?

1 个答案:

答案 0 :(得分:1)

我很难根据评论马拉松重建你所做的事情,所以相反我想我会提供代码来说明我将如何解决这个问题。请注意,以下代码假定您的不等式约束为100*x[1] + 2000*x[2] <= 100

using NLopt
function myfunc(x::Vector{Float64}, grad::Vector{Float64})
    if length(grad) > 0
        grad[1] = 2 * x[1]
        grad[2] = 5
    end
    xOut = x[1]^2 + 5*x[2] - 3
    println("Obj func = " * string(xOut))
    return(xOut)
end
function myconstraint(x::Vector{Float64}, grad::Vector{Float64})
    if length(grad) > 0
        grad[1] = 100
        grad[2] = 2000
    end
    xOut = 100*x[1] + 2000*x[2] - 100
    println("Constraint val = " * string(xOut))
    return(xOut)
end
opt = Opt(:LD_MMA, 2)
lower_bounds!(opt, [0, 0])
upper_bounds!(opt,[10,5])
xtol_rel!(opt,1e-10)
min_objective!(opt, myfunc);
inequality_constraint!(opt, myconstraint, 1e-10)

(minf,minx,ret) = optimize(opt, [0.1,0.1])

我的代码和你的代码有三个主要区别:

  1. 我已明确包含渐变函数更新。这将使收敛例程对于任何基于梯度的算法(其中MMA是一个)更有效。

  2. 我在每一步都打印出目标函数和约束函数的值。这对于调试目的很有用,并且可以了解幕后发生的事情。

  3. 我在代码中已经非常清楚我的约束函数的返回值是f(x),其中约束由等式f(x) <= 0定义。这是与NLopt一起使用的适当语法。

  4. 您在评论中表示,当您尝试将inequality_constraint!更改为equality_constraint!时,您收到了错误消息。这是因为您选择的算法(MMA)仅支持不等式约束。可以找到NLopt算法的说明here。注意:

      

    只有MMA和SLSQP支持任意非线性不等式约束,只有SLSQP支持非线性等式约束

    因此,将算法切换为:LD_SLSQP,瞧,您现在可以将不等式约束转换为等式约束。