darwin-rs, evolutionary algorithms with rust

Overview

Build Status MIT licensed

darwin-rs

This library allows you to write evolutionary algorithms (EA) using the Rust programming language.

Written by Willi Kappler, License: MIT - Version 0.4 (2017.06.26)

Documentation: darwin-rs

tsp start

tsp end

The example folder contains these examples:

  • TSP (traveling salesman problem): the classic type of problem for EA (see two pictures above).
  • Sudoku: a sudoku solver using EA.
  • Queens: solving the queens problem with EA. Although not as fast as this one or this one ;-)
  • OCR: a simple optical character recognition example. Two strings are drawn (rendered) using a truetype font on a image buffer and then a perfect match representing the drawn text is found.

darwin-rs uses semantic versioning

Usage:

Add the following to the Cargo.toml in your project:

[dependencies]
darwin-rs = "0.4"

And this in the rust source code of your application:

extern crate darwin_rs;

use darwin_rs::{Individual, SimulationBuilder, Population, PopulationBuilder, SimError};

Basically you have to implement the trait Individual for your data structure:

#[derive(Debug, Clone)]
struct MyStruct {
    text: String
}

impl Individual for MyStruct {
    fn mutate(&mut self) {
        // Mutate the struct here.
        ...
    }

    fn calculate_fitness(&mut self) -> f64 {
        // Calculate how good the data values are compared to the perfect solution
        ...
    }

    fn reset(&mut self) {
      // Resets all the data for this individual instance.
      // This is done to avoid getting stuck in a local minimum.
      ...
    }
}

These three methods are needed:

mutate(&mut self): Mutates the content of the struct.

calculate_fitness(&mut self) -> f64: This calculates the fitness value, that is how close is this individual struct instance to the perfect solution ? Lower values means better fit (== less error == smaller distance from the optimum).

reset(&mut self): Resets all the data after a specific number of iteration (see reset_limit), to avoid local minima.

There is one more method (new_fittest_found) but it is optional and the default implementation does nothing.

If you want to share a large data structure between all the individuals you need Arc, see TSP and OCR examples.

Now you have to create one or more populations that can have different properties:

// A helper function that creates a vector of individuals of your data structure:
let my_pop = make_population(100);

let population1 = PopulationBuilder::<MyStruct>::new()
    .set_id(1)
    .initial_population(&my_pop)
    .increasing_exp_mutation_rate(1.03)
    .reset_limit_increment(100)
    .reset_limit_start(100)
    .reset_limit_end(1000)
    .finalize().unwrap();


let population2 = PopulationBuilder::<MyStruct>::new()
    .set_id(2)
    .initial_population(&my_pop)
    .increasing_exp_mutation_rate(1.04)
    .reset_limit_increment(200)
    .reset_limit_start(100)
    .reset_limit_end(2000)
    .finalize().unwrap();

set_id(): Sets the population ID. This can be any positive u32 integer. Currently this is only used for internal statistics, for example: which population does have the most fittest individuals ? This may help you to set the correct parameters for your simulations.

initial_population(): This method takes a vector of individuals. The best practice is to use a helper function, see examples.

increasing_exp_mutation_rate(): Sets the mutation rate for each individual: Use exponential mutation rate.

reset_limit_increment(): Increase the reset limit by this amount every time the iteration counter reaches the limit

reset_limit_start(): The start value of the reset limit.

reset_limit_end(): The end value of the reset limit. If this end value is reached the reset limit is reset to the start value above.

Alternatively you can also put all the populations inside a vector.

After that you have to create a new instance of the simulation and provide the settings:

let my_builder = SimulationBuilder::<MyStruct>::new()
    .factor(0.34)
    .threads(2)
    .add_population(population1)
    .add_population(population2)
    .finalize();

    match my_builder {
        Err(SimError::EndIterationTooLow) => println!("more than 10 iteratons needed"),
        Ok(mut my_simulation) => {
            my_simulation.run();

            println!("total run time: {} ms", my_simulation.total_time_in_ms);
            println!("improvement factor: {}", my_simulation.simulation_result.improvement_factor);
            println!("number of iterations: {}", my_simulation.simulation_result.iteration_counter);

            my_simulation.print_fitness();
        }
    }

factor(): Sets the termination condition: if the improvement factor is better or equal to this value, the simulation stops.

threads(): Number of threads to use for the simulation.

add_population(): This adds the previously created population to the simulation.

finalize(): Finish setup and do sanity check. Returns Ok(Simulation) if there are no errors in the configuration.

