Source code for neurogenesis.evolution.islands

"""Island evolution of genomes coded as [0, 1] gene vectors (neurogenesis.genome).

One island: a population starts around a founding genome (u0 + sigma N(0, 1), the founder itself kept), and each
generation is evaluated on fresh development seeds; the best `elite` individuals are kept, the rest are mutated
children of the best `parents`. Run several islands (different `island` numbers) in parallel and choose among their
results on validation seeds, then audit on held-out seeds (neurogenesis.evolution.robust).
"""
from __future__ import annotations

import time

import numpy as np

from ..genome.genes import INTEGER_ROOTS, from_unit, to_unit


[docs] def seeds_of(island, generation, n): """Development seeds of one generation: distinct across islands and generations, never equal to small audit seeds.""" return tuple(100000 * (island + 1) + 10 * generation + k for k in range(n))
[docs] def evolve(base, genes, evaluate, island=0, pop=64, gens=150, seeds_per_gen=6, elite=2, parents=16, sigma=0.1, integer_roots=INTEGER_ROOTS, log=None): """Evolve one island. evaluate(genomes, seeds) -> (fitness array, list of per-genome info dicts). Returns (final population as [0, 1] vectors, history list). log(dict) is called after every generation. """ rng = np.random.default_rng(island) u0 = to_unit(base, genes) P = np.clip(u0[None] + sigma * rng.standard_normal((pop, len(genes))), 0, 1) P[0] = u0 hist, t0 = [], time.time() for gen in range(gens): fit, info = evaluate([from_unit(base, genes, u, integer_roots) for u in P], seeds_of(island, gen, seeds_per_gen)) fit = np.asarray(fit, float) o = np.argsort(-fit) hist.append(dict(generation=gen, best=float(fit[o[0]]), median=float(np.median(fit)), best_info=info[o[0]], wall_s=round(time.time() - t0, 1))) if log: log(hist[-1]) keep = o[:min(elite, pop)] n_par = min(parents, pop) pick = o[:n_par][rng.integers(0, n_par, pop - len(keep))] P = np.concatenate([P[keep], np.clip(P[pick] + sigma * rng.standard_normal((len(pick), len(genes))), 0, 1)]) return P, hist
[docs] def choose(base, genes, P, evaluate, seeds, integer_roots=INTEGER_ROOTS, top=None): """Best genome of a final population on given (validation) seeds. Returns (genome, its evaluation info).""" gs = [from_unit(base, genes, u, integer_roots) for u in (P if top is None else P[:top])] fit, info = evaluate(gs, seeds) b = int(np.argmax(fit)) return gs[b], info[b]