7. Optimización de funciones Se describen aquí algunos algoritmos básicos de optimización de funciones. 7.1. Método Simplex El procedimiento se debe a Nelder y Mead. Se trata de un algoritmo simple (de ahí su nombre) que sólo requiere la evaluación de la función y no de sus derivadas. Esto le confiere diversas características. En principio es un buen método cuando la función a optimizar no es derivable (funciones de argumentos enteros, por ejemplo) o cuando la derivada no es calculable (o de cálculo muy costoso). Para una función analítica el método no es de los más eficientes pero permite obtener una respuesta al problema planteado. El procedimiento también se utiliza en el diseño de experimentos: cuando las variables son parámetros experimentales, se va evaluando la función objetivo a medida que el procedimiento va requiriendo la evaluación de la función en diversos puntos. Un simplex es una figura poliédrica de n+1 vértices inmersa en un espacio de dimensión n. Así, por ejemplo, en el plano un triángulo es un simples y en el espacio tridimensional lo es un tetraedro. Estas figuras, en general, no tienen porque ser regulares. Los simplex que se deben considerar son los que tienen área, volumen o hipervolumen no nulos. Supondremos que queremos encontrar un máximo de la función. A continuación se va a exponer el algoritmo de forma sucinta y simple. Más información se puede encontrar en el libro de Press et al. Algoritmo básico simplex para encontrar un punto óptimo (en este caso el máximo) de una función f(x) de n variables: 1. Considerar n+1 puntos del espacio n dimensional. En todos ellos se evalúa la función f. Estos puntos deben generar un hipervolumen no nulo. Ello se puede comprobar viendo como el determinante de la matriz formada por los n-1 vectores posición de cada punto respecto a uno de ellos que se toma como origen no es nulo. 2. Del conjunto de puntos, se considera el punto asociado al valor mínimo de f: Este peor punto se debe sustituir por otro nuevo. La forma habitual de hacerlo es considerar el centro de masas de los restantes n puntos y hacer una reflexión del peor punto a través de ese centro de masas. En esa reflexión el punto ha “recorrido” una distancia 2d (siendo d la distancia inicial entre el punto y el centro de masas). Se evalua la función en el nuevo punto obtenido. 2.1. Si el valor de f es mayor que el del mejor punto, se prueba de nuevo la reflexión pero avanzando un paso 3d (expansión). Se elige la opción que nos de el mejor nuevo punto. Pasar a 3. 7-1 2.2. Si el nuevo punto tiene un valor peor (menor) que el del segundo peor punto, se hace una reflexión con un paso igual a 1.5d (contracción) 2.2.1. Si se continúa obteniendo un valor menor que el del segundo peor punto se hace una contracción del simplex (homotecia) con un factor de 0.5 manteniendo el mejor punto. Se evalúa la función en los nuevos puntos así obtenidos. Se pasa a 2. 2.2.2. Se pasa a 3. 2.3. Se acepta el nuevo punto calculado en 2. 3. Aplicar el criterio de convergencia: Si la distancia d recorrida es menor que un cierto valor predeterminado (figura simplex muy diminuta), se acaba el proceso. En caso contrario se pasa a 2. 7.2. Método de gradiente de Newton El método de gradiente o de Newton-Raphson es un método analítico básico y bastante eficiente. El método se basa en expandir una función de n variables x=(x1,x2,...,xn), f(x), en un punto x0 en serie de Taylor truncada hasta los términos de primer orden: f (x ) ≈ f (x 0 ) + [∇f (x 0 )] (x − x 0 ) . T En esta notación, el vector gradiente evaluado en el punto x0 es ∂f (x ) ∂x 1 ∂f (x ) ∇f (x 0 ) = ∂x . 1 M ∂f (x ) ∂x n x =x0 Considerando que el punto x0 no es estacionario (máximo o mínimo) mientras que el punto x sí que lo es y está lo suficientemente próximo a x0 (tanto como para que la aproximación de hasta primer orden sea suficientemente precisa) entonces podemos plantear que ∇f ( x ) = 0 y { } 0 = ∇f (x ) ≈ ∇ f (x 0 ) + [∇f (x 0 )] (x − x 0 ) , T con lo cual 0 = ∇f (x 0 ) + ∇[∇f (x 0 )] (x − x 0 ) , T 7-2 El gradiente del vector gradiente es la matriz hesiana, la cual contiene todas las segundas derivadas evaluadas en el punto x0: ∂ 2 f (x ) ∂x 1∂x 1 ∂ 2 f (x ) ∇[∇f (x 0 )] = H (x 0 ) = ∂x ∂x 2 1 M ∂ 2 f (x ) ∂x n ∂x 1 ∂ 2 f (x ) ∂x 1∂x 2 ∂ 2 f (x ) ∂x 2 ∂x 2 M ∂ 2 f (x ) ∂x n ∂x 2 ∂ 2 f (x ) ∂x 1∂x n ∂ 2 f (x ) L . ∂x 2 ∂x n O M ∂ 2 f (x ) L ∂x n ∂x n x = x 0 L Para una función analítica que se comporte bien, la matriz hesiana es simétrica: ∂ 2 f (x ) ∂ 2 f (x ) = ∀ i, j. ∂x i ∂x j ∂x j ∂x i Continuando, escribimos 0 = ∇f (x 0 ) + H (x 0 )(x − x 0 ) y podemos despejar cual es el punto x: x = x 0 − [H (x 0 )] ∇f (x 0 ) . −1 Hemos de suponer que el punto x así calculado, si no es ya un punto estacionario, nos da una mejor aproximación al punto óptimo de la función de lo que era el punto x0. El método requiere la inversión de una matriz. En algunas ocasiones esta matriz se puede simplificar considerando sólo los elementos diagonales. De esta manera su inversión es inmediata. Así pues, el algoritmo iterativo consiste en lo siguiente: 1. Considerar la tolerancia del proceso 0<ε→0. 2. Considerar un punto inicial x0. 3. Evaluar el vector gradiente g= ∇f (x 0 ) . 4. 5. 6. 7. Si | g |<ε, el punto óptimo es x0. Terminar. −1 Evaluar x = x 0 − [H (x 0 )] ∇f (x 0 ) . Redefinir x0=x. Ir al paso 3. 7-3 Ejercicios 1. Considerar la función f(x,y)=x2+xy+y2. Partiendo del punto (1,1), aplicar numéricamente el algoritmo de Newton. Comprobar que se llega al punto del máximo (0,0) en un solo paso. ¿Por qué? 2. Confeccionar programas que codifiquen los algoritmos aquí descritos. 3. Utilizando los algoritmos descritos aquí y partiendo de un punto (o puntos) 2 2 arbitrario(s), buscar el máximo de las funciones z = x 2 + y 2 y z = e − (x + y ) , los cuales se encuentran en el punto (0,0). ¿Por qué para la primera función el método de Newton encuentra la solución en un único paso? 4. ¿Qué cambios cabe efectuar en los algoritmos anteriores para poder localizar mínimos de funciones? ¿Se te ocurre alguna otra estrategia para mantener los algoritmos sin modificar y aún así poder localizar máximos o mínimos de las funciones? 7-4 Programas !-------------------------------------------------------------------! Busqueda de un maximo de una funcion segun el metodo basico simplex ! Ejemplo para la funcion f=exp[-(x**2+y**2)] de dos variables (n=2): ! el simplex es de dimension n+1=3 !-------------------------------------------------------------------implicit double precision (a-h,o-z) ! Dimensionalidad parameter (n=2,n1=n+1) dimension x(n,n1),z(n1),cdm(n),v(n),xnew(n),xnew2(n) common /counter/ nveces ! Tolerancia para el critero de terminacion toler=1.0d-3 nveces=0 ! Veces que se evalua la funcion ! Puntos iniciales x(1,1)=-5.0; x(2,1)=-5.0 x(1,2)=-1.0; x(2,2)=-1.0 x(1,3)= 5.0; x(2,3)=-1.0 ! Evalua la funcion en cada punto do i=1,n1 z(i)=f(x(1,i),x(2,i)) end do DO ! Proceso iterativo mi=1 ! Indicaran los puntos minimo y maximo ma=1 ! (peor y mejor) de los n+1 que se consideran zmi=z(mi); zma=z(ma) do i=2,n1 if (z(i)>zma) then zma=z(i) ma=i end if if (z(i)<zmi) then zmi=z(i) mi=i end if end do ! Centro de masas cdm(:)=0.0d0 do i=1,n1 if (i/=mi) then ! excluye el punto del minimo do j=1,n cdm(j)=cdm(j)+x(j,i) end do end if end do cdm(:)=cdm(:)/n ! Calcula vector desplazamiento (de modulo d) d=0.0d0 do i=1,n v(i)=cdm(i)-x(i,mi) d=d+v(i)**2 7-5 end do d=dsqrt(d) ! Nuevo punto (desplazamiento 2d) y valor de la funcion en el do i=1,n xnew(i)=x(i,mi)+2*v(i) end do znew=f(xnew(1),xnew(2)) if (znew>z(ma)) then ! Se ha mejorado lo mejor. Prueba 3d do i=1,n xnew2(i)=xnew(i)+v(i) end do znew2=f(xnew2(1),xnew2(2)) if (znew2>znew) then ! Este nuevo punto es el elegido znew=znew2 xnew(:)=xnew2(:) end if x(:,mi)=xnew(:) z(mi)=znew else ! Necesita buscar el segundo peor punto ! mi2 indica el segundo peor punto do i=1,n1 if (i/=mi .and. i/=ma) then ! Descarta mi y ma mi2=i zmi2=z(mi2) exit end if end do do i=1,n1 if (i/=mi .and. i/=ma) then ! Descarta mi y ma if (z(i)<zmi2) then zmi2=z(i) mi2=i end if end if end do if (znew<zmi2) then ! Peor que el segundo peor punto do i=1,n xnew2(i)=xnew(i)+1.5*v(i) ! Contraccion end do znew2=f(xnew2(1),xnew2(2)) if (znew2<zmi2) then ! Continua siendo malo: homotecia do i=1,n1 ! Recorre los puntos if (i/=ma) then ! Descarta el mejor do j=1,n dist=x(j,i)-x(j,ma) x(j,i)=x(j,ma)+dist/2 ! Homotecia end do z(i)=f(x(1,i),x(2,i)) end if end do CYCLE end if x(:,mi)=xnew2(:) z(mi)=znew2 7-6 else x(:,mi)=xnew(:) z(mi)=znew end if end if ! Criterio de convergencia if (d<toler) exit ! Final END DO write(*,*) " Mejor punto encontrado:" write(*,*) xnew(:) write(*,'(" Valor de la funcion:",g14.6)') znew write(*,'(" La funcion se ha evaluado",i5," veces.")') nveces END !-------------------------------------------------------------------double precision function f(x,y) implicit double precision (a-h,o-z) common /counter/ nveces f=exp(-(x**2+y**2)) nveces=nveces+1 END !-------------------------------------------------------------------- 7-7 !----------------------------------------------------------------! Busqueda el punto optimo segun el metodo de Newton ! Solucion particular del problema 1: f=x**2+x*y*y**2 !----------------------------------------------------------------implicit double precision (a-h,o-z) dimension x0(2),x(2),g(2),H(2,2) dimension Ht(2,2),S(2,2),T(2,2),Ti(2,2),Tit(2,2),Hi(2,2),Si(2,2) ! Punto inicial x0(1)=1.0d0; x0(2)=1.0d0 DO ! Calcula el gradiente call gradfun(x0,g) ! Criterio de convergencia gmod=SUM(g(:)**2) if (gmod<1.0d-10) then ! Se acaba aqui write(*,'(" Punto optimo:",2g14.6)') x0(:) write(*,'(" Modulo del gradiente:",g14.6)') gmod stop "Programa acabado normalmente." end if ! Obtiene la matriz Hessiana call Hess(x0,H) ! INVIERTE HESSIANA. Esta matriz es simetrica ! Se utilizan mas matrices de lo necesario para que ! el codigo sea mas legible ! Matriz simetrica S=HtH definida no negativa call producto_de_matrices(H,H,S,2,2,2) ! Efectua la descomposicion de Cholesky de S call Cholesky(S,2,T) ! Inversa de la matriz triangular T: Ti call inversa_T(T,2,Ti) ! Genera la matriz transpuesta de Ti: Tit call transpone(Ti,2,2,Tit) ! Calcula la inversa de S: Si=Ti*Tit call producto_de_matrices(Ti,Tit,Si,2,2,2) ! Calcula la inversa de H: H(-1)=Si*H call producto_de_matrices(Si,H,Hi,2,2,2) ! Calcula en nuevo punto call producto_de_matriz_vector(Hi,g,x,2,2) ! El vector Hg x0(:)=x0(:)-x(:) ! Nuevo punto END DO END !----------------------------------------------------------------- 7-8 !----------------------------------------------------------------subroutine gradfun(x,g) implicit double precision (a-h,o-z) dimension x(2),g(2) g(1)= 2*x(1)+x(2) ! df/dx = 2x+y g(2)= x(1)+2*x(2) ! df/dy = x+2y END !----------------------------------------------------------------!----------------------------------------------------------------subroutine Hess(x,H) implicit double precision (a-h,o-z) dimension x(2),H(2,2) H(1,1)= H(1,2)= H(2,1)= H(2,2)= 2.0d0 1.0d0 1.0d0 2.0d0 ! ! ! ! d2f/dxdx d2f/dxdy d2f/dydx d2f/dydy = = = = 2. 1. 1. 2. ! En general, estos terminos ! deberian ser funciones ! ! END !----------------------------------------------------------------!-------------------------------------------------------------------SUBROUTINE transpone(A,n,m,B) implicit double precision (A-H,O-Z) dimension A(n,m),B(m,n) do i=1,m do j=1,n B(i,j)=A(j,i) end do end do END !-------------------------------------------------------------------!-------------------------------------------------------------------SUBROUTINE producto_de_matrices(A,B,C,ma,na,mb) implicit double precision (A-H,O-Z) dimension A(ma,na),B(na,mb),C(ma,mb) do i=1,ma do j=1,mb C(i,j)=0.0 do k=1,na C(i,j)=C(i,j)+A(i,k)*B(k,j) end do end do end do END !-------------------------------------------------------------------!-------------------------------------------------------------------SUBROUTINE producto_de_matriz_vector(A,u,v,n,m) implicit double precision (A-H,O-Z) dimension A(n,m),u(n),v(n) do i=1,n v(i)=0.0 do j=1,m v(i)=v(i)+A(i,j)*u(j) end do end do END !-------------------------------------------------------------------- 7-9 !-------------------------------------------------------------------subroutine Cholesky(S,n,T) implicit double precision (a-h,o-z) dimension S(n,n),T(n,n) ! Define el triangulo inferior con ceros do i=1,n do j=1,i-1 T(i,j)=0.0 end do end do ! Descomposicion de Cholesky do i=1,n sum=0.0 do k=1,i-1 sum=sum+t(k,i)**2 end do t(i,i)=dsqrt(s(i,i)-sum) do j=i+1,n sum=0.0 do k=1,i-1 sum=sum+t(k,i)*t(k,j) end do t(i,j)=(s(i,j)-sum)/t(i,i) end do end do END !-------------------------------------------------------------------!-------------------------------------------------------------------subroutine inversa_T(T,n,Ti) implicit double precision (a-h,o-z) dimension T(n,n),Ti(n,n) ! Define el triangulo inferior con ceros do i=1,n do j=1,i-1 Ti(i,j)=0.0 end do end do ! Inversa de la matriz triangular superior do L=0,n-1 do i=1,n-L if (L.eq.0) then Ti(i,i)=1.0d0/t(i,i) else iL=i+L sum=0.0d0 do k=i+1,iL sum=sum+t(i,k)*ti(k,iL) end do ti(i,iL)=-sum/t(i,i) end if end do end do END !-------------------------------------------------------------- 7-10 Código que debe cambiarse para buscar el punto óptimo de la función 2 2 z = e − (x + y ) . Se trata de las funciones de cálculo del gradiente y la hessiana: gradfun() y Hess(). !----------------------------------------------------------------! Busqueda el punto optimo segun el metodo de Newton ! Solucion particular para la funcion f=exp[-(x**2+y**2)] !----------------------------------------------------------------!----------------------------------------------------------------subroutine gradfun(x,g) implicit double precision (a-h,o-z) dimension x(2),g(2) expo=dexp(-(x(1)**2+x(2)**2)) g(1)= -2*x(1)*expo ! df/dx = -2*x*expo g(2)= -2*x(2)*expo ! df/dy = -2*y*expo END !----------------------------------------------------------------!----------------------------------------------------------------subroutine Hess(x,H) implicit double precision (a-h,o-z) dimension x(2),H(2,2) expo=dexp(-(x(1)**2+x(2)**2)) H(1,1)= H(1,2)= H(2,1)= H(2,2)= 2*expo*(2*x(1)**2-1.0d0) -4*x(1)*x(2)*expo H(1,2) 2*expo*(2*x(2)**2-1.0d0) ! ! ! ! d2f/dxdx = 2*expo*(2x**2-1) d2f/dxdy = -4xy*expo Simetrica d2f/dydy = 2*expo*(2y**2-1) END !----------------------------------------------------------------- 7-11