UNPKG

5.51 kBMarkdownView Raw
1# enome
2## [![Build Status](https://travis-ci.org/fiberwire/enome.svg?branch=master)](https://travis-ci.org/fiberwire/enome)
3## A Genome generation library
4
5## Note: This library is still in the early stages of active development, and should not be considered producion-ready by any means.
6
7### This library is written in TypeScript, and I recommend using it with a TypeScript project.
8
9### There are a few different ways you can use enome.
10
111. `Natural Selection`
12 - Automatically evolves genomes based on their fitness.
132. `Artificial Selection`
14 - Allows you to select which genomes will reproduce to spawn future generations
15 - Genomes are presented in a queue-like manner, where you review and take action on genomes one at a time.
163. `Artificial Pooled Selection`
17 - Allows you to select which genomes will be parents to future generations
18 - Parents are not recycled back into the general population queue, and are instead part of a separate pool of genomes that are exclusively used for reproduction.
19 - You can set the size of the parent pool, and when the capacity is reached, any new additions will remove the oldest parent from the pool.
204. Go it on your own
21 - You can use enome primitives (genomes and genes) however you want.
22 - The premade population types are just there to make your life easier. If their functionality doesn't fit your needs, you're free to make your own, or not use one at all.
23 - enome provides a host of operators for doing various things to/with genomes.
24
25How enome generates `Genome`s:
26- Generates a `sequence` of `values` between `zero` and `one`
27- Groups those `values` into `Genes` by averaging them together
28 - This results in the `Genome` being less sensitive to `mutation`
29 - The sensitivity is customizable by varying the number of `values` that go into each `Gene`
30- Groups those `Genes` into a `Genome`
31 - `Genome` exposes a property called `nucleo` that allows you to get the next `Gene` in the `Genome`.
32 - This allows you to pass the `Genome` around, consuming its `Gene`s as you need them.
33
34How enome determines the `fitness` of a `Genome`:
35- You define your own `fitness` function.
36 - Generally, your `fitness` function should accept a `Genome` and return an `Evaluation`.
37 - Your fitness function will necessarily create an object from your genome that it will test.
38 - `Evaluation` is just an interface that has the following properties
39 - `fitness`: `number`
40 - the relative `fitness` of the `Genome` being evaluated.
41 - `genome`: `Genome`
42 - the genome that is being evaluated.
43 - `result`: `T`
44 - the object that is created from your genome.
45
46What enome allows you to do:
47 - write code that maps a `Genome` to whatever `object` you want to build by consuming genes one at a time.
48 - Define your hyperparameters in your `options` object.
49 - `mutate` and `evolve` that object by mutating and evolving the `Genome` that maps to that object.
50 - do it very simply, by providing upper and lower bounds for each variable you want to evolve.
51
52
53 # Example usage for Natural Selection
54 say you want to evolve a list of three numbers between 1 and 100 that will add up to 256.
55
56```
57import * as _ from 'lodash';
58import {
59 sampledReproduce,
60 best,
61 Evaluation,
62 Genome,
63 GenomeOptions,
64 Gene,
65 Population,
66 PopulationOptions,
67 replenish
68} from 'enome';
69
70// create an interface that adds your custom options to GenomeOptions
71interface ListOptions extends GenomeOptions {
72 min: number,
73 max: number,
74 length: number
75}
76
77//define a function that will map a Genome to whatever kind of object you want.
78function createList(genome: Genome<ListOptions>): number[] {
79 return _.range(genome.options.length)
80 .map(i => genome.nucleo.int(genome.options.min, genome.options.max));
81}
82
83//define a function that will determine the fitness of a Genome.
84function fitness(genome: Genome<ListOptions>): Evaluation<ListOptions, number[]> {
85 let target = 256;
86
87 let list = createList(replenish(genome));
88 let sum = _.sum(list);
89 let error = Math.abs(target - sum);
90
91 return { fitness: 1/error, genome: genome, result: list };
92}
93
94//set genome options
95let gOptions: ListOptions = {
96 genomeLength: 10,
97 geneLength: 1,
98 min: 1,
99 max: 100,
100 length: 3,
101 loopGenes: false
102}
103
104//set population options
105let pOptions: PopulationOptions = {
106 populationSize: 20,
107 fillType: 'random', //can be either worst or random
108 fillPercent: 0.15,
109 mutateOptions: {
110 safe: false,
111 sampled: false,
112 sampleSize: 5,
113 mutateChance: 0.15,
114 mutateType: 'sub' //can be either sub or avg
115 },
116 reproduceOptions: {
117 safe: true,
118 sampled: false,
119 sampleSize: 5
120 }
121};
122
123//create population
124let pop = new NaturalSelection(
125 pOptions,
126 gOptions,
127 createList,
128 fitness
129);
130
131//evolve synchronously
132let evSync = pop.evolve(100);
133let list = evSync.result;
134let fit = evSync.fitness;
135console.log(`\t`, `list: ${list}, sum: ${_.sum(list)}, fitness: ${fit}`);
136
137//or reactively
138let ev = pop.evolve$(100)
139 .subscribe(e => {
140 let list = e.result;
141 let fit = e.fitness;
142 console.log(`\t`, `list: ${list}, sum: ${_.sum(list)}, fitness: ${fit}`);
143 },
144 err => console.log(err))
145
146```
\No newline at end of file