Main Content

Restricciones no lineales con gradientes

Este ejemplo muestra cómo resolver un problema no lineal con restricciones no lineales utilizando información de las derivadas.

Por lo general, las rutinas de minimización utilizan gradientes numéricos calculados por aproximación de diferencias finitas. Este procedimiento perturba sistemáticamente cada variable para calcular las derivadas parciales de la función y la restricción. También puede proporcionar una función para calcular las derivadas parciales analíticamente. Habitualmente, cuando se proporciona información de las derivadas, los solvers trabajan con más precisión y eficiencia.

Función objetivo y restricción no lineal

El problema consiste en resolver

minxf(x)=ex1(4x12+2x22+4x1x2+2x2+1),

sujeto a las restricciones

x1x2-x1-x2-1.5x1x2-10.

Puesto que el solver fmincon espera que las restricciones estén escritas en formato c(x) 0, escriba la función de restricción de forma que devuelva el siguiente valor:

c(x)=[x1x2-x1-x2+1.5-10-x1x2].

Función objetivo con gradiente

La función objetivo es

f(x)=ex1(4x12+2x22+4x1x2+2x2+1).

Calcule el gradiente de f(x) con respecto a las variables x1 y x2.

f(x)=[f(x)+exp(x1)(8x1+4x2)exp(x1)(4x1+4x2+2)].

La función auxiliar objfungrad al final de este ejemplo devuelve tanto la función objetivo f(x) como su gradiente en la segunda salida gradf. Establezca @objfungrad como el objetivo.

fun = @objfungrad;

Función de restricción con gradiente

La función auxiliar confungrad es la función de restricción no lineal; aparece al final de este ejemplo.

En la información de las derivadas para la restricción de desigualdad, cada columna se corresponde con una restricción. En otras palabras, el gradiente de las restricciones tiene el siguiente formato:

[c1x1c2x1c1x2c2x2]=[x2-1-x2x1-1-x1].

Establezca @confungrad como la función de restricción no lineal.

nonlcon = @confungrad;

Establecer opciones para utilizar la información de las derivadas

Indique al solver de fmincon que la función objetivo y la función de restricción proporcionan información de las derivadas. Para hacerlo, use optimoptions para establecer los valores de las opciones SpecifyObjectiveGradient y SpecifyConstraintGradient en true.

options = optimoptions('fmincon',...
    'SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true);

Resolver el problema

Establezca el punto inicial en [-1,1].

x0 = [-1,1];

El problema no tiene límites ni restricciones lineales, así que establezca esos valores de argumento en [].

A = [];
b = [];
Aeq = [];
beq = [];
lb = [];
ub = [];

Llame a fmincon para resolver el problema.

[x,fval] = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)
Local minimum found that satisfies the constraints.

Optimization completed because the objective function is non-decreasing in 
feasible directions, to within the value of the optimality tolerance,
and constraints are satisfied to within the value of the constraint tolerance.
x = 1×2

   -9.5473    1.0474

fval = 0.0236

La solución es la misma que la del ejemplo Restricciones de desigualdad no lineales, que resuelve el problema sin usar información de las derivadas. La ventaja de utilizar derivadas es que para resolver el problema se necesitan menos evaluaciones de funciones al tiempo que se gana robustez, aunque esta ventaja no es obvia en este ejemplo. Utilizar incluso más información de derivadas, como en Algoritmo interior-point de fmincon con matriz hessiana analítica, da incluso más beneficios, como menos iteraciones del solver.

Funciones auxiliares

Este código crea la función auxiliar objfungrad.

function [f,gradf] = objfungrad(x)
f = exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1);
% Gradient of the objective function:
if nargout  > 1
    gradf = [ f + exp(x(1)) * (8*x(1) + 4*x(2)), 
    exp(x(1))*(4*x(1)+4*x(2)+2)];
end
end

Este código crea la función auxiliar confungrad.

function [c,ceq,DC,DCeq] = confungrad(x)
c(1) = 1.5 + x(1) * x(2) - x(1) - x(2); % Inequality constraints
c(2) = -x(1) * x(2)-10; 
% No nonlinear equality constraints
ceq=[];
% Gradient of the constraints:
if nargout > 2
    DC= [x(2)-1, -x(2);
        x(1)-1, -x(1)];
    DCeq = [];
end
end

Temas relacionados