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
🧮 alphatensor matrix breakthrough algorithms + simd + rust.

simd-alphatensor-rs tldr; alphatensor matrix breakthrough algorithims + simd + rust. This repo contains the cutting edge matrix multiplication algorit

drbh 50 Feb 11, 2023
Personal experiments with genetic algorithms and neuroevolution, in Rust, with the Bevy engine.

The Tango Problem Personal experiments with genetic algorithms and neuroevolution, in Rust, with the Bevy engine. A number of "Psychics" are placed in

null 3 Nov 20, 2023
DBSCAN and OPTICS clustering algorithms.

petal-clustering A collection of clustering algorithms. Currently this crate provides DBSCAN and OPTICS. Examples The following example shows how to c

Petabi 15 Dec 15, 2022
Nearest neighbor search algorithms including a ball tree and a vantage point tree.

petal-neighbors Nearest neighbor search algorithms including a ball tree and a vantage point tree. Examples The following example shows how to find tw

Petabi 6 Oct 19, 2022
A suite of benchmarks to test e-graph extraction algorithms

Extraction Gym A suite of benchmarks to test e-graph extraction algorithms. Add your algorithm in src/extract and then add a line in src/main.rs. To r

null 7 Jul 1, 2023
Msgpack serialization/deserialization library for Python, written in Rust using PyO3, and rust-msgpack. Reboot of orjson. msgpack.org[Python]

ormsgpack ormsgpack is a fast msgpack library for Python. It is a fork/reboot of orjson It serializes faster than msgpack-python and deserializes a bi

Aviram Hassan 139 Dec 30, 2022
Practice repo for learning Rust. Currently going through "Rust for JavaScript Developers" course.

rust-practice ?? Practice repo for learning Rust. Directories /rust-for-js-dev Files directed towards "Rust for JavaScript Developers" course. Thank y

Sammy Samkough 0 Dec 25, 2021
A Rust library with homemade machine learning models to classify the MNIST dataset. Built in an attempt to get familiar with advanced Rust concepts.

mnist-classifier Ideas UPDATED: Finish CLI Flags Parallelize conputationally intensive functions Class-based naive bayes README Image parsing Confusio

Neil Kaushikkar 0 Sep 2, 2021
🦀Rust Turkiye - Rust Dersleri

Rust Turkiye - Rust Dersleri CURIOSITY - Featuring Richard Feynman Bu repo Rust Turkiye tarafindan duzenlenen Rust Dersleri egitiminin alistirma ve ko

Theo M. Bulut 12 Jan 14, 2023
A Rust machine learning framework.

Linfa linfa (Italian) / sap (English): The vital circulating fluid of a plant. linfa aims to provide a comprehensive toolkit to build Machine Learning

Rust-ML 2.2k Jan 2, 2023
Machine Learning library for Rust

rusty-machine This library is no longer actively maintained. The crate is currently on version 0.5.4. Read the API Documentation to learn more. And he

James Lucas 1.2k Dec 31, 2022
Rust library for Self Organising Maps (SOM).

RusticSOM Rust library for Self Organising Maps (SOM). Using this Crate Add rusticsom as a dependency in Cargo.toml [dependencies] rusticsom = "1.1.0"

Avinash Shenoy 26 Oct 17, 2022
Rust language bindings for TensorFlow

TensorFlow Rust provides idiomatic Rust language bindings for TensorFlow. Notice: This project is still under active development and not guaranteed to

null 4.1k Jan 1, 2023
Machine learning crate for Rust

rustlearn A machine learning package for Rust. For full usage details, see the API documentation. Introduction This crate contains reasonably effectiv

Maciej Kula 547 Dec 28, 2022
Rust bindings for the C++ api of PyTorch.

tch-rs Rust bindings for the C++ api of PyTorch. The goal of the tch crate is to provide some thin wrappers around the C++ PyTorch api (a.k.a. libtorc

Laurent Mazare 2.3k Jan 1, 2023
个人的 rust 学习资料

?? 通知: 项目文档迁移到: https://github.com/higker/learn-rust learning-rust-zh 个人的 rust 学习资料 学习目录 目录 源代码地址 相关解析 第一个rust程序 https://github.com/higker/learning-ru

Jarvib Ding 16 Jun 21, 2022
Distributed compute platform implemented in Rust, and powered by Apache Arrow.

Ballista: Distributed Compute Platform Overview Ballista is a distributed compute platform primarily implemented in Rust, powered by Apache Arrow. It

Ballista 2.3k Jan 3, 2023
Tensors and differentiable operations (like TensorFlow) in Rust

autograd Differentiable operations and tensors backed by ndarray. Motivation Machine learning is one of the field where Rust lagging behind other lang

Ryo ASAKURA 403 Dec 25, 2022
Rust numeric library with R, MATLAB & Python syntax

Peroxide Rust numeric library contains linear algebra, numerical analysis, statistics and machine learning tools with R, MATLAB, Python like macros. W

Tae Geun Kim 351 Dec 29, 2022