c Scilab ( http://www.scilab.org/ ) - This file is part of Scilab c Copyright (C) INRIA c c This file must be used under the terms of the CeCILL. c This source file is licensed as described in the file COPYING, which c you should have received as part of this distribution. The terms c are also available at c http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt c subroutine n1qn2a (simul,prosca,n,x,f,g,dxmin,df1,epsg, / impres,io,mode,niter,nsim,m, / d,gg,aux,alpha,ybar,sbar,izs,rzs,dzs) c c---- c c code d'optimisation proprement dit c c---- c c arguments c integer n,impres,io,mode,niter,nsim,m,izs(*) real rzs(*) double precision x(n),f,g(n),dxmin,df1,epsg,d(n),gg(n),aux(n), / alpha(m),ybar(n,m),sbar(n,m) double precision dzs(*) external simul,prosca c c variables locales c integer i,iter,moderl,isim,jmin,jmax,indic real r double precision d1,t,tmin,tmax,gnorm,eps1,precon,ff double precision ps,ps2,hp0 character bufstr*(4096) c c---- parametres c double precision rm1,rm2 parameter (rm1=0.90d+0,rm2=0.10d-3) double precision pi parameter (pi=3.14159270d+0) c c---- initialisation c iter=0 isim=1 call prosca (n,g,g,ps,izs,rzs,dzs) gnorm=sqrt(ps) if (impres.ge.1) then write (bufstr,900) f,gnorm call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 900 format (5x,'f = ',d15.8, / /,5x,'norme de g = ',d15.8) c c ---- direction de descente initiale c (avec mise a l'echelle) c precon=2.0d+0*df1/gnorm**2 do 10 i=1,n d(i)=-g(i)*precon 10 continue if (impres.ge.5) then write(bufstr,899) precon call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 899 format (' n1qn2a: direction de descente -g: precon = ',d10.3) if (impres.eq.3) then write(bufstr,901) call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) write(bufstr,9010) call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif if (impres.eq.4) then write(bufstr,901) call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif c c ---- initialisation pour nlis0 c tmax=1.0d+20 call prosca (n,d,g,hp0,izs,rzs,dzs) c c ---- initialisation pour strang c jmin=1 jmax=0 c c---- debut de l'iteration. on cherche x(k+1) de la forme x(k) + t*d, c avec t > 0. on connait d. c c Si impres<0 et l'itération est un multiple de -impres, c alors on appelle la fonction fournie, avec indic=1. c 100 iter=iter+1 if (impres.lt.0) then if(mod(iter,-impres).eq.0) then indic=1 call simul (indic,n,x,f,g,izs,rzs,dzs) c error in user function if(indic.eq.0) goto 1000 endif endif if (impres.ge.5) then write(bufstr,901) call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 901 format (1x,79('-')) if (impres.ge.4) then write(bufstr,9010) call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 9010 format (1x,' ') if (impres.ge.3) then write (bufstr,902) iter,isim call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) write (bufstr,9020) f,hp0 call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 902 format (' n1qn2: iter ',i3,', simul ',i3) 9020 format (', f=',d15.8,', h''(0)=',d12.5) do 101 i=1,n gg(i)=g(i) 101 continue ff=f c c ---- recherche lineaire et nouveau point x(k+1) c if (impres.ge.5) then write (bufstr,903) call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 903 format (/,' n1qn2: recherche lineaire') c c ---- calcul de tmin c tmin=0.0d+0 do 200 i=1,n tmin=max(tmin,abs(d(i))) 200 continue tmin=dxmin/tmin t=1.0d+0 d1=hp0 c call nlis0 (n,simul,prosca,x,f,d1,t,tmin,tmax,d,g,rm1,rm2, / impres,io,moderl,isim,nsim,aux,izs,rzs,dzs) c c ---- nlis0 renvoie les nouvelles valeurs de x, f et g c if (moderl.ne.0) then if (moderl.lt.0) then c c ---- calcul impossible c t, g: ou les calculs sont impossible c x, f: ceux du t_gauche (donc f <= ff) c mode=moderl elseif (moderl.eq.1) then c c ---- descente bloquee sur tmax c [sortie rare (!!) d'apres le code de nlis0] c mode=3 if (impres.ge.1) then write(bufstr,904) iter call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 904 format (/,' >>> n1qn2 (iteration ',i3, / '): recherche lineaire bloquee sur tmax: ', / 'reduire l''echelle') elseif (moderl.eq.4) then c c ---- nsim atteint c x, f: ceux du t_gauche (donc f <= ff) c mode=5 elseif (moderl.eq.5) then c c ---- arret demande par l'utilisateur (indic = 0) c x, f: ceux en sortie du simulateur c mode=0 elseif (moderl.eq.6) then c c ---- arret sur dxmin ou appel incoherent c x, f: ceux du t_gauche (donc f <= ff) c mode=6 endif goto 1000 endif c c ---- tests d'arret c call prosca(n,g,g,ps,izs,rzs,dzs) eps1=sqrt(ps)/gnorm c if (impres.ge.5) then write (bufstr,905) eps1 call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 905 format (/,' n1qn2: test d''arret sur g: ',d12.5) if (eps1.lt.epsg) then mode=1 goto 1000 endif if (iter.eq.niter) then mode=4 if (impres.ge.1) then write (bufstr,906) iter call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 906 format (/,' >>> n1qn2 (iteration ',i3, / '): nombre maximal d''iterations atteint') goto 1000 endif if (isim.ge.nsim) then mode=5 if (impres.ge.1) then write (bufstr,907) iter,isim call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 907 format (/,' >>> n1qn2 (iteration ',i3,'): ',i6, / ' appels a simul (nombre maximal atteint)') goto 1000 endif c c ---- mise a jour de la matrice c jmax=jmax+1 if (iter.gt.m) then jmin=jmin+1 if (jmin.gt.m) jmin=jmin-m if (jmax.gt.m) jmax=jmax-m endif c c ---- y, s et (y,s) c do 400 i=1,n sbar(i,jmax)=t*d(i) ybar(i,jmax)=g(i)-gg(i) 400 continue call prosca (n,ybar(1,jmax),sbar(1,jmax),d1,izs,rzs,dzs) if (d1.le.0.0d+0) then mode=7 if (impres.ge.1) then write (bufstr,908) iter,d1 call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 908 format (/,' >>> n1qn2 (iteration ',i2, / '): le produit scalaire (y,s) = ',d12.5, / /,27x,'n''est pas positif') goto 1000 endif c c ---- precon: facteur de mise a l'echelle c call prosca (n,ybar(1,jmax),ybar(1,jmax),ps,izs,rzs,dzs) precon=d1/ps if (impres.ge.5) then write (bufstr,909) d1,precon call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 909 format (/,' n1qn2: mise a jour: (y,s) = ',d10.3, / ' Oren-Spedicato = ',d10.3) c c ---- ybar, sbar c d1=sqrt(1.0d+0/d1) do 410 i=1,n sbar(i,jmax)=d1*sbar(i,jmax) ybar(i,jmax)=d1*ybar(i,jmax) 410 continue c c ---- calcul de la nouvelle direction de descente d = - h.g c do 510 i=1,n d(i)=-g(i) 510 continue call strang(prosca,n,m,d,jmin,jmax, / precon,alpha,ybar,sbar,izs,rzs,dzs) c c ---- test: la direction d est-elle de descente ? c hp0 sera utilise par nlis0 c call prosca (n,d,g,hp0,izs,rzs,dzs) if (hp0.ge.0.0d+0) then mode=7 if (impres.ge.1) then write (bufstr,910) iter,hp0 call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) endif 910 format (/,' >>> n1qn2 (iteration ',i2,'): ', / /,5x,'la direction de recherche d n''est pas de ', / 'descente: (g,d) = ',d12.5) goto 1000 endif if (impres.ge.5) then call prosca (n,g,g,ps,izs,rzs,dzs) ps=sqrt(ps) call prosca (n,d,d,ps2,izs,rzs,dzs) ps2=sqrt(ps2) ps=hp0/ps/ps2 ps=min(-ps,1.0d+0) ps=acos(ps) r=real(ps*180./pi) write (bufstr,911) r call basout(io_out ,io ,bufstr(1:lnblnk(bufstr))) 911 format (/,' n1qn2: direction de descente d: ', / 'angle(-g,d) = ',f5.1,' degres') endif c c---- on poursuit les iterations c goto 100 c c retour c 1000 epsg=eps1 niter=iter nsim=isim return end