def __init__(self, f, x0, ranges=None, neighbor=GaussianNeighbor, optm=None, T0=1000., rt=0.95, emax=1e-8, imax=1000): ''' Initializes the optimizer. To create an optimizer of this type, instantiate the class with the parameters given below: :Parameters: f A multivariable function to be optimized. The function should have only one parameter, a multidimensional line-vector, and return the function value, a scalar. x0 First estimate of the minimum. Estimates can be given in any format, but internally they are converted to a one-dimension vector, where each component corresponds to the estimate of that particular variable. The vector is computed by flattening the array. ranges A range of values might be passed to the algorithm, but it is not necessary. If supplied, this parameter should be a list of ranges for each variable of the objective function. It is specified as a list of tuples of two values, ``(x0, x1)``, where ``x0`` is the start of the interval, and ``x1`` its end. Obviously, ``x0`` should be smaller than ``x1``. It can also be given as a list with a simple tuple in the same format. In that case, the same range will be applied for every variable in the optimization. neighbor Neighbor function. This is a function used to compute the neighbor of the present estimate. You can use the ones defined in the ``neighbor`` module, or you can implement your own. In any case, the ``neighbor`` parameter must be an instance of ``ContinuousNeighbor`` or of a subclass. Please, see the documentation on the ``neighbor`` module for more information. The default is ``GaussianNeighbor``, which computes the new estimate based on a gaussian distribution around the present estimate. optm A standard optimizer such as gradient or Newton. This is used in case the estimate is not accepted by the algorithm -- in this case, a new estimate is computed in a standard way, providing a little improvement in any case. It defaults to None; in that case, no standard optimizatiion will be used. Notice that, if you want to use a standard optimizer, you must create it before you instantiate this class. By doing it this way, you can configure the optimizer in any way you want. Please, consult the documentation in ``Gradient``, ``Newton`` and others. T0 Initial temperature of the system. The temperature is, of course, an analogy. Defaults to 1000. rt Temperature decreasing rate. The temperature must slowly decrease in simulated annealing algorithms. In this implementation, this is controlled by this parameter. At each step, the temperature is multiplied by this value, so it is necessary that ``0 < rt < 1``. Defaults to 0.95, smaller values make the temperature decay faster, while larger values make the temperature decay slower. h Convergence step. In the case that the neighbor estimate is not accepted, a simple gradient step is executed. This parameter is the convergence step to the gradient step. emax Maximum allowed error. The algorithm stops as soon as the error is below this level. The error is absolute. imax Maximum number of iterations, the algorithm stops as soon this number of iterations are executed, no matter what the error is at the moment. ''' self.__f = f self.__x = array(x0).ravel() self.__fx = f(self.__x) # Determine ranges of the variables if ranges is not None: ranges = list(ranges) if len(ranges) == 1: ranges = array(ranges * len(x0[0])) else: ranges = array(ranges) self.ranges = ranges '''Holds the ranges for every variable. Although it is a writable property, care should be taken in changing parameters before ending the convergence.''' # Verifies the validity of the neighbor method try: issubclass(neighbor, ContinuousNeighbor) neighbor = neighbor() except TypeError: pass if isinstance(neighbor, types.FunctionType): neighbor = ContinuousNeighbor(neighbor) if not isinstance(neighbor, ContinuousNeighbor): raise TypeError, 'not a valid neighbor function' else: self.__nb = neighbor self.__optm = optm self.__t = float(T0) self.__r = float(rt) self.__emax = float(emax) self.__imax = int(imax)
def __init__(self, f, x0, ranges=[], fmt=None, neighbor=InvertBitsNeighbor, T0=1000., rt=0.95, emax=1e-8, imax=1000): ''' Initializes the optimizer. To create an optimizer of this type, instantiate the class with the parameters given below: :Parameters: f A multivariable function to be optimized. The function should have only one parameter, a multidimensional line-vector, and return the function value, a scalar. x0 First estimate of the minimum. Estimates can be given in any format, but internally they are converted to a one-dimension vector, where each component corresponds to the estimate of that particular variable. The vector is computed by flattening the array. ranges Ranges of values allowed for each component of the input vector. If given, ranges are checked and a new estimate is generated in case any of the components fall beyond the value. ``range`` can be a tuple containing the inferior and superior limits of the interval; in that case, the same range is used for every variable in the input vector. ``range`` can also be a list of tuples of the same format, inferior and superior limits; in that case, the first tuple is assumed as the range allowed for the first variable, the second tuple is assumed as the range allowed for the second variable and so on. fmt A ``struct``-module string with the format of the data used. Please, consult the ``struct`` documentation, since what is explained there is exactly what is used here. For example, if you are going to use the optimizer to deal with three-dimensional vectors of continuous variables, the format would be something like:: fmt = 'fff' Default value is an empty string. Notice that this is implemented as a ``bitarray``, so this module must be present. It is strongly recommended that integer numbers are used! Floating point numbers can be simulated with long integers. The reason for this is that random bit sequences can have no representation as floating point numbers, and that can make the algorithm not perform adequatelly. The default value for this parameter is ``None``, meaning that a default format is not supplied. If a format is not supplied, then the estimate will be passed as a bitarray to the objective function. This means that your function must take care to decode the bit stream to extract meaning from it. neighbor Neighbor function. This is a function used to compute the neighbor of the present estimate. You can use the ones defined in the ``neighbor`` module, or you can implement your own. In any case, the ``neighbor`` parameter must be an instance of ``BinaryNeighbor`` or of a subclass. Please, see the documentation on the ``neighbor`` module for more information. The default is ``InvertBitsNeighbor``, which computes the new estimate by inverting some bits in the present estimate. T0 Initial temperature of the system. The temperature is, of course, an analogy. Defaults to 1000. rt Temperature decreasing rate. The temperature must slowly decrease in simulated annealing algorithms. In this implementation, this is controlled by this parameter. At each step, the temperature is multiplied by this value, so it is necessary that ``0 < rt < 1``. Defaults to 0.95, smaller values make the temperature decay faster, while larger values make the temperature decay slower. emax Maximum allowed error. The algorithm stops as soon as the error is below this level. The error is absolute. imax Maximum number of iterations, the algorithm stops as soon this number of iterations are executed, no matter what the error is at the moment. ''' self.__f = f self.format = fmt self.__set_x(x0) # Determine ranges if ranges is None: self.ranges = None elif len(ranges) == 1: self.ranges = array(ranges * len(fmt)) else: self.ranges = array(ranges) # Verifies the validity of the neighbor method try: issubclass(neighbor, BinaryNeighbor) neighbor = neighbor() except TypeError: pass if isinstance(neighbor, types.FunctionType): neighbor = BinaryNeighbor(neighbor) if not isinstance(neighbor, BinaryNeighbor): raise TypeError, 'not a valid neighbor function' else: self.__nb = neighbor self.__t = float(T0) self.__r = float(rt) self.__xbest = self.__x[:] # Holds the best estimate so far and self.__fbest = f( self.__get_x()) # its value on the objective function. self.__emax = float(emax) self.__imax = int(imax)
def __init__(self, f, x0, ranges=[ ], fmt=None, neighbor=InvertBitsNeighbor, T0=1000., rt=0.95, emax=1e-8, imax=1000): ''' Initializes the optimizer. To create an optimizer of this type, instantiate the class with the parameters given below: :Parameters: f A multivariable function to be optimized. The function should have only one parameter, a multidimensional line-vector, and return the function value, a scalar. x0 First estimate of the minimum. Estimates can be given in any format, but internally they are converted to a one-dimension vector, where each component corresponds to the estimate of that particular variable. The vector is computed by flattening the array. ranges Ranges of values allowed for each component of the input vector. If given, ranges are checked and a new estimate is generated in case any of the components fall beyond the value. ``range`` can be a tuple containing the inferior and superior limits of the interval; in that case, the same range is used for every variable in the input vector. ``range`` can also be a list of tuples of the same format, inferior and superior limits; in that case, the first tuple is assumed as the range allowed for the first variable, the second tuple is assumed as the range allowed for the second variable and so on. fmt A ``struct``-module string with the format of the data used. Please, consult the ``struct`` documentation, since what is explained there is exactly what is used here. For example, if you are going to use the optimizer to deal with three-dimensional vectors of continuous variables, the format would be something like:: fmt = 'fff' Default value is an empty string. Notice that this is implemented as a ``bitarray``, so this module must be present. It is strongly recommended that integer numbers are used! Floating point numbers can be simulated with long integers. The reason for this is that random bit sequences can have no representation as floating point numbers, and that can make the algorithm not perform adequatelly. The default value for this parameter is ``None``, meaning that a default format is not supplied. If a format is not supplied, then the estimate will be passed as a bitarray to the objective function. This means that your function must take care to decode the bit stream to extract meaning from it. neighbor Neighbor function. This is a function used to compute the neighbor of the present estimate. You can use the ones defined in the ``neighbor`` module, or you can implement your own. In any case, the ``neighbor`` parameter must be an instance of ``BinaryNeighbor`` or of a subclass. Please, see the documentation on the ``neighbor`` module for more information. The default is ``InvertBitsNeighbor``, which computes the new estimate by inverting some bits in the present estimate. T0 Initial temperature of the system. The temperature is, of course, an analogy. Defaults to 1000. rt Temperature decreasing rate. The temperature must slowly decrease in simulated annealing algorithms. In this implementation, this is controlled by this parameter. At each step, the temperature is multiplied by this value, so it is necessary that ``0 < rt < 1``. Defaults to 0.95, smaller values make the temperature decay faster, while larger values make the temperature decay slower. emax Maximum allowed error. The algorithm stops as soon as the error is below this level. The error is absolute. imax Maximum number of iterations, the algorithm stops as soon this number of iterations are executed, no matter what the error is at the moment. ''' self.__f = f self.format = fmt self.__set_x(x0) # Determine ranges if ranges is None: self.ranges = None elif len(ranges) == 1: self.ranges = array(ranges * len(fmt)) else: self.ranges = array(ranges) # Verifies the validity of the neighbor method try: issubclass(neighbor, BinaryNeighbor) neighbor = neighbor() except TypeError: pass if isinstance(neighbor, types.FunctionType): neighbor = BinaryNeighbor(neighbor) if not isinstance(neighbor, BinaryNeighbor): raise TypeError, 'not a valid neighbor function' else: self.__nb = neighbor self.__t = float(T0) self.__r = float(rt) self.__xbest = self.__x[:] # Holds the best estimate so far and self.__fbest = f(self.__get_x()) # its value on the objective function. self.__emax = float(emax) self.__imax = int(imax)