![]() |
AGA V1
Asexual Genetic Algorithm Version 1.0
|
00001 !======================================================================= 00002 !> @file extfunc.f90 00003 !> @brief User provided functions and subroutines module 00004 !> @authors Ary Rodriguez-Gonzalez & Alejandro Esquivel 00005 !> @date 23/Jun/2011 00006 ! 00007 ! Copyright (c) 2011 Ary Rodriguez-Gonzalez & Alejandro Esquivel 00008 ! 00009 ! This file is part of AGA-V1. 00010 ! 00011 ! AGA-V1 is free software; you can redistribute it and/or modify 00012 ! it under the terms of the GNU General Public License as published by 00013 ! the Free Software Foundation; either version 3 of the License, or 00014 ! (at your option) any later version. 00015 ! 00016 ! This program is distributed in the hope that it will be useful, 00017 ! but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 ! GNU General Public License for more details. 00020 ! You should have received a copy of the GNU General Public License 00021 ! along with this program. If not, see http://www.gnu.org/licenses/. 00022 !======================================================================= 00023 !> @brief Number of Gaussian components 00024 !> @details Short module to implement the number of Gaussian components 00025 !! used for fit (employed for HH34) as a variable of easy global access. 00026 module numgaus 00027 !> @param ngaus : number of Gaussian components to be fit 00028 integer :: ngaus 00029 end module numgaus 00030 !----------------------------------------------------------------------- 00031 !> @brief External functions module 00032 !> @details Here the user needs to provide a 00033 !> target (tarfunc) and a merit function (meritfunc). We recommend to 00034 !! preserve the names and interface in order to avoid changing code 00035 !! elsewhere. 00036 module exfunc 00037 contains 00038 !--------------------------------------------------------------- 00039 !> @brief Target Function 00040 !> @details User provided target function. \n 00041 !! In case some observational or experimental data is being fit, 00042 !! this is the function adjusted.\n 00043 !! For the example implemented here, finding a maxima of a given 00044 !! function, the evaluation of the level of fitness can be made directly 00045 !! inside the merit function, thus the target function returns a zero 00046 !! (and it is actually not called). Three examples of target functions 00047 !! can be found commented below: several Gaussian components, one 00048 !! or two Lorentzians, and a PNe luminosity function. 00049 !> @param[in] x : Independent variable (abscissa) 00050 !> @param[in] npar : Number of independent parameters 00051 !> @param[in] q(npar) : Vector of independent parameters 00052 !> @return Value of the target function 00053 real function tarfunc(x,npar,q) 00054 ! 00055 use numgaus 00056 ! 00057 implicit none 00058 integer, intent(in) :: npar 00059 real, dimension(npar), intent(in):: q 00060 real, intent(in) :: x 00061 ! real, sum0,dintg,intg 00062 ! integer, NumPNs 00063 ! 00064 ! Funcion Gausianas 00065 ! select case (ngaus) 00066 ! case (1) 00067 ! tarfunc=q(1)*exp(-(x-q(2))**2/q(3)) 00068 ! case (2) 00069 ! tarfunc=q(1)*exp(-(x-q(2))**2/q(3))& 00070 ! +q(4)*exp(-(x-q(5))**2/q(6))+q(7) 00071 ! case (3) 00072 ! tarfunc=q(1)*exp(-(x-q(2))**2/q(3))& 00073 ! +q(4)*exp(-(x-q(5))**2/q(6))& 00074 ! +q(7)*exp(-(x-q(8))**2/q(9)) 00075 ! case (4) 00076 ! tarfunc=q(1)*exp(-(x-q(2))**2/q(3))& 00077 ! +q(4)*exp(-(x-q(5))**2/q(6))& 00078 ! +q(7)*exp(-(x-q(8))**2/q(9))& 00079 ! +q(10)*exp(-(x-q(11))**2/q(12)) 00080 ! case (5) 00081 ! tarfunc=q(1)*exp(-(x-q(2))**2/q(3))& 00082 ! +q(4)*exp(-(x-q(5))**2/q(6))& 00083 ! +q(7)*exp(-(x-q(8))**2/q(9))& 00084 ! +q(10)*exp(-(x-q(11))**2/q(12))& 00085 ! +q(13)*exp(-(x-q(14))**2/q(15)) 00086 ! case (6) 00087 ! tarfunc=q(1)*exp(-(x-q(2))**2/q(3))& 00088 ! +q(4)*exp(-(x-q(5))**2/q(6))& 00089 ! +q(7)*exp(-(x-q(8))**2/q(9))& 00090 ! +q(10)*exp(-(x-q(11))**2/q(12))& 00091 ! +q(13)*exp(-(x-q(14))**2/q(15))& 00092 ! +q(16)*exp(-(x-q(17))**2/q(18)) 00093 ! end select 00094 00095 ! Funcion Lorentzians 00096 ! select case (ngaus) 00097 ! pi=3.141592 00098 ! case (1) 00099 ! tarfunc=q(1)/(pi*q(2)*(1.+((x+q(3)))/q(2))) 00100 ! case (2) 00101 ! tarfunc=q(1)/(pi*q(2)*(1.+((x+q(3)))/q(2)))& 00102 ! +q(4)/(pi*q(5)*(1.+((x+q(6)))/q(5))) 00103 ! 00104 ! end select 00105 ! 00106 ! Planetary Nebulae Luminosity Function 00107 ! tarfunc=q(1)*exp(0.307*x)*(1.-exp(3.*(q(2)-x))) 00108 ! 00109 ! NumPNs=100 00110 ! summ0=0. 00111 ! Do j=0,NumPNs-1 00112 ! summ0=3.*exp(3*q(1))/(exp(3.*q(1))-exp(3.*A(0,j)))+summ0 00113 ! EndDo 00114 ! dintg=1.114*(exp(3.*q(1)-2.693*ml)-exp(0.307*q(1))) 00115 ! 00116 tarfunc=0. 00117 return 00118 end function tarfunc 00119 !----------------------------------------------------------------------- 00120 !> @brief Merit Function 00121 !> @details User provided merit function. \n 00122 !! This function computes the fitness level of each individual. \n 00123 !! The program assumes that a low value has the highest level of fitness 00124 !! (since its primary application is to fit functions with a merit 00125 !! function that is an error measure, e.g. @f$\chi^2@f$). If one needs 00126 !! to find a maximum of a function, one can use its reciprocal as merit 00127 !! function.\n 00128 !! The interface of the function is designed to adjust a target function 00129 !! to a set of observational/experimental data, there some arguments 00130 !! become dummy if the merit function does not need to be 00131 !! called. 00132 !> @param[in] xobs(ndata) : Vector of data abscissae 00133 !> @param[in] yobs(ndata) : Vector of data ordinates 00134 !> @param[in] ysigma(ndata) : Vector of uncertainties in the ordinate 00135 !> @param[in] q(npar) : Vector of parameters to be adjusted 00136 !> @param[in] npar : Number of parameters adjusted 00137 !> @param[in] ndata : Number of data points 00138 !> @return Value of the merit function (lowest value=fittest individual) 00139 real function meritfunc(xobs,yobs,ysigma,q,npar,ndata) 00140 implicit none 00141 real, dimension(ndata), intent(in) :: xobs,yobs,ysigma 00142 real, dimension(npar), intent(in) :: q 00143 real :: chi2,yfunc,pi,a,b,sig,x0,y0,r 00144 integer, intent(in):: npar,ndata 00145 integer :: i,n 00146 ! 00147 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00148 ! Chi^2 fitting ! 00149 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00150 ! chi2=0. 00151 ! do i=1,ndata 00152 ! yfunc=tarfunc(xobs(i),npar,q) 00153 ! chi2=chi2+((yobs(i)-yfunc)/(ysigma(i)))**2 00154 ! enddo 00155 ! meritfunc=chi2 00156 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00157 ! TEST FUNCTION 1 ! 00158 ! f(x,y)=[16x(1-x)y(1-y)sin(n*pi*x)sin(n*pi*y)]^2 ! 00159 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00160 pi=3.141592 00161 n=9 00162 meritfunc=16.*q(1)*(1.-q(1))*q(2)*(1.-q(2))*sin(pi*n*q(1))*sin(pi*n*q(2)) 00163 meritfunc=1.-meritfunc 00164 ! 00165 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00166 ! TEST FUNCTION 2 ! 00167 ! r=sqrt((x-x0)^2+(y-y0)^2) ! 00168 ! f(r)=cos^a(b*pi*r)*exp(-r^2/(2*sig^2)) ! 00169 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00170 ! a=2. 00171 ! b=3. 00172 ! sig=2. 00173 ! x0=0.25 00174 ! y0=0.25 00175 ! pi=3.141592 00176 ! r=sqrt((q(1)-x0)**2+(q(2)-y0)**2) 00177 ! meritfunc=(cos(b*pi*r))**a*exp(-r**2/(2.*sig)) 00178 ! meritfunc=1.-meritfunc 00179 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00180 ! TEST FUNCTION 3 ! 00181 ! f(x,y)=(1+cos(12sqrt(x^2+y^2)))/(0.5(x^2+y^2)+2) ! 00182 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00183 00184 ! meritfunc=(1+cos(12*sqrt(q(1)**2+q(2)**2)))/(0.5*(q(1)**2+q(2)**2)+2) 00185 ! meritfunc=1.-meritfunc 00186 ! 00187 ! 00188 return 00189 end function meritfunc 00190 !----------------------------------------------------------------------- 00191 end module exfunc 00192 !----------------------------------------------------------------------- 00193 !======================================================================= 00194 !> @brief Input from data and options file. 00195 !> @details contains routines to read the input data and run-time 00196 !! parameters. 00197 module input 00198 contains 00199 !> @brief Observational/experimental data input 00200 !> @details Reads experimental/observational data from file. Data are 00201 !! ordered by columns (see example in ObsData.dat) 00202 !> @param[out] xobs(ndata) : vector of abscissae 00203 !> @param[out] yobs(ndata) : vector of ordinates 00204 !> @param[out] ysigma(ndata) : vector of uncertainties of the ordinates 00205 !> @param[out] ndata : number of experimental points. 00206 subroutine ReadData(xobs,yobs,ysigma,ndata) 00207 implicit none 00208 real, dimension(:), allocatable, intent(out) :: xobs,yobs,ysigma 00209 integer, intent(out) :: ndata 00210 ! 00211 real, dimension(:), allocatable :: x1,y1,ys1 00212 integer :: i, status 00213 integer, parameter :: n=10000000 00214 ! 00215 ! read the input file (3 columns, x,y,sigma_y, and determine the 00216 ! number of lines it contains 00217 open(1,file='ObsData.dat',status='old',iostat=status) 00218 allocate(x1(n),y1(n),ys1(n)) 00219 ndata=0 00220 do i=1,n 00221 read(1,*,iostat=status) x1(i),y1(i),ys1(i) 00222 if (status /= 0) exit 00223 ndata=ndata+1 00224 enddo 00225 close(1) 00226 ! 00227 ! allocate the arrays (size=number of lines in input file) 00228 allocate(xobs(ndata),yobs(ndata),ysigma(ndata)) 00229 ! 00230 ! fill the arrays with the temporary buffers and free memory 00231 xobs (:) = x1 (1:ndata) 00232 yobs (:) = y1 (1:ndata) 00233 ysigma(:) = ys1(1:ndata) 00234 deallocate(x1,y1,ys1) 00235 ! 00236 return 00237 end subroutine ReadData 00238 !--------------------------------------------------------------------- 00239 !> @brief Reads runtime parameters from file and initializes arrays 00240 !> @details Reads from file (InitCond.dat) all the runtime input 00241 !! parameters, initializes the values of the hyperboxes, and allocates 00242 !! memory for all the parents and population. 00243 !> @param[out] nsteps : Number of iterations before the hyperboxes are 00244 !! restored to their initial size 00245 !> @param[out] nruns : Number of times that the hyperboxes are returned 00246 !! to their initial size 00247 !> @param[out] nparent : Number of parents 00248 !> @param[out] nind : Number of individuals 00249 !> @param[out] nerr : Number of realizations performed to obtain an 00250 !! estimate of the errors 00251 !> @param[out] deltaconst : if equal to 1 the reduction of the hyperboxes 00252 !! is at a constant rate (see reduc), otherwise hyperboxes are reduced 00253 !! with the standard deviation of each parameter. 00254 !> @param[out] nmig : turns on/off migration. If its value is 0, 00255 !! migration is disabled, otherwise is enabled 00256 !> @param[out] ngaussdev : : if value equal to 1, offsprinf is obtained 00257 !! with a Gaussian distribution, otherwise they are obtained with 00258 !! uniform random deviates. 00259 !> @param[out] igaus : ????? Quiza deberia pasarse al modulo de las 00260 !! gaussianas 00261 !> @param[out] npar : number of free parameters 00262 !> @param[out] gensize : size of the new generation from each parent. 00263 !! Since the parent is kept gensize=num of sons + 1 00264 !> @param[out] reduc : reducing factor, if a constant speed is chosen the 00265 !! hyper-box is reduced according to: 00266 !> @param[out] beta : Tolerance value 00267 !> @param[out] qbounds(2,npar) : limits of the original (user provided) 00268 !! hyperbox 00269 !> @param[out] q0(npar) : Initial guess, computed as the position at the 00270 !! center of the initial hyperbox 00271 !> @param[out] delta0(npar) : Initial window half-size 00272 !> @param[out] fit(nind) : Array to store the fitness level of the 00273 !! population 00274 !> @param[out] arrmain(npar,nind) : Array for the entire population 00275 !> @param[out] arrpar(npar,nparent) : Array for the parents only 00276 !> @param[out] arrgen(npar,gensize) : Array to store a single generation 00277 !! of each parent 00278 subroutine InitCond(nsteps,nruns,nparent,nind,nerr, deltaconst, nmig, & 00279 ngaussdev, igaus, npar, gensize, reduc, beta, & 00280 qbounds,q0,delta0,fit,arrmain,arrpar,arrgen ) 00281 implicit none 00282 integer, intent(out):: npar,nsteps,nruns,nparent,nind,gensize, 00283 deltaconst,nmig,ngaussdev,nerr,igaus 00284 real, intent(out) :: reduc,beta 00285 real, dimension(:), allocatable, intent(out):: q0,delta0,fit 00286 real, dimension(:,:), allocatable, intent(out):: arrmain,arrpar, 00287 arrgen,qbounds 00288 real, dimension(:,:), allocatable :: aux 00289 ! 00290 integer :: i,status 00291 integer, parameter :: n=10000 00292 ! 00293 open(1,file='InitCond.dat',status='old',iostat=status) 00294 allocate(aux(2,1000)) 00295 ! 00296 ! 00297 2 continue 00298 read(1,*,err=2) nsteps,nruns,nparent,nind,nerr 00299 ! 00300 3 continue 00301 read(1,*,err=3) deltaconst, nmig ,ngaussdev, igaus 00302 ! 00303 4 continue 00304 read(1,*,err=4) reduc,beta 00305 ! 00306 5 continue 00307 read(1,*,err=5)aux(1,1),aux(2,1) 00308 ! 00309 npar=1 00310 do i=2,n 00311 read(1,*,iostat=status)aux(1,i),aux(2,i) 00312 if (status/=0)exit 00313 npar=npar+1 00314 enddo 00315 ! 00316 close(1) 00317 ! 00318 allocate(q0(npar),delta0(npar)) 00319 allocate(qbounds(2,npar)) 00320 qbounds(1,:)=aux(1,1:npar) 00321 qbounds(2,:)=aux(2,1:npar) 00322 q0(:)=(qbounds(1,1:npar)+qbounds(2,1:npar))/2. 00323 delta0(:)=(qbounds(2,1:npar)-qbounds(1,1:npar))/2. 00324 ! 00325 deallocate(aux) 00326 ! 00327 gensize=nind/nparent 00328 allocate(fit(nind), arrmain(npar,nind),arrpar(npar,nparent), & 00329 arrgen(npar,gensize)) 00330 ! 00331 return 00332 end subroutine InitCond 00333 !-------------------------------------------------------------------- 00334 end module input 00335 !----------------------------------------------------------------------