From 8d67a003e2b1baf38cc2455363754e0d540a28df Mon Sep 17 00:00:00 2001 From: William Song <30965609+Freakwill@users.noreply.github.com> Date: Thu, 14 Dec 2023 10:21:39 +0800 Subject: [PATCH] new example --- docs/source/Install.md | 2 +- examples/comparison0.py | 1 - pyrimidine/base.py | 46 +++++++++++++++++++++++++---------------- pyrimidine/meta.py | 4 ++-- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/docs/source/Install.md b/docs/source/Install.md index ed2d625..0a1fbd4 100644 --- a/docs/source/Install.md +++ b/docs/source/Install.md @@ -8,7 +8,7 @@ **Documentation as PDF**: download latest -`pyrimidine` is a framework for genetic algorithm. +`pyrimidine` stands as a versatile framework designed for GAs, offering exceptional extensibility for a wide array of evolutionary algorithms, including particle swarm optimization and difference evolution. ## Install pyrimidine diff --git a/examples/comparison0.py b/examples/comparison0.py index 70e358e..5960659 100644 --- a/examples/comparison0.py +++ b/examples/comparison0.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- """An easy knapsack problem diff --git a/pyrimidine/base.py b/pyrimidine/base.py index 84f2af3..c719c91 100755 --- a/pyrimidine/base.py +++ b/pyrimidine/base.py @@ -115,19 +115,31 @@ def __str__(self): def random(cls, size=None): raise NotImplementedError + def copy(self, *args, **kwargs): + raise NotImplementedError + + def transition(self, *args, **kwargs): + self.mutate() + def x(self, other): # alias for cross return self.cross(other) def cross(self, other): + # crossover operation raise NotImplementedError - def merge(self, *other): - raise NotImplementedError - + @side_effect def mutate(self): + # mutation operation raise NotImplementedError + def replicate(self): + # Replication operation of a chromosome + ind = self.copy() + ind.mutate() + return ind + def decode(self): """Decoding of the chromesome Translate the chromesome to (part of) solution, maybe a number. @@ -142,15 +154,6 @@ def encode(cls, x): def equal(self, other): return np.array_equal(self, other) - def copy(self, *args, **kwargs): - raise NotImplementedError - - def replicate(self): - # Replication operation of a chromosome - ind = self.copy() - ind.mutate() - return ind - class BaseIndividual(FitnessMixin, metaclass=MetaContainer): """Base class of individuals @@ -203,6 +206,9 @@ def copy(self, type_=None, *args, **kwargs): else: return type_([c.copy(type_=type_.element_class) for c in self]) + def transition(self, *args, **kwargs): + self.mutate() + def cross(self, other): # Cross operation of two individual return self.__class__([chromosome.cross(other_c) for chromosome, other_c in zip(self, other)]) @@ -258,6 +264,7 @@ def __sub__(self, other): return self.__class__([this - that for this, that in zip(self.chromosomes, other.chromosomes)]) def __rmul__(self, other): + # assert isinstance(other, np.number) return self.__class__([other * this for this in self.chromosomes]) @@ -479,19 +486,22 @@ class BaseMultiPopulation(PopulationMixin, metaclass=MetaHighContainer): 'best_population': 'best_element', 'worst_population': 'worst_element', "get_best_population": "get_best_element", - "get_best_populations": "get_best_elements"} + "get_best_populations": "get_best_elements" + } def __str__(self): return '\n\n'.join(map(str, self)) - def migrate(self, migrate_prob=None): + def migrate(self, migrate_prob=None, copy=True): + migrate_prob = migrate_prob or self.migrate_prob for population, other in zip(self[:-1], self[1:]): - if random() < (migrate_prob or self.migrate_prob): - other.append(population.get_best_individual(copy=True)) - population.append(other.get_best_individual(copy=True)) + if random() < migrate_prob: + other.append(population.get_best_individual(copy=copy)) + population.append(other.get_best_individual(copy=copy)) def transition(self, *args, **kwargs): - super().transition(*args, **kwargs) + for p in self: + p.transition(*args, **kwargs) self.migrate() def max_fitness(self): diff --git a/pyrimidine/meta.py b/pyrimidine/meta.py index 8a8820b..51d8eae 100755 --- a/pyrimidine/meta.py +++ b/pyrimidine/meta.py @@ -439,9 +439,9 @@ def __new__(cls, name, bases, attrs): if 'element_class' in attrs: element_class = attrs['element_class'] if (not isinstance(element_class, MetaContainer) - and isinstance(element_class, tuple) and not isinstance(element_class[0], MetaContainer) + and isinstance(element_class, tuple) and not any(isinstance(ec, MetaContainer) for ec in element_class) and not isinstance(element_class, ParamType)): - raise TypeError('`element_class` should be an instance of MetaContainer, or a list of such instances.') + raise TypeError('`element_class` should be an instance of `MetaContainer`, or a tuple where one element is an instance of `MetaContainer`.') def _flatten(self, type_): elms = []