Crates.io | perestroika |
lib.rs | perestroika |
version | |
source | src |
created_at | 2022-09-19 14:39:52.13096 |
updated_at | 2024-11-15 08:37:30.808406 |
description | Perestroika is a library for genetic algorithms. |
homepage | https://codeberg.org/dimonade/perestroika |
repository | https://codeberg.org/dimonade/perestroika.git |
max_upload_size | |
id | 669175 |
Cargo.toml error: | TOML parse error at line 20, column 1 | 20 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
Perestroika
- a library for simulating evolution.
Perestroika
is a perhaps naive library that provides primitives to design simulations that are based on genetic algorithms.
These primitives include Node
s which are agreggated into Layer
s,
which in turn are interconnected with Connection
s.
The whole structure is then considered to be a Genome
,
which is capable of trying to propagate an input to an output.
Genomes are also subjects to mutation events
, which can happen randomly or controllably.
This can be used to drive optimization processes and evolution simulations.
Unlike CNNs, in Perestroika
, the connections can connect nodes from different layers, as long as the relationship between
the source and target is from a shallow layer to a deeper layer.
Add this to your Cargo.toml
:
[dependencies]
perestroika = "0.1"
Or
cargo add perestroika
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.
To generate the smallest useful Genome
with an input and an output Layer
s and a Connection
:
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
use perestroika::Error;
use perestroika::Genome;
use perestroika::GenomeBuilder;
use perestroika::DepthType;
// 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 node a single output node
// and a connection between them.
let mut genome: Genome = GenomeBuilder::new()
.with_shape(&[1, 1])?
.with_fully_connected_layers(&[[DepthType::Input, DepthType::Output]])?
.build()?;
// Nodes by default use the Identity activation function.
let output = genome.propagate(&[0.42])?;
assert_ne!(output, &[0.0]);
# Ok::<(), Error>(())
Generating a more complex genome and propagating through it.
use rand::Rng;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
use perestroika::Error;
use perestroika::Genome;
use perestroika::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].
# Ok::<(), Error>(())
It is possible to use other random number generators, as long as they impl
Rng + 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::Error;
use perestroika::Genome;
use perestroika::GenomeBuilder;
let mut std_rng = StdRng::seed_from_u64(17);
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)?;
# Ok::<(), Error>(())
See the crate's documentation for the docs.
Check out the examples
directory for examples to get going:
examples/01_simple_node.rs
- Creating a number of simple nodes.examples/02_simlpe_connection.rs
- Creating a couple nodes and a connection between them.examples/03_simple_genome.rs
- Creating a couple of genomes through different methods.examples/04_simple_propagation.rs
- Create a genome and propagate an input to an output.examples/05_simple_mutations.rs
- Create a genome and initiate specific mutations and a random one.examples/06_simple_simulation.rs
- Create a CLI simulation in which creatures with Genomes exist on a grid and their task is to adapt to move to the right side of the grid.For a more comprehensive simulation example with GUI and tunable parameters, check the kombinat repository.
Note 1: The current roadmap is to figure an API within the 0.1.* versions and stabilize it. This means that until 0.2, the API and functionality will probably change, break or differ in one way or another between versions.
Note 2: Perestroika
aims to be a minimalist simulation library with very minimal dependencies.
Currently (v0.1.6), it depends only on rand-*
for the generators.
For issues, bugs, suggestions, comments or anything of the sort feel free to open a new issue on the repository.
Perestroika's Zulip might be a place for more direct communication, although it is pretty empty at the moment.
The motivation behind this project is to make a full scale project in Rust, while integrating many more other fields such as game development in Bevy, DevOps and, of course, neural networks.
Currently being used in an in-development game that I prototype in my spare time.
More projects that employ perestroika will be listed below.
"Perestroika" is the Russian word for "Reconstruction" and serves as a double pun: Perestroika was a late USSR political movement trying to reconstruct the regime; it is also a very fitting description for Genetic recombination (or genetic reshuffling) which is the target of this library.
Efficient Evolution of Neural Networks through Complexification as the paper and background.
The Bibites provide a good overview of an already implemented game that follows similar principles.