C ================================================================= C File: grasp.f C ================================================================= program grasp C This program try to find some y such that f(y) <= f(x) by C using the GRASP algorithm, described in: C C C.N. MENESES, P.M. PARDALOS, AND M.G.C. RESENDE. GRASP FOR C NONLINEAR OPTIMIZATION. AT&T Labs Research Technical C Report TD-6DUTRG. C PARAMETERS integer MaxNumIterNoImprov, MaxIter, MaxNoFunctionImprov,nmax,mmax double precision INFINITO,alpha,ZERO parameter ( MaxNumIterNoImprov = 20 ) parameter ( MaxIter = 2000 ) parameter ( INFINITO = 10000000000000000.0d0 ) parameter ( ZERO = 0.000000000001d0 ) parameter ( alpha = 0.3d0 ) parameter ( MaxNoFunctionImprov = 100 ) parameter ( nmax = 1000 ) parameter ( mmax = 1 ) C LOCAL SCALARS real etime,ntime,btime integer n,m,i,iter,NumIterNoImprov,err,itbest,NoFunctionImprov, + nsamples,bnsamples,totevalf,bevalf,fcnmb double precision seed,drand,h,BestSolValue,SolValue,vdummy C LOCAL ARRAYS real dum(2) double precision BestSolution(nmax),xlocalopt(nmax),y(nmax), + l(nmax),u(nmax), + lambda(mmax),rho(mmax),equatn(mmax),linear(mmax) C SET LOCAL SCALARS h = 1.0d0 SolValue = INFINITO BestSolValue = INFINITO C SET LOCAL COUNTERS totevalf = 0 nsamples = 0 C SETUP PROBLEM call inip(n,y,l,u,m,lambda,rho,equatn,linear) C SET INITIAL POINT do i = 1,n y(i) = l(i) + ( u(i) - l(i) ) * 0.5d0 end do nsamples = nsamples + 1 C START METHOD C do while ( ( iter .lt. MaxIter ) .and. C + ( f .le. BestSolValue ) ) iter = 1 NoFunctionImprov = 0 open(11,file='fbest.txt') do while ( iter .le. MaxIter ) call ConstructGreedyRandomizedSolution(y,n,h,l,u,seed,alpha, + fcnmb) totevalf = totevalf + fcnmb C call tun_lissajous(n,y,m,lambda,rho,l,u,SolValue,err) if ( n .le. 4 ) then call LocalSearch(y,h,n,l,u,xlocalopt,fcnmb,err) C call evalal(n,xlocalopt,m,SolValue,err) call evalf(n,xlocalopt,SolValue,err) totevalf = totevalf + fcnmb + 1 C call tun_lissajous(n,y,m,lambda,rho,l,u,err) C call evalal(n,y,m,SolValue,err) C if ( SolValue .lt. BestSolValue ) then C do i = 1,n C y(i) = xlocalopt(i) C end do C end if else C call EvaluateFunction(x,SolValue) C call evalal(n,y,m,SolValue,err) call evalf(n,y,SolValue,err) totevalf = totevalf + 1 end if C CHECK IF ITS BETTER THAN f(x) ntime = etime(dum) if( BestSolValue .gt. ( SolValue + 0.0001 * abs( SolValue ) + + 1.0E-6 ) ) then C UPDATES FUNCTION IMPROVEMENT ONLY FOR RELEVANT VALUES NoFunctionImprov = 0 NumIterNoImprov = 0 C UPDATES THE BEST SOLUTION do i = 1,n BestSolution(i) = y(i) end do itbest = iter btime = ntime bevalf = totevalf bnsamples = nsamples write(*,*) "--------------- ",iter," -------------------" write(*,*) " " write(*,*) "h,inoi,nfci | F,bt | x0,totf > ", h, + NumIterNoImprov,NoFunctionImprov,' | ', + SolValue,btime,' | ',bnsamples,bevalf BestSolValue = SolValue else NumIterNoImprov = NumIterNoImprov + 1 NoFunctionImprov = NoFunctionImprov + 1 end if C SET A NEW SAMPLE POINT if ( NoFunctionImprov .ge. MaxNoFunctionImprov ) then seed = iter+1 vdummy = drand(seed) do i = 1,n y(i) = l(i) + ( u(i) - l(i) ) * drand(seed) end do nsamples = nsamples + 1 C RETURNS TO ORIGINAL GRID h = 1.0d0 NumIterNoImprov = 0 NoFunctionImprov = 0 else C MAKES THE GRID MORE DENSE if( NumIterNoImprov .ge. MaxNumIterNoImprov ) then h = h / 2.0d0 NumIterNoImprov = 0 end if end if write(11,0011) iter,SolValue,BestSolValue,ntime C ITERATE iter = iter + 1 end do close(11) write(*,*) "............... FINAL ..................." write(*,*) " " write(*,*) 'f(*) : ',BestSolValue,' | it(*) : ',itbest write(*,*) 'bt : ',btime,'( ',ntime,' ) ' write(*,*) 'evalf : ',bevalf,' | tot(x0) : ',bnsamples do i = 1,n write(*,*) 'x (',i,') = ',BestSolution(i) end do write(*,*) "........................................" do i = 1,n write(*,*) 'x0 (',i,') = ',l(i) + ( u(i) - l(i) ) * 0.5d0 end do C NON-EXECUTABLE STATEMENTS 0010 format('f = ',D25.16) 0011 format(I7,1X,D25.16,1X,D25.16,1X,F8.2) end; C ****************************************************************** C ****************************************************************** subroutine ConstructGreedyRandomizedSolution(x,n,h,l,u,seed, + alpha,totevalf) C This subroutine try to find some y such that f(y) <= f(x) by C using the GRASP algorithm, described in: C C C.N. MENESES, P.M. PARDALOS, AND M.G.C. RESENDE. GRASP FOR C NONLINEAR OPTIMIZATION. AT&T Labs Research Technical C Report TD-6DUTRG. C PARAMETERS double precision INFINITO parameter ( INFINITO = 10000000000000000.0d0 ) C SCALAR ARGUMENTS integer n,totevalf,fcnmb double precision seed,alpha,h C ARRAY ARGUMENTS double precision x(n),l(n),u(n) C LOCAL SCALARS integer i,j,k,RandomlySelectElement double precision vmax,vmin,xibest C LOCAL ARRAYS integer S(n+1),RCL(n+1) double precision z(n),g(n),y(n) C SET LOCAL SCALARS totevalf = 0 fcnmb = 0 do i = 1,n S(i) = i RCL(i) = -1 y(i) = x(i) end do S(n+1) = n RCL(n+1) = 0 C TRY TO FIND SOME POINT z SUCH THAT f(x) < f(x) do while( S(n+1) .gt. 0 ) vmin = INFINITO vmax = ( -1.0d0 ) * INFINITO do i = 1,S(n+1) C MINIMIZE COMPONENT y( S(i) ) WITH STEP h C Minimize(x,h,indx,n,l,u,xibest,fbest,m) call Minimize(y,h,S(i),n,l,u,xibest,g(S(i)),fcnmb) totevalf = totevalf + fcnmb z(S(i)) = xibest if( vmin .gt. g(S(i)) ) then vmin = g(S(i)) end if if( vmax .lt. g(S(i)) ) then vmax = g(S(i)) end if end do C SET SOLUTION CANDIDATES RCL(n+1) = 0 do i=1,S(n+1) if( g( S(i) ) .le. ( vmin + alpha * ( vmax - vmin ) ) ) + then RCL(n+1) = RCL(n+1) + 1 RCL( RCL(n+1) ) = i end if end do C RANDOMLY SELECT A RCL ELEMENT seed = ( S(n+1) + seed ) / 2.0d0 j = RandomlySelectElement(seed,1,RCL(n+1)) C UPDATES x,y x( RCL(j) ) = z( RCL(j) ) y( RCL(j) ) = z( RCL(j) ) C S = S \ {j} k = S( RCL(j) ) S( RCL(j) ) = S( S(n+1) ) S( S(n+1) ) = k S(n+1) = S(n+1) - 1 end do end C ****************************************************************** C ****************************************************************** integer function RandomlySelectElement(seed,l,u) C This subroutine returns a random integer between l and u C Parameters of the subroutine: C C On Entry: C C seed double precision, C C l integer, C intervals lower bound, C C u integer, C intervals upper bound, C C SCALAR ARGUMENTS integer l,u double precision seed C LOCAL SCALARS integer delta double precision drand,nran delta = u - l + 1 nran = drand(seed) nran = drand(seed) RandomlySelectElement = max(nint( nran * delta ),1) return end; C ****************************************************************** C ****************************************************************** subroutine Minimize(x,h,indx,n,l,u,xibest,fbest,totevalf) C C Parameters of the subroutine: C C On Entry: C C x double precision x(n), C initial point, C C h double precision, C grid density C C indx integer, C index to be moved, C C n integer, C number of variables, C C l double precision l(n), C lower bounds on x, C C u double precision u(n), C upper bounds on x, C C On Return C C xibest double precision, C best position found C C fbest double precision C best f's value (with xibest) C PARAMETERS double precision INFINITO parameter ( INFINITO = 10000000000000000.0d0 ) C SCALAR ARGUMENTS integer n,totevalf,indx double precision h,xibest,fbest C ARRAY ARGUMENTS double precision x(n),l(n),u(n) C LOCAL SCALARS integer i,err double precision vmin,vle C LOCAL ARRAYS double precision t(n) C SET LOCAL SCALARS totevalf = 0 do i = 1,n t(i) = x(i) end do t(indx) = l(indx) vmin = INFINITO C write(*,*) 'xa -----> ',t(1),t(2),t(3),t(4) do while ( t(indx) .le. u(indx) ) C call EvaluateFunction(t,vle) C call evalal(n,t,m,vle,err) call evalf(n,t,vle,err) totevalf = totevalf + 1 if( vmin .gt. vle ) then vmin = vle xibest = t(indx) end if C write(*,*) 'h,indx,t,xibest,vle,vmin > ', h,indx,t(indx), C + xibest,vle,vmin t(indx) = t(indx) + h end do fbest = vmin C write(*,*) 'xd -----> ',t(1),t(2),t(3),t(4) C write(*,*) 'FB -> ',fbest C read(*,*) i end C ****************************************************************** C ****************************************************************** subroutine LocalSearch(x,h,n,l,u,xlocalopt, + totevalf,err) C PARAMETERS double precision INFINITO parameter ( INFINITO = 10000000000000000.0d0 ) C SCALAR ARGUMENTS integer n,totevalf,err double precision h C ARRAY ARGUMENTS double precision x(n),xlocalopt(n), + l(n),u(n) C LOCAL SCALARS integer i,maxldir,ldir double precision xlocaloptValue,xprimeValue logical Feasible,Improved C ARRAY SCALARS double precision all_dir(324),dir(n),xprime(n) totevalf = 0 if ( n .gt. 4 ) then err = 1 else C SET LOCAL SCALARS Improved = .true. do i = 1,n xlocalopt(i) = x(i) end do call GenerateDir(n,all_dir,maxldir,err) ldir = 0 C call evalal(n,xlocalopt,m,xlocaloptValue,err) call evalf(n,xlocalopt,xlocaloptValue,err) totevalf = totevalf + 1 do while ( Improved ) Improved = .false. do while ( ( ldir .lt. maxldir ) .and. + ( .not. ( Improved ) ) ) C SET NEW DIRECTION do i=1,n dir(i) = all_dir( ldir + i ) end do ldir = ldir + n do i=1,n xprime(i) = xlocalopt(i) + h * dir(i) end do C call evalal(n,xprime,m,xprimeValue,err) call evalf(n,xprime,xprimeValue,err) totevalf = totevalf + 1 if ( ( Feasible(xprime,n,l,u) ) .and. + ( xprimeValue .lt. xlocaloptValue ) ) then do i=1,n xlocalopt(i) = xprime(i) end do xlocaloptValue = xprimeValue Improved = .true. ldir = 0 end if end do end do end if end C ****************************************************************** C ****************************************************************** subroutine GenerateDir(n,dir,ldir,err) C This subroutine generates a set of directions indicated by dir. C For n < 5 only. C Parameters of the subroutine: C C On Entry: C C n integer, C problem dimension C C dir integer, C intervals lower bound, C C On Return: C C dir double precision dir(321), C directions C C err integer, C return status: -1 error, else ok C C SCALAR ARGUMENTS integer n,ldir,err C ARRAY ARGUMENTS double precision dir(324) C LOCAL SCALARS integer i,j,ilocal,tset,addone C LOCAL ARRAYS double precision next(4) C SET dir index tset = ( 3**n ) ldir = tset * n C SET LOCAL SCALARS next(1) = -1.0d0 next(2) = -1.0d0 next(3) = -1.0d0 next(4) = -1.0d0 err = -1 C VERIFY IF n < 5 if ( n .lt. 5 ) then do i = 1,ldir ilocal = mod(i,n) C Verify if the series finished if ( ilocal .eq. 0 ) then dir(i) = next(n) addone = 1.0d0 do j = 1,n next(j) = next(j) + addone if( next(j) .gt. 1.0d0 ) then next(j) = -1.0d0 else addone = 0.0d0 end if end do else dir(i) = next(ilocal) end if end do err = 0 end if end; C ****************************************************************** C ****************************************************************** logical function Feasible(x,n,l,u) C PARAMETERS C SCALAR ARGUMENTS integer n C ARRAY ARGUMENTS double precision x(n),l(n),u(n) C LOCAL SCALARS integer i logical feas feas = .true. i = 1 do while ( ( i .le. n ) .and. ( feas ) ) if ( ( x(i) .lt. l(i) ) .or. ( x(i) .gt. u(i) ) ) then feas = .false. end if i = i + 1 end do Feasible = feas return end C ****************************************************************** C ****************************************************************** double precision function drand(ix) double precision ix double precision a,p,b15,b16,xhi,xalo,leftlo,fhi,k data a/16807.d0/,b15/32768.d0/,b16/65536.d0/,p/2147483647.d0/ xhi= ix/b16 xhi= xhi - dmod(xhi,1.d0) xalo= (ix-xhi*b16)*a leftlo= xalo/b16 leftlo= leftlo - dmod(leftlo,1.d0) fhi= xhi*a + leftlo k= fhi/b15 k= k - dmod(k,1.d0) ix= (((xalo-leftlo*b16)-p)+(fhi-k*b15)*b16)+k if (ix.lt.0) ix= ix + p drand= ix*4.656612875d-10 return end