2016-01-20 15 views
6

Sto tentando di riscrivere una funzione di ottimizzazione fmincon di Matlab in Julia.Ottimizzazione da Matlab a Julia: funzione in JuMP @SetNLObjective

Ecco il codice 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 

e qui è il mio codice Giulia:

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 ottimizzazione funziona quando definisco esplicitamente la funzione obiettivo in @setNLObjective tuttavia questo non è adatto come il l'input dell'utente può cambiare risultando in una funzione obiettivo diversa, che puoi vedere da come viene creata la funzione obiettivo.

Il problema sembra essere la limitazione di salto nel modo in cui la funzione obiettivo può essere inserito nella discussione @setNLObjective:

Tutte le espressioni devono essere semplici operazioni scalari. Non è possibile utilizzare i prodotti a punti, a matrice vettoriale, le sezioni vettoriali, ecc. Tradurre le operazioni vettoriali in operazioni esplicite di somma {}.

C'è un modo per aggirare questo? O ci sono altri pacchetti in Julia che risolvono questo, tenendo presente che non avrò il jacobian o hessian.

Molte grazie.

+2

Il pacchetto 'NLopt' non ha questa limitazione. Puoi passare a qualsiasi funzione o funzione anonima. –

+0

Ho dato un'occhiata a NLopt e sembra essere quello che sto cercando, ma la mancanza di esempi sta fermando i miei progressi. Potresti darmi un esempio semplice usando NLopt? o anche la mia funzione in NLopt. Grazie – kulsuri

+2

Ho fatto una domanda su 'NLopt' qui su SO circa una settimana fa che includeva un esempio funzionante di un problema semplice. [Qui] (http://stackoverflow.com/questions/34755612/unexpected-behaviour-of-ftol-abs-and-ftol-rel-in-nlopt) è il collegamento. Assicurati di averlo funzionante sulla tua macchina, quindi se hai ancora problemi, torna da me qui e vedrò se posso fornire ulteriore aiuto. –

risposta

4

Esempio di funzionamento del codice Matlab utilizzando il pacchetto di ottimizzazione Julia e 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])