diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c5a0a4767..b8e28c49d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -19,6 +19,8 @@ jobs: python.version: '3.6' Python37_VS2017: python.version: '3.7' + Python38_VS2017: + python.version: '3.8' steps: - task: UsePythonVersion@0 inputs: @@ -53,6 +55,8 @@ jobs: python.version: '3.6' Python37_macOS1014: python.version: '3.7' + Python38_macOS1014: + python.version: '3.8' steps: - task: UsePythonVersion@0 inputs: @@ -83,6 +87,8 @@ jobs: python.version: '3.6' Python37_macOS1013: python.version: '3.7' + Python38_macOS1013: + python.version: '3.8' steps: - task: UsePythonVersion@0 inputs: diff --git a/deap/__init__.py b/deap/__init__.py index ce97ecc30..e045a3de3 100644 --- a/deap/__init__.py +++ b/deap/__init__.py @@ -14,4 +14,4 @@ # License along with DEAP. If not, see . __author__ = "DEAP Team" __version__ = "1.3" -__revision__ = "1.3.0" +__revision__ = "1.3.1" diff --git a/deap/algorithms.py b/deap/algorithms.py index 4105fefd3..b08897209 100644 --- a/deap/algorithms.py +++ b/deap/algorithms.py @@ -467,6 +467,10 @@ def eaGenerateUpdate(toolbox, ngen, halloffame=None, stats=None, evaluate(population) toolbox.update(population) + + This function expects :meth:`toolbox.generate` and :meth:`toolbox.evaluate` aliases to be + registered in the toolbox. + .. [Colette2010] Collette, Y., N. Hansen, G. Pujol, D. Salazar Aponte and R. Le Riche (2010). On Object-Oriented Programming of Optimizers - Examples in Scilab. In P. Breitkopf and R. F. Coelho, eds.: diff --git a/deap/base.py b/deap/base.py index b57b9663b..57d6a8d72 100644 --- a/deap/base.py +++ b/deap/base.py @@ -52,11 +52,11 @@ def __init__(self): def register(self, alias, function, *args, **kargs): """Register a *function* in the toolbox under the name *alias*. You may provide default arguments that will be passed automatically when - calling the registered function. Fixed arguments can then be overriden + calling the registered function. Fixed arguments can then be overridden at function call time. :param alias: The name the operator will take in the toolbox. If the - alias already exist it will overwrite the the operator + alias already exist it will overwrite the operator already present. :param function: The function to which refer the alias. :param argument: One or more argument (and keyword argument) to pass @@ -124,7 +124,7 @@ def decorate(self, alias, *decorators): class Fitness(object): """The fitness is a measure of quality of a solution. If *values* are - provided as a tuple, the fitness is initalized using those values, + provided as a tuple, the fitness is initialized using those values, otherwise it is empty (or invalid). :param values: The initial values of the fitness as a tuple, optional. @@ -185,6 +185,7 @@ def getValues(self): return tuple(map(truediv, self.wvalues, self.weights)) def setValues(self, values): + assert len(values) == len(self.weights), "Assigned values have not the same length than fitness weights" try: self.wvalues = tuple(map(mul, values, self.weights)) except TypeError: diff --git a/deap/benchmarks/tools.py b/deap/benchmarks/tools.py index 3a4072993..471bc059e 100644 --- a/deap/benchmarks/tools.py +++ b/deap/benchmarks/tools.py @@ -9,7 +9,7 @@ numpy = False try: - from scipy.spatial import distance + import scipy.spatial except ImportError: scipy = False @@ -314,5 +314,5 @@ def igd(A, Z): """ if not scipy: raise ImportError("idg requires scipy module") - distances = distance.cdist(A, Z) + distances = scipy.spatial.distance.cdist(A, Z) return numpy.average(numpy.min(distances, axis=0)) diff --git a/deap/cma.py b/deap/cma.py index 201b645b7..4f6e62a21 100644 --- a/deap/cma.py +++ b/deap/cma.py @@ -437,10 +437,10 @@ def _select(self, candidates): mid_front = None not_chosen = list() - # Fill the next population (chosen) with the fronts until there is not enouch space + # Fill the next population (chosen) with the fronts until there is not enough space # When an entire front does not fit in the space left we rely on the hypervolume # for this front - # The remaining fronts are explicitely not chosen + # The remaining fronts are explicitly not chosen full = False for front in pareto_fronts: if len(chosen) + len(front) <= self.mu and not full: diff --git a/deap/creator.py b/deap/creator.py index 552c40671..9b0f61aab 100644 --- a/deap/creator.py +++ b/deap/creator.py @@ -61,7 +61,7 @@ def __deepcopy__(self, memo): @staticmethod def __new__(cls, iterable): """Creates a new instance of a numpy.ndarray from a function call. - Adds the possibility to instanciate from an iterable.""" + Adds the possibility to instantiate from an iterable.""" return numpy.array(list(iterable)).view(cls) def __setstate__(self, state): diff --git a/deap/gp.py b/deap/gp.py index 451a2dadc..44bd8bd07 100644 --- a/deap/gp.py +++ b/deap/gp.py @@ -325,7 +325,7 @@ def addPrimitive(self, primitive, in_types, ret_type, name=None): """Add a primitive to the set. :param primitive: callable object or a function. - :parma in_types: list of primitives arguments' type + :param in_types: list of primitives arguments' type :param ret_type: type returned by the primitive. :param name: alternative name for the primitive instead of its __name__ attribute. diff --git a/deap/tools/crossover.py b/deap/tools/crossover.py index 4f086fdc2..e64d02deb 100644 --- a/deap/tools/crossover.py +++ b/deap/tools/crossover.py @@ -72,12 +72,12 @@ def cxTwoPoints(ind1, ind2): def cxUniform(ind1, ind2, indpb): """Executes a uniform crossover that modify in place the two - :term:`sequence` individuals. The attributes are swapped accordingto the + :term:`sequence` individuals. The attributes are swapped according to the *indpb* probability. :param ind1: The first individual participating in the crossover. :param ind2: The second individual participating in the crossover. - :param indpb: Independent probabily for each attribute to be exchanged. + :param indpb: Independent probability for each attribute to be exchanged. :returns: A tuple of two individuals. This function uses the :func:`~random.random` function from the python base @@ -390,7 +390,7 @@ def cxMessyOnePoint(ind1, ind2): def cxESBlend(ind1, ind2, alpha): """Executes a blend crossover on both, the individual and the strategy. The individuals shall be a :term:`sequence` and must have a :term:`sequence` - :attr:`strategy` attribute. Adjustement of the minimal strategy shall be done + :attr:`strategy` attribute. Adjustment of the minimal strategy shall be done after the call to this function, consider using a decorator. :param ind1: The first evolution strategy participating in the crossover. diff --git a/deap/tools/emo.py b/deap/tools/emo.py index 7d7573785..ab9149fb0 100644 --- a/deap/tools/emo.py +++ b/deap/tools/emo.py @@ -146,24 +146,26 @@ def selTournamentDCD(individuals, k): """Tournament selection based on dominance (D) between two individuals, if the two individuals do not interdominate the selection is made based on crowding distance (CD). The *individuals* sequence length has to - be a multiple of 4. Starting from the beginning of the selected - individuals, two consecutive individuals will be different (assuming all - individuals in the input list are unique). Each individual from the input - list won't be selected more than twice. + be a multiple of 4 only if k is equal to the length of individuals. + Starting from the beginning of the selected individuals, two consecutive + individuals will be different (assuming all individuals in the input list + are unique). Each individual from the input list won't be selected more + than twice. This selection requires the individuals to have a :attr:`crowding_dist` attribute, which can be set by the :func:`assignCrowdingDist` function. :param individuals: A list of individuals to select from. - :param k: The number of individuals to select. + :param k: The number of individuals to select. Must be less than or equal + to len(individuals). :returns: A list of selected individuals. """ - - if len(individuals) % 4 != 0: - raise ValueError("selTournamentDCD: individuals length must be a multiple of 4") - - if k % 4 != 0: - raise ValueError("selTournamentDCD: number of individuals to select must be a multiple of 4") + + if k > len(individuals): + raise ValueError("selTournamentDCD: k must be less than or equal to individuals length") + + if k == len(individuals) and k % 4 != 0: + raise ValueError("selTournamentDCD: k must be divisible by four if k == len(individuals)") def tourn(ind1, ind2): if ind1.fitness.dominates(ind2.fitness): @@ -448,7 +450,7 @@ def sweepB(best, worst, front): class selNSGA3WithMemory(object): """Class version of NSGA-III selection including memory for best, worst and extreme points. Registering this operator in a toolbox is a bit different - than classical operators, it requires to instanciate the class instead + than classical operators, it requires to instantiate the class instead of just registering the function:: >>> from deap import base diff --git a/deap/tools/mutation.py b/deap/tools/mutation.py index ac0075d7c..bb882528a 100644 --- a/deap/tools/mutation.py +++ b/deap/tools/mutation.py @@ -148,10 +148,10 @@ def mutUniformInt(individual, low, up, indpb): :param individual: :term:`Sequence ` individual to be mutated. :param low: The lower bound or a :term:`python:sequence` of - of lower bounds of the range from wich to draw the new + of lower bounds of the range from which to draw the new integer. :param up: The upper bound or a :term:`python:sequence` of - of upper bounds of the range from wich to draw the new + of upper bounds of the range from which to draw the new integer. :param indpb: Independent probability for each attribute to be mutated. :returns: A tuple of one individual. diff --git a/deap/tools/support.py b/deap/tools/support.py index 3f4ac7ed9..389a83f3e 100644 --- a/deap/tools/support.py +++ b/deap/tools/support.py @@ -48,7 +48,7 @@ class History(object): import networkx graph = networkx.DiGraph(history.genealogy_tree) - graph = graph.reverse() # Make the grah top-down + graph = graph.reverse() # Make the graph top-down colors = [toolbox.evaluate(history.genealogy_history[i])[0] for i in graph] networkx.draw(graph, node_color=colors) plt.show() @@ -126,7 +126,7 @@ def getGenealogy(self, individual, max_depth=float("inf")): :func:`~deap.tools.History.update` in order to retrieve its associated genealogy tree. The returned graph contains the parents up to *max_depth* variations before this individual. If not provided - the maximum depth is up to the begining of the evolution. + the maximum depth is up to the beginning of the evolution. :param individual: The individual at the root of the genealogy tree. :param max_depth: The approximate maximum distance between the root @@ -264,7 +264,7 @@ class Logbook(list): Data can be retrieved via the :meth:`select` method given the appropriate names. - The :class:`Logbook` class may also contain other logbooks refered to + The :class:`Logbook` class may also contain other logbooks referred to as chapters. Chapters are used to store information associated to a specific part of the evolution. For example when computing statistics on different components of individuals (namely :class:`MultiStatistics`), @@ -291,7 +291,7 @@ def __init__(self): logbook.chapters["size"].select("mean") Compiling a :class:`MultiStatistics` object returns a dictionary - containing dictionnaries, therefore when recording such an object in a + containing dictionaries, therefore when recording such an object in a logbook using the keyword argument unpacking operator (**), chapters will be automatically added to the logbook. :: @@ -321,7 +321,7 @@ def __init__(self): logbook.header = ("gen", "mean", "max") - If not set the header is built with all fields, in arbritrary order + If not set the header is built with all fields, in arbitrary order on insertion of the first data. The header can be removed by setting it to :data:`None`. """ @@ -334,7 +334,7 @@ def __init__(self): def record(self, **infos): """Enter a record of event in the logbook as a list of key-value pairs. - The informations are appended chronogically to a list as a dictionary. + The informations are appended chronologically to a list as a dictionary. When the value part of a pair is a dictionary, the informations contained in the dictionary are recorded in a chapter entitled as the name of the key part of the pair. Chapters are also Logbook. @@ -519,10 +519,10 @@ def update(self, population): worst individuals in it by the best individuals present in *population* (if they are better). The size of the hall of fame is kept constant. - + :param population: A list of individual with a fitness attribute to update the hall of fame with. - """ + """ for ind in population: if len(self) == 0 and self.maxsize !=0: # Working on an empty hall of fame is problematic for the @@ -593,7 +593,7 @@ class ParetoFront(HallOfFame): that ever lived in the population. That means that the Pareto front hall of fame can contain an infinity of different individuals. - :param similar: A function that tels the Pareto front whether or not two + :param similar: A function that tells the Pareto front whether or not two individuals are similar, optional. The size of the front may become very large if it is used for example on diff --git a/doc/conf.py b/doc/conf.py index 602949c0f..42299be67 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -182,7 +182,7 @@ # Custom sidebar templates, maps document names to template names. html_sidebars = { - 'index': 'indexsidebar.html', + 'index': ['indexsidebar.html'], } # Additional templates that should be rendered to pages, maps page names to diff --git a/doc/examples/gp_symbreg.rst b/doc/examples/gp_symbreg.rst index ae1f45b21..aa1168542 100644 --- a/doc/examples/gp_symbreg.rst +++ b/doc/examples/gp_symbreg.rst @@ -112,7 +112,7 @@ the MSE (Mean Squared Error), which is returned as the fitness of the individual Afterwards, we register the evaluation function. We also choose the selection method (a tournament of size 3), the mate method (one point crossover with -uniform probability over all the nodes), the mutation method (an uniform +uniform probability over all the nodes), and the mutation method (a uniform probability mutation which may append a new full sub-tree to a node). Then, we decorate the mate and mutate method to limit the height of generated diff --git a/doc/tutorials/basic/part1.rst b/doc/tutorials/basic/part1.rst index ee34f0c0f..989d2f3d8 100644 --- a/doc/tutorials/basic/part1.rst +++ b/doc/tutorials/basic/part1.rst @@ -167,7 +167,7 @@ arguments. :lines: 2- Calling :func:`toolbox.individual` will readily return a complete particle with -a speed vector and a maximizing two objectives fitness attribute. +a speed vector and a fitness attribute for maximizing two objectives. .. _funky: diff --git a/setup.py b/setup.py index e68c05220..03dd3cd16 100644 --- a/setup.py +++ b/setup.py @@ -7,8 +7,8 @@ from setuptools import setup, Extension, find_packages modules = find_packages(exclude=['examples']) except ImportError: - warnings.append("warning: using disutils.core.setup, cannot use \"develop\" option") - from disutils.core import setup, Extension + warnings.append("warning: using distutils.core.setup, cannot use \"develop\" option") + from distutils.core import setup, Extension modules = ['deap', 'deap.benchmarks', 'deap.tests', 'deap.tools', 'deap.tools._hypervolume'] from setuptools.command.build_ext import build_ext