Package: bluegenes
BluegenesThis library is meant to be an easy-to-use library for optimization using
genetic algorithms.StatusModels + testsOptimization functions + testsDecent documentationOverviewThe general concept with a genetic algorithm is to evaluate a population for
fitness (an arbitrary metric) and use fitness, recombination, and mutation to
drive evolution toward a more optimal result. In this simple library, the
genetic material is a sequence of ints, floats, or strs, and it is organized
into the following hierarchy:Genecontains bases (list[int|float|str])AllelecontainsGenesChromosomecontainsAllelesGenomecontainsChromosomesEach of these classes has astr nameattribute to identify the genetic
material. These names can be generated as random alphanumeric strs if not
supplied in the relevant instantiation calls.There are four optimization functions available currently:optimize_gene- optimizes a Geneoptimize_allele- optimizes an Alleleoptimize_chromosome- optimizes a Chromosomeoptimize_genome- optimizes a GenomeThese optimization functions have largely similar parameters for tuning the
optimization process. See theUsagesection below.For more detailed documentation, see thedocs filegenerated automagically byautodox.InstallationInstallation is with pip.pipinstallbluegenesThere are no dependencies.UsageThere are are least three ways to use this library: using an included
optimization function, using a custom optimization function, and using the
genetic classes as the basis for an artificial life simulation. Below is a
trivial example of how to do the first of these three.frombluegenesimportGene,optimize_gene,set_hookfromrandomimportrandint,random# optional functionality: set a hook to be passed every generation as it completeslogs=[]deflog_generation(count:int,generation:list[tuple[float],Gene])->None:logs.append((count,generation))set_hook(log_generation)target=123456defmeasure_fitness(gene:Gene)->float:"""Produces a fitness score. Passed as parameter to optimize_gene."""return1/(1+abs(sum(gene.bases)-target))defmutate_gene(gene:Gene)->Gene:"""Mutates the Gene randomly. Passed as parameter to optimize_gene."""foriinrange(len(gene.bases)):val=random()ifval<=0.1:gene.bases[i]=int(gene.bases[i]/randint(1,3))elifval<=0.2:gene.bases[i]=int(gene.bases[i]*randint(1,3))elifval<=0.6:gene.bases[i]+=randint(0,11)else:gene.bases[i]-=randint(0,11)returngenecount,population=optimize_gene(measure_fitness,mutate_gene)best=population[0]score=sum(best.bases)print(f"{count}generations passed")print(f"the best result had{score=}compared to{target=}")print(best)Creating custom fitness functions or artificial life simulations is left as an
exercise to the reader.TestingTo test, run the following:foriin{0..10};dopythontests/test_genes.py;doneforiin{0..10};dopythontests/test_optimization.py;doneNote that the randomness may cause some tests to occasionally fail. I halved the
change of a random test failure every time one was encountered, but there are by
definition no guarantees of deterministic behavior when working with random
numbers. In other words, the test suites should each be run a few times, and a
random failure or two should be excused. I have tuned it for <1% chance of a
random test failure (measured), but it will eventually happen if the tests are
run enough times.ISC LicenseISC LicenseCopyleft (c) 2023 k98kurzPermission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyleft notice and this permission notice appear in
all copies.THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.