public release 2.2.0 - see README.md and CHANGES.md for details
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
base classes for population-based optimizers.
|
||||
|
||||
a _population_ is a set of individuals or particles
|
||||
that can assume coordinates from the parameter domain.
|
||||
that can assume coordinates from the parameter space.
|
||||
a tuple of coordinates is also called _model parameters_ which define the _model_.
|
||||
the individuals travel through parameter space according to an algorithm defined separately.
|
||||
depending on the algorithm, the population can converge towards the optimum coordinates based on calculated R-factors.
|
||||
@@ -117,7 +117,7 @@ class Population(object):
|
||||
## @var pos
|
||||
# (numpy.ndarray) current positions of each particle.
|
||||
#
|
||||
# the column names include the names of the model parameters, taken from domain.start,
|
||||
# the column names include the names of the model parameters, taken from model_space.start,
|
||||
# and the special names @c '_particle', @c '_model', @c '_rfac'.
|
||||
# the special fields have the following meanings:
|
||||
#
|
||||
@@ -299,7 +299,7 @@ class Population(object):
|
||||
arr[k] = model_dict[k]
|
||||
return arr
|
||||
|
||||
def setup(self, size, domain, **kwargs):
|
||||
def setup(self, size, model_space, **kwargs):
|
||||
"""
|
||||
set up the population arrays seeded with previous results and the start model.
|
||||
|
||||
@@ -315,12 +315,12 @@ class Population(object):
|
||||
|
||||
@param size: requested number of particles.
|
||||
|
||||
@param domain: definition of initial and limiting model parameters
|
||||
@param model_space: definition of initial and limiting model parameters
|
||||
expected by the cluster and parameters functions.
|
||||
@arg domain.start: initial guess.
|
||||
@arg domain.min: minimum values allowed.
|
||||
@arg domain.max: maximum values allowed. if min == max, the parameter is kept constant.
|
||||
@arg domain.step: depends on the actual algorithm.
|
||||
@arg model_space.start: initial guess.
|
||||
@arg model_space.min: minimum values allowed.
|
||||
@arg model_space.max: maximum values allowed. if min == max, the parameter is kept constant.
|
||||
@arg model_space.step: depends on the actual algorithm.
|
||||
not used in particle swarm.
|
||||
standard deviation of mutations in genetic optimization.
|
||||
|
||||
@@ -335,14 +335,14 @@ class Population(object):
|
||||
"""
|
||||
self.size_req = size
|
||||
self.size_act = size
|
||||
self.model_start = domain.start
|
||||
self.model_min = domain.min
|
||||
self.model_max = domain.max
|
||||
self.model_step = domain.step
|
||||
self.model_start_array = self.get_model_array(domain.start)
|
||||
self.model_min_array = self.get_model_array(domain.min)
|
||||
self.model_max_array = self.get_model_array(domain.max)
|
||||
self.model_step_array = self.get_model_array(domain.step)
|
||||
self.model_start = model_space.start
|
||||
self.model_min = model_space.min
|
||||
self.model_max = model_space.max
|
||||
self.model_step = model_space.step
|
||||
self.model_start_array = self.get_model_array(model_space.start)
|
||||
self.model_min_array = self.get_model_array(model_space.min)
|
||||
self.model_max_array = self.get_model_array(model_space.max)
|
||||
self.model_step_array = self.get_model_array(model_space.step)
|
||||
|
||||
# allocate arrays
|
||||
dt = self.get_pop_dtype(self.model_start)
|
||||
@@ -378,8 +378,8 @@ class Population(object):
|
||||
"""
|
||||
initializes a random population.
|
||||
|
||||
the position array is filled with random values (uniform distribution) from the parameter domain.
|
||||
velocity values are randomly chosen between -1/8 to 1/8 times the width (max - min) of the parameter domain.
|
||||
the position array is filled with random values (uniform distribution) from the parameter space.
|
||||
velocity values are randomly chosen between -1/8 to 1/8 times the width (max - min) of the parameter space.
|
||||
|
||||
the method does not update the particle info fields.
|
||||
|
||||
@@ -402,8 +402,8 @@ class Population(object):
|
||||
the method does not update the particle info fields.
|
||||
|
||||
@param params: dictionary of model parameters.
|
||||
the keys must match the ones of domain.start.
|
||||
values that lie outside of the domain are skipped.
|
||||
the keys must match the ones of model_space.start.
|
||||
values that lie outside of the model space are skipped.
|
||||
|
||||
@param index: index of the particle that is seeded.
|
||||
the index must be in the allowed range of the self.pos array.
|
||||
@@ -440,7 +440,7 @@ class Population(object):
|
||||
this method is called as a part of setup().
|
||||
it must not be called after the optimization has started.
|
||||
|
||||
parameter values that lie outside the parameter domain (min/max) are left at their previous value.
|
||||
parameter values that lie outside the model space (min/max) are left at their previous value.
|
||||
|
||||
@note this method does not initialize the remaining particles.
|
||||
neither does it set the velocity and best position arrays of the seeded particles.
|
||||
@@ -488,7 +488,7 @@ class Population(object):
|
||||
count_limit = self.pos.shape[0]
|
||||
count_limit = min(count_limit, self.pos.shape[0] - first_particle)
|
||||
|
||||
seed = np.genfromtxt(seed_file, names=True)
|
||||
seed = np.atleast_1d(np.genfromtxt(seed_file, names=True))
|
||||
try:
|
||||
seed = seed[seed['_rfac'] <= rfac_limit]
|
||||
except ValueError:
|
||||
@@ -561,7 +561,7 @@ class Population(object):
|
||||
this method does not handle exceptions coming from numpy.genfromtxt
|
||||
such as missing file (IOError) or conversion errors (ValueError).
|
||||
exception handling should be done by the owner of the population (typically the model handler).
|
||||
patch values that lie outside the population domain aresilently ignored.
|
||||
patch values that lie outside the model space are silently ignored.
|
||||
|
||||
@param patch_file: path and name of the patch file.
|
||||
the file must have the correct format for load_array(),
|
||||
@@ -572,7 +572,7 @@ class Population(object):
|
||||
|
||||
@raise ValueError for conversion errors.
|
||||
"""
|
||||
self.pos_patch = np.genfromtxt(patch_file, names=True)
|
||||
self.pos_patch = np.atleast_1d(np.genfromtxt(patch_file, names=True))
|
||||
source_fields = set(self.pos_patch.dtype.names)
|
||||
dest_fields = set(self.model_start.keys())
|
||||
common_fields = source_fields & dest_fields
|
||||
@@ -592,7 +592,7 @@ class Population(object):
|
||||
|
||||
the method overwrites only parameter values, not control variables.
|
||||
_particle indices that lie outside the range of available population items are ignored.
|
||||
parameter values that lie outside the parameter domain (min/max) are ignored.
|
||||
parameter values that lie outside the model space (min/max) are ignored.
|
||||
"""
|
||||
if self.pos_patch is not None:
|
||||
logger.warning(BMsg("patching generation {gen} with new positions.", gen=self.generation))
|
||||
@@ -658,7 +658,7 @@ class Population(object):
|
||||
elif isinstance(source, str):
|
||||
for i in range(timeout):
|
||||
try:
|
||||
array = np.genfromtxt(source, names=True)
|
||||
array = np.atleast_1d(np.genfromtxt(source, names=True))
|
||||
except IOError:
|
||||
time.sleep(1)
|
||||
else:
|
||||
@@ -708,7 +708,7 @@ class Population(object):
|
||||
|
||||
the method also performs a range check.
|
||||
the parameter values are constrained according to self.position_constrain_mode
|
||||
and the parameter domain self.model_min and self.model_max.
|
||||
and the model space self.model_min and self.model_max.
|
||||
if the constrain mode is `error`, models that violate the constraints are ignored
|
||||
and removed from the import queue.
|
||||
|
||||
@@ -844,18 +844,18 @@ class Population(object):
|
||||
"""
|
||||
constrain a position to the given bounds.
|
||||
|
||||
this method resolves violations of parameter boundaries, i.e. when a particle is leaving the designated domain.
|
||||
if a violation is detected, the method calculates an updated position inside the domain
|
||||
this method resolves violations of parameter boundaries, i.e. when a particle is leaving the designated model space.
|
||||
if a violation is detected, the method calculates an updated position inside the model space
|
||||
according to the selected algorithm.
|
||||
in some cases the velocity or boundaries have to be updated as well.
|
||||
|
||||
the method distinguishes overshoot and undershoot violations.
|
||||
overshoot is the normal case when the particle is leaving the domain.
|
||||
overshoot is the normal case when the particle is leaving the model space.
|
||||
it is handled according to the selected algorithm.
|
||||
|
||||
undershoot is a special case where the particle was outside the boundaries before the move.
|
||||
this case can occur in the beginning if the population is seeded with out-of-bounds values.
|
||||
undershoot is always handled by placing the particle at a random position in the domain
|
||||
undershoot is always handled by placing the particle at a random position in the model space
|
||||
regardless of the chosen constraint mode.
|
||||
|
||||
@note it is important to avoid bias while handling constraint violations.
|
||||
@@ -877,7 +877,7 @@ class Population(object):
|
||||
|
||||
@param _mode: what to do if a boundary constraint is violated:
|
||||
@arg 're-enter': re-enter from the opposite side of the parameter interval.
|
||||
@arg 'bounce': fold the motion vector at the boundary and move the particle back into the domain.
|
||||
@arg 'bounce': fold the motion vector at the boundary and move the particle back into the model space.
|
||||
@arg 'scatter': place the particle at a random place between its old position and the violated boundary.
|
||||
@arg 'stick': place the particle at the violated boundary.
|
||||
@arg 'expand': move the boundary so that the particle fits.
|
||||
@@ -982,7 +982,7 @@ class Population(object):
|
||||
@param search_array: population-like numpy structured array to search for the model.
|
||||
defaults to self.results if None.
|
||||
|
||||
@param precision: precision relative to model domain at which elements should be considered equal.
|
||||
@param precision: precision relative to model space at which elements should be considered equal.
|
||||
|
||||
@return index of the first occurrence.
|
||||
|
||||
@@ -1071,7 +1071,7 @@ class Population(object):
|
||||
|
||||
@raise AssertionError if the number of rows of the two files differ.
|
||||
"""
|
||||
data = np.genfromtxt(filename, names=True)
|
||||
data = np.atleast_1d(np.genfromtxt(filename, names=True))
|
||||
assert data.shape == array.shape
|
||||
for name in data.dtype.names:
|
||||
array[name] = data[name]
|
||||
@@ -1182,7 +1182,7 @@ class PopulationHandler(handlers.ModelHandler):
|
||||
which may slow down convergence.
|
||||
|
||||
if calculations take a long time compared to the available computation time
|
||||
or spawn a lot of sub-tasks due to complex symmetry,
|
||||
or spawn a lot of sub-tasks due to complex model space,
|
||||
and you prefer to allow for a good number of generations,
|
||||
you should override the population size.
|
||||
|
||||
@@ -1190,7 +1190,7 @@ class PopulationHandler(handlers.ModelHandler):
|
||||
|
||||
@param slots: number of calculation processes available through MPI.
|
||||
|
||||
@return: None
|
||||
@return (int) population size
|
||||
"""
|
||||
super(PopulationHandler, self).setup(project, slots)
|
||||
|
||||
@@ -1206,10 +1206,10 @@ class PopulationHandler(handlers.ModelHandler):
|
||||
outfile.write(" ".join(self._pop.results.dtype.names))
|
||||
outfile.write("\n")
|
||||
|
||||
return None
|
||||
return self._pop_size
|
||||
|
||||
def setup_population(self):
|
||||
self._pop.setup(self._pop_size, self._project.create_domain(), **self._project.optimizer_params)
|
||||
self._pop.setup(self._pop_size, self._project.create_model_space(), **self._project.optimizer_params)
|
||||
|
||||
def cleanup(self):
|
||||
super(PopulationHandler, self).cleanup()
|
||||
@@ -1235,7 +1235,7 @@ class PopulationHandler(handlers.ModelHandler):
|
||||
the effect can be reduced by making the population larger than the number of processes.
|
||||
|
||||
the created tasks are returned as the function result and added to self._pending_tasks.
|
||||
|
||||
|
||||
@return list of generated tasks.
|
||||
empty list if the optimization has converged (see Population.is_converged())
|
||||
or if the time limit is approaching.
|
||||
|
||||
Reference in New Issue
Block a user