Skip to content

Commit

Permalink
workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
Freakwill committed Nov 24, 2023
1 parent 0c11008 commit 4095732
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name: build
1 change: 1 addition & 0 deletions .github/workflows/draft-pdf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
on [push]
65 changes: 65 additions & 0 deletions pyrimidine/ssa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3

"""
Self-adaptive
"""


from .base import BaseIndividual, BaseChromosome
from .population import HOFPopulation
from .chromosome import FloatChromosome
from .utils import random, choice_with_fitness

def lim(r, e):
e -= 0.0001
return 0 if r <= e else (r - e)**2 / (1 - e)


class SSAPopulation(HOFPopulation):

def transit(self, *args, **kwargs):
"""Transitation of the states of population
It is considered to be the standard flow of the Genetic Algorithm
"""
self.mate()
self.mutate()
self.doom()

for individual in self.individuals:
individual.age += 1
if self.is_crowd():
self.select(0.3)

def doom(self):
self.individuals = [individual for individual in self.individuals if not individual.is_dead()]

def mate(self):
self.rank()
children = []
for individual, other in zip(self.individuals[:-1], self.individuals[1:]):
if random() < min(individual.cross_prob, other.cross_prob):
if self.match(individual, other):
children.append(individual.cross(other))
self.add_individuals(children)

@classmethod
def match(cls, individual, other):
if individual.label != other.label:
a, b, c = lim(other.ranking, individual.expect), lim(individual.ranking, other.expect), abs(individual.age - other.age)
p = 1 - c/(20*min(a, b)+1)
return random() < p
else:
return random() < 0.05

def is_crowd(self):
return len(self) > 8 * self.default_size

def select(self, p=0.5):
# self.select(n_sel=p)
self.individuals = choice_with_fitness(self.individuals, fs=None, n=int(self.n_individuals*p))
# self.individuals = [individual for individual in self.individuals if random() < p]


class SSAIndividual(BaseIndividual):
pass
49 changes: 49 additions & 0 deletions tests/test_de.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python3

import unittest

from pyrimidine.individual import MonoIndividual
from pyrimidine.population import HOFPopulation, BasePopulation
from pyrimidine.chromosome import FloatChromosome
from pyrimidine.de import DifferentialEvolution

from pyrimidine.benchmarks.special import rosenbrock


class TestDE(unittest.TestCase):

def setUp(self):

n = 20
f = rosenbrock

class MyIndividual(MonoIndividual):
element_class = FloatChromosome // n

def _fitness(self):
return -f(self.chromosome)

class _Population1(DifferentialEvolution, BasePopulation):
element_class = MyIndividual
default_size = 10

class _Population2(HOFPopulation):
element_class = MyIndividual
default_size = 10

# _Population2 = HOFPopulation[MyIndividual] // 10
self.Population1 = _Population1
self.population1 = Population1.random()
self.Population2 = _Population2
self.population2 = Population2.random()

def test_clone(self):
self.population2 = self.population1.clone(type_=self.Population2) # population 2 with the same initial values to population 1
assert isinstance(self.population2, self.Population2)

def test_evolve(self):
stat={'Mean Fitness':'mean_fitness', 'Best Fitness':'best_fitness'}
data1 = self.population1.evolve(stat=stat, n_iter=10, history=True)
data2 = self.population2.evolve(stat=stat, n_iter=10, history=True)
assert True

63 changes: 63 additions & 0 deletions tests/test_ga.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env python3

import unittest

from pyrimidine import MonoIndividual, BinaryChromosome
from pyrimidine import StandardPopulation, HOFPopulation
from pyrimidine.benchmarks.optimization import *


class TestGA(unittest.TestCase):

def setUp(self):

n_bags = 10
_evaluate = Knapsack.random(n_bags)

class MyIndividual(MonoIndividual):

element_class = BinaryChromosome.set(default_size=n_bags)

def _fitness(self) -> float:
return _evaluate(self.chromosome)

class MyPopulation(StandardPopulation):
element_class = MyIndividual
default_size = 8

self.MyPopulation = MyPopulation

class YourPopulation(HOFPopulation):
element_class = MyIndividual
default_size = 8

self.YourPopulation = YourPopulation
self.population = self.MyPopulation.random()

def test_random(self):
self.population = self.MyPopulation.random()
cpy = self.population.clone()
self.population.merge(cpy, n_sel=8)
assert len(self.population) == 16

def test_evolve(self):
self.population.evolve(n_iter=2)
assert True

def test_stat(self):
stat={'Mean Fitness':'mean_fitness', 'Best Fitness':'best_fitness'}
data = self.population.evolve(stat=stat, n_iter=3, history=True)
assert 'mean_fitness' in data.columns and 'best_fitness' in data.columns


def test_hof(self):
population = self.YourPopulation.random()

stat={'Mean Fitness':'mean_fitness', 'Best Fitness':'best_fitness'}
data = population.evolve(stat=stat, n_iter=5, history=True)

def increasing(x):
all(xi <= xj for xi, xj in zip(x[:-1], x[1:]))

assert increasing(data['best_fitness'])

15 changes: 15 additions & 0 deletions tests/test_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python3

import unittest

from pyrimidine import IterativeModel


class TestMeta(unittest.TestCase):

def test_iteration(self):
class TuringModel(IterativeModel):
pass

tm = TuringModel()
assert True

0 comments on commit 4095732

Please sign in to comment.