diff --git a/.travis.yml b/.travis.yml index 10514ea0f..ec6e95156 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,8 +18,9 @@ matrix: - python: "3.7" dist: xenial env: NUMPY=numpy - - python: "pypy" - env: NUMPY="git+https://bitbucket.org/pypy/numpy.git" + - python: "3.8" + dist: xenial + env: NUMPY=numpy addons: apt: packages: diff --git a/deap/tools/crossover.py b/deap/tools/crossover.py index e64d02deb..859803164 100644 --- a/deap/tools/crossover.py +++ b/deap/tools/crossover.py @@ -259,6 +259,45 @@ def cxBlend(ind1, ind2, alpha): return ind1, ind2 +def cxBlendBounded(ind1, ind2, low, up, alpha): + """Executes a blend crossover that modify in-place the input individuals. + The blend crossover expects :term:`sequence` individuals of floating point + numbers. + + :param ind1: The first individual participating in the crossover. + :param ind2: The second individual participating in the crossover. + :param low: A value or a :term:`python:sequence` of values that is the lower + bound of the search space. + :param up: A value or a :term:`python:sequence` of values that is the upper + bound of the search space. + :param alpha: Extent of the interval in which the new values can be drawn + for each attribute on both side of the parents' attributes. + :returns: A tuple of two individuals. + + This function uses the :func:`~random.random` function from the python base + :mod:`random` module. + """ + + size = min(len(ind1), len(ind2)) + if not isinstance(low, Sequence): + low = repeat(low, size) + elif len(low) < size: + raise IndexError("low must be at least the size of the shorter individual: %d < %d" % (len(low), size)) + if not isinstance(up, Sequence): + up = repeat(up, size) + elif len(up) < size: + raise IndexError("up must be at least the size of the shorter individual: %d < %d" % (len(up), size)) + + for i, (x1, x2, xl, xu) in enumerate(zip(ind1, ind2, low, up)): + gamma = (1. + 2. * alpha) * random.random() - alpha + c1 = (1. - gamma) * x1 + gamma * x2 + c2 = gamma * x1 + (1. - gamma) * x2 + + ind1[i] = min(max(c1, xl), xu) + ind2[i] = min(max(c2, xl), xu) + + return ind1, ind2 + def cxSimulatedBinary(ind1, ind2, eta): """Executes a simulated binary crossover that modify in-place the input @@ -455,7 +494,7 @@ def cxESTwoPoints(ind1, ind2): # List of exported function names. __all__ = ['cxOnePoint', 'cxTwoPoint', 'cxUniform', 'cxPartialyMatched', - 'cxUniformPartialyMatched', 'cxOrdered', 'cxBlend', + 'cxUniformPartialyMatched', 'cxOrdered', 'cxBlend', "cxBlendBounded", 'cxSimulatedBinary', 'cxSimulatedBinaryBounded', 'cxMessyOnePoint', 'cxESBlend', 'cxESTwoPoint'] diff --git a/doc/api/tools.rst b/doc/api/tools.rst index 9bca2db62..b72ced981 100644 --- a/doc/api/tools.rst +++ b/doc/api/tools.rst @@ -27,6 +27,7 @@ Here is a list of the implemented operators in DEAP, .. :func:`cxUniformPartialyMatched` :func:`mutUniformInt` :func:`selSPEA2` .. .. :func:`cxOrdered` :func:`mutESLogNormal` :func:`selRandom` .. .. :func:`cxBlend` .. :func:`selBest` .. + .. :func:`cxBlendBounded` .. .. :func:`cxESBlend` .. :func:`selWorst` .. .. :func:`cxESTwoPoint` .. :func:`selTournamentDCD` .. .. :func:`cxSimulatedBinary` .. :func:`selDoubleTournament` .. @@ -86,6 +87,8 @@ Crossover .. autofunction:: deap.tools.cxBlend +.. autofunction:: deap.tools.cxBlendBounded + .. autofunction:: deap.tools.cxESBlend .. autofunction:: deap.tools.cxESTwoPoint