La función "fmincon" se utiliza para resolver problemas de este tipo:
calcular x, minimizando fun(x)
sujeto a las siguientes restricciones:
calcular x, minimizando fun(x)
sujeto a las siguientes restricciones:
- g(x) <= 0
- geq(x) = 0
- A·x - B <= 0
- C·x - D = 0
- xmin <= x <= xmax
Dicha función se utiliza de las siguientes maneras:
- fmincon(@(x) fun(x), x0, A,B)
- fmincon(@(x) fun(x), x0, A,B,C,D,xmin,xmax)
- fmincon(@(x) fun(x), x0, A,B,C,D,xmin,xmax,@(x) funrest(x))
donde:
- x0 es el valor inicial a partir del que Matlab empieza a tantear.
- Si uno de los parámetros no existe, se pone [].
- fun(x) es la función a optimizar, y devuelve un escalar.
- las restricciones lineales se añaden con las matrices A, B, C y D.
- las restricciones no lineales se escriben dentro de una función ("funrest(x)"), que devuelve dos dos vectores, g(x) y geq(x). (El tamaño de los dos vectores corresponde con el número de restricciones de tipo "menor o igual que" e "igual que".)
Por ejemplo, queremos optimizar la función de Rosenbrock siguiente:
z = (1-x)2 + 2·(y-x2)2
teniendo en cuenta las siguientes restricciones lineales:
z = (1-x)2 + 2·(y-x2)2
teniendo en cuenta las siguientes restricciones lineales:
- y + x -1 <= 0
- -y -1/3·x - 2/3 <= 0
y las siguientes restricciones no lineales:
- y + 0.94·x2 - 0.14·x -3 <= 0
- -y +0.143·x2 - 1.03 <= 0
Primero, creamos el fichero "f01.m" con la función a minimizar:
function z = f01(u)
x = u(1);
y = u(2);
z = (1-x).^2 + 2*(y-x.^2).^2;
A continuación, creamos el fichero "frest01.m" con las restricciones no lineales.
function [z zz] = fc01(x)
z(1) = x(2)+0.9375*x(1).^2-0.125*x(1)-3;
z(2) = -x(2)+0.1333*x(1).^2-1.0333;
zz = [];
En este caso, "z" son las restricciones de tipo "menor o igual que", mientras que "zz" son las restricciones de tipo "igual que". Como en este ejemplo, no hay restricciones del segundo tipo, la salida de "zz" es el conjunto vacío.
El mínimo de la función de Rosenbrock está en (1,1). En la siguiente figura se pueden ver las isolíneas de dicha función.
Para representar la anterior figura, lo hice con las siguientes líneas:
x = [-2:0.1:2];
y = [-1:0.1:3];
nx = length(x);
ny = length(y);
[X,Y] = meshgrid(x,y);
Z = zeros(nx,ny);
for i=1:1:nx
for j=1:1:ny
Z(i,j) = f01([X(i,j),Y(i,j)]);
end
end
[u,f] = fminsearch(@(u) f01(u),[0 0]);
figure(1)
hold on
contour(X,Y,Z,[75])
plot(u(1),u(2),'+k')
set(gca,'XTick',[-2:1:2])
set(gca,'YTick',[-1:1:3])
set(gca,'Fontsize',10)
axis([-2 2 -1 3])
box on
A continuación, represento el área permitida a partir de las restricciones del ejemplo. Como se ve, el punto (1,1) está fuera de este área.
Para representar el área permitida, lo hice con las siguientes líneas:
t = linspace(-1.7476,-0.9785,100)';
r = -0.9375*t.^2+0.125*t+3;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
t = linspace(0.8262,1.6639,100)';
r = 0.1333*t.^2-1.0333;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
t = linspace(-0.9785,1.6639,100)';
r = 1-t;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
t = linspace(-1.7476,0.8262,100)';
r = -1/3*t-2/3;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
x(2)+0.9375*x(1).^2-0.125*x(1)-3;
A continuación, resolvemos el problema de optimización con la función "fmincon", como muestro a continuación:
A = [1 1; -1/3 -1];B = [1; 2/3];
[xs,fs] = fmincon(@(u) f01(u), [0,0],A,B,[],[],[],[],@(u) frest01(u))
Matlab devuelve la solución:
xs =
0.6512 0.3488
fs =
0.1330
Finalmente, representamos la solución del problema en el gráfico:
plot(xs(1),xs(2),'o','MarkerSize',10,'Color',[1 0 0],'LineWidth',2)
Por último, vamos a añadir la siguiente restricción de igualdad no lineal.
- y - (0.08·x3 + 0.4·x2 - 0.4·x - 1.2)·(x+2 )-1 = 0
Es decir, la solución debe encontrarse, sobre dicha curva.
t = (-2:0.05:2)';
r = (0.08*t.^3+0.4*t.^2-0.4*t-1.2)./(t+2);
plot(t,r,'-','LineWidth',2,'Color',[1 0 0])
Para ello, lo único que tenemos que hacer es modificar el archivo con las restricciones no lineales ("frest01"), como muestro a continuación:
function [z zz] = frest01(x)
z(1) = x(2)+0.9375*x(1).^2-0.125*x(1)-3;
z(2) = -x(2)+0.1333*x(1).^2-1.0333;
zz = x(2) - (0.08*x(1).^3+0.4*x(1).^2-0.4*x(1)-1.2)./(x(1)+2);
Finalmente, calculamos la nueva solución:
[xs,fs] = fmincon(@(u) f01(u), [0,0],A,B,[],[],[],[],@(u) frest01(u))
plot(xs(1),xs(2),'o','MarkerSize',10,'Color',[0 0 0],'LineWidth',2)
Matlab calcula los siguientes valores:
xs =
0.3428 -0.5493
fs =
1.3212
No hay comentarios:
Publicar un comentario