Skip to content
Snippets Groups Projects
PSO_v2012.R 123.91 KiB
# File PSO_v2012.R
# Part of the hydroPSO package, http://www.rforge.net/hydroPSO/
# Copyright 2008-2012 Mauricio Zambrano-Bigiarini
# Distributed under GPL 2 or later

################################################################################
##                          Random.Bounded.Matrix                             ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                        ##
################################################################################
# Created: 2008                                                               ##
# Updates: 23-Nov-2010                                                        ##
################################################################################
# Purpose  : To create a matrix randomly generated, with a bounded uniform distribution

# 'npart'   : number of particles in the swarm
# 'X.MinMax': Matrix of 'n' rows and 2 columns, 
#             the first column has the minimum values for each dimension, and
#             the second column has the maximum values for each dimension
Random.Bounded.Matrix <- function(npart, x.MinMax) {

  # dimension of the solution space (number of parameters )
  n <- nrow(x.MinMax)
	
  lower <- x.MinMax[,1]
  upper <- x.MinMax[,2]
	
  ##x <- lower + (upper-lower)*matrix(runif(n*npart,0,1), nrow=npart, ncol=n)
  
  # random initialization for all the particles, with a value in [0,1]
  X <- matrix(runif(n*npart,0,1), nrow=npart, ncol=n)

  # Transforming X into the real range defined by the user
  X <- t( lower +  (upper - lower )*t(X) )
	
  return(X)
	
} # 'Random.Bounded.Matrix2' end
#Random.Bounded.Matrix(10, X.MinMax)


################################################################################
##                        random Latin-Hypercube Sampling                     ##
################################################################################
# Author: Mauricio Zambrano-Bigiarini
# Created: 17-Dec-2010
# Updates:
################################################################################
# Purpose  : Draws a Latin Hypercube Sample from a set of uniform distributions
#            for use in creating a Latin Hypercube Design
################################################################################
# Output   : An n by ndim Latin Hypercube Sample matrix with values uniformly 
#            distributed on [0,1] 
################################################################################

# 'n'      : number of strata used to divide each parameter range
# 'ranges' : Matrix of 'N' rows and 2 columns, (N is the number of parameters)
#            the first column has the minimum values for each dimension, and
#            the second column has the maximum values for each dimension
rLHS <- function(n, ranges) {

  # dimension of the solution space (number of parameters )
  ndim <- nrow(ranges)
  
  lower <- ranges[,1]
  upper <- ranges[,2]
	
  ### LHS initialization for all the particles
  ##require(lhs)
  ##X <- lower + (upper-lower)*randomLHS(n, ndim) 
  
  # LHS initialization for all the particles, with a value in [0,1]
  require(lhs)
  X <- randomLHS(n, ndim) 

  # Transforming X into the real range defined by the user
  X <- t( lower +  (upper - lower )*t(X) )
	
  return(X)
	
} # 'rLHS' end



################################################################################
#                               compute.CF Function                            #
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Created: 2008                                                                #
# Updates:                                                                     #
################################################################################
# Computes the Clerc's Constriction Factor
# Clerc, M.; Kennedy, J.; , "The particle swarm - explosion, stability, and 
# convergence in a multidimensional complex space," Evolutionary Computation, 
# IEEE Transactions on , vol.6, no.1, pp.58-73, Feb 2002
# doi: 10.1109/4235.985692

compute.CF <- function(c1, c2) {
    psi <- c1 + c2  # psi >= 4
    CF <- 2 / abs( 2 - psi - sqrt(psi^2 - 4*psi) )
} # 'compute.CF' end


   
# 'x' 	      : vector of 'n' parameters, corresponding to one particle
# 'v'         : vector of 'n' velocities of each parameter, corresponding to the current particle
# 'vmax.perc' : percentage of the range of each dimension that is allowed as 
#               maximum velocity in that dimension
# 'Pbest'     : matrix with the current best parameter values for all the particles
# 'gbest'     : vector with the best parameter values in the swarm
# 'w'	      : Inertial factor.
# 'c1'        : constant that encourages the exploration of the solution space
# 'c2'	      : constant that encourages the exploitation of the current global best
# 'CF'        : constant representing the Clerk's Constriction Factor,to insure convergence of the PSO algorithm
# 'x.MinMax'  : Matrix with the valid range for each parameter of 'X'.
#               Rows = 'n' (number of parameter
#               Columns = 2, 
#               First column has the minimum possible value for each parameter
#               Second column has the maximum possible value for each parameter
# 'topology'  : character, with the topology to be used in PSO. Valid values
#               are in c('gbest', 'lbest')
# 'method'    : character, with the method to be used as PSO algorithm. Valid values
#               are in c('pso', 'ipso', 'fips', 'wfips')

# Result      : vector of 'n' velocities, one for each parameter, corresponding to the current particle
################################################################################
##                        compute.veloc Function                              ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Created: 2008                                                                #
# Updates: Oct-2011 ; Nov-2011                                                 #
################################################################################
compute.veloc <- function(x, v, w, c1, c2, CF, Pbest, part.index, gbest, 
                          topology, method, MinMax, neighs.index, 
                          localBest, localBest.pos, 
                          ngbest.fit, ngbest, lpbest.fit) {

  pbest <- Pbest[part.index, ]
  
  # dimension of 'x' (number of parameters)
  n <- length(gbest)

  r1 <- runif(n, min=0, max=1)
  r2 <- runif(n, min=0, max=1)
  
  if ( method=="pso" ) {
  
    ifelse(part.index != localBest.pos,  
           vn <- CF * ( w*v + r1*c1*(pbest-x) + r2*c2*(localBest-x) ),
           vn <- CF * ( w*v + r1*c1*(pbest-x) ) )
    
  } else if ( method=="ipso" ) {
  
        # number of best particles that have to be considered      
        nngbest <- length(ngbest.fit)
  
        R2 <-  matrix(rep(r2,nngbest), nrow=nngbest, byrow=TRUE)
        
        # computing the c2 values for each one of the best particles,
        # weighted according to their fitness value
        ifelse(MinMax == "min", c2i <- c2 * ( (1/ngbest.fit)/sum(1/ngbest.fit) ), 
                                c2i <- c2 * ( ngbest.fit/sum(ngbest.fit) )
              ) 
              
        # transforming 'x' into a matrix, with the same values in each row, in 
        # order to be able to substract 'x' from 'ngest'
        X <- matrix(rep(x, nngbest), ncol=n, byrow=TRUE)
        
        # computing the velocity
        vn <- CF * ( w*v + r1*c1*(pbest-x) + colSums(R2*c2i*(ngbest-X) ) )  
           
     } else if ( method=="fips" ) {
              
              neighs.index <- neighs.index[!is.na(neighs.index)] # only for topology=='random' 
              N   <- length(neighs.index)              
              X   <- matrix(rep(x,N), nrow=N, byrow=TRUE)
              P   <- Pbest[neighs.index, ]
              phi <- c1 + c2
              r   <- runif(N, min=0, max=phi)
                 
              vn  <-  CF * ( w*v + (1/N)*colSums( r*(P-X) ) )
              
               
            } else if ( method=="wfips" ) {
            
                neighs.index <- neighs.index[!is.na(neighs.index)] # only for topology=='random' 
                N    <- length(neighs.index)              
                X    <- matrix(rep(x,N), nrow=N, byrow=TRUE)
                P    <- Pbest[neighs.index, ]
                pfit <- lpbest.fit[neighs.index]
                phi  <- c1 + c2
                r    <- runif(N, min=0, max=phi)
                ifelse(MinMax == "min", wght <- (1/lpbest.fit)/sum(1/lpbest.fit), 
                                        wght <- lpbest.fit/sum(lpbest.fit) 
                      ) 
                   
                vn  <-  CF * ( w*v + (1/N) * colSums( wght*r*(P-X) ) )	  
              } # ELSE end
  
  return(vn)
  
} # 'compute.veloc' end



################################################################################
##                             roll.vector Function                           ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Created: 2009                                                                #
# Updates:                                                                     #
################################################################################
# 'old.vector': vector of length 'L' that will be rolled
# 'new.value' : real that will be put at the end of 'old.vector'

# Result: a vector with elements x.new[i] = x.old[i+1], i=1,L-1, x.new[L]= 'new.value'
roll.vector <- function(old.vector, new.value) {
  tmp	<- old.vector
  L		<- length(old.vector)  
  tmp[1:(L-1)]	<- old.vector[2:L]
  tmp[L]        <- new.value
  
  return(tmp)

} # 'roll.vector' end


################################################################################
##                       compute.value.with.iter Function                     ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Created: 2008                                                                #
# Updates:                                                                     #
################################################################################
# 'iter'    : the current iteration number
# 'niter'   : maximum number of iteration that can be done within a single run
# 'nexp'    : nonlinear modulation index
# 'val.ini' : initial inertial weight at the start of a given run
# 'val.fin' : fiinal inertial weight at the end of a given run

# Result    : Nonlinear modulated inertial weight
compute.value.with.iter <- function(iter, niter, nexp, val.ini, val.fin) {

  w <- ( ( (niter - iter) / niter )^nexp ) * ( val.ini - val.fin) + val.fin
  
  return(w)

} # 'compute.value.with.iter' end


################################################################################
##                         compute.w.aiwf Function                            ##
##                 Adaptive inertial weight factor (AIWF)                     ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini
################################################################################
# Started: 2008
# Updates: 24-Nov-2011
################################################################################
# Reference:
# According to Liu et al., 2005 ("Improved Particle Swarm Combined with Caos")
# B. Liu, et al., "An improved particle swarm optimization combined with chaos," 
# Chaos, Solitons and Fractals, vol. 25, pp. 1261-1271, 2005.

# 'iter.fit'    : vector with 'n.particles' values corresponding to the fitness
#                 obtained in the current iteration for each one of the particles
# 'particle.pos': position of the particle, for identifying it
# 'gbest.fit'   : number with the best fitness found so far, considering all the particles
# 'w.max'       : initial inertial weight at the start of a given run (maximum value)
# 'w.min'       : final inertial weight at the end of a given run (minimum value)
# 'MinMax'      : string indicating if PSO have to find a minimum or a maximum for the fitness function.
#                 valid values are: "min", "max"

# Result        : Adaptive inertial weight factor (AIWF)
  
compute.w.aiwf <- function(iter.fit, particle.pos, gbest.fit, w.max, w.min, MinMax) {
  # 'f' : fitness value of the particle in the current iteration
  f <- iter.fit[particle.pos]
  
  # 'f.avg': mean fitness value of all the particles in the current iteration
  f.avg <- mean(iter.fit, na.rm=TRUE)
  
  # 'f.min': best fitness value of all the particles in the current iteration
  ifelse(MinMax == "min", f.min <- min(iter.fit, na.rm=TRUE), f.min <- max(iter.fit, na.rm=TRUE) )
   
  ifelse(MinMax == "min", to.apply <- (f <= f.avg), to.apply <- (f >= f.avg) )
  
  if (to.apply) {
    w <- w.min + ( ( (w.max - w.min) * abs(f - f.min) ) / abs(f.avg - f.min) )
  } else w <- w.max
  
  return(w)

} # 'compute.w.aiwf' end



################################################################################
##                      compute.w.with.GLratio Function                       ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Started: 23-Dec-2010                                                         #
# Updates:                                                                     #
################################################################################
compute.w.with.GLratio <- function(MinMax, gbest.fit, pbest.fit) {
  
  # If we are Minimizing, the ratio 'gbest/pbest' have to be less than 1,
  # and the closer to 1, the closer the particle to 'gbest'
  ifelse(MinMax == "min", 
         w <- 1.1 - ( gbest.fit / mean(pbest.fit) ), 
         w <- 1.1 - ( mean(pbest.fit) / gbest.fit )
        )  
  
  return(w)

} # 'compute.w.with.GLratio' END


################################################################################
##                       compute.c1.with.GLratio Function                     ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Started: 27-Dec-2010                                                         #
# Updates:                                                                     #
################################################################################
# Based on M. Senthil Arumugam and M.V.C. Rao; 2008. Applied Soft Computing
# "On the improved Performances of the particle swarm optimization algorithms
#  with adaptive parameters, cross-over operators and root mean square (RMS) 
#  variants for computing optimal control of a class of hybrid systems"

# 'gbest.fit': global best objective function
# 'pbest.fit': best objective function of the current particle
compute.c1.with.GLratio <- function(MinMax, gbest.fit, pbest.fit) {
  
  # If we are Minimizing, the ratio 'gbest/pbest' have to be less than 1,
  # and the closer to 1, the closer the particle to 'gbest'
  ifelse(MinMax == "min", 
         c1 <- 1.0 + ( gbest.fit / pbest.fit ), 
         c1 <- 1.0 + ( pbest.fit / gbest.fit )
        )  
  
  return(c1)

} # 'compute.c1.with.GLratio' END


################################################################################
##                    velocity.boundary.treatment Function                    ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Started: 2008                                                                #
# Updates:                                                                     #
################################################################################
# 'x' 		  : vector of 'n' parameters, corresponding to one particle
# 'n'             : dimension of the solution space (number of parameters)
# 'X.MinMax'      : string indicating if PSO have to find a minimum or a maximum 
#                   for the fitness function.
#                   valid values are: "min", "max"
# 'v'             : vector of 'n' velocities of each parameter, corresponding to 
#                   the current particle
# 'boundary.wall' : boundary treatment that is used to limit the sea
#                   the limits given by 'X.MinMax'.
#                   Valid values are: 'absorbing', 'reflecting' and 'invisible'

# Result          : vector of 'n' velocities, one for each parameter, 
#                   corresponding to the current particle
velocity.boundary.treatment <- function(v, vmax ) {	
  
  byd.vmax.pos <- which( abs(v) > vmax )
  if ( length(byd.vmax.pos) > 0 ) 
       v[byd.vmax.pos] <- sign(v[byd.vmax.pos])*abs(vmax[byd.vmax.pos])
  
  return(v)
	
} # 'velocity.boundary.treatment' end


################################################################################
##                  position.update.and.boundary.treatment Function           ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Started: 2008                                                                #
# Updates:                                                                     #
################################################################################
# 'x'             : vector of 'n' parameters, corresponding to one particle
# 'X.MinMax'      : string indicating if PSO have to find a minimum or a maximum 
#                   for the fitness function.
#                   valid values are: "min", "max"
# 'v'             : vector of 'n' velocities of each parameter, corresponding to 
#                   the current particle
# 'boundary.wall' : boundary treatment that is used to limit the sea
#                   the limits given by 'X.MinMax'.
#                   Valid values are: 'absorbing', 'reflecting', 'invisible', 'damping'

# Result          : vector of 'n' velocities, one for each parameter, 
#                   corresponding to the current particle

