Skip to content

Instantly share code, notes, and snippets.

@oxyflour
Created September 20, 2020 09:52
Show Gist options
  • Save oxyflour/987a42d3be27be3d54ab3ed81ed90a55 to your computer and use it in GitHub Desktop.
Save oxyflour/987a42d3be27be3d54ab3ed81ed90a55 to your computer and use it in GitHub Desktop.
simple async ea
import asyncio
from random import random, choices
def clip(x, x0, x1):
return x0 if x < x0 else x1 if x > x1 else x
def make_masks(geneSize, popSize, crossoverNum):
mask0 = [0] * geneSize
mask1 = [int(i / int(geneSize / crossoverNum)) % 2 for i in range(geneSize)]
mask2 = [-x for x in mask1]
return [mask0 if i == popSize - 1 else mask1 if i % 2 == 0 else mask2 for i in range(popSize)]
async def run(bound, func, popSize=100, selectSize=5, crossoverNum=3, mutation=0.01, maxGenNum=100):
pop = [[lower + (upper - lower) * random() for lower, upper in bound] for i in range(popSize)]
masks = make_masks(len(bound), popSize, crossoverNum)
generation = 0
while generation < maxGenNum:
# get fitness
ret = [[chromo, fitness] for chromo, fitness in zip(pop, await func(pop))]
# select
selected = sorted(ret, key=lambda x: x[1], reverse=True)[0:selectSize]
# get parents
parents = [choices([c[i] for c, _ in selected], [w for _, w in selected], k=popSize) for i in range(len(bound))]
# crossover to create offsprings
offsprings = [[parents[j][i + m[j]] for j in range(len(parents))] for i, m in enumerate(masks)]
# mutation
for offspring in offsprings:
for i, [lower, upper] in enumerate(bound):
if random() < mutation:
delta = random() * (upper - lower)
offspring[i] = clip(offspring[i] + delta, lower, upper)
pop = offsprings
generation += 1
return selected[0]
async def eval(xs):
return [sum([v * v for v in x]) for x in xs]
async def main():
print(await run([[0, 1]] * 100, eval))
asyncio.run(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment