Crate perestroika
source ·Expand description
Perestroika - A library for simulating evolution.
This crate aims to help the users to create “Brains”, or in Perestroika’s terminology, Genome
s.
Genome
s are essentially self contained decision making machines - given an input, they will
propagate it, and return a decision.
Genome
s consist of NodeGene
s split between (or aggregated into) different Layer
s.
In order to be able to propagate the inputs the NodeGenes
must be connected via
ConnectionGene
s.
As in a real brain, not all NodeGenes
must be connected to each other or the next layer.
Genomes
also have the ability to mutate.
If NodeGenes
and ConnectionGenes
are the building blocks of the brain, then mutation is the
engine of evolution.
Since the crate relies heavily on randomness, in many examples a specific seed is used for the sake of reproducibility, this is an intended use case of the crate as well.
§Quick start
§Minimal
To generate the smallest useful Genome
with an input and an output Layer
s and a
ConnectionGene
:
use perestroika::errors::PerestroikaError;
use perestroika::genome::Genome;
use perestroika::genome_builder::GenomeBuilder;
use perestroika::node_gene::DepthType;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
// This genome uses ChaCha8Rng as the random number generator.
// Let's also set a seed for reproducibility:
let rng: ChaCha8Rng = ChaCha8Rng::seed_from_u64(42);
// It is a very simple genome, consisting of a single input NodeGene a single output NodeGene
// and a ConnectionGene which connects them.
let mut genome: Genome = GenomeBuilder::new()
.with_shape(&[1, 1])?
.with_fully_connected_layers(&[[DepthType::Input, DepthType::Output]], true)?
.build()?;
// NodeGenes by default use the Identity activation function and have a bias of 0.
// This means, they pass the input onward to the next one, without changing it.
let output = genome.propagate(&[0.42])?;
assert_ne!(output, &[0.0]);
§More practical
Generating a more complex Genome and propagating through it.
use rand::Rng;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
use perestroika::errors::PerestroikaError;
use perestroika::genome::Genome;
use perestroika::genome_builder::GenomeBuilder;
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567);
let mut genome: Genome = GenomeBuilder::new()
.with_shape(&vec![8, 6, 4, 2, 4, 6, 4])?
.with_cnn_structure()?
.build()?;
// Let's create an input vector:
let input_vector: Vec<f64> = vec![0.1, 0.2, 0.3, 0.31428, 0.424242, 0.999, -0.17, 0.5];
// Be sure that the input vector and the InputLayer have matching dimensions.
// Propagate it through the genome to get the output:
let output: Vec<f64> = genome.propagate(&input_vector)?;
// Output: [1.0, 0.20511543379524064, -1.0, 0.15121278824891932].
§Using different random number generators
It is possible to use other random number generators, as long as they impl
Rng +?Sized + Clone
.
A possible place to use the generator is in the mutate_randomly
method.
use rand::rngs::StdRng;
use rand::Rng;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
use perestroika::errors::PerestroikaError;
use perestroika::genome::Genome;
use perestroika::genome_builder::GenomeBuilder;
let mut std_rng = StdRng::seed_from_u64(42);
let mut chacha8_rng = rand_chacha::ChaCha8Rng::seed_from_u64(17);
let mut genome: Genome = GenomeBuilder::new()
.with_shape(&vec![4, 16, 4])?
.with_cnn_structure()?
.build()?;
// Mutate the Genome.
genome.mutate_randomly(&mut std_rng)?;
genome.mutate_randomly(&mut chacha8_rng)?;
Re-exports§
pub use crate::connection_gene::ConnectionGene;
pub use crate::connection_gene_builder::ConnectionGeneBuilder;
pub use crate::errors::PerestroikaError;
pub use crate::genome::Genome;
pub use crate::genome_builder::GenomeBuilder;
pub use crate::layer::Layer;
pub use crate::layer::LayerBuilder;
pub use crate::node_gene::NodeGene;
pub use crate::node_gene_builder::NodeGeneBuilder;
Modules§
- Connection gene functionality aggregator.
- Connection gene builder functionality.
- Error type of Perestroika.
- Aggregation of functionality of the
Genome
. - Genome builder functionality.
- Layer functionality aggregator.
- A collection of applicable mutations.
- Node gene functionality aggregator.
- Node gene builder functionality.