# References:
# Robinson, J.; Rahmat-Samii, Y.; Particle swarm optimization in electromagnetics. 
# Antennas and Propagation, IEEE Transactions on , vol.52, no.2, pp. 397-407, 
# Feb. 2004. doi: 10.1109/TAP.2004.823969

# Huang, T.; Mohan, A.S.; , A hybrid boundary condition for robust particle
# swarm optimization. Antennas and Wireless Propagation Letters, IEEE , vol.4, 
# no., pp. 112-117, 2005. doi: 10.1109/LAWP.2005.846166
position.update.and.boundary.treatment <- function(x, v, x.MinMax, boundary.wall) {
 
 # dimension of 'x' (number of parameters)
 n <- nrow(x.MinMax)
 
 # Vector with the new positions of the current particle
 x.new <- x + v
 
 # By default the new velocity is assumed not to be limited
 v.new <- v
 
 # Minimum and maximum values for each dimension
 x.min <- x.MinMax[,1]
 x.max <- x.MinMax[,2]
 
 byd.min.pos <- which(x.new < x.min)
 if ( length(byd.min.pos) > 0) { 
    if ( boundary.wall == "absorbing") {     
       x.new[byd.min.pos] <- x.min[byd.min.pos]
       v.new[byd.min.pos] <- 0*v[byd.min.pos]      
    } else if ( boundary.wall == "reflecting") {    
           x.new[byd.min.pos] <- 2*x.min[byd.min.pos] - x.new[byd.min.pos] 
           v.new[byd.min.pos] <- v[byd.min.pos]
      } else if ( boundary.wall == "invisible") {
             x.new[byd.min.pos] <- x[byd.min.pos]
             v.new[byd.min.pos] <- v[byd.min.pos]
        } else if ( boundary.wall == "damping") {
             L                  <- abs( x.min[byd.min.pos] - x.new[byd.min.pos] )
             x.new[byd.min.pos] <- x.min[byd.min.pos] + runif(1)*L
             v.new[byd.min.pos] <- v[byd.min.pos]
        }# ELSE end
 } # IF end
      
 byd.max.pos <- which( x.new > x.max )
 if ( length(byd.max.pos) > 0 ) {	 
    if ( boundary.wall == "absorbing") { 
       x.new[byd.max.pos] <- x.max[byd.max.pos]
       v.new[byd.max.pos] <- 0*v[byd.max.pos] 
    } else if ( boundary.wall == "reflecting") {
           x.new[byd.max.pos] <- 2*x.max[byd.max.pos] - x.new[byd.max.pos] 
           v.new[byd.max.pos] <- v[byd.max.pos]
      } else if ( boundary.wall == "invisible") {
             x.new[byd.max.pos] <- x[byd.max.pos]
             v.new[byd.max.pos] <- v[byd.max.pos]
        } else if ( boundary.wall == "damping") {
             L                  <- abs( x.new[byd.max.pos] - x.max[byd.max.pos])
             x.new[byd.max.pos] <- x.max[byd.max.pos] - runif(1)*L
             v.new[byd.max.pos] <- v[byd.max.pos]
        }# ELSE end
 } # IF end
 
 out <- list(x.new=x.new, v.new=v.new)		
		
 return(out)

} # 'position.update.and.boundary.treatment' end


################################################################################
##                    async.update.pgbests Function                           ##
################################################################################
## Author : Mauricio Zambrano-Bigiarini                                       ## 
################################################################################
## Started: 2008                                                              ##
## Updated: 26-Jan-2012                                                       ##
################################################################################
# Function for updating the values of 'pbest', 'x.best', 'gbest.fit' and 'gbest.pos'
# for ONLY 1 particle !!

# 'x'           : vector with the 'n' parameters of a single particle
# 'x.pos'       : position of the current particle
# 'xt.fitness'  : particle's fitness
# 'MinMax'      : string indicating if PSO have to find a minimum or a maximum 
#                 for the fitness function.
#                 valid values are: "min", "max"
# 'of.name'     : function that will be used for computing the fitness.
# 'l.pbest.fit' : best fitness value found by the particle so far.
# 'gbest.fit'   : best fitness value found by the swarm so far.
# 'gbest.pos'   : position of the particle corresponding to 'gbest.fit'.
# 'x.best'      : 'n' values corresponding to the parameters of the particle 
#                 that achieve the best fitness value for the particle

# Result        : a list of 4 components (this values are different of the input ones,
#                 only if the new values provide a better fitness value )
#               : 1: pbest      : real with the new best fitness value of the particle
#               : 2: x.best     : vector with the new 'n' best parameters for the particle
#               : 3: gbest.fit  : real with the new best fitness value for the swarm
#               : 4: gbest.pos  : integer with the location of the particle that has
#                                 the best fitness value in the swarm

async.update.pgbests <- function(x, 
                                 x.pos, 
                                 xt.fitness,
                                 MinMax, 
                                 l.pbest.fit, 
                                 gbest.fit, 
                                 gbest.pos, 
                                 x.best
                                 ) {
  
  ifelse(MinMax == "max", l.update <- which(xt.fitness > l.pbest.fit ),
                          l.update <- which(xt.fitness < l.pbest.fit ) )
  
  # Updating 'pbest.fit', 'gbest.fit', 'gbest.pos' and 'x.best.part'
  if ( length(l.update>0) ) {
  
    # 'pbest.fit': updating the value of the best fit of the particles
    l.pbest.fit <- xt.fitness
    
    # 'X.best' updating
    x.best <- x  
    
    # 'gbest.fit': updating the value of the best global fit
    # 'gbest.pos': updating the position of the particle with the best global fit
    if ( MinMax=="max" ) {
      if ( l.pbest.fit > gbest.fit ) { 
          gbest.fit <- l.pbest.fit 
          gbest.pos <- x.pos 
      } # IF end 
    } else if ( MinMax=="min" ) {
        if ( l.pbest.fit < gbest.fit ) { 
           gbest.fit <- l.pbest.fit
           gbest.pos <- x.pos 
        } # IF end 
      } # ELSE end 
  
  } # IF end  
                
  tmp      <- list(4)
  tmp[[1]] <- l.pbest.fit
  tmp[[2]] <- x.best
  tmp[[3]] <- gbest.fit
  tmp[[4]] <- gbest.pos 
  names(tmp)  <- c("pbest", "x.best", "gbest.fit", "gbest.pos") 
                
  return(tmp)
                 
} # 'async.update.pgbests' end


################################################################################
##                        sync.update.pgbests Function                        ##
################################################################################
## Author : Mauricio Zambrano-Bigiarini                                       ## 
################################################################################
## Started: 2008                                                              ##
## Updated: 27-Jan-2012                                                       ##
################################################################################
# Function for updating the values of 'pbest', 'x.best', 'gbest.fit' and 'gbest.pos'
# for the ALL the SWARM !!

# 'x'                : Matrix with the 'n' parameters of all the particles
# 'xt.fitness'       : numeric vector of 'n.particles', with the current fitness 
#                      obtained by all the particles in the swarm
# 'MinMax'           : Character indicating if PSO have to find a minimum or a 
#                      maximum for the fitness function.
#                      Valid values are in: c('min', 'max')
# 'pbest.fit'        : numeric vector with length equal to 'n.particles', with the best 
#                      fitness value found by each particle in the swarm so far.
# 'gbest.fit'        : numeric, with the best fitness value found by the swarm so far.
# 'gbest.pos'        : numeric, with the position of the particle corresponding 
#                      to 'gbest.fit'.
# 'x.best'           : Matrix of 'n*n.particles' values, corresponding to the
#                      'n' parameters of each one of the particles in the swarm 
#                      that achieve the best fitness value for the particle

# Result: a list of 4 components (this values are different of the input ones,
#         only if the new values provide a better fitness value )
#       : 1: pbest.fit  : numeric vector with the new best fitness value of each 
#                         particle
#       : 2: x.best     : matrix with the new 'n' best parameters for each particle
#       : 3: gbest.fit  : numeric (single value) with the new best fitness value 
#                         for the swarm
#       : 4: gbest.pos  : integer with the location of the particle that has the 
#                         best fitness value in the swarm   

sync.update.pgbests <- function(x, 
                                xt.fitness, 
                                MinMax, 
                                pbest.fit, 
                                gbest.fit, 
                                gbest.pos, 
                                x.best
                                ) {
  
  # index of all the particles which current fit is better than their last 'pbest'
  ifelse(MinMax == "max", better.index <- which( xt.fitness > pbest.fit ),
                          better.index <- which( xt.fitness < pbest.fit ) )
                          
  # if it exists some particles that have a better fitness value
  if (length(better.index) > 0) {
  
    # 'pbest.fit': updating the value of the best fit for each particle
    pbest.fit[ better.index ] <- xt.fitness[better.index ]
    
    # 'X.best.part': updating the value of the best parameters for the particles 
    #                with better fitness
    x.best[better.index, ] <- x[better.index, ]  
    
    # 'gbest.fit': updating the value of the best global fit
    # 'gbest.pos': updating the position of the particle with the best global fit
    if ( MinMax == "max" ) {    
      if ( max(pbest.fit, na.rm=TRUE) > gbest.fit ) { 
          gbest.pos <- which.max(pbest.fit) 
          #gbest.fit <- max(xt.fitness[better.index ])          
          gbest.fit <- pbest.fit[gbest.pos]
      } # IF end          
    } else if ( MinMax == "min" ) {    
          if ( min(pbest.fit, na.rm=TRUE) < gbest.fit ) { 
              gbest.pos <- which.min(pbest.fit) 
              #gbest.fit <- min(xt.fitness[better.index ])
              gbest.fit <- pbest.fit[gbest.pos]
          } # IF end          
      } # ELSE end 
                                                   
  } # IF end   
  
  # Creating the output
  tmp      <- list(4) 
  tmp[[1]] <- pbest.fit
  tmp[[2]] <- x.best
  tmp[[3]] <- gbest.fit
  tmp[[4]] <- gbest.pos 
  names(tmp)  <- c("pbest", "x.best", "gbest.fit", "gbest.pos") 
                
  return(tmp)
  
} # 'sync.update.pgbests' end


################################################################################
#                          computeCurrentXmaxMin                               #
################################################################################
# Author: Mauricio Zambrano-Bigiarini
# Started: 22-Dec-2010
################################################################################
# Purpose: To compute the minimum parameter range currently embraced for the best
#          positions found so far in the swarm
################################################################################
# 'x.best.part': matrix with the best parameter values for each particle.
#                nrows = number of particles
#                ncols = number of parameters = n 
computeCurrentXmaxMin <- function(x.best.part) {

  # number of parameters
  n <- ncol(x.best.part)

  x.min <- sapply(1:n, function(i,y) { min(y[,i], na.rm=TRUE) }, y = x.best.part)
  x.max <- sapply(1:n, function(i,y) { max(y[,i], na.rm=TRUE) }, y = x.best.part)
	
  out <- cbind(x.min, x.max)
	
  return(out)

                              
}  # 'computeCurrentXmaxMin' END


################################################################################
#                      decrease.search.space Function                          #
################################################################################
## Author : Mauricio Zambrano-Bigiarini                                       ## 
################################################################################
## Started: 2010                                                              ##
## Updated:                                                                   ##
################################################################################
# Decrease the search space according to the methodology proposed in the CPSO #

# 'Lmin.min'        : vector of 'n' elements, with the minimum value that each dimension
#                     take within the minimum searching space defined by the user
# 'Lmin.max'        : vector of 'n' elements, with the maximum value that each dimension
#                     take within the minimum searching space defined by the user
# 'Lmin'            : vector of 'n' elements, with the minimum length that each dimension
#                     can take in the searching space defined by the user
# 'x.MinMaxCurrent' : Matrix with the minimum and maximum values for each dimension 
#                     during the current iteration
#                     Rows = 'n' (number of parameters)
#                     Columns = 2, 
#                     First column has the minimum possible value for each parameter
#                     Second column has the maximum possible value for each parameter
# 'x.MinMaxRange'   : Matrix with the valid range for each parameter of 'X', as 
#                     defined by the user
#                     Rows = 'n' (number of parameters)
#                     Columns = 2, 
#                     First column has the minimum possible value for each parameter
#                     Second column has the maximum possible value for each parameter
# 'x.best'          : vector of 'n' elements with the parameters of the particle 
#                     with the best fitness value
# 'r'               : real between 0 and 1.  Only required when 'use.CLS' =TRUE
#                     represents the rate that is used for decreasing the 
#                     searching space in the chaotic implementation 

# Result            : vector with the 'n' parameters of only 1 particle
decrease.search.space <- function(Lmin, x.MinMaxCurrent, x.MinMaxRange, x.best, r) {
  
  # name of each parameter  
  param.IDs <- row.names(x.MinMaxRange)
  
  # number of dimensions
  n <- length(param.IDs)

  # Removing possible attributes
  x.best     <- as.numeric( x.best ) 
  x.min.curr <- as.numeric( x.MinMaxCurrent[ ,1] )
  x.max.curr <- as.numeric( x.MinMaxCurrent[ ,2] )
  x.min.rng  <- as.numeric( x.MinMaxRange[ ,1] )
  x.max.rng  <- as.numeric( x.MinMaxRange[ ,2] )

  # Current lenght of the parameter space in each dimension
  Lcurr <- x.max.curr - x.min.curr 

  # New desired lenght of the parameter space in each dimension
  Lnew  <- r*Lcurr  

  # Creating the new minimum and maximum boundaries
  x.min.new <- x.min.curr
  x.max.new <- x.max.curr

  # Updating the boundaries when the new length is larger than Lmin
  for (i in 1:n) {
    if (Lnew[i] >= Lmin[i]) {
      x.min.new[i] <- max( x.min.curr[i], x.best[i] - 0.5*Lnew[i] )
      x.max.new[i] <- min( x.max.curr[i], x.best[i] + 0.5*Lnew[i] )
      #x.min.new[i] <- max( x.min.rng[i], x.best[i] - 0.5*Lnew[i] )
      #x.max.new[i] <- min( x.max.rng[i], x.best[i] + 0.5*Lnew[i] )
    } # IF end      
  } # FOR end

  # New lenght of the parameter space in each dimension
  Lnew  <- x.max.new - x.min.new 

  #x.min.new <- pmax(x.min.rng, x.best - 0.5*Lnew )
  #x.max.new <- pmin(x.max.rng, x.best + 0.5*Lnew )
  
  x.MinMaxCurrent[ ,1] <- x.min.new
  x.MinMaxCurrent[ ,2] <- x.max.new
  
  # Relative change achieved in each dimension
  rel.change        <- (Lnew-Lcurr)/Lcurr
  names(rel.change) <- param.IDs 
  
  return(x.MinMaxCurrent) 

} # 'decrease.search.space' end 
#decrease.search.space(Lmin, x.MinMaxCurrent, x.MinMaxRange, x.best, r)