add_muliple_populations(): Allows you to add all the populations inside a vector in one method call.

Then just do a match on the result of finalize() and call simulation.run() to start the simulation. After the finishing it, you can access some statistics (total_time_in_ms, improvement_factor, iteration_counter) and the populations of course:

    for population in my_simulation.habitat {
      for wrapper in population.population {...}
    }

Each individual is wrapped inside a Wrapper struct that contains additional information needed for the simulation: fitness and the number of mutations. See also the example folder for full working programs.

Discussion:

Used crates:

Similar crates:

Any feedback is welcome!

Comments
  • Clean Up Parts of the Code

    Clean Up Parts of the Code

    This mostly introduces the idiomatic Rust formatting, cleans up some iterations that used i as index before, fixes some typos and introduces the quick-error crate for idiomatic error handling.

    opened by CryZe 3
  • NQueens comparison

    NQueens comparison

    Hello.

    In the README, you say that https://github.com/reem/rust-n-queens is faster than your example.

    You can maybe also point to my genetic algorithm implementation, that solves the N Queens problem for N=255 in only few seconds 🙂: https://github.com/Martin1887/oxigen.

    Regards.

    opened by Martin1887 2
  • Fix clippy warnings in examples.

    Fix clippy warnings in examples.

    This fixes clippy warnings for all examples except the ocr example (I can't compile the ocr example because I have incompatible versions of native libfreetype and libpng libraries on my machine).

    I did separate commits for each example for the sake of better review, I can squash them if you want.

    opened by zummenix 1
  • [Question] What about Individual crossover?

    [Question] What about Individual crossover?

    From my basic knowledge on this subject, cross over between fit individuals is a crucial part on this algorithm, but I don't see the method on the Individual trait. Why was this choice made?

    opened by lsunsi 2
  • Serialise individuals

    Serialise individuals

    Add support for serialization, so that the whole simulation can be stopped and continued with the same states afterwards.

    This could also be a first step to support clusters (OpenMPI or other mechanims) by transmitting the current state of each individual over the wire.

    opened by willi-kappler 0
  • Super optimisation?

    Super optimisation?

    Maybe add a configuration flag for super optimisation, that is only those optimisations are allowed that improve the fitness or leave it at the same value.

    IndividualWrapper could be used to make a copy of the actual Individual before mutating and if the new mutated version is worse then the previous one just undo the mutation by copying it back.

    opened by willi-kappler 0
  • Phantom type for builder pattern

    Phantom type for builder pattern

    There is a discussion about using phanton types for the builder pattern:

    https://www.reddit.com/r/rust/comments/2pgrz7/required_parameters_utilizing_the_builder_pattern

    This may help detecting wrong configurations at compile time.

    opened by willi-kappler 0
  • Use crate random choice for selecting samples by fitness

    Use crate random choice for selecting samples by fitness

    Is there an interest to use the crate random choice in order to select samples by their fitness?

    It should be with a runtime of O(n) faster than the existing solution which sorts the samples (O (n * log n))

    https://github.com/StefanoD/Rust_Random_Choice

    opened by StefanoD 6
Releases(v0.4)
  • v0.4(Jun 26, 2017)

    • Allow user to specify num_of_global_fittest, fixes https://github.com/willi-kappler/darwin-rs/issues/12 .
    • Use error_chain.
    • Add output_every, to only output every nth time a new fittest individual is found.
    • Add share_every, to only share fittest individual after a number of iterations.
    Source code(tar.gz)
    Source code(zip)
  • v0.3(Aug 29, 2016)

    • Write output into a log file instead of using print!().
    • Remove new() from trait Individual, provide reset() instead.
    • All mutexes removed.
    • User must now provide whole population but can now use shared configuration / data instead of using lazy_static.
    • Calculate_fitness now needs (&mut self).
    • Add option share_fittest to share the fittest individual between all population after each iteration.
    • Add ocr2 example.
    • Add optional method new_fittest_found() to write out some statistics. Default implementation does nothing.
    • Add fitness counter statistic to population.
    • Fix bug in parallelization using jobsteal.
    • Fix bug in TSP2 example.
    Source code(tar.gz)
    Source code(zip)
  • 0.2(Aug 16, 2016)

    This release contains:

    • Code refactoring.
    • Better documentation.
    • Bug fix in the example.
    • Allow user to add multiple populations to a simulation.
    • Multi-Threading: Now for each population instead for each individual.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Jun 13, 2016)

