2016-01-20 10 views
6

Ich versuche, eine Matlab Fmincon Optimierung Funktion in Julia neu zu schreiben.Matlab zu Julia Optimierung: Funktion in JuMP @SetNLObjective

Hier ist der Matlab-Code:

function [x,fval] = example3() 

    x0 = [0; 0; 0; 0; 0; 0; 0; 0]; 
    A = [];       
    b = []; 
    Ae = [1000 1000 1000 1000 -1000 -1000 -1000 -1000]; 
    be = [100];      
    lb = [0; 0; 0; 0; 0; 0; 0; 0]; 
    ub = [1; 1; 1; 1; 1; 1; 1; 1]; 
    noncon = [];     

    options = optimset('fmincon'); 
    options.Algorithm = 'interior-point'; 

    [x,fval] = fmincon(@objfcn,x0,A,b,Ae,be,lb,ub,@noncon,options); 

end 

function f = objfcn(x) 

    % user inputs 
    Cr = [ 0.0064 0.00408 0.00192 0; 
     0.00408 0.0289 0.0204 0.0119; 
     0.00192 0.0204 0.0576 0.0336; 
     0 0.0119 0.0336 0.1225 ]; 

    w0 = [ 0.3; 0.3; 0.2; 0.1 ]; 
    Er = [0.05; 0.1; 0.12; 0.18]; 

    % calculate objective function 
    w = w0+x(1:4)-x(5:8); 
    Er_p = w'*Er; 
    Sr_p = sqrt(w'*Cr*w); 

    % f = objective function 
    f = -Er_p/Sr_p; 

end 

und hier ist meine Julia Code:

using JuMP 
using Ipopt 

m = Model(solver=IpoptSolver()) 

# INPUT DATA 
w0 = [ 0.3; 0.3; 0.2; 0.1 ] 
Er = [0.05; 0.1; 0.12; 0.18] 
Cr = [ 0.0064 0.00408 0.00192 0; 
    0.00408 0.0289 0.0204 0.0119; 
    0.00192 0.0204 0.0576 0.0336; 
    0 0.0119 0.0336 0.1225 ] 

# VARIABLES 
@defVar(m, 0 <= x[i=1:8] <= 1, start = 0.0) 
@defNLExpr(w, w0+x[1:4]-x[5:8]) 
@defNLExpr(Er_p, w'*Er) 
@defNLExpr(Sr_p, w'*Cr*w) 
@defNLExpr(f, Er_p/Sr_p) 

# OBJECTIVE 
@setNLObjective(m, Min, f) 

# CONSTRAINTS 
@addConstraint(m, 1000*x[1] + 1000*x[2] + 1000*x[3] + 1000*x[4] - 
1000*x[5] - 1000*x[6] - 1000*x[7] - 1000*x[8] == 100) 

# SOLVE 
status = solve(m) 

# DISPLAY RESULTS 
println("x = ", round(getValue(x),4)) 
println("f = ", round(getObjectiveValue(m),4)) 

Julia Optimierung funktioniert, wenn ich die Zielfunktion in @setNLObjective explizit definieren dies ist jedoch ungeeignet, da die Die Benutzereingabe kann sich ändern, was zu einer anderen Zielfunktion führt, die Sie an der Erstellung der Zielfunktion erkennen können.

Das Problem scheint JuMP die Beschränkung, wie die Zielfunktion zu sein, kann im @setNLObjective Argument eingegeben werden:

Alle Ausdrücke einfache skalare Operationen sein. Sie können Punkt-, Matrix-Vektor-Produkte, Vektor-Slices usw. nicht verwenden. Übersetzen Sie Vektoroperationen in explizite sum {} -Operationen.

Gibt es einen Weg um dies? Oder gibt es noch andere Pakete in Julia, die dies lösen, wenn ich bedenke, dass ich weder Jacobi noch Hessian haben werde.

Vielen Dank.

+2

Das Paket 'NLopt' hat diese Einschränkung nicht. Sie können jede Funktion oder anonyme Funktion übergeben. –

+0

Ich habe mir NLopt angeschaut und es sieht so aus, als ob ich es möchte, aber der Mangel an Beispielen hält meinen Fortschritt auf. Könnten Sie mir vielleicht ein einfaches Beispiel mit NLopt geben? oder sogar meine Funktion in NLopt. Danke – kulsuri

+2

Ich habe eine Frage über 'NLopt' hier auf SO vor etwa einer Woche gestellt, die ein Arbeitsbeispiel für ein einfaches Problem enthielt. [Hier] (http://stackoverflow.com/questions/34755612/unexpected-behaviou-of-ftol-abs-and-ftol-rel-in-nlopt) ist der Link. Stellen Sie sicher, dass Sie mit Ihrem Gerät arbeiten, und wenn Sie immer noch Probleme haben, wenden Sie sich an mich und ich werde sehen, ob ich Ihnen weitere Hilfe anbieten kann. –

Antwort

4

Beispiel für den Matlab-Code mit Julia und NLopt Optimierungspaket.

using NLopt 

function objective_function(x::Vector{Float64}, grad::Vector{Float64}) 

    w0 = [ 0.3; 0.3; 0.2; 0.1 ] 
    Er = [0.05; 0.1; 0.12; 0.18] 
    Cr = [ 0.0064 0.00408 0.00192 0; 
      0.00408 0.0289 0.0204 0.0119; 
      0.00192 0.0204 0.0576 0.0336; 
      0 0.0119 0.0336 0.1225 ] 

    w = w0 + x[1:4] - x[5:8] 

    Er_p = w' * Er 

    Sr_p = sqrt(w' * Cr * w) 

    f = -Er_p/Sr_p 

    obj_func_value = f[1] 

    return(obj_func_value) 
end 

function constraint_function(x::Vector, grad::Vector) 

    constraintValue = 1000*x[1] + 1000*x[2] + 1000*x[3] + 1000*x[4] - 
1000*x[5] - 1000*x[6] - 1000*x[7] - 1000*x[8] - 100   

return constraintValue 
end 

opt1 = Opt(:LN_COBYLA, 8) 

lower_bounds!(opt1, [0, 0, 0, 0, 0, 0, 0, 0]) 
upper_bounds!(opt1, [1, 1, 1, 1, 1, 1, 1, 1]) 

#ftol_rel!(opt1, 0.5) 
#ftol_abs!(opt1, 0.5) 

min_objective!(opt1, objective_function) 
equality_constraint!(opt1, constraint_function) 

(fObjOpt, xOpt, flag) = optimize(opt1, [0, 0, 0, 0, 0, 0, 0, 0])