################################################################################
#                            InitializateX                                     #
################################################################################
# Author : Mauricio Zambrano-Bigiarini
# Started: 23-Dec-2010
# Updates: 24-Dec-2010
################################################################################
# Purpose: Function for the initialization of the position and the velocities 
# of all the particles in the swarm
################################################################################
# -) npart     : number of particles
# -) param.IDs : character, with the ID of each parameter/dimension.
#                It has 'n' elements, where 'n' is the number of dimensions
# -) X.MinMax  : Matrix with the minimum and maximum values for each dimension 
#                during the current iteration
#              -) Rows = 'n' (number of parameters)
#              -) Columns = 2, 
#                 First column has the minimum possible value for each parameter
#                 Second column has the maximum possible value for each parameter
# 'init.type' : character, indicating how to carry out the initialization 
#               of the position of all the particles in the swarm
#               valid values are in c('random', 'lhs') 
InitializateX <- function(npart, param.IDs, x.MinMax, x.ini.type) {

  # Number of parameters
  n <- length(param.IDs)
 
  # 'X' #
  # Matrix of unknown parameters. 
  # Rows = 'npart'; 
  # Columns = 'n' (Dimension of the Solution Space)
  # Random bounded values are assigned to each dimension
  if ( x.ini.type=="random" ) {
      X <- Random.Bounded.Matrix(npart, x.MinMax)
  } else X <- rLHS(npart, x.MinMax)      
  colnames(X) <- param.IDs 
  rownames(X) <- paste("Part", 1:npart, sep="")

  return(X)

} # InitializateX


################################################################################
#                            InitializateV                                     #
################################################################################
# Author : Mauricio Zambrano-Bigiarini
# Started: 24-Dec-2010
# Updates: 24-Nov-2011
################################################################################
# Purpose: Function for the initialization of the position and the velocities 
#          of all the particles in the swarm
################################################################################
# -) npart     : number of particles
# -) param.IDs : character, with the ID of each parameter/dimension.
#                It has 'n' elements, where 'n' is the number of dimensions
# -) X.MinMax  : Matrix with the minimum and maximum values for each dimension 
#                during the current iteration
#              -) Rows = 'n' (number of parameters)
#              -) Columns = 2, 
#                 First column has the minimum possible value for each parameter
#                 Second column has the maximum possible value for each parameter
# 'v.ini'      : character, indicating how to carry out the initialization 
#                of the velocitites of all the particles in the swarm
#                valid values are in c(0, 'random', 'lhs') 
InitializateV <- function(npart, param.IDs, x.MinMax, v.ini.type, Xini) {

  # Number of parameters
  n <- length(param.IDs)
 
  # 'V' #
  # Matrix of velocities for each particles and iteration. 
  # Rows = 'npart'; 
  # Columns = 'n' (Dimension of the Solution Space)
  # Random bounded values are assigned to each dimension
  if ( v.ini.type=="random" ) {
      V <- ( Random.Bounded.Matrix(npart, x.MinMax) - Xini)/2
  } else if ( v.ini.type=="lhs" ) {
      V <- ( rLHS(npart, x.MinMax) - Xini)/2
    } else if ( v.ini.type=="zero" ) {
        V <- matrix(0, ncol=n, nrow=npart, byrow=TRUE)    
      }
  colnames(V) <- param.IDs 
  rownames(V) <- paste("Part", 1:npart, sep="")

  return(V)

} # InitializateV



################################################################################
##                            UpdateLocalBest                                 ##
################################################################################
# Author : Mauricio Zambrano-Bigiarini
# Started: 24-Dec-2010
# Updates: 29-Dec-2010 ; 
#          14-Nov-2011 ; 27-Jan-2011
################################################################################
# Purpose: Function for computing the best value in the neighbourhood of each 
#          particle
################################################################################
# pbest.fit    : numeric, with best fitness in the history of each particle
# LocalBest.fit: numeric, best fitness in the history of the neighbourhood of 
#                each particle
# x.neighbours : numeric matrix, with the index/position of the particles that 
#                are considered "informants" of each particle.
#                rows   = number of particles
#                columns= K+1 ; K: nmbr of informants provided by the user
# MinMax       : character, indicating if PSO have to find a minimum or a 
#                maximum for the fitness function.
#                Valid values are in: c('min', 'max')
 
UpdateLocalBest <- function(pbest.fit, localBest.pos, localBest.fit, x.neighbours, MinMax) {

  # Number of particles
  npart <- nrow(x.neighbours)  
  
  for ( i in 1:npart ) {
  
    # index of all the particles that are "neighbours" to the particle 'i'
    neighs.index <- x.neighbours[i,]
   
    # if one or more of the "neighbours" have a better fitness than the current Local Best
    ifelse(MinMax == "max", better.index <- which( pbest.fit[neighs.index] > localBest.fit[i] ),
                            better.index <- which( pbest.fit[neighs.index] < localBest.fit[i] ) )   
   
    # if there are some particles that have a better fitness value
    if (length(better.index) > 0)  
      ifelse(MinMax == "max", localBest.fit[i] <- max( pbest.fit[neighs.index], na.rm=TRUE ) ,
                              localBest.fit[i] <- min( pbest.fit[neighs.index], na.rm=TRUE ) ) 
                              
      ifelse(MinMax == "max", localBest.pos[i] <- neighs.index[which.max( pbest.fit[neighs.index] )] ,
                              localBest.pos[i] <- neighs.index[which.min( pbest.fit[neighs.index] )] )  
    
  } # FOR end 
  
  out <- list(localBest.pos=localBest.pos, localBest.fit=localBest.fit)
  
  return(out)

} # UpdateLocalBest


################################################################################
#                            UpdateNgbest                                      #
################################################################################
# Author : Mauricio Zambrano-Bigiarini
# Started: 24-Dec-2010
# Updates: 29-Dec-2010
################################################################################
# Purpose: Function for computing the 'n.neighbours' best values in the swarm, 
#          and its positions
################################################################################
# pbest.fit : numeric, with best fitness in the history of each particle
# ngbest    : Number of local best that have to be considered
# MinMax    : character, indicating if PSO have to find a minimum or a 
#             maximum for the fitness function.
#             Valid values are in: c('min', 'max')
 
UpdateNgbest <- function(pbest.fit, ngbest, MinMax) {
  
  ifelse(MinMax=="max", sorted.fit <- sort(pbest.fit, decreasing= TRUE), 
                        sorted.fit <- sort(pbest.fit, decreasing= FALSE) ) 
                            
  # Ordered index of all the particles, 
  # MinMax=="max" => Decreasing order
  # MinMax=="min" => Increasing order
  sorted.index <- pmatch(sorted.fit, pbest.fit)
  
  ngbest.fit <- pbest.fit[sorted.index][1:ngbest]  
  ngbest.pos <- sorted.index[1:ngbest]    

  # Creating the output
  out <- list(2)
  out[[1]] <- ngbest.fit
  out[[2]] <- ngbest.pos
  names(out) <- c("ngbest.fit", "ngbest.pos")
  
  return(out)

} # UpdateNgbest


################################################################################
#                    ComputeSwarmRadiusAndDiameter                             #
################################################################################
# Author : Mauricio Zambrano-Bigiarini
# Started: 12-Jan-2011
# Updates: 12-Jan-2011 ; 28-Oct-2011
################################################################################
# Purpose: Function for computing the sarm radius, for detecting premature 
#          convergence, in order to avoid stagnation 
################################################################################
# X      : matrix, with the current parameter values for all the particles
# gbest  : numeric, with the parameter values for the best particle in the swarm
# MinMax : character, indicating if PSO have to find a minimum or a 
#          maximum for the fitness function.
#          Valid values are in: c('min', 'max')
# Lmax   : 
 
ComputeSwarmRadiusAndDiameter <- function(x, gbest, Lmax, MinMax, pbest.fit) {
  
  # number of parameters
  n <- ncol(x)
  
  # number of particles
  npart <- nrow(x)
  
  # Euclidean distance, in the n-dimensional space for all the particles
  radius <- numeric(npart)
  
  gbest  <- matrix(rep(gbest, npart), nrow=npart, byrow=TRUE)
  radius <- sqrt( rowSums( (x-gbest)^2 ) )
  
  swarm.radius   <- max(radius, na.rm=TRUE)
  swarm.diameter <- sqrt(sum(Lmax^2))
  
  # creating the output
  out        <- list(2)
  out[[1]]   <- swarm.radius
  out[[2]]   <- swarm.diameter
  names(out) <- c("swarm.radius", "swarm.diameter")
  
  return( out )

} # ComputeSwarmRadiusAndDiameter


################################################################################
#                           RegroupingSwarm                                    #
################################################################################
# Author : Mauricio Zambrano-Bigiarini
# Started: 13-Jan-2011
# Updates: 18-Nov-2011
################################################################################
# Purpose: Function for regrouping the swarm in a search space centred around 
#          the global best, which is hoped to be both, small enough for efficient 
#          search and large enough to allow the swarm to escape from the current
#          local best
################################################################################
RegroupingSwarm <- function(x, 
                            gbest, 
                            x.Range,
                            Lmax,
                            RG.thr,
                            RG.r) {

  # number of parameters
  n <- ncol(x)
  
  # number of particles
  npart <- nrow(x)

  # Regrouping factor 
  rf <- RG.r          # user-defined
  #rf <- 6/(5*RG.thr) # Evers & Ghalia
  #rf <- (1/RG.thr)/2 # MZB
  
  # name of each parameter  
  param.IDs <- row.names(x.Range)

  # Removing possible attributes
  gbest      <- as.numeric( gbest ) 
  x.min.rng  <- as.numeric( x.Range[ ,1] )
  x.max.rng  <- as.numeric( x.Range[ ,2] )

  # Maximum length of the parameter space in each dimension
  Lmax <- x.max.rng - x.min.rng 

  # Transforming the 'gbest' into a matrix, in order to make easier some 
  # further computations
  Gbest <- matrix(rep(gbest, npart), nrow=npart, byrow=TRUE)

  # New desired length of the parameter space in each dimension
  # Is equal to the product of the regrouping factor with the maximum distance of 
  # each particle to the global best, for each dimension
  Lnew <- rf * apply( abs(x-Gbest), MARGIN=2, FUN=max) 
  #Lnew <- rf * apply( abs(x-Gbest), MARGIN=2, FUN=mean) 
  
  # Making sure that the new range for each dimension is no larger than the original one
  Lnew <- pmin(Lmax, Lnew)

  # Re-initializing particle's positions around gbest
  for (part in 1:npart) {
    r3        <- runif(n, 0, 1) 
    x[part, ] <- gbest + r3*Lnew - 0.5*Lnew
    # If needed, Clamping the particle positions to the maximum value
    x[part, ] <- pmin(x[part,], x.max.rng)
    # If needed, Clamping the particle positions to the minimum value 
    x[part, ] <- pmax(x[part,], x.min.rng)
  } # FOR end
  
  # Relative change achieved in each dimension
  rel.change        <- (Lnew-Lmax)/Lmax
  names(rel.change) <- param.IDs 

  out      <- list(2)
  out[[1]] <- x
  out[[2]] <- Lnew
  names(out)  <- c("X", "Lnew") 
  
  return(out) 
  
} # 'RegroupingSwarm' end


################################################################################
#                      Random.Topology.Generation                              #
################################################################################
# Author : Mauricio Zambrano-Bigiarini
# Started: 23-Nov-2011
# Updates: 
################################################################################
# Purpose: Function for creating a random topology, as implemented on the 
#          Standard PSO 2007
################################################################################
Random.Topology.Generation <- function(npart, K, 
                                       psoout.drty, iter # only needed during testing phase
                                       ) { 

  p.avg <- 1 - (1 - 1/npart)^K
  tmp   <- matrix(runif(npart*npart, 0, 1) <= p.avg, nrow=npart, ncol=npart)
  diag(tmp) <- TRUE
  X.neighbours <- matrix(rep(NA, npart*npart), ncol=npart, nrow=npart, byrow=TRUE)
  for (i in 1:npart) {
       l <- length(which(tmp[,i]))
       X.neighbours[i, 1:l] <- which(tmp[,i])
  } # FOR end
  rownames(X.neighbours) <- paste("Part", 1:npart, sep="")
  colnames(X.neighbours) <- paste("Neigh", 1:npart, sep="")
  
  return(X.neighbours)

} # ELSE end


################################################################################
###  Function for evaluating the hydrological model for a single particle  #####
################################################################################
### Started: 21-Jun-2011                                                     ###
### Updates: 28-Jun-2011                                                     ###
###          19-Jun-2012 ; 03-Jul-2012                                       ###
################################################################################
hydromod.eval <- function(part, Particles, iter, npart, maxit, 
                          REPORT, verbose, digits, 
                          model.FUN, model.FUN.args 
                          ) {

  if ( iter/REPORT == floor(iter/REPORT) ) {
    if (verbose) message("================================================================================")
    if (verbose) message( "[Iter: ", format( iter, width=4, justify="left" ), "/", maxit, 
					   ".  Particle: ", format( part, width=4, justify="left" ), "/", npart, 
				   ":  Starting...]" )
    if (verbose) message("================================================================================")
  } # IF end
    
  # Creating the R output
  nelements <- 2        
  out       <- vector("list", nelements)

  # Evaluating the hydrological model
  model.FUN.args <- modifyList(model.FUN.args, list(param.values=Particles[part,]) ) 
  hydromod.out   <- do.call(model.FUN, as.list(model.FUN.args)) 
   
  out[[1]] <- as.numeric(hydromod.out[["GoF"]])
  out[[2]] <- hydromod.out[["sim"]]
  
  # meaningful names
  names(out)[1:nelements] <- c("GoF", "model.out") 

  if ( iter/REPORT == floor(iter/REPORT) ) {
    if (verbose) message("================================================================================")
    if (verbose) message( "[Iter: ", format( iter, width=4, justify="left" ), "/", maxit,  
                          ".   Particle: ", format( part, width=4, justify="left" ), "/", npart,  
                          ".   Finished !.   GoF: ", format(hydromod.out[["GoF"]], scientific=TRUE, digits=digits), 
                          "]" )
    if (verbose) message("================================================================================")
    if (verbose) message("                                    |                                           ")  
    if (verbose) message("                                    |                                           ")    
  } # IF end
        
  return(out)
  
} # 'hydromod.eval' END


