2016-01-20 9 views
6

Próbuję przepisać funkcję optymalizacji Matlab fmincon w Julia.Optymalizacja Matlab do Julii: funkcja w JuMP @ SetNLObjective

Oto kod Matlab:

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 

i tu jest mój kod Julia:

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)) 

optymalizacja Julia pracuje kiedy jawnie zdefiniować funkcję celu w @setNLObjective jednak ten nie nadaje się jako dane wejściowe użytkownika mogą się zmienić, co skutkuje inną funkcją celu, którą można zobaczyć na podstawie sposobu tworzenia funkcji celu.

Problem wydaje się być ograniczenie skakać w jaki sposób funkcja celu może być wpisana do @setNLObjective argumentu:

Wszystkie wyrażenia muszą być proste operacje skalarne. Nie można używać produktów dot, matrix-vector, plasterków wektorowych itp. Przetłumacz operacje wektorowe na jawne operacje sum {}.

Czy istnieje sposób obejścia tego? Czy są jakieś inne pakiety w Julii, które rozwiązują to, mając na uwadze, że nie będę miał jacobian ani hessian.

Wielkie dzięki.

+2

Pakiet 'NLopt' nie ma tego ograniczenia. Możesz przekazać dowolną funkcję lub funkcję anonimową. –

+0

Spojrzałem na NLopt i wygląda na to, co chcę, ale brak przykładów powstrzymuje moje postępy. Czy mógłbyś podać mi prosty przykład używając NLopt? lub nawet moja funkcja w NLopt. Dzięki – kulsuri

+2

zadałem pytanie na temat 'NLopt' tutaj na SO około tydzień temu, który zawiera działający przykład prostego problemu. [Tutaj] (http://stackoverflow.com/questions/34755612/nexpected-behaviour-of-ftol-abs-and-ftol-rel-in-nlopt) jest linkiem. Upewnij się, że działasz na komputerze, a jeśli nadal masz problemy, wróć do mnie tutaj, a ja zobaczę, czy mogę zapewnić dodatkową pomoc. –

Odpowiedz

4

Przykład pracy kodu Matlab przy użyciu pakietu optymalizacji Julia i NLopt.

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])