enome
A Genome generation and evolution library
Note: This library is still in the early stages of development, and should not be considered producion-ready.
This library is written in TypeScript, and I recommend using it with a TypeScript project.
What is enome?
enome is a javascript/typescript library that allows you to asynchronously (using rxjs) evolve any kind of object you can think of.
enome has three main parts to its evolution system.
-
Organism
:- an
Organism
is just an object that contains agenotype
and aphenotype
and has the ability to interact with anEnvironment
.- a
genotype
, in this case, is aGenome
, which contains genetic information that you use to create aphenotype
. - a
phenotype
, in this case, is whatever kind of object you would like to evolve.
- a
-
Organisms
record data as they are interacting with theEnvironment
.- Once the
Organism
has done a specified number ofinteractions
, it evaluates itself based on the data it collected and sends the evaluation to thePopulation
, which will decide how to evolve the organism. - You specify the function that determines the
fitness
of theOrganism
based on its data.
- Once the
- an
-
Environment
:- an
Environment
is essentially just an asynchronous state container. - You interact with an
Environment
by sendingIStateUpdates
to itsstate
property. - an
Environment
may have multipleOrganisms
interacting with it at a time. -
Environments
have aninteractionRate
property which you can set that limits how often it acceptsIStateUpdates
(think of it like a frame rate).-
Environments
deal with multiple asynchronous sources of incomingIStateUpdates
by buffering them over time based on theinteractionRate
and then randomly choosing between them. TheEnvironment
will only accept state updates that are based on the currentstate
, otherwise state updates could happen out of order (think of it like an asynchronous way of having a shared order of events even though everything is happening out of order, technically).
-
- an
-
Population
-
Populations
populate environments with organisms. -
Populations
are also in charge of determining howOrganisms
evolve.- when a
Population
receives an evaluation, it looks at thefitness
and determines what it wants to do with thegenotype
.-
Populations
can update the genotype in the following ways:-
Reproduce
will mix the genomes of the top organisms in the population based on fitness. (You can specify the percentage of organisms that qualifies as "top", which lets you determine whether you want to refine what is already working well or find new solutions) -
Mutate
will give each value in the Genome's sequence a chance to mutate and has two different mutation methods to choose from.-
sub
will substitute the value for a new randomly generated one. -
avg
will average the value with a new randomly generated one.
-
-
Randomize
will replace the genome with a new randomly generated one (using the same options). -
Keep
will just send the organism back into the environment. This is good for when you get a genotype with a very good fitness and you don't want it to be mutated which has the possibility of making it worse.
-
- By default,
Populations
will choose between the different update methods randomly based on an array of weights that you provide.
-
- when a
-
Genomes
and Genes
:
Underlying the evolution system are -
Genome
:- A
Genome
is just a container for genetic information, or asequence
. - At its heart, a
sequence
is just an array of numbers between 0 and 1. - When created, the
Genome
takes thatsequence
and producesGenes
from it. -
Genome
provides theg
property which allows you to get the nextGene
in the list, so you can consume them one by one in a queue-like manner.
- A
-
Gene
:- A
Gene
is just a container for avalue
between 0 and 1. -
Genes
give you methods that interpolate their value into a value that it useful when creating thephenotype
.- for instance, say your phenotype is a first and last name:
interface Name { first: string; last: string; } interface NameOptions extends IGenomeOptions { firstMinLength: number; firstMaxLength: number; lastMinLength: number; lastMaxLength: number; } public createPhenotype(genome: Genome<NameOptions>): Name { // determine length of first name const firstLength = genome.g.int( genome.options.firstMinLength, genome.options.firstMaxLength ); // determine length of last name const lastLength = genome.g.int( genome.options.lastMinLength, genome.options.lastMaxLength ); //create first name const first = _.range(firstLength) .map(i => genome.g.letter()) .reduce((first, letter) => `${first}${letter}`) // create last name const last = _.range(lastLength) .map(i => genome.g.letter()) .reduce((last, letter) => `${last}${letter}`) return { first, last }; }
- A
How enome generates Genomes
:
- Generates a
sequence
ofvalues
between 0 and 1. - Groups those
values
intoGenes
by averaging them together- This results in the
Genome
being less sensitive tomutation
- The sensitivity is customizable by varying the number of
values
that go into eachGene
- This results in the
- Groups those
Genes
into aGenome
-
Genome
exposes a property calledg
that allows you to get the nextGene
in theGenome
.- This allows you to pass the
Genome
around, consuming itsGenes
as you need them.
- This allows you to pass the
-
Install instructions
npm install enome