Owner
Willi Kappler
Willi Kappler
A tool used to evaluate the output of retrieval algorithms. Written in Rust.

Rusteval A tool used to evaluate the output of retrieval algorithms. Written in Rust. Building Install Rust with curl -sSf https://static.rust-lang.or

Giorgos Sfikas 17 Mar 22, 2022
This crate implements fast route planning algorithms in Rust.

This crate implements fast route planning algorithms in Rust. Algorithms Currently implemented: Contraction Hierarchies: The implementat

Payas Rajan 4 Aug 15, 2021
A browser app that evolves vehicles using genetic algorithms, written in Rust and Bevy

Vehicle Evolver Deluxe This is a simulation that uses AI (to be specific: genetic algorithms) to try to build better and better vehicles. The vehicles

null 95 Dec 26, 2022
"Algorithms for approximate string matching" in Rust, with Python bindings.

ukkonen Implementation of a bounded Levenshtein distance by Esko Ukkonen in "Algorithms for approximate string matching" in Rust, with Python bindings

Ethan Smith 1 Dec 1, 2021
Common data structures and algorithms for competitive programming in Rust

algorithm-rs algorithm-rs is common data structures and algorithms for competitive programming in Rust. Contents TBA How To Contribute Contributions a

Chris Ohk 16 Dec 21, 2022
zine/book about bitmap drawing algorithms and math with code examples in Rust

A Bitmapper's Companion - zine/book about bitmap drawing algorithms and math with code examples in Rust A small zine/book written in LaTeX. In progres

Manos Pitsidianakis 42 Nov 8, 2022
Algorithms implemented in Rust, explained.

Rusty Algorithms & Data Structures for Learners This repository presents Rust implementations of common algorithms and data structures, many of which

Tianyi Shi 327 Dec 19, 2022
Bandit Algorithms in Rust

Multi-armed bandit algorithms in Rust Cargo [dependencies] bandit = "0.12.3" Description and Scope This library currently only implements the annealin

Michael Bohn 30 Nov 24, 2022
A Rust implementation the HOTP and TOTP Algorithms

xotp A Rust implementation the HOTP and TOTP Algorithms. HOTP was implemented in accordance with RFC4226 TOTP was implemented in accordance with RFC62

Tejas Mehta 3 Jan 21, 2022
Radiate is a parallel genetic programming engine capable of evolving solutions to many problems as well as training learning algorithms.

Radiate Coming from Evolutionary Radiation. Evolutionary radiation is a rapid increase in the number of species with a common ancestor, characterized

kalivas 109 Dec 18, 2022
Compare binary files using alignment algorithms

biodiff Compare binary files using alignment algorithms. What is this This is a tool for binary diffing. The tool is able to show two binary files sid

null 483 Dec 22, 2022
Genetic Algorithms Library

genx genx provides modular building blocks to run simulations of optimization and search problems using Genetic Algorithms (GA). The vision for genx i

Lakshya Singh 29 Aug 9, 2022
DSP algorithms for embedded. Often integer math.

This crate contains some tuned DSP algorithms for general and especially embedded use.

QUARTIQ 12 Nov 3, 2022
ECFFT algorithms on the BN254 base field

ECFFT algorithms on the BN254 base field This crate implements structs and traits for the ECFFT algorithms from the paper Elliptic Curve Fast Fourier

null 36 Nov 28, 2022
A library that can be used as a building block for high-performant graph algorithms.

graph A library that can be used as a building block for high-performant graph algorithms. Graph provides implementations for directed and undirected

Martin Junghanns 222 Jan 1, 2023
This library provides implementations of many algorithms and data structures that are useful for bioinformatics.

This library provides implementations of many algorithms and data structures that are useful for bioinformatics. All provided implementations are rigorously tested via continuous integration.

Rust-Bio 1.2k Dec 26, 2022
A small collection of procedural dungeon generation algorithms.

mapgen A small collection of procedural dungeon generation algorithms. Built with Rust & macroquad. WebAssembly build deployed here. Animated version

null 16 Aug 17, 2022
Genetic Algorithm library in Rust

RsGenetic Summary and Features RsGenetic is a framework for executing genetic algorithms in Rust. It is designed to have a simple but modular API. Exa

Mathieu De Coster 74 Dec 27, 2022
Rust implementation of real-coded GA for solving optimization problems and training of neural networks

revonet Rust implementation of real-coded genetic algorithm for solving optimization problems and training of neural networks. The latter is also know

Yury Tsoy 19 Aug 11, 2022