################################################################################
#                                    P.S.O.                                    #
################################################################################
# Author : Mauricio Zambrano-Bigiarini                                         #
################################################################################
# Started: 2008                                                                #
# Updates: Dec-2010                                                            #
#          May-2011    ; 28-Oct-2011 ; 14-Nov-2011 ; 23-Nov-2011 ;             #
#          15-Jan-2012 ; 23-Jan-2012 ; 30-Jan-2012 ; 23-Feb-2012 ; 23-Mar-2012 #
#          14-Jun-2012 ; 15-Jun-2012 ; 03-Jul-2012 ; 06-Jul-2012               #
#          11-Jul-2012 ; 17-Jul-2012 ; 18-Jul-2012 ; 13-Sep-2012; 14-Sep-2012  #                         
################################################################################
# 'lower'           : minimum possible value for each parameter
# 'upper'           : maximum possible value for each parameter
# 'of.name'         : String with the test function that will be used for computing the fitness.
#                     Valid values are in: c('sinc', 'rosenbrock', 'sphere', 
#                     'rastrigin', 'griewank', 'schafferF6', 'hydromod')
# 'MinMax'          : character, indicating if PSO have to find a minimum or a 
#                     maximum for the fitness function.
#                     Valid values are in: c('min', 'max')
# 'npart'           : number of particles that makes the swarm. 
#                     Must be divisible by 5 (requirement for the chaotic part)
# 'maxit'           : numeric, with the maximum number of iterations
# 'c1'              : numeric, representing the cognition constant. 
#                     Encourages the exploration of the solution space.
#                     How much the particle is influenced by the memory of his best location
# 'c2'              : numeric, representing the social constant. 
#                     Encourages the exploitation of the current global best
#                     How much the particle is influenced by the rest of the swarm	
# 'use.CF'          : logical, indicating if the Clerc's Constriction Factor have to be used
#                     to ensure the convergence of the PSO algorithm
# 'lambda'          : numeric in [0,1] representing a percentage to limit
#                     the maximum velocity for each dimension, which is computed
#                     as 'vmax = Vmax.perc*(Xmax-Xmin)'
# 'par'             : OPTIONAL. numeric of length 'n' (number of parameters), 
#                     providing a first guess for the parameters to be optimised. 
#                     If it is not present, all the particles are randomly initialized,
#                     according to the value of \code{Xini.type}
# 'Xini.type'       : character, indicating how to initialise the position of all
#                     the particles in the swarm, within the ranges defined by 
#                     \code{X.Boundaries}. Valid values are: \cr
#                     -) "random": random initialisation
#                     -) "lhs"   : Latin Hypercube initialisation. \bold{it 
#                                  requires the \pkg{lhs} package}
# 'Vini.type        : character, indicating how to initialise the velocity of all
#                     the particles in the swarm, within the ranges defined by 
#                     \code{X.Boundaries}. Valid values are: \cr
#                     -) 0       : all the particles are initialised with zero velocity
#                     -) "random": random initialisation
#                     -) "lhs"   : Latin Hypercube initialisation. \bold{it 
#                                  requires the \pkg{lhs} package}
# 'best.update'     : character, indicating when to update the global and local best
#                     Valid values are: \cr
#                     -) "sync" : the update is made in a synchronous way, i.e., 
#                                 after computing the position and fitness of 
#                                 ALL the particles in the swarm
#                     -) "async": the update is made in an asynchronous way, i.e., 
#                                 after computing the position and fitness of 
#                                 EACH particle in the swarm
# 'boundary.wall'   : Boundary treatment that is used to limit the sea
#                     the limits given by 'X.Boundaries'.
#                     Valid values are: 'absorbing', 'reflecting' and 'invisible'
#                     See  \citet{RobinsonRahmatSamii2004}
# 'topology'        : character, with the neighbourhood topology to be used in PSO. 
#                     Valid values are in \code{c('gbest', 'lbest', 'ipso')}:
#                      \kbd{gbest}: every particle is connected to every other individual,
#                                   and in particular to the best one. This is 
#                                   also termed \textit{star} topology, and it is 
#                                   generally assumed to have a fast convergence. 
#                                   However, if the global optimum is not close 
#                                   to the attraction zone of the best particle, 
#                                   the swarm can get trapped into local optima.
#                                   see Kennedy 1999; Kennedy and Mendes 2002
#                      \kbd{lbest}: each particle is connected to its \textit{K} 
#                                   immediate neighbours only. This is also termed 
#                                   \textit{circles} or \textit{ring} topology, 
#                                   and generally the swarm will converge slower 
#                                   than with the \kbd{gbest} topology,
#                                   but it has a greater chance to locate the
#                                   global optimum. see Kennedy 1999; Kennedy and Mendes 2002
#                      \kbd{ipso}:  At each iteration, al the particles in the swarm
#                                   are rearranged in descending order according 
#                                   to  their fitness value and the best \kbd{ngbest}
#                                   particles to modify particle's position and velocity. 
#                                   See Zhao 2006.
# 'K'               : OPTIONAL. Only used when \code{topology=='lbest'}
#                     numeric, with the total amount of neighbours of each particle
#                     to be considered in the computation of their personal best.
#                     It MUST BE an even number, in order to consider the same 
#                     amount of neighbours to the left and the right of each particle.
#                     By default \code{K=3}. 
# 'iter.ini'        : OPTIONAL. Only used when \code{topology=='lbest'}
#                     numeric, with the amount of iterations in which the topology 
#                     \kbd{gbest} will be used before starting to use the \kbd{lbest}
#                     topology for the computation of the personal best of each particle.
#                     This argument has not been found in literature, and it aims at
#                     making faster the localization of the global zone of attraction. 
#                     By default \code{iter.ini=0}.
# 'ngbest'          : OPTIONAL. Only used when \code{topology=='ipso'}
#                     numeric, with the amount of particles that will be considered 
#                     in the computation of the global best. \cr
#                     By default \code{ngbest=4}. See Zhao 2006.
# 'use.IW'          : logical, indicating if an inertia weight (\env{w}) will be used
#                     to avoid particles fly around their best position without 
#                     converging into it. See Shi and Eberhart 1998 and Zheng et al. 2003.
# 'IW.type'         : OPTIONAL, only required when \code{use.IW= TRUE}.
#                     character, that defined how to vary the inertia weight 
#                     \env{w} along the iterations. Valid values are: \cr
#                     Valid values are: \cr
#                     -) "linear"    : \env{w} varies linearly between the initial 
#                                       and final values specified by the user 
#                                       in \code{IW.w}. 
#                                       See Shi and Eberhart, 1998. and Zheng et al., 2003
#                     -) "non-linear": \env{w} varies non-linearly between the initial 
#                                       and final values specified by the user 
#                                       in \code{IW.w}. 
#                                       See Chatterjee and Siarry, 2006. \cr
#                     -) "runif"     : \env{w} is a uniform random variable in
#                                       the range [w.min, w.max] specified by the user 
#                                       in \code{IW.w}. It is a generalization of 
#                                       the variation proposed in Eberhart and Shi, 2001b
#                     -) "aiwf"      : Adaptive inertia weight factor, where the 
#                                      inertia weight is varied adaptively 
#                                      depending of the objective values of the particles \cr
#                                      See Liu et al., 2005 \cr
#                     -) "GLratio"   : \env{w} varies according to the ration between 
#                                      the global best and the average of the particle's 
#                                      local best. See Arumugam and Rao, 2008 \cr
# 'IW.w'            : OPTIONAL, only required when \code{use.IW= TRUE & IW.type!='GLratio'}
#                     numeric with the inertia weight(s) (\env{w} or \env{[w.ini, w.fin]}). 
#                     It can be one single number which is then used during all the algorithm, 
#                     or it can be a vector of length 2, with the initial and final values 
#                     (in that order) that \env{w} will take along the iterations
# 'IW.exp'          : OPTIONAL, only required when \code{use.IW= TRUE} AND \code{IW.type= 'non-linear'}
#                     non-linear modulation index. See Chatterjee and Siarry, 2006. \cr
#                     When \code{IW.type='linear'}, \code{IW.exp} is set to 1.
# 'use.TVc1'        : logical, indicating if the cognitive constant (c1) will have
#                     a time-varying value instead of a constant one provided by the user.
#                     See Ratnaweera et al., 2004
# 'TVc1.type'       : character, required only when \code{use.TVc1 = TRUE}.
#                     Valid values are in: \code{c('linear', 'non-linear', 'GLratio')}
# 'TVc1.rng'        : OPTIONAL, only required when \code{use.TVc1= TRUE & TVc1.type!='GLratio'}
#                     numeric with the initial and final values for the cognitive 
#                     constant \env{[c1.ini, c1.fin]} (in that order) along the iterations
# 'TVc1.exp'        : OPTIONAL, only required when \code{use.TVc1= TRUE} AND ('TVc1.type'= "non-linear"). \cr
#                     non-linear modulation index. When  \code{TVc1.type= 'linear} 
#                     \code{TVc1.exp} is set to 1.   
#                     When \code{TVc1.exp} is equal to 1, \code{TVc1} corresponds 
#                     to the improvement proposed by Ratnaweera et al., 2004,
#                     whereas when \code{TVc1.exp} is different from one, no reference 
#                     has been found in literature by the authors, but it was included 
#                     as an option taking into account the work of Chatterjee and 
#                     Siarry 2006 for the inertia weight.\cr                      
# 'use.TVc2'        : logical, indicating if the social constant (c2) will have
#                     a time-varying value instead of a constant one provided by the user.
#                     See Ratnaweera et al., 2004
# 'TVc2.type'       : character, required only when \code{use.TVc2 = TRUE}.
#                     Valid values are in: \code{c('linear', 'non-linear')}
# 'TVc2.rng'        : OPTIONAL, only required when \code{use.TVc2= TRUE}
#                     numeric with the initial and final values for the social 
#                     constant \env{[c2.ini, c2.fin]} (in that order) 
#                     for \env{c1} along the iterations
# 'TVc2.exp'        : OPTIONAL, only required when \code{use.TVc1= TRUE} AND ('TVc1.type'= "non-linear"). \cr
#                     non-linear modulation index. When  \code{TVc1.type= 'linear} 
#                     \code{TVc1.exp} is set to 1. 
#                     When \code{TVc2.exp} is equal to 1, \code{TVc2} corresponds 
#                     to the improvement proposed by Ratnaweera et al., 2004,
#                     whereas when \code{TVc2.exp} is different from one, no reference 
#                     has been found in literature by the authors, but it was included 
#                     as an option taking into account the work of Chatterjee and 
#                     Siarry 2006 for the inertia weight.\cr  
# 'use.RG'          : logical, indicating if the swarm should be regrouped when 
#                     premature convergence is detected. When \code{use.RG=TRUE} 
#                     the swarm is regrouped in a search space centred about gbest,
#                     which is hoped to be both small enough for efficient search 
#                     and large enough to allow the swarm to escape from stagnation. 
#                     See Evers and Ghalia 2009
# 'RG.thr'          : ONLY required when \code{use.RG=TRUE}. \cr
#                     numeric with a positive value representing the 
#                     \kbd{stagnation threshold}, which is used to decide if the 
#                     swarm has to be regrouped or not. See Evers and Galia 2009 
#                     for further details \cr
#                     Regrouping occurs when the \kbd{normalised swarm radius} 
#                     is less than \code{RG.thr}.                   
# 'RG.r'            : ONLY required when \code{use.RG=TRUE}. \cr
#                     numeric with a positive value representing the 
#                     \kbd{regrouping factor}, which is used to regroup the swarm 
#                     in a search space centred about the global best, which is 
#                     hoped to be both small enough for efficient search and 
#                     large enough to allow the swarm escape from the current well. 
#                     See Evers and Galia 2009 for further details 
# 'RG.miniter'      : ONLY required when \code{use.RG=TRUE}. \cr
#                     numeric with the minimum number of iterations needed before 
#                     regrouping
# 'psoout.drty'     : character, with the name of the directory where the output 
#                     files will be written
# 'use.DS'          : Boolean. It indicates if the solution space will be decreased 
#                     when the particles are stagned around gbest
# 'DS.dmin'         : Real between 0 and 1, indicating the minimum length of 
#                     each dimension accepted by the user. 
#                     Only required when 'use.DS' = TRUE 
# 'DS.tol'          : Real. Tolerance that will be used for deciding when
#                     to decrease the solution space 
#                     It starts when 'gbest.fit.rate' < DS.tol, 
#                     gbest.fit.rate = abs( [gbest.fit(n)-gbest.fit(n-1)/gbest.fit(n) )
#                     Only required when 'use.DS' = TRUE 
# 'DS.r'            : Real between 0 and 1. 
#                     represents the rate that is used for decreasing the 
#                     searching space 
#                     Only required when 'use.DS' = TRUE 
# 'out.with.pbest'  : Logical, indicating if the best parameter values for each 
#                     particle and their fitness has to be included in the output 
#                     of the algorithm 
# 'out.with.fit.iter: Logical,indicating if the fitness of each particle and in 
#                     each iteration has to be included in the output of the algorithm
# 'write2disk'      : Logical, indicating if output files have to be written to
#                     the disk or not  
# 'param.ranges'    : character, with the name of the file that stores the desired 
#                     range of variation for each
# 'verbose'         : logical, should progress messages be printed ?
# 'REPORT'          : OPTIONAL, only used when \code{verbose=TRUE}.
#                     The frequency of report messages printed to the screen. Default
#                     to every 10 iterations

# optim:
#    par, fn, gr = NULL, ..., method = c("Nelder-Mead", 
#    "BFGS", "CG", "L-BFGS-B", "SANN"), lower = -Inf, upper = Inf, 
#    control = list(), hessian = FALSE

hydroPSO <- function(
                    par, 
                    fn="hydromod",  
                    ...,
                    method=c("pso", "ipso", "fips", "wfips"),
                    lower=-Inf,
                    upper=Inf,                
                    control=list(),
                    model.FUN=NULL,
                    model.FUN.args=list()
                    ) {

    ########################################################################
    # 0) Checkings and Basic computations - Start                          #
    ########################################################################

    if (!missing(par)) { 
      if (class(par)=="numeric") {
	n <- length(par)
      } else if ( (class(par)=="matrix") | (class(par)=="data.frame") ) {
	  n <- ncol(par)
	} # ELSE IF end
    } else n <- NULL
    if (missing(fn)) {
      stop("Missing argument: 'fn' must be provided")
    } else {
	fn.name <- fn
	fn      <- match.fun(fn)
      } # ELSE end 

    method <- match.arg(method)       

    if (length(lower) != length(upper) )
      stop( paste( "Invalid argument: 'length(lower) != length(upper) (", length(lower), "!=", length(upper), ")'", sep="" ) )

    if (!is.null(n)) {
       if (length(lower) != n)
	 stop( paste( "Invalid argument: 'length(lower) != nparam (", length(lower), "!=", n, ")'", sep="" ) )             
       if (length(upper) != n)
	 stop( paste( "Invalid argument: 'length(upper) != nparam (", length(lower), "!=", n, ")'", sep="" ) )
    } else n <- length(lower)      

    ############################################################################

    con <- list(
	    drty.in="PSO.in",
	    drty.out="PSO.out",
	    param.ranges="ParamRanges.txt",    
	    digits=7,

	    MinMax=c("min", "max"), 
	    npart=NA, 
	    maxit=1000, 
	    maxfn=Inf,
	    c1= 0.5+log(2), 
	    c2= 0.5+log(2), 
	    use.CF= FALSE, 
	    lambda= 1, 
	    abstol= NULL,    
	    reltol=sqrt(.Machine$double.eps),             
	    Xini.type=c("lhs", "random"),  
	    Vini.type=c("lhs", "random", "zero"), 
	    best.update=c("sync", "async"),
	    random.update=TRUE,
	    boundary.wall=c("reflecting", "damping", "absorbing", "invisible"),
	    topology=c("random", "gbest", "lbest", "vonNeumann"), K=3, iter.ini=0, ngbest=4, # only used when 'method=ipso'   

	    use.IW = TRUE, IW.type=c("linear", "non-linear", "runif", "aiwf", "GLratio"), IW.w=1/(2*log(2)), IW.exp= 1, 
	    use.TVc1= FALSE, TVc1.type=c("non-linear", "linear", "GLratio"), TVc1.rng= c(1.28, 1.05), TVc1.exp= 1.5, 
	    use.TVc2= FALSE, TVc2.type=c("non-linear", "linear"), TVc2.rng= c(1.05, 1.28), TVc2.exp= 1.5, 
	    use.TVlambda=FALSE, TVlambda.type=c("non-linear", "linear"), TVlambda.rng= c(1, 0.25), TVlambda.exp= 1, 
	    use.RG = FALSE, RG.thr= 1.1e-4, RG.r= 0.8, RG.miniter= 5, # RG.r not used in reagrouping
	    
	    plot=FALSE,                
	    out.with.pbest=FALSE,
	    out.with.fit.iter=FALSE,
	    write2disk=TRUE,

	    verbose=TRUE,
	    REPORT=100 
	       )

    MinMax        <- match.arg(control[["MinMax"]], con[["MinMax"]])
    Xini.type     <- match.arg(control[["Xini.type"]], con[["Xini.type"]]) 
    Vini.type     <- match.arg(control[["Vini.type"]], con[["Vini.type"]]) 
    best.update   <- match.arg(control[["best.update"]], con[["best.update"]]) 
    boundary.wall <- match.arg(control[["boundary.wall"]], con[["boundary.wall"]]) 
    topology      <- match.arg(control[["topology"]], con[["topology"]]) 
    IW.type       <- match.arg(control[["IW.type"]], con[["IW.type"]])
    TVc1.type     <- match.arg(control[["TVc1.type"]], con[["TVc1.type"]]) 
    TVc2.type     <- match.arg(control[["TVc2.type"]], con[["TVc2.type"]]) 
    TVlambda.type <- match.arg(control[["TVlambda.type"]], con[["TVlambda.type"]])
        	       
    nmsC <- names(con)
    con[(namc <- names(control))] <- control
    if (length(noNms <- namc[!namc %in% nmsC])) 
      warning("[Unknown names in control: ", paste(noNms, collapse = ", "), " (not used) !]")	       

    drty.in           <- con[["drty.in"]]
    drty.out          <- con[["drty.out"]]
    param.ranges      <- con[["param.ranges"]]         
    digits            <- con[["digits"]]

    npart             <- ifelse(is.na(con[["npart"]]),ceiling(10+2*sqrt(n)),con[["npart"]])
    maxit             <- con[["maxit"]] 
    maxfn             <- con[["maxfn"]] 
    c1                <- con[["c1"]] 
    c2                <- con[["c2"]] 
    use.CF            <- con[["use.CF"]] 
    lambda            <- con[["lambda"]]  
    abstol            <- con[["abstol"]]     
    reltol            <- con[["reltol"]]             
    random.update     <- as.logical(con[["random.update"]])
    K                 <- con[["K"]]      
    iter.ini          <- con[["iter.ini"]]
    ngbest            <- con[["ngbest"]]             
    use.IW            <- as.logical(con[["use.IW"]])
    IW.w              <- con[["IW.w"]]
    IW.exp            <- con[["IW.exp"]]
    use.TVc1          <- as.logical(con[["use.TVc1"]])
    TVc1.rng          <- con[["TVc1.rng"]]
    TVc1.exp          <- con[["TVc1.exp"]]
    use.TVc2          <- as.logical(con[["use.TVc2"]])
    TVc2.rng          <- con[["TVc2.rng"]]
    TVc2.exp          <- con[["TVc2.exp"]]
    use.TVlambda      <- as.logical(con[["use.TVlambda"]])
    TVlambda.rng      <- con[["TVlambda.rng"]]
    TVlambda.exp      <- con[["TVlambda.exp"]]
    use.RG            <- as.logical(con[["use.RG"]])
    RG.thr            <- con[["RG.thr"]]
    RG.r              <- con[["RG.r"]]
    RG.miniter        <- con[["RG.miniter"]]
    plot              <- as.logical(con[["plot"]])            
    out.with.pbest    <- as.logical(con[["out.with.pbest"]])
    out.with.fit.iter <- as.logical(con[["out.with.fit.iter"]])
    write2disk        <- as.logical(con[["write2disk"]])
    verbose           <- as.logical(con[["verbose"]])
    REPORT            <- con[["REPORT"]] 

    ############################################################################
    ######################### Dummy checkings ##################################

    if (maxit < REPORT) {
      REPORT <- maxit
      warning("[ 'REPORT' is greater than 'maxit' => 'REPORT=maxit' ]")
    } # IF end

    if ( (lambda < 0) | (lambda >1) )
      stop("Invalid argument: 'lambda' has to be in [0, 1] !!")

    if ( K > npart ) {
      K <- npart
      warning("[ 'K' is greater than 'npart' => 'K=npart' ]")
    } # IF end

    if ( (K < 1) | (floor(K) != K) ) {
      K <- npart
      stop("'K' must be a positive integer (> 0) !!'")
    } # IF end
    
    ifelse( ("gof.Ini" %in% names(model.FUN.args)), gof.Ini.exists <- TRUE, gof.Ini.exists <- FALSE )
    ifelse( ("gof.Fin" %in% names(model.FUN.args)), gof.Fin.exists <- TRUE, gof.Fin.exists <- FALSE )
    ############################################################################  
    # 1)                              Initialisation                           #
    ###################################################$$$$#####################  
    if (verbose) message("                                                                                ")          
    if (verbose) message("================================================================================")
    if (verbose) message("[                                Initialising  ...                             ]")
    if (verbose) message("================================================================================")
    if (verbose) message("                                                                                ")        

    tmp.stg <- c("npart", "maxit", "method", "topology", "boundary.wall")
    tmp.val <- c(npart, maxit, method, topology, boundary.wall)
    message("[", paste(tmp.stg, tmp.val, collapse = " ; ", sep="="), "]")

    if (length(yesNms <- namc[namc %in% nmsC])) {          
      yesVals <- con[pmatch(namc[namc %in% nmsC], nmsC)][c(yesNms)]
      message("         ")
      message("[ user-definitions in control: ", paste(yesNms, yesVals, collapse = " ; ", sep="="), " ]")
      message("         ")          
    } # IF end

    if (fn.name=="hydromod") {

      if (drty.in == basename(drty.in) )
	drty.in <- paste( getwd(), "/", drty.in, sep="")

      if ( !file.exists( file.path(drty.in) ) )
	 stop( paste("Invalid argument: The directory '", drty.in, "' doesn't exist !", sep="") )

      if (param.ranges == basename(param.ranges) )
	 param.ranges <- paste( file.path(drty.in), "/", param.ranges, sep="")

      if ( !file.exists( param.ranges ) )
	 stop( paste("Invalid argument: The file '", param.ranges, "' doesn't exist !", sep="") ) 

      if ( is.null(model.FUN) ) {
	stop( "'model.FUN' has to be defined !" )
      } else  {
	  model.FUN.name <- model.FUN
	  model.FUN      <- match.fun(model.FUN)
	} # ELSE end

      if ( length(model.FUN.args)==0 ) {
	warning( "[ 'model.FUN.args' is an empty list. Are you sure your model does not have any argument(s) ? ]" )
      } else {
	  model.FUN.argsDefaults <- formals(model.FUN)
	  model.FUN.args         <- modifyList(model.FUN.argsDefaults, model.FUN.args) 
	} # ELSe end

    } # IF end    

    # checking 'X.Boundaries' 
    if (fn.name=="hydromod") {

	if (verbose) message("================================================================================")
	if (verbose) message("[                          Reading 'param.ranges' ...                          ]")
	if (verbose) message("================================================================================") 

	X.Boundaries <- read.ParameterRanges(ParamRanges.fname=param.ranges) 

    } else {
	if ( (lower[1L] == -Inf) || (upper[1L] == Inf) ) {
	  stop( "Invalid argument: 'lower' and 'upper' boundaries must be finite !!'" )
	} else X.Boundaries <- cbind(lower, upper)              
      } # ELSE end

    n <- nrow(X.Boundaries)

    if (is.null(rownames(X.Boundaries))) {
      param.IDs <- paste("Param", 1:n, sep="")
    } else param.IDs <- rownames(X.Boundaries)   

    if (drty.out == basename(drty.out) )
      drty.out <- paste( getwd(), "/", drty.out, sep="")

    if (!file.exists(file.path(drty.out))) {
      if (write2disk) {
	dir.create(file.path(drty.out))
	if (verbose) message("                                            ")
	if (verbose) message("[ Output directory '", basename(drty.out), "' was created on: '", dirname(drty.out), "' ]") 
	if (verbose) message("                                            ")
      } # IF end
    } # IF end  

    if (is.null(abstol)) ifelse(MinMax == "max", abstol <- +Inf, abstol <- -Inf)

    if (Xini.type=="lhs") { 
	if ( is.na( match("lhs", installed.packages()[,"Package"] ) ) ) {
	    warning("[ Package 'lhs' is not installed =>  Xini.type='random' ]")
	    Xini.type <- "random"
	}  # IF end  
    } # IF end

    if (Vini.type=="lhs") { 
	if ( is.na( match("lhs", installed.packages()[,"Package"] ) ) ) {
	    warning("[ Package 'lhs' is not installed =>  Vini.type='random' ]")
	    Vini.type <- "random"
	}  # IF end  
    } # IF end

    if (use.IW) {
       w <- IW.w   

       if (length(w) == 2) {    
	   w.ini <- w[1] #initial inertial weight at the start of a given run
	   w.fin <- w[2] #final inertial weight at the end of a given run
       } else if (length(w) == 1) {
	      w.ini <- w
	      w.fin <- w
	 } else stop("Invalid argument: 'length(w)' must be 1 or 2 !!")

       if  (IW.type == "linear") {
	   if (IW.exp != 1) {
	     warning("[ IW.type == 'linear' => 'IW.exp=1' ]")
	     IW.exp= 1 
	   } # IF end
       } # IF end                
    } # IF end

    if (use.CF) {
      if (c1+c2 < 4) stop("Invalid argument: 'c1+c2' must be >= 4 when 'use.CF=TRUE'")
      CF <- compute.CF(c1, c2)

      if ( use.TVc1 ) stop("Invalid argument: You can not use 'TVc1' when 'use.CF=TRUE'")
      if ( use.TVc2 ) stop("Invalid argument: You can not use 'TVc2' when 'use.CF=TRUE'")
    } else CF <- 1  

    if ( use.IW & use.CF ) 
      stop("Invalid argument: Inertia Weight and Constriction Factor can not be used simultaneously !!")       

    if (use.TVc1) {         
       c1.ini <- TVc1.rng[1]
       c1.fin <- TVc1.rng[2]                
       if  (TVc1.type == "linear") {
	   if (TVc1.exp != 1) {
	     warning("[ TVc1.type == 'linear' => 'TVc1.exp=1' ]")
	     TVc1.exp= 1 
	   } # IF end
       } # IF end              
    } # IF end
    if (use.TVc2) {      
       c2.ini <- TVc2.rng[1]
       c2.fin <- TVc2.rng[2]                  
       if  (TVc2.type == "linear") {
	   if (TVc2.exp != 1) {
	     warning("[ TVc2.type == 'linear' => 'TVc2.exp=1' ]")
	     TVc2.exp= 1 
	   } # IF end
       } # IF end             
    } # IF end

    if (use.TVlambda) {            
       # Computing ('vmax.ini', 'vmax.fin') 
       vmax.ini <- TVlambda.rng[1]
       vmax.fin <- TVlambda.rng[2]                  
       if  (TVlambda.type == "linear") {
	   if (TVlambda.exp != 1) {
	     warning("[ TVlambda.type == 'linear' => 'TVlambda.exp=1' ]")
	     TVlambda.exp= 1 
	   } # IF end
       } # IF end             
    } # IF end

    if ( (topology == "lbest") | (topology == "random") ) {

       if (topology == "lbest") {
	 if (K != npart) {
	   if ( (trunc((K-1)/2) -(K-1)/2) != 0 )
	       stop("Invalid argument: 'K' must be odd" )
	 } # IF end
       } # IF end
    } else if (topology=="vonNeumann") {
	   topology <- "lbest"
	   if (npart < 5) stop("Invalid argument: for 'vonNeumann' topology 'npart' should be >= 5 !!")
	   if (K != 5) K <- 5
	   } else if (topology == "gbest") {
	       K <- npart  
	     } # ELSE end

    if ( method == "ipso" ) {
       if ( (ngbest < 1) | (ngbest > npart) )
	 stop("Invalid argument: 'ngbest' must be in [1, 'npart]'" )

       if ( topology!="gbest") {
	 if (verbose) warning("[ Note: 'method=ipso' => 'topology' was changed to 'gbest' !]" )
	 topology <- "gbest"
       } # IF end
    } # IF end

    Lmax <- (X.Boundaries[ ,2] - X.Boundaries[ ,1])        

    ########################################################################
    # 2) Initialization of Swarm location and velocities                   #
    ########################################################################

    X.Boundaries.current <- X.Boundaries

    Vmax <- lambda*Lmax

    X <- InitializateX(npart=npart, param.IDs=param.IDs, 
		       x.MinMax=X.Boundaries, x.ini.type=Xini.type)
    V <- InitializateV(npart=npart, param.IDs=param.IDs, 
		       x.MinMax=X.Boundaries, v.ini.type=Vini.type, Xini=X)
    V <- t(apply(V, MARGIN=1, FUN=velocity.boundary.treatment, vmax=Vmax))

    if (!missing(par)) {
      if (!any(is.na(par)) && all(par>=lower) && all(par<=upper)) { 
	if (class(par)=="numeric") {
	  X[1,] <- par 
	} else if ( (class(par)=="matrix") | (class(par)=="data.frame") ) {
	  tmp <- ncol(par)
	  if ( tmp != n )
	    stop( paste("Invalid argument: 'ncol(par) != n' (",tmp, "!=", n, ")", sep="") )
	  tmp <- nrow(par)
	  X[1:tmp,] <- par 
	} # ELSE end
      } # IF end  
    } # IF end

    X.best.part <- X

    # Worst possible value defined for the objective function
    ifelse(MinMax == "max", fn.worst.value <- -.Machine$double.xmax/2, 
                            fn.worst.value <- +.Machine$double.xmax/2)
                            
    pbest.fit            <- rep(fn.worst.value, npart)     
    pbest.fit.iter       <- fn.worst.value
    pbest.fit.iter.prior <- fn.worst.value*2
			    
    gbest.fit       <- fn.worst.value
    gbest.fit.iter  <- rep(gbest.fit, maxit)
    gbest.fit.prior <- gbest.fit
    gbest.pos       <- 1

    Xt.fitness <- matrix(rep(fn.worst.value, maxit*npart), ncol=npart, nrow=maxit, byrow=TRUE)       
    colnames(Xt.fitness) <- paste("Part", 1:npart, sep="")
    rownames(Xt.fitness) <- paste("iter.", 1:maxit, sep="") 

    if (topology != "random") {
      nc <- K  
      ifelse(trunc(K/2) != ceiling(K/2), N   <- (K-1)/2, N  <- K/2)
      ifelse(trunc(K/2) != ceiling(K/2), NN  <- 1, NN  <- 0)

      X.neighbours <- matrix(rep(-NA, nc*npart), ncol=nc, nrow=npart, byrow=TRUE)
      for ( i in 1:npart) {
	for ( j in -N:N ) {
	  neigh.index <- i + j
	  if ( neigh.index  < 1 )           neigh.index <- npart + neigh.index
	  if ( neigh.index  > npart ) neigh.index <- neigh.index - npart

	  X.neighbours[i,j+N+NN] <- neigh.index
	} # FOR end
      } # FOR end                      
      rownames(X.neighbours) <- paste("Part", 1:npart, sep="")
      colnames(X.neighbours) <- paste("Neigh", 1:nc, sep="")
    } # IF end 

    LocalBest.fit <- rep(fn.worst.value, npart)

    LocalBest.pos <- 1:npart

    if ( topology == "ipso") { 
      ngbest.fit <- rep(fn.worst.value, ngbest)

      ngbest.pos <- rep(1, ngbest)
    } else {
	ngbest.fit <- NA           
	ngbest.pos <- NA
      } # ELSE end

    ############################################################################  
    #                          Text Files initialization                       #
    ############################################################################  
    if (write2disk) {

      if (verbose) message("                                                                                ")
      if (verbose) message("================================================================================")
      if (verbose) message("[ Writing the 'PSO_logfile.txt' file ...                                       ]")
      if (verbose) message("================================================================================") 

      PSOparam.fname <- paste(file.path(drty.out), "/", "PSO_logfile.txt", sep="")
      PSOparam.TextFile  <- file(PSOparam.fname , "w+")
      
      writeLines("================================================================================", PSOparam.TextFile)  
      writeLines(c("Platform          :", sessionInfo()[[1]]$platform), PSOparam.TextFile, sep="  ")
      writeLines("", PSOparam.TextFile) 
      writeLines(c("R version         :", sessionInfo()[[1]]$version.string), PSOparam.TextFile, sep="  ")
      writeLines("", PSOparam.TextFile) 
      writeLines(c("hydroPSO version  :", sessionInfo()$otherPkgs$hydroPSO$Version), PSOparam.TextFile, sep="  ")
      writeLines("", PSOparam.TextFile) 
      writeLines(c("hydroPSO Built    :", sessionInfo()$otherPkgs$hydroPSO$Built), PSOparam.TextFile, sep="  ")
      writeLines("", PSOparam.TextFile) 
      writeLines("================================================================================", PSOparam.TextFile)  
      Time.Ini <- Sys.time()
      writeLines(c("Starting Time     :", date()), PSOparam.TextFile, sep=" ")
      writeLines("", PSOparam.TextFile) 
      writeLines("================================================================================", PSOparam.TextFile)  
      writeLines(c("Objective Function:", fn.name), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      writeLines(c("Dimension         :", n), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      writeLines(c("Nmbr of Particles :", npart), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      writeLines(c("Max Iterations    :", maxit), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      writeLines(c("Method            :", method), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      if ( method == "ipso" ) {
	writeLines(c("ngbest           :", ngbest), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile)  
      } # IF end
      writeLines(c("Topology          :", topology), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      if ( (topology == "lbest") | (topology == "random") ) {
	writeLines(c("K                 :", K), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile)  
	writeLines(c("iter.ini          :", iter.ini), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile)  
      } # IF end
      writeLines(c("Boundary wall     :", boundary.wall), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      writeLines(c("Best update method:", best.update), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      writeLines(c("Random update     :", random.update), PSOparam.TextFile, sep=" ") 
      writeLines("", PSOparam.TextFile) 
      if (use.TVc1) {
	writeLines(c("use.TVc1          :", use.TVc1), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVc1.type         :", TVc1.type), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVc1.rng          :", TVc1.rng), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVc1.exp          :", TVc1.exp), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
      } else {
        writeLines(c("c1                :", c1), PSOparam.TextFile, sep=" ") 
        writeLines("", PSOparam.TextFile) 
      } # ELSE end
      if (use.TVc2) {
	writeLines(c("use.TVc2          :", use.TVc2), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVc2.type         :", TVc2.type), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVc2.rng          :", TVc2.rng), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVc2.exp          :", TVc2.exp), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
      } else {
        writeLines(c("c2                :", c2), PSOparam.TextFile, sep=" ") 
        writeLines("", PSOparam.TextFile) 
      } # ELSE end 
      if (use.TVlambda) {
	writeLines(c("use.TVlambda      :", use.TVlambda), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVlambda.type     :", TVlambda.type), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVlambda.rng      :", TVlambda.rng), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("TVlambda.exp      :", TVlambda.exp), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
      } else {
        writeLines(c("lambda            :", lambda), PSOparam.TextFile, sep=" ") 
        writeLines("", PSOparam.TextFile)   
      }  # ELSE end
      if (use.IW) {
	writeLines(c("use.IW            :", use.IW), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("IW.type           :", IW.type), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("IW.w              :", IW.w), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
	writeLines(c("IW.exp            :", IW.exp), PSOparam.TextFile, sep=" ") 
	writeLines("", PSOparam.TextFile) 
      }  # IF end
      writeLines(c("maxfn             :", maxfn), PSOparam.TextFile, sep=" ")  
      writeLines("", PSOparam.TextFile) 
      writeLines(c("abstol            :", abstol), PSOparam.TextFile, sep=" ")  
      writeLines("", PSOparam.TextFile) 
      writeLines(c("reltol            :", reltol), PSOparam.TextFile, sep=" ")  
      writeLines("", PSOparam.TextFile)       
      close(PSOparam.TextFile) 

      # File 'Model_out.txt' #
      OFout.Text.fname <- paste(file.path(drty.out), "/", "Model_out.txt", sep="")
      OFout.Text.file  <- file(OFout.Text.fname, "w+")
      
      writeLines(c("Iter", "Part", "GoF", "Model_Output"), OFout.Text.file, sep="  ") 
      writeLines("", OFout.Text.file) 
      close(OFout.Text.file) 

      # File 'Particles.txt' #
      Particles.Textfname <- paste(file.path(drty.out), "/", "Particles.txt", sep="")
      Particles.TextFile  <- file(Particles.Textfname, "w+")
      
      writeLines(c("Iter", "Part", "GoF", param.IDs), Particles.TextFile, sep=" ") 
      writeLines("", Particles.TextFile) 
      close(Particles.TextFile) 

      # File 'Velocities.txt' #
      Velocities.Textfname <- paste(file.path(drty.out), "/", "Velocities.txt", sep="")
      Velocities.TextFile  <- file(Velocities.Textfname, "w+")
      
      writeLines(c("Iter", "Part", "GoF", param.IDs), Velocities.TextFile, sep=" ") 
      writeLines("", Velocities.TextFile) 
      close(Velocities.TextFile) 

      # File 'ConvergenceMeasures.txt' #
      ConvergenceMeasures.Textfname <- paste(file.path(drty.out), "/", "ConvergenceMeasures.txt", sep="")
      ConvergenceMeasures.TextFile  <- file(ConvergenceMeasures.Textfname, "w+")
      
      writeLines(c("Iter", "Gbest", "GbestRate[%]", "IterBestFit", "normSwarmRadius", "|gbest-mean(pbest)|/mean(pbest)[%]"), ConvergenceMeasures.TextFile, sep=" ") 
      writeLines("", ConvergenceMeasures.TextFile) 
      close(ConvergenceMeasures.TextFile)   

      # File 'BestParamPerIter.txt' #
      BestParamPerIter.Textfname <- paste(file.path(drty.out), "/", "BestParamPerIter.txt", sep="")
      BestParamPerIter.TextFile  <- file(BestParamPerIter.Textfname, "w+")
      
      writeLines(c("Iter", "GoF", param.IDs), BestParamPerIter.TextFile, sep="  ") 
      writeLines("", BestParamPerIter.TextFile) 
      close(BestParamPerIter.TextFile) 
      
      # File 'PbestPerIter.txt' #
      PbestPerIter.Textfname <- paste(file.path(drty.out), "/", "PbestPerIter.txt", sep="")
      PbestPerIter.TextFile  <- file(PbestPerIter.Textfname, "w+")
      
      writeLines(c("Iter", paste("Part", 1:npart, sep="") ), PbestPerIter.TextFile, sep="  ") 
      writeLines("", PbestPerIter.TextFile) 
      close(PbestPerIter.TextFile) 
      
      # File 'LocalBestPerIter.txt' #
      LocalBestPerIter.Textfname <- paste(file.path(drty.out), "/", "LocalBestPerIter.txt", sep="")
      LocalBestPerIter.TextFile  <- file(LocalBestPerIter.Textfname, "w+")
      
      writeLines(c("Iter", paste("Part", 1:npart, sep="") ), LocalBestPerIter.TextFile, sep="  ") 
      writeLines("", LocalBestPerIter.TextFile) 
      close(LocalBestPerIter.TextFile) 

      if (use.RG) {
	# File 'Xmin.txt' #
	Xmin.Text.fname <- paste(file.path(drty.out), "/", "Xmin.txt", sep="")
	Xmin.Text.file  <- file(Xmin.Text.fname, "w+")
	
	writeLines(c("Iter", param.IDs), Xmin.Text.file, sep="  ") 
	writeLines("", Xmin.Text.file) 
	writeLines(as.character(c(1, X.Boundaries[,1])), Xmin.Text.file, sep=" ")
	writeLines("", Xmin.Text.file) 
	close(Xmin.Text.file)     

	# File 'Xmax.txt' #
	Xmax.Text.fname <- paste(file.path(drty.out), "/", "Xmax.txt", sep="")
	Xmax.Text.file  <- file(Xmax.Text.fname, "w+")
	
	writeLines(c("Iter", param.IDs ), Xmax.Text.file, sep="  ")
	writeLines("", Xmax.Text.file)  
	writeLines(as.character(c(1, X.Boundaries[,2])), Xmax.Text.file, sep=" ")
	writeLines("", Xmax.Text.file) 
	close(Xmax.Text.file)      
      } # IF end  

      if (fn.name=="hydromod") {
	##############################################################################
	# 2)                           Writing Info File
	##############################################################################  

	if (verbose) message("================================================================================")
	if (verbose) message("[ Writing the 'hydroPSO_logfile.txt' file ...                                  ]")
	if (verbose) message("================================================================================") 


	# File 'hydroPSO_logfile.txt' #        
	hydroPSOparam.fname <- paste(file.path(drty.out), "/", "hydroPSO_logfile.txt", sep="")
	hydroPSOparam.TextFile  <- file(hydroPSOparam.fname , "w+")
	
	writeLines("================================================================================", hydroPSOparam.TextFile) 
	writeLines(c("Platform               :", sessionInfo()[[1]]$platform), hydroPSOparam.TextFile, sep="  ")
	writeLines("", hydroPSOparam.TextFile) 
	writeLines(c("R version              :", sessionInfo()[[1]]$version.string), hydroPSOparam.TextFile, sep="  ")
	writeLines("", hydroPSOparam.TextFile) 
	writeLines(c("hydroPSO version       :", sessionInfo()$otherPkgs$hydroPSO$Version), hydroPSOparam.TextFile, sep="  ")
	writeLines("", hydroPSOparam.TextFile) 
	writeLines(c("hydroPSO Built         :", sessionInfo()$otherPkgs$hydroPSO$Built), hydroPSOparam.TextFile, sep="  ")
	writeLines("", hydroPSOparam.TextFile) 
	writeLines("================================================================================", hydroPSOparam.TextFile) 
	Time.Ini <- Sys.time()
	writeLines(c("Starting Time          :", date()), hydroPSOparam.TextFile, sep="  ")
	writeLines("", hydroPSOparam.TextFile) 
	writeLines("================================================================================", hydroPSOparam.TextFile) 
	writeLines(c("PSO Input Directory    :", drty.in), hydroPSOparam.TextFile, sep=" ") 
	writeLines("", hydroPSOparam.TextFile) 
	writeLines(c("PSO Output Directory   :", drty.out), hydroPSOparam.TextFile, sep=" ") 
	writeLines("", hydroPSOparam.TextFile) 
	writeLines(c("Parameter Ranges       :", basename(param.ranges)), hydroPSOparam.TextFile, sep=" ") 
	writeLines("", hydroPSOparam.TextFile) 
	try(writeLines(c("hydromod function      :", model.FUN.name), hydroPSOparam.TextFile, sep=" ") , TRUE)
	writeLines("", hydroPSOparam.TextFile) 
	writeLines(c("hydromod args          :"), hydroPSOparam.TextFile, sep=" ") 
	writeLines("", hydroPSOparam.TextFile) 
	for ( i in 1:length(model.FUN.args) ) {

	 arg.name  <- names(model.FUN.args)[i]
	 arg.name  <- format(paste("  ", arg.name, sep=""), width=22, justify="left" )
	 arg.value <- ""
	 arg.value <- try(as.character( as.character(model.FUN.args[i])), TRUE)

	 writeLines(c(arg.name, ":", arg.value), hydroPSOparam.TextFile, sep=" ") 
	 writeLines("", hydroPSOparam.TextFile) 

	} # FOR end
	# Closing the text file
	close(hydroPSOparam.TextFile) 

      } # IF 'fn.name' END

    } # IF 'write2disk' end

    ########################################################################
    GPbest.fit.rate <- Inf

    iter     <- 1
    nfn      <- 1
    iter.rg  <- 1
    nregroup <- 0

    iter.tv  <- iter
    niter.tv <- maxit

    if (write2disk) {
      OFout.Text.file              <- file(OFout.Text.fname, "a")           
      Particles.TextFile           <- file(Particles.Textfname, "a")  
      Velocities.TextFile          <- file(Velocities.Textfname, "a") 
      ConvergenceMeasures.TextFile <- file(ConvergenceMeasures.Textfname, "a")   
      BestParamPerIter.TextFile    <- file(BestParamPerIter.Textfname, "a")
      PbestPerIter.TextFile        <- file(PbestPerIter.Textfname, "a") 
      LocalBestPerIter.TextFile    <- file(LocalBestPerIter.Textfname, "a") 
      if (use.RG) {
	Xmin.Text.file <- file(Xmin.Text.fname, "a")        
	Xmax.Text.file <- file(Xmax.Text.fname, "a")
      } # IF end
    } # IF end      

    ######################### START Main Iteration Loop ########################
    abstol.conv <- FALSE
    reltol.conv <- FALSE
    improvement <- FALSE

    end.type.stg  <- "Unknown"
    end.type.code <- "-999"

    ############################################################################  
    # 3)                              Main Algorithm                           #
    ############################################################################  
    if (verbose) message("                                                                                ")          
    if (verbose) message("================================================================================")
    if (verbose) message("[                                 Running  PSO ...                             ]")
    if (verbose) message("================================================================================")
    if (verbose) message("                                                                                ")        

    while ( (iter <= maxit)  && (!abstol.conv) && (!reltol.conv) && (nfn <= maxfn) ) { 

      if ( (topology=="random") & (!improvement) ) 
	X.neighbours <- Random.Topology.Generation(npart, K, drty.out, iter)
	
      ModelOut <- vector("list", npart)
      
      # IW: linear, non-linear, runif
      if (!use.IW) {
         w <- 1   
      } else {                   
	   if ( (IW.type == "linear") | (IW.type == "non-linear") ) {
	      w <- compute.value.with.iter(iter=iter.tv, niter=niter.tv, 
					   nexp=IW.exp, val.ini=w.ini, 
					   val.fin=w.fin)                   
	   } else if (IW.type == "runif") {
	       w <- runif(1, min=w.ini, max=w.fin)
             } # ELSE end
	} # ELSE end 

        # TVc1: linear, non-linear
	if ( (use.TVc1) & (TVc1.type != "GLratio") ) {
	  if ( (TVc1.type == "linear") | (TVc1.type == "non-linear") )
	     c1 <- compute.value.with.iter(iter=iter.tv, niter=niter.tv, 
					   nexp=TVc1.exp, val.ini=c1.ini, 
					   val.fin=c1.fin)  
	} # If end  

        # TVc2
	if (use.TVc2) 
	  c2 <- compute.value.with.iter(iter=iter.tv, niter=niter.tv, 
					nexp=TVc2.exp, val.ini=c2.ini, 
					val.fin=c2.fin)  
					
        # lambda
	if (use.TVlambda) {
	  lambda <- compute.value.with.iter(iter=iter.tv, niter=niter.tv, 
					    nexp=TVlambda.exp, val.ini=vmax.ini, 
					    val.fin=vmax.fin)  
	  Vmax   <- lambda*Lmax
	} # IF end  

      ##########################################################################  
      # 3.a) Evaluate the particles fitness
      if ( fn.name != "hydromod" ) {

	 # Evaluating an R Function 
	 GoF <- apply(X, fn, MARGIN=1, ...)
	 
         Xt.fitness[iter, 1:npart] <- GoF
         ModelOut[1:npart]         <- GoF  ###

	 nfn <- nfn + npart

      } else { # fn.name = "hydromod"       

	     if ("verbose" %in% names(model.FUN.args)) {
	       verbose.FUN <- model.FUN.args[["verbose"]] 
	     } else verbose.FUN <- verbose
	     
	     out <- lapply(1:npart, hydromod.eval,       
                                      Particles=X, 
                                      iter=iter, 
                                      npart=npart, 
                                      maxit=maxit, 
                                      REPORT=REPORT, 
                                      verbose=verbose.FUN, 
                                      digits=digits, 
                                      model.FUN=model.FUN, 
                                      model.FUN.args=model.FUN.args
                                      )
                                        
             for (part in 1:npart){         
                   GoF                    <- out[[part]][["GoF"]] 
                   Xt.fitness[iter, part] <- GoF            
                   ModelOut[[part]]       <- out[[part]][["model.out"]]  
                   if(is.finite(GoF)) nfn <- nfn + 1   
             } #FOR part end               

	} # ELSE end


      if ( best.update == "sync" ) {
	    tmp <- sync.update.pgbests(x=X, 
				       xt.fitness= Xt.fitness[iter, ], 
				       MinMax= MinMax, 
				       pbest.fit= pbest.fit, 
				       gbest.fit= gbest.fit, 
				       gbest.pos= gbest.pos, 
				       x.best= X.best.part
				       )                               

	    pbest.fit   <- tmp[["pbest"]]
	    X.best.part <- tmp[["x.best"]]
	    gbest.fit   <- tmp[["gbest.fit"]]
	    gbest.pos   <- tmp[["gbest.pos"]]
	    
	    tmp <- UpdateLocalBest(pbest.fit=pbest.fit, 
			     localBest.pos=LocalBest.pos,
			     localBest.fit=LocalBest.fit, 
			     x.neighbours=X.neighbours, 
			     MinMax=MinMax) 
            LocalBest.fit <- tmp[["localBest.fit"]]
            LocalBest.pos <- tmp[["localBest.pos"]]

            if ( method == "ipso" ) {
               tmp <- UpdateNgbest(pbest.fit=pbest.fit, 
        	                   ngbest=ngbest, 
        			   MinMax=MinMax) 
               ngbest.fit <- tmp[["ngbest.fit"]]
               ngbest.pos <- tmp[["ngbest.pos"]]
            } # IF end

      } # IF end 
      
      # 'X.bak' is only needed to correctly compute the Normalised Swarm Radious
      # for the current iteration
      X.bak <- X           

      ##########################################################################  
      ###################   Particles Loop (j) - Start  ########################
      ##########################################################################  
      
      ifelse( (best.update == "async") & random.update, 
              index.part.upd <- sample(npart), 
              index.part.upd <- 1:npart)
        
      for (j in index.part.upd) {
      
        if (write2disk) {
        
          GoF <- Xt.fitness[iter, j]
        
          # File 'Model_Out.txt'          
          if(is.finite(GoF)) {
             writeLines(as.character(c(iter, j, 
				       formatC(GoF, format="E", digits=digits, flag=" "), 
				       formatC(ModelOut[[j]], format="E", digits=digits, flag=" ") ) ), 
			OFout.Text.file, sep="  ") 
          } else writeLines(as.character(c(iter, j, "NA", "NA" ) ), OFout.Text.file, sep="  ")
	  writeLines("", OFout.Text.file) 
	  flush(OFout.Text.file)
          
          # File 'Particles.txt' #
	  if(is.finite(GoF)) {
	    writeLines(as.character( c(iter, j, 
				     formatC(GoF, format="E", digits=digits, flag=" "), #GoF
				     formatC(X[j, ], format="E", digits=digits, flag=" ") 
				      ) ), Particles.TextFile, sep="  ") 
	  } else writeLines(as.character( c(iter, j, "NA",
					  formatC(X[j, ], format="E", digits=digits, flag=" ") 
				      ) ), Particles.TextFile, sep="  ") 
	  writeLines("", Particles.TextFile)
	  flush(Particles.TextFile)
        
	  # File 'Velocities.txt' #
	  if(is.finite(GoF)) {
	    writeLines( as.character( c(iter, j, 
					formatC(GoF, format="E", digits=digits, flag=" "), # GoF
					formatC(V[j, ], format="E", digits=digits, flag=" ")                                            
					) ), Velocities.TextFile, sep="  ") 
	  } else writeLines( as.character( c(iter, j, "NA",
					formatC(V[j, ], format="E", digits=digits, flag=" ")                                            
					) ), Velocities.TextFile, sep="  ")
	  writeLines("", Velocities.TextFile) 
	  flush(Velocities.TextFile)
	  
        } # IF end
	    

	if ( best.update == "async" ) {
	   tmp <- async.update.pgbests(x=X[j,], 
	                               x.pos=j, 
                                       xt.fitness= Xt.fitness[iter, j],
                                       MinMax= MinMax, 
                                       l.pbest.fit= pbest.fit[j], 
                                       gbest.fit= gbest.fit, 
                                       gbest.pos= gbest.pos,
                                       x.best= X.best.part[j, ]
	                               )                                    

	   pbest.fit[j]    <- tmp[["pbest"]]
	   X.best.part[j,] <- tmp[["x.best"]]       
	   gbest.pos       <- tmp[["gbest.pos"]] 
	   gbest.fit       <- tmp[["gbest.fit"]] 
	   
	   tmp <- UpdateLocalBest(pbest.fit=pbest.fit, 
			     localBest.pos=LocalBest.pos,
			     localBest.fit=LocalBest.fit, 
			     x.neighbours=X.neighbours, 
			     MinMax=MinMax) 
           LocalBest.fit <- tmp[["localBest.fit"]]
           LocalBest.pos <- tmp[["localBest.pos"]]

           if ( method == "ipso" ) {
              tmp <- UpdateNgbest(pbest.fit=pbest.fit, 
                                  ngbest=ngbest, 
                                  MinMax=MinMax) 
              ngbest.fit <- tmp[["ngbest.fit"]]
              ngbest.pos <- tmp[["ngbest.pos"]]
           } # IF end

	} # IF end  
	
	### IW, TVc1, Tv2, lambda
	
	# IW: aiwf, GLratio
	if (use.IW) { 
	  if (IW.type == "aiwf") { 
	        w <- compute.w.aiwf(iter.fit= Xt.fitness[iter, ],
                                    particle.pos =j, 
                                    gbest.fit=gbest.fit, 
                                    w.max=max(w.ini, w.fin), 
                                    w.min=min(w.ini, w.fin),
                                    MinMax=MinMax
                                    )   

	  } else if (IW.type == "GLratio") {
		w <- compute.w.with.GLratio(MinMax, gbest.fit, pbest.fit)   
	    }  # ELSE end
	} # IF end
	
	
	# TVc1: GLratio
	if ( (use.TVc1) & (TVc1.type == "GLratio") ) 
           c1 <- compute.c1.with.GLratio(MinMax, gbest.fit, pbest.fit[j])   

	######################################################################## 
	# 3.b) Updating the velocity of all the particles
	ifelse( (topology=="lbest") & (iter <= iter.ini), ltopology <- "gbest", 
							  ltopology <- topology)

	V[j,] <- compute.veloc( 
				x= X[j, ], 
				v= V[j, ], 
				w= w, 
				c1= c1, 
				c2= c2, 
				CF= CF,
				Pbest= X.best.part,
				part.index=j,
				gbest= X.best.part[gbest.pos, ],
				topology=ltopology,
				method=method,                                    
				MinMax=MinMax,                             # topology="ipso" | method="wfips"
				neighs.index=X.neighbours[j, ],            # method in c("fips", "wfips")
				localBest=X.best.part[LocalBest.pos[j], ], # topology="lbest"
				localBest.pos=LocalBest.pos[j],            # topology=c("random", "lbest")
				ngbest.fit=ngbest.fit,                     # topology="ipso"
				ngbest=X.best.part[ngbest.pos, ],          # topology="ipso"
				lpbest.fit= pbest.fit[X.neighbours[j, ]]   # method="wfips"
				)  

	V[j,] <- velocity.boundary.treatment(v= V[j,], vmax=Vmax)

        ########################################################################  
	# 4.c) Moving the particles: X[j,] <- X[j,] +  V[j,]
	out <- position.update.and.boundary.treatment(x= X[j,], v=V[j,], x.MinMax=X.Boundaries, boundary.wall=boundary.wall)
	X[j,] <- out[["x.new"]]
	V[j,] <- out[["v.new"]]

      } # FOR j end: Particles Loop
      ##########################################################################  
      ###################   Particles Loop (j) - End  ##########################
      ########################################################################## 
       
      if ( plot ) {
	ifelse(MinMax == "max", lgof <- max(GoF, na.rm=TRUE), lgof <- min(GoF, na.rm=TRUE)) 
	colorRamp= colorRampPalette(c("darkred", "red", "orange", "yellow", "green", "darkgreen", "cyan"))
	XX.Boundaries.current <- computeCurrentXmaxMin(X) 
	xlim <- range(XX.Boundaries.current)
	ylim <- range(XX.Boundaries.current)
	if (iter==1) {
	   plot(X[,1], X[,2], xlim=X.Boundaries[1,], ylim=X.Boundaries[2,], 
	        main=paste("Iter= ", iter, ". GoF= ", 
	        format(lgof, scientific=TRUE, digits=digits), sep=""), 
	        col=colorRamp(npart), cex=0.5 )
	} else plot(X[,1], X[,2], xlim=X.Boundaries[1,], ylim=X.Boundaries[2,], 
	            main=paste("Iter= ", iter, ". GoF= ", 
	            format(lgof, scientific=TRUE, digits=digits), sep=""), 
	            col=colorRamp(npart), cex=0.5 )
	#plotParticles2D(X)
      } # IF end 
      
      gbest.fit.iter[iter] <- gbest.fit
      
      suppressWarnings(ifelse(MinMax=="max", pbest.fit.iter <- max( Xt.fitness[iter, ], na.rm=TRUE ),  
			                     pbest.fit.iter <- min( Xt.fitness[iter, ], na.rm=TRUE) ) )  

      GPbest.fit.rate <- mean(pbest.fit, na.rm=TRUE)
      ifelse( (is.finite(GPbest.fit.rate) ) & ( GPbest.fit.rate !=0 ), 
	      GPbest.fit.rate <- abs( ( gbest.fit - GPbest.fit.rate ) / GPbest.fit.rate ), 
	      GPbest.fit.rate <- +Inf)

      ifelse( (gbest.fit.prior != 0) & (is.finite(gbest.fit.prior) ) , 
	      gbest.fit.rate <- abs( ( gbest.fit - gbest.fit.prior ) / gbest.fit.prior ), 
	      gbest.fit.rate <- +Inf)

      out <- ComputeSwarmRadiusAndDiameter(x=X.bak, gbest= X.best.part[gbest.pos, ], Lmax=Lmax, 
					   MinMax=MinMax, pbest.fit=pbest.fit) 
      swarm.radius    <- out[["swarm.radius"]] 
      swarm.diameter  <- out[["swarm.diameter"]]
      NormSwarmRadius <- swarm.radius/swarm.diameter

      if ( (verbose) & ( iter/REPORT == floor(iter/REPORT) ) ) 
	   message( "iter:", format(iter, width=6, justify="right"), 
		    "   Gbest:", formatC( gbest.fit, format="E", digits=digits, flag=" "), 
		    "   Gbest_rate:", format( round(gbest.fit.rate*100, 2), width=6, nsmall=2, justify="left"), "%",
		    "   Iter_best_fit:", formatC(pbest.fit.iter, format="E", digits=digits, flag=" "),               
		    "   nSwarm_Radius:", formatC(NormSwarmRadius, format="E", digits=digits, flag=" "),
		    "   |g-mean(p)|/mean(p):", format( round(GPbest.fit.rate*100, 2), width=6, nsmall=2, justify="left"), "%" )

      ##########################################################################  
      # Random Generation around gbest, if requested                           #
      ##########################################################################  
      do.RandomGeneration <- ( use.RG && (NormSwarmRadius < RG.thr)  
				      && (iter.rg >= RG.miniter) )

      if (do.RandomGeneration)  {        

	  if (topology == "gbest") {
	    gbest.fit.bak <- gbest.fit
	    gbest.pos.bak <- gbest.pos
	    x.bak         <- X[gbest.pos,]
	    v.bak         <- V[gbest.pos,]                
	  } # IF end

	  if (topology == "ipso") {
	   x.bak         <- X[ngbest.pos,]
	   v.bak         <- V[ngbest.pos,]
	   gbest.fit.bak <- ngbest.fit
	  } # IF end

	  if (verbose) message("[Re-grouping particles in the swarm (iter: ", iter, ") ...]")

	  tmp <- RegroupingSwarm(x=X, 
				 gbest= X.best.part[gbest.pos, ], 
				 x.Range=X.Boundaries,
				 #x.Range=X.Boundaries.current,
				 Lmax=Lmax,
				 RG.thr=RG.thr,
				 RG.r=RG.r) 

	  X    <- tmp[["X"]]
	  
	  if (topology == "gbest") {
	    X[gbest.pos,] <- x.bak
	    #V[gbest.pos,] <- v.bak
	    gbest.fit     <- gbest.fit.bak
	    gbest.pos     <- gbest.pos.bak
	  } # IF end

	  if (topology == "ipso") {
	    X[ngbest.pos,] <- x.bak
	    gbest.fit      <- gbest.fit.bak
	    gbest.pos     <- gbest.pos.bak
	  } # IF end

	  V <- InitializateV(npart=npart, param.IDs=param.IDs, 
			     x.MinMax=X.Boundaries, v.ini.type=Vini.type, 
			     Xini=X)

	  GPbest.fit.rate <- +Inf              
	  ifelse(MinMax=="max", gbest.fit.prior <- +Inf, gbest.fit.prior <- 0) 

	  niter.tv <- maxit - iter
	  iter.tv  <- 1   
	  iter.rg  <- 1   
	  nregroup <- nregroup + 1

      } # IF end

      ##########################################################################  
      # Updates required before the next iteration
      ##########################################################################  

      ifelse(MinMax=="max", abstol.conv <- gbest.fit >= abstol, 
			    abstol.conv <- gbest.fit <= abstol )
                     
      if (reltol==0) {
        reltol.conv <- FALSE
      } else {
        tmp <- abs(pbest.fit.iter.prior - pbest.fit.iter)
        ifelse(tmp==0, reltol.conv <- FALSE, reltol.conv <- tmp <= abs(reltol) )
      } # ELSE end
                     
      pbest.fit.iter.prior <- pbest.fit.iter

      # Gbest was improved ?
      ifelse(gbest.fit.prior==gbest.fit, improvement <- FALSE, improvement <- TRUE) 

      gbest.fit.prior <- gbest.fit
            

      if (abstol.conv ) {
	end.type.stg  <- "Converged ('abstol' criterion)"
	end.type.code <- 0
      } else if (reltol.conv) {
	end.type.stg <- "Converged ('reltol' criterion)"
	end.type.code <- 1
      } else if (nfn >= maxfn) {
	end.type.stg <- "Maximum number of function evaluations reached"
	end.type.code <- 2
      } else if (iter >= maxit) {
	end.type.stg <- "Maximum number of iterations reached"
	end.type.code <- 3
      } # ELSE end

      if (write2disk) {
      
        # File 'ConvergenceMeasures.txt'
	writeLines(as.character( c(iter, 
				   formatC(gbest.fit, format="E", digits=digits, flag=" "), 
				   format( round(gbest.fit.rate*100, 3), nsmall=3, width=7, justify="right"),
				   formatC(pbest.fit.iter, format="E", digits=digits, flag=" "),
				   formatC(NormSwarmRadius, format="E", digits=digits, flag=" "),
				   format( round(GPbest.fit.rate*100, 3), nsmall=3, width=7, justify="right")
				  ) ), ConvergenceMeasures.TextFile, sep="  ")
	writeLines("", ConvergenceMeasures.TextFile)
	flush(ConvergenceMeasures.TextFile) 
        
        # File 'BestParamPerIter.txt' #
        GoF <- gbest.fit
	if(is.finite(GoF)) {
	  writeLines( as.character( c(iter,
	                              formatC(GoF, format="E", digits=digits, flag=" "), 
	                              formatC(X.best.part[gbest.pos, ], format="E", digits=digits, flag=" ")	                                                            
	                          ) ), BestParamPerIter.TextFile, sep="  ") 
	} else writeLines( as.character( c(iter,
	                                   "NA",
	                                   formatC(X.best.part[gbest.pos, ], format="E", digits=digits, flag=" ")                                                                                  
	                               ) ), BestParamPerIter.TextFile, sep="  ")
	writeLines("", BestParamPerIter.TextFile)  
	flush(BestParamPerIter.TextFile)
	
	# File 'PbestPerIter.txt' #
        GoF <- pbest.fit
	writeLines( as.character( c(iter,
	                            formatC(GoF, format="E", digits=digits, flag=" ") 
	                           ) ), PbestPerIter.TextFile, sep="  ")
	writeLines("", PbestPerIter.TextFile)  
	flush(PbestPerIter.TextFile)
	
	# File 'LocalBestPerIter.txt' #
        GoF <- LocalBest.fit
	writeLines( as.character( c(iter,
	                            formatC(GoF, format="E", digits=digits, flag=" ") 
	                           ) ), LocalBestPerIter.TextFile, sep="  ")
	writeLines("", LocalBestPerIter.TextFile)  
	flush(LocalBestPerIter.TextFile)
	
      } # IF end

      iter    <- iter + 1
      iter.tv <- iter.tv + 1
      iter.rg <- iter.rg + 1

    } # WHILE end
    ########################## END Main Iteration Loop #########################

    if (write2disk) {
      close(OFout.Text.file)        
      close(Particles.TextFile)
      close(Velocities.TextFile)
      close(ConvergenceMeasures.TextFile)
      close(BestParamPerIter.TextFile)
      close(PbestPerIter.TextFile) 
      close(LocalBestPerIter.TextFile)
      if (use.RG) {
	close(Xmin.Text.file)        
	close(Xmax.Text.file)
      } # IF end
    } # IF end

    ############################################################################  
    # Sorting the particles according to their best fit
    ############################################################################  
    ifelse(MinMax=="max", sorted.fit <- sort(pbest.fit, decreasing= TRUE), 
			  sorted.fit <- sort(pbest.fit, decreasing= FALSE) ) 

    sorted.index <- pmatch(sorted.fit, pbest.fit)

    ###################   START WRITING OUTPUT FILES     ###################
    if (write2disk) {

      if (verbose) message("                           ")
      if (verbose) message("[ Writing output files... ]")
      if (verbose) message("                           ")

      niter.real <- iter - 1 
      PSOparam.TextFile <- file(PSOparam.fname, "a")    
      
      writeLines("================================================================================", PSOparam.TextFile) 
      writeLines(c("Ending Time       :", date()), PSOparam.TextFile, sep="  ")
      writeLines("", PSOparam.TextFile) 
      Time.Fin <- Sys.time()
      writeLines("================================================================================", PSOparam.TextFile) 
      writeLines(c("Elapsed Time      :", format(round(Time.Fin - Time.Ini, 2))), PSOparam.TextFile, sep="  ")
      writeLines("", PSOparam.TextFile) 
      writeLines("================================================================================", PSOparam.TextFile) 
      close(PSOparam.TextFile)

      # Writing the file 'BestParameterSet.txt'
      tmp.fname <- paste(file.path(drty.out), "/", "BestParameterSet.txt", sep="") 
      tmp.TextFile  <- file(tmp.fname , "w+")
      writeLines(c("BestParticle", "GoF   ", param.IDs), tmp.TextFile, sep="  ") 
      writeLines("", tmp.TextFile)  
      tmp <- formatC(c(gbest.fit, X.best.part[gbest.pos,]), format="E", digits=digits, flag=" ")
      writeLines(as.character(c(gbest.pos, tmp)), tmp.TextFile, sep="  ") 
      writeLines("", tmp.TextFile)  
      close(tmp.TextFile) 

      # Writing a file with the maximum ranges used during PSO
      fname <- paste(file.path(drty.out), "/", "XMinMax.txt", sep="") 					
      write.table(format(X.Boundaries, scientific=TRUE, digits=digits), file=fname, col.names=TRUE, row.names=FALSE, sep="  ", quote=FALSE) 

      # Writing the file 'Particles_GofPerIter.txt', with the GoF for each particle in each iteration
      tmp.fname <- paste(file.path(drty.out), "/", "Particles_GofPerIter.txt", sep="") 
      tmp.TextFile  <- file(tmp.fname , "w+")
      writeLines(paste("Iter", paste(colnames(Xt.fitness), collapse="    "), sep="    "), tmp.TextFile, sep="  ") 
      writeLines("", tmp.TextFile)  
      for ( i in (1:niter.real) ) {               
	tmp <- formatC(Xt.fitness[i, ], format="E", digits=digits, flag=" ")
	writeLines(as.character(c(i, tmp)), tmp.TextFile, sep="  ") 
	writeLines("", tmp.TextFile)    
      } # FOR end 
      close(tmp.TextFile) 

      # Writing the file 'BestParamPerParticle.txt', with ...
      fname <- paste(file.path(drty.out), "/", "BestParamPerParticle.txt", sep="") 
      tmp <- cbind(X.best.part, pbest.fit)
      colnames(tmp)[ncol(tmp)] <- "GoF"	
      write.table(format(tmp, scientific=TRUE, digits=digits), file=fname, col.names=TRUE, row.names=FALSE, sep="  ", quote=FALSE)

      # Writing the file 'X.neighbours.txt' 
      fname <- paste(file.path(drty.out), "/", "Particles_Neighbours.txt", sep="") 	
      write.table(X.neighbours, file=fname, col.names=TRUE, row.names=TRUE, sep="  ", na="", quote=FALSE)

      # Writing the file 'LocalBest.txt' 
      fname <- paste(file.path(drty.out), "/", "LocalBest.txt", sep="") 	
      write.table(format(LocalBest.fit, scientific=TRUE, digits=digits), file=fname, col.names=TRUE, row.names=FALSE, sep="  ", quote=FALSE)

      if (fn.name=="hydromod") {

	hydroPSOparam.TextFile <- file(hydroPSOparam.fname, "a")    
	
	writeLines("================================================================================", hydroPSOparam.TextFile) 
	writeLines(c("Ending Time            :", date()), hydroPSOparam.TextFile, sep=" ")
	writeLines("", hydroPSOparam.TextFile) 
	writeLines("================================================================================", hydroPSOparam.TextFile) 
	Time.Fin <- Sys.time()
	writeLines(c("Elapsed Time           :", format(round(Time.Fin - Time.Ini, 2))), hydroPSOparam.TextFile, sep=" ")
	writeLines("", hydroPSOparam.TextFile) 
	writeLines("================================================================================", hydroPSOparam.TextFile) 
	close(hydroPSOparam.TextFile)

      } # IF 'fn.name' END           

    } # IF end
    #####################     END WRITING OUTPUT FILES     #####################

    ############################################################################
    if (verbose) message("                                    |                                           ")  
    if (verbose) message("================================================================================")
    if (verbose) message("[                          Creating the R output ...                           ]")
    if (verbose) message("================================================================================")

    # Creating the R output
    nelements <- 6 
    out       <- vector("list", nelements)

    out[[1]]        <- X.best.part[gbest.pos,]
    names(out[[1]]) <- param.IDs
    out[[2]] <- gbest.fit
    out[[3]] <- gbest.pos
    out[[4]] <- c("function.calls"=nfn-1, "iterations"=iter-1, "regroupings"=nregroup)
    out[[5]] <- end.type.code
    out[[6]] <- end.type.stg

    names(out)[1:nelements] <- c("par",           # "Best.Parameter.Values", 
				 "value",         # "Global.Best.Value", 
				 "best.particle", # "Global.Best.Position",
				 "counts", 
				 "convergence", 
				 "message") 

    if (out.with.pbest) {            
      out[[nelements+1]] <- X.best.part

      out[[nelements+2]] <- pbest.fit

      names(out)[(nelements+1):(nelements+2)] <- c("pbest.Parameter.Values", "pbest.fit") 

      nelements <- nelements + 2                
    } # IF end

    if (out.with.fit.iter) {            
      out[[nelements+1]] <- Xt.fitness          
      names(out)[nelements+1] <- c("part.fit.per.iter")  
    } # IF end

    ############################################################################  
    if (fn.name=="hydromod") {

      if (verbose) message("                                                                                ")  
      if (verbose) message("                                    |                                           ")  
      if (verbose) message("================================================================================")
      if (verbose) message("[         Running one last time the model with the 'best' parameter set ...    ]")
      if (verbose) message("================================================================================")  
      if (verbose) message("                                    |                                           ")  
      if (verbose) message("                                                                                ")  

      model.FUN.args <- modifyList(model.FUN.args, 
				   list(param.values=out[["par"]])
				   ) 
      hydromod.out   <- do.call(model.FUN, as.list(model.FUN.args))   

      if ("obs" %in% names(model.FUN.args)) {
        fname <- paste(file.path(drty.out), "/", "Observations.txt", sep="") 	
	obs <- model.FUN.args[["obs"]] 
        if (is.zoo(obs)) {
          if (gof.Ini.exists) obs <- window( obs, start=as.Date(model.FUN.args[["gof.Ini"]]) )
          if (gof.Fin.exists) obs <- window( obs, end=as.Date(model.FUN.args[["gof.Fin"]]) )
          write.zoo(x=obs, file=fname)
        } else {
            obs <- cbind(1:length(obs), obs)
            write.table(obs, file=fname, col.names=FALSE, row.names=FALSE, sep="  ", quote=FALSE)
          } # ELSE end
      } # IF end

    } # IF end    

    ############################################################################
    # 7)                                 Output                                #
    ############################################################################

    return(out)
        
} # 'PSO' end