From 8aa17a0579ed1b4559f36b6135036482b089ced5 Mon Sep 17 00:00:00 2001 From: Ben Elliston Date: Mon, 24 Apr 2023 16:04:40 +1000 Subject: [PATCH] Round one of flake8 warnings. --- deap/benchmarks/__init__.py | 12 +++++++++++- deap/benchmarks/gp.py | 10 +++++++++- deap/benchmarks/movingpeaks.py | 6 +++++- deap/benchmarks/tools.py | 7 +++++++ deap/creator.py | 2 ++ deap/tests/test_algorithms.py | 5 +++++ deap/tests/test_creator.py | 4 ++++ deap/tests/test_logbook.py | 4 +--- deap/tests/test_mutation.py | 1 + deap/tests/test_pickle.py | 3 ++- deap/tools/_hypervolume/pyhv.py | 15 ++------------- deap/tools/constraint.py | 4 ++++ deap/tools/emo.py | 17 +++++++++++++++++ deap/tools/indicator.py | 1 + deap/tools/init.py | 4 +++- deap/tools/migration.py | 1 + deap/tools/selection.py | 6 +++++- deap/tools/support.py | 8 ++++++-- 18 files changed, 86 insertions(+), 24 deletions(-) diff --git a/deap/benchmarks/__init__.py b/deap/benchmarks/__init__.py index ca2acd89b..a371ddc02 100644 --- a/deap/benchmarks/__init__.py +++ b/deap/benchmarks/__init__.py @@ -22,6 +22,7 @@ from operator import mul from functools import reduce + # Unimodal def rand(individual): r"""Random test objective function. @@ -41,6 +42,7 @@ def rand(individual): """ return random.random(), + def plane(individual): r"""Plane test objective function. @@ -59,6 +61,7 @@ def plane(individual): """ return individual[0], + def sphere(individual): r"""Sphere test objective function. @@ -77,6 +80,7 @@ def sphere(individual): """ return sum(gene * gene for gene in individual), + def cigar(individual): r"""Cigar test objective function. @@ -95,6 +99,7 @@ def cigar(individual): """ return individual[0]**2 + 1e6 * sum(gene * gene for gene in individual[1:]), + def rosenbrock(individual): r"""Rosenbrock test objective function. @@ -117,6 +122,7 @@ def rosenbrock(individual): return sum(100 * (x * x - y)**2 + (1. - x)**2 \ for x, y in zip(individual[:-1], individual[1:])), + def h1(individual): r""" Simple two-dimensional function containing several local maxima. From: The Merits of a Parallel Genetic Algorithm in Solving Hard @@ -145,7 +151,7 @@ def h1(individual): denum = ((individual[0] - 8.6998)**2 + (individual[1] - 6.7665)**2)**0.5 + 1 return num / denum, - # + # Multimodal def ackley(individual): r"""Ackley test objective function. @@ -596,6 +602,7 @@ def dtlz5(ind, n_objs): reduce(lambda x,y: x*y, [cos(theta(a)) for a in ind[1:m-1]], 1) * sin(theta(ind[m-1]))) return fit + def dtlz6(ind, n_objs): r"""DTLZ6 multiobjective function. It returns a tuple of *obj* values. The individual must have at least *obj* elements. @@ -616,6 +623,7 @@ def dtlz6(ind, n_objs): reduce(lambda x,y: x*y, [cos(theta(a)) for a in ind[1:m-1]], 1) * sin(theta(ind[m-1]))) return fit + def dtlz7(ind, n_objs): r"""DTLZ7 multiobjective function. It returns a tuple of *obj* values. The individual must have at least *obj* elements. @@ -627,6 +635,7 @@ def dtlz7(ind, n_objs): fit.append((1 + gval) * (n_objs - sum([a / (1.0 + gval) * (1 + sin(3 * pi * a)) for a in ind[:n_objs-1]]))) return fit + def fonseca(individual): r"""Fonseca and Fleming's multiobjective function. From: C. M. Fonseca and P. J. Fleming, "Multiobjective optimization and @@ -642,6 +651,7 @@ def fonseca(individual): f_2 = 1 - exp(-sum((xi + 1/sqrt(3))**2 for xi in individual[:3])) return f_1, f_2 + def poloni(individual): r"""Poloni's multiobjective function on a two attribute *individual*. From: C. Poloni, "Hybrid GA for multi objective aerodynamic shape optimization", diff --git a/deap/benchmarks/gp.py b/deap/benchmarks/gp.py index 94423bc00..a196d2615 100644 --- a/deap/benchmarks/gp.py +++ b/deap/benchmarks/gp.py @@ -15,6 +15,7 @@ from math import exp, sin, cos + def kotanchek(data): """Kotanchek benchmark function. @@ -29,6 +30,7 @@ def kotanchek(data): """ return exp(-(data[0] - 1)**2) / (3.2 + (data[1] - 2.5)**2) + def salustowicz_1d(data): """Salustowicz benchmark function. @@ -43,8 +45,9 @@ def salustowicz_1d(data): """ return exp(-data[0]) * data[0]**3 * cos(data[0]) * sin(data[0]) * (cos(data[0]) * sin(data[0])**2 - 1) + def salustowicz_2d(data): - """Salustowicz benchmark function. + r"""Salustowicz benchmark function. .. list-table:: :widths: 10 50 @@ -57,6 +60,7 @@ def salustowicz_2d(data): """ return exp(-data[0]) * data[0]**3 * cos(data[0]) * sin(data[0]) * (cos(data[0]) * sin(data[0])**2 - 1) * (data[1] - 5) + def unwrapped_ball(data): """Unwrapped ball benchmark function. @@ -71,6 +75,7 @@ def unwrapped_ball(data): """ return 10. / (5. + sum((d - 3)**2 for d in data)) + def rational_polynomial(data): """Rational polynomial ball benchmark function. @@ -85,6 +90,7 @@ def rational_polynomial(data): """ return 30. * (data[0] - 1) * (data[2] - 1) / (data[1]**2 * (data[0] - 10)) + def sin_cos(data): """Sine cosine benchmark function. @@ -99,6 +105,7 @@ def sin_cos(data): """ 6 * sin(data[0]) * cos(data[1]) + def ripple(data): """Ripple benchmark function. @@ -113,6 +120,7 @@ def ripple(data): """ return (data[0] - 3) * (data[1] - 3) + 2 * sin((data[0] - 4) * (data[1] - 4)) + def rational_polynomial2(data): """Rational polynomial benchmark function. diff --git a/deap/benchmarks/movingpeaks.py b/deap/benchmarks/movingpeaks.py index b90a558ed..c0ca45218 100644 --- a/deap/benchmarks/movingpeaks.py +++ b/deap/benchmarks/movingpeaks.py @@ -30,6 +30,7 @@ except: from collections import Sequence + def cone(individual, position, height, width): """The cone peak function to be used with scenario 2 and 3. @@ -41,6 +42,7 @@ def cone(individual, position, height, width): value += (x - p)**2 return height - width * math.sqrt(value) + def sphere(individual, position, height, width): value = 0.0 for x, p in zip(individual, position): @@ -58,6 +60,7 @@ def function1(individual, position, height, width): value += (x - p)**2 return height / (1 + width * value) + class MovingPeaks: """The Moving Peaks Benchmark is a fitness function changing over time. It consists of a number of peaks, changing in height, width and location. The @@ -161,7 +164,6 @@ def __init__(self, dim, random=random, **kargs): else: self.peaks_height = [self.random.uniform(self.min_height, self.max_height) for _ in range(npeaks)] - if uniform_width != 0: self.peaks_width = [uniform_width for _ in range(npeaks)] else: @@ -382,6 +384,7 @@ def changePeaks(self): "width_severity": 0.5, "period": 1000} + def diversity(population): nind = len(population) ndim = len(population[0]) @@ -391,6 +394,7 @@ def diversity(population): d = [di / nind for di in d] return math.sqrt(sum((di - xi)**2 for x in population for di, xi in zip(d, x))) + if __name__ == "__main__": mpb = MovingPeaks(dim=2, npeaks=[1,1,10], number_severity=0.1) print(mpb.maximums()) diff --git a/deap/benchmarks/tools.py b/deap/benchmarks/tools.py index bc3043e2f..bce1d2680 100644 --- a/deap/benchmarks/tools.py +++ b/deap/benchmarks/tools.py @@ -22,6 +22,7 @@ # fallback on python version from ..tools._hypervolume import pyhv as hv + class translate(object): """Decorator for evaluation functions, it translates the objective function by *vector* which should be the same length as the individual @@ -61,6 +62,7 @@ def evaluate(individual): """ self.vector = vector + class rotate(object): """Decorator for evaluation functions, it rotates the objective function by *matrix* which should be a valid orthogonal NxN rotation matrix, with N @@ -114,6 +116,7 @@ def evaluate(individual): """ self.matrix = numpy.linalg.inv(matrix) + class noise(object): """Decorator for evaluation functions, it evaluates the objective function and adds noise by calling the function(s) provided in the *noise* @@ -168,6 +171,7 @@ def evaluate(individual): except TypeError: self.rand_funcs = repeat(noise) + class scale(object): """Decorator for evaluation functions, it scales the objective function by *factor* which should be the same length as the individual size. When @@ -209,6 +213,7 @@ def evaluate(individual): # objective function self.factor = tuple(1.0/f for f in factor) + class bound(object): """Decorator for crossover and mutation functions, it changes the individuals after the modification is done to bring it back in the allowed @@ -253,6 +258,7 @@ def __init__(self, bounds, type): elif type == "clip": self.bound = self._clip + def diversity(first_front, first, last): """Given a Pareto front `first_front` and the two extreme points of the optimal Pareto front, this function returns a metric of the diversity @@ -275,6 +281,7 @@ def diversity(first_front, first, last): delta = (df + dl + di)/(df + dl + len(dt) * dm ) return delta + def convergence(first_front, optimal_front): """Given a Pareto front `first_front` and the optimal Pareto front, this function returns a metric of convergence diff --git a/deap/creator.py b/deap/creator.py index 06e00e8a7..3976797f9 100644 --- a/deap/creator.py +++ b/deap/creator.py @@ -90,6 +90,8 @@ def __deepcopy__(self, memo): def __reduce__(self): return (self.__class__, (list(self),), self.__dict__) + + class_replacers[array.array] = _array diff --git a/deap/tests/test_algorithms.py b/deap/tests/test_algorithms.py index 62e17a757..dbece852c 100644 --- a/deap/tests/test_algorithms.py +++ b/deap/tests/test_algorithms.py @@ -36,19 +36,23 @@ def setup_func_single_obj(): creator.create(FITCLSNAME, base.Fitness, weights=(-1.0,)) creator.create(INDCLSNAME, list, fitness=creator.__dict__[FITCLSNAME]) + def setup_func_multi_obj(): creator.create(FITCLSNAME, base.Fitness, weights=(-1.0, -1.0)) creator.create(INDCLSNAME, list, fitness=creator.__dict__[FITCLSNAME]) + def setup_func_multi_obj_numpy(): creator.create(FITCLSNAME, base.Fitness, weights=(-1.0, -1.0)) creator.create(INDCLSNAME, numpy.ndarray, fitness=creator.__dict__[FITCLSNAME]) + def teardown_func(): # Messy way to remove a class from the creator del creator.__dict__[FITCLSNAME] del creator.__dict__[INDCLSNAME] + @with_setup(setup_func_single_obj, teardown_func) def test_cma(): NDIM = 5 @@ -65,6 +69,7 @@ def test_cma(): assert best.fitness.values < (1e-8,), "CMA algorithm did not converged properly." + @with_setup(setup_func_multi_obj, teardown_func) def test_nsga2(): NDIM = 5 diff --git a/deap/tests/test_creator.py b/deap/tests/test_creator.py index a7e3178cd..016ffff29 100644 --- a/deap/tests/test_creator.py +++ b/deap/tests/test_creator.py @@ -27,9 +27,11 @@ CNAME = "CLASS_NAME" + def teardown_func(): creator.__dict__.pop(CNAME) + @with_setup(None, teardown_func) def test_create(): creator.create(CNAME, list) @@ -44,6 +46,7 @@ def test_attribute(): assert l.a == 1, "%s, expected %i" % (l.a, 1) + @with_setup(None, teardown_func) def test_array(): creator.create(CNAME, array.array, typecode="i") @@ -56,6 +59,7 @@ def test_array(): assert a == ta, "%s, expected %s" % (a, ta) assert b == tb, "%s, expected %s" % (b, tb) + @skipIf(not numpy, "Cannot import Numpy numerical library") @with_setup(None, teardown_func) def test_numpy_nocopy(): diff --git a/deap/tests/test_logbook.py b/deap/tests/test_logbook.py index 3194adebc..369eaad90 100644 --- a/deap/tests/test_logbook.py +++ b/deap/tests/test_logbook.py @@ -1,8 +1,8 @@ -import sys import unittest from deap import tools + class LogbookTest(unittest.TestCase): def setUp(self): @@ -37,8 +37,6 @@ def test_no_chapters(self): print(self.logbook.stream) - if __name__ == "__main__": suite = unittest.TestLoader().loadTestsFromTestCase(LogbookTest) unittest.TextTestRunner(verbosity=2).run(suite) - diff --git a/deap/tests/test_mutation.py b/deap/tests/test_mutation.py index 2822f8a83..666809ed3 100644 --- a/deap/tests/test_mutation.py +++ b/deap/tests/test_mutation.py @@ -3,6 +3,7 @@ from deap.tools.mutation import mutInversion + class MutationTest(unittest.TestCase): def test_mutInverstion_size_zero_chromosome_returns_unchanged_chromosome_in_tuple(self): diff --git a/deap/tests/test_pickle.py b/deap/tests/test_pickle.py index 873db8f46..7bf1eb1de 100644 --- a/deap/tests/test_pickle.py +++ b/deap/tests/test_pickle.py @@ -13,9 +13,11 @@ from deap import gp from deap import tools + def func(): return "True" + class Pickling(unittest.TestCase): def setUp(self): @@ -131,7 +133,6 @@ def test_pickle_population(self): self.assertEqual(pop[2], pop_l[2], "Unpickled individual list != pickled individual list") self.assertEqual(pop[2].fitness, pop_l[2].fitness, "Unpickled individual fitness != pickled individual fitness") - # @unittest.skipIf(platform.python_implementation() == "PyPy", "PyPy support for pickling ndarrays (thus stats) is very unstable.") def test_pickle_logbook(self): stats = tools.Statistics() diff --git a/deap/tools/_hypervolume/pyhv.py b/deap/tools/_hypervolume/pyhv.py index 2a9fb3439..c6059a29b 100644 --- a/deap/tools/_hypervolume/pyhv.py +++ b/deap/tools/_hypervolume/pyhv.py @@ -28,6 +28,7 @@ import numpy + def hypervolume(pointset, ref): """Compute the absolute hypervolume of a *pointset* according to the reference point *ref*. @@ -54,7 +55,6 @@ def __init__(self, referencePoint): self.referencePoint = referencePoint self.list = [] - def compute(self, front): """Returns the hypervolume that is dominated by a non-dominated front. @@ -99,7 +99,6 @@ def weaklyDominates(point, other): hyperVolume = self.hvRecursive(dimensions - 1, len(relevantPoints), bounds) return hyperVolume - def hvRecursive(self, dimIndex, length, bounds): """Recursive call to hypervolume calculation. @@ -178,7 +177,6 @@ def hvRecursive(self, dimIndex, length, bounds): hvol -= q.area[dimIndex] * q.cargo[dimIndex] return hvol - def preProcess(self, front): """Sets up the list data structure needed for calculation.""" dimensions = len(self.referencePoint) @@ -189,7 +187,6 @@ def preProcess(self, front): nodeList.extend(nodes, i) self.list = nodeList - def sortByDimension(self, nodes, i): """Sorts the list of nodes by the i-th value of the contained points.""" # build a list of tuples of (point[i], node) @@ -200,7 +197,6 @@ def sortByDimension(self, nodes, i): nodes[:] = [node for (_, node) in decorated] - class _MultiList: """A special data structure needed by FonsecaHyperVolume. @@ -236,7 +232,6 @@ def __init__(self, numberLists): self.sentinel.next = [self.sentinel] * numberLists self.sentinel.prev = [self.sentinel] * numberLists - def __str__(self): strings = [] for i in range(self.numberLists): @@ -251,12 +246,10 @@ def __str__(self): stringRepr += string + "\n" return stringRepr - def __len__(self): """Returns the number of lists that are included in this _MultiList.""" return self.numberLists - def getLength(self, i): """Returns the length of the i-th list.""" length = 0 @@ -267,7 +260,6 @@ def getLength(self, i): node = node.next[i] return length - def append(self, node, index): """Appends a node to the end of the list at the given index.""" lastButOne = self.sentinel.prev[index] @@ -277,7 +269,6 @@ def append(self, node, index): self.sentinel.prev[index] = node lastButOne.next[index] = node - def extend(self, nodes, index): """Extends the list at the given index with the nodes.""" sentinel = self.sentinel @@ -289,7 +280,6 @@ def extend(self, nodes, index): sentinel.prev[index] = node lastButOne.next[index] = node - def remove(self, node, index, bounds): """Removes and returns 'node' from all lists in [0, 'index'[.""" for i in range(index): @@ -301,7 +291,6 @@ def remove(self, node, index, bounds): bounds[i] = node.cargo[i] return node - def reinsert(self, node, index, bounds): """ Inserts 'node' at the position it had in all lists in [0, 'index'[ @@ -315,6 +304,7 @@ def reinsert(self, node, index, bounds): if bounds[i] > node.cargo[i]: bounds[i] = node.cargo[i] + __all__ = ["hypervolume_kmax", "hypervolume"] if __name__ == "__main__": @@ -333,4 +323,3 @@ def reinsert(self, node, index, bounds): if hv: print("C version: %f" % hv.hypervolume(pointset, ref)) print("Approximated: %f" % hypervolume_approximation(pointset, ref)) - diff --git a/deap/tools/constraint.py b/deap/tools/constraint.py index 5617aff35..673331ac8 100644 --- a/deap/tools/constraint.py +++ b/deap/tools/constraint.py @@ -7,6 +7,7 @@ except ImportError: from collections import Sequence + class DeltaPenalty(object): r"""This decorator returns penalized fitness for invalid individuals and the original fitness value for valid individuals. The penalized fitness is made @@ -63,8 +64,10 @@ def wrapper(individual, *args, **kwargs): return wrapper + DeltaPenality = DeltaPenalty + class ClosestValidPenalty(object): r"""This decorator returns penalized fitness for invalid individuals and the original fitness value for valid individuals. The penalized fitness is made @@ -131,6 +134,7 @@ def wrapper(individual, *args, **kwargs): return wrapper + ClosestValidPenality = ClosestValidPenalty # List of exported function names. diff --git a/deap/tools/emo.py b/deap/tools/emo.py index 19fb796a2..ab273c90c 100644 --- a/deap/tools/emo.py +++ b/deap/tools/emo.py @@ -11,6 +11,7 @@ # Non-Dominated Sorting (NSGA-II) # ###################################### + def selNSGA2(individuals, k, nd='standard'): """Apply NSGA-II selection operator on the *individuals*. Usually, the size of *individuals* will be larger than *k* because any individual @@ -115,6 +116,7 @@ def sortNondominated(individuals, k, first_front_only=False): return fronts + def assignCrowdingDist(individuals): """Assign a crowding distance to each individual's fitness. The crowding distance can be retrieve via the :attr:`crowding_dist` @@ -141,6 +143,7 @@ def assignCrowdingDist(individuals): for i, dist in enumerate(distances): individuals[i].fitness.crowding_dist = dist + def selTournamentDCD(individuals, k): """Tournament selection based on dominance (D) between two individuals, if the two individuals do not interdominate the selection is made @@ -197,11 +200,13 @@ def tourn(ind1, ind2): # Generalized Reduced runtime ND sort # ####################################### + def identity(obj): """Returns directly the argument *obj*. """ return obj + def isDominated(wvalues1, wvalues2): """Returns whether or not *wvalues2* dominates *wvalues1*. @@ -218,6 +223,7 @@ def isDominated(wvalues1, wvalues2): not_equal = True return not_equal + def median(seq, key=identity): """Returns the median of *seq* - the numeric value separating the higher half of a sample from the lower half. If there is an even number of @@ -230,6 +236,7 @@ def median(seq, key=identity): else: return (key(sseq[(length - 1) // 2]) + key(sseq[length // 2])) / 2.0 + def sortLogNondominated(individuals, k, first_front_only=False): """Sort *individuals* in pareto non-dominated fronts using the Generalized Reduced Run-Time Complexity Non-Dominated Sorting Algorithm presented by @@ -274,6 +281,7 @@ def sortLogNondominated(individuals, k, first_front_only=False): else: return pareto_fronts[0] + def sortNDHelperA(fitnesses, obj, front): """Create a non-dominated sorting of S on the first M objectives""" if len(fitnesses) < 2: @@ -295,6 +303,7 @@ def sortNDHelperA(fitnesses, obj, front): sortNDHelperB(best, worst, obj-1, front) sortNDHelperA(worst, obj, front) + def splitA(fitnesses, obj): """Partition the set of fitnesses in two according to the median of the objective index *obj*. The values equal to the median are put in @@ -323,6 +332,7 @@ def splitA(fitnesses, obj): else: return best_b, worst_b + def sweepA(fitnesses, front): """Update rank number associated to the fitnesses according to the first two objectives using a geometric sweep procedure. @@ -342,6 +352,7 @@ def sweepA(fitnesses, front): stairs.insert(idx, -fit[1]) fstairs.insert(idx, fit) + def sortNDHelperB(best, worst, obj, front): """Assign front numbers to the solutions in H according to the solutions in L. The solutions in L are assumed to have correct front numbers and the @@ -371,6 +382,7 @@ def sortNDHelperB(best, worst, obj, front): sortNDHelperB(best1, worst2, obj-1, front) sortNDHelperB(best2, worst2, obj, front) + def splitB(best, worst, obj): """Split both best individual and worst sets of fitnesses according to the median of objective *obj* computed on the set containing the @@ -410,6 +422,7 @@ def splitB(best, worst, obj): else: return best1_b, best2_b, worst1_b, worst2_b + def sweepB(best, worst, front): """Adjust the rank number of the worst fitnesses according to the best fitnesses on the first two objectives using a sweep @@ -443,6 +456,7 @@ def sweepB(best, worst, front): # Non-Dominated Sorting (NSGA-III) # ###################################### + NSGA3Memory = namedtuple("NSGA3Memory", ["best_point", "worst_point", "extreme_points"]) @@ -806,6 +820,7 @@ def selSPEA2(individuals, k): return [individuals[i] for i in chosen_indices] + def _randomizedSelect(array, begin, end, i): """Allows to select the ith smallest element from array without sorting it. Runtime is expected to be O(n). @@ -819,11 +834,13 @@ def _randomizedSelect(array, begin, end, i): else: return _randomizedSelect(array, q + 1, end, i - k) + def _randomizedPartition(array, begin, end): i = random.randint(begin, end) array[begin], array[i] = array[i], array[begin] return _partition(array, begin, end) + def _partition(array, begin, end): x = array[begin] i = begin - 1 diff --git a/deap/tools/indicator.py b/deap/tools/indicator.py index b34c13571..e51729529 100644 --- a/deap/tools/indicator.py +++ b/deap/tools/indicator.py @@ -7,6 +7,7 @@ # fallback on python version from ._hypervolume import pyhv as hv + def hypervolume(front, **kargs): """Returns the index of the individual with the least the hypervolume contribution. The provided *front* should be a set of non-dominated diff --git a/deap/tools/init.py b/deap/tools/init.py index ac4ad56a8..d79429850 100644 --- a/deap/tools/init.py +++ b/deap/tools/init.py @@ -22,6 +22,7 @@ def initRepeat(container, func, n): """ return container(func() for _ in range(n)) + def initIterate(container, generator): """Call the function *container* with an iterable as its only argument. The iterable must be returned by @@ -49,6 +50,7 @@ def initIterate(container, generator): """ return container(generator()) + def initCycle(container, seq_func, n=1): """Call the function *container* with a generator function corresponding to the calling *n* times the functions present in *seq_func*. @@ -72,6 +74,7 @@ def initCycle(container, seq_func, n=1): """ return container(func() for _ in range(n) for func in seq_func) + __all__ = ['initRepeat', 'initIterate', 'initCycle'] @@ -84,4 +87,3 @@ def initCycle(container, seq_func, n=1): random.seed(64) doctest.run_docstring_examples(initIterate, globals()) doctest.run_docstring_examples(initCycle, globals()) - diff --git a/deap/tools/migration.py b/deap/tools/migration.py index 421410e37..3e1bf914a 100644 --- a/deap/tools/migration.py +++ b/deap/tools/migration.py @@ -47,4 +47,5 @@ def migRing(populations, k, selection, replacement=None, migarray=None): indx = populations[to_deme].index(immigrant) populations[to_deme][indx] = emigrants[from_deme][i] + __all__ = ['migRing'] diff --git a/deap/tools/selection.py b/deap/tools/selection.py index e6fdcaf5e..185b9e958 100644 --- a/deap/tools/selection.py +++ b/deap/tools/selection.py @@ -8,6 +8,7 @@ # Selections # ###################################### + def selRandom(individuals, k): """Select *k* individuals at random from the input *individuals* with replacement. The list returned contains references to the input @@ -67,6 +68,7 @@ def selTournament(individuals, k, tournsize, fit_attr="fitness"): chosen.append(max(aspirants, key=attrgetter(fit_attr))) return chosen + def selRoulette(individuals, k, fit_attr="fitness"): """Select *k* individuals from the input *individuals* using *k* spins of a roulette. The selection is made by looking only at the first @@ -178,6 +180,7 @@ def _fitTournament(individuals, k, select): tsize = partial(_sizeTournament, select=selRandom) return _fitTournament(individuals, k, tsize) + def selStochasticUniversalSampling(individuals, k, fit_attr="fitness"): """Select the *k* individuals among the input *individuals*. The selection is made by using a single random value to sample all of the @@ -210,6 +213,7 @@ def selStochasticUniversalSampling(individuals, k, fit_attr="fitness"): return chosen + def selLexicase(individuals, k): """Returns an individual that does the best on the fitness cases when considered one at a time in random order. @@ -276,6 +280,7 @@ def selEpsilonLexicase(individuals, k, epsilon): return selected_individuals + def selAutomaticEpsilonLexicase(individuals, k): """ Returns an individual that does the best on the fitness cases when considered one at a @@ -319,4 +324,3 @@ def selAutomaticEpsilonLexicase(individuals, k): __all__ = ['selRandom', 'selBest', 'selWorst', 'selRoulette', 'selTournament', 'selDoubleTournament', 'selStochasticUniversalSampling', 'selLexicase', 'selEpsilonLexicase', 'selAutomaticEpsilonLexicase'] - diff --git a/deap/tools/support.py b/deap/tools/support.py index 475e7199e..0f13920be 100644 --- a/deap/tools/support.py +++ b/deap/tools/support.py @@ -13,6 +13,7 @@ def identity(obj): """ return obj + class History(object): """The :class:`History` class helps to build a genealogy of all the individuals produced in the evolution. It contains two attributes, @@ -131,6 +132,7 @@ def getGenealogy(self, individual, max_depth=float("inf")): """ gtree = {} visited = set() # Adds memory to the breadth first search + def genealogy(index, depth): if index not in self.genealogy_tree: return @@ -146,6 +148,7 @@ def genealogy(index, depth): genealogy(individual.history_index, 0) return gtree + class Statistics(object): """Object that compiles statistics on a list of arbitrary objects. When created the statistics object receives a *key* argument that @@ -204,6 +207,7 @@ def compile(self, data): entry[key] = func(values) return entry + class MultiStatistics(dict): """Dictionary of :class:`Statistics` object allowing to compute statistics on multiple keys using a single call to :meth:`compile`. It @@ -253,6 +257,7 @@ def register(self, name, function, *args, **kargs): for stats in self.values(): stats.register(name, function, *args, **kargs) + class Logbook(list): """Evolution records as a chronological list of dictionaries. @@ -634,13 +639,12 @@ def update(self, population): if not is_dominated and not has_twin: self.insert(ind) + __all__ = ['HallOfFame', 'ParetoFront', 'History', 'Statistics', 'MultiStatistics', 'Logbook'] if __name__ == "__main__": import doctest - from operator import itemgetter - import numpy doctest.run_docstring_examples(Statistics, globals()) doctest.run_docstring_examples(Statistics.register, globals()) doctest.run_docstring_examples(Statistics.compile, globals())