• Stars
    star
    107
  • Rank 323,587 (Top 7 %)
  • Language
    Rust
  • License
    MIT License
  • Created almost 9 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

darwin-rs, evolutionary algorithms with rust

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!

More Repositories

1

node_crunch

Allows to distribute computations across several nodes
Rust
75
star
2

mandel-rust

Mandelbrot set in rust, serial and parallel example
Rust
47
star
3

rust_2020

Rust 2020 Roadmap: Scientific Rust
27
star
4

natural_constants

Pre-defined constants from all disciplines (math, physics, ...) as a Rust library
Rust
20
star
5

simple_units

A simple unit system for Rust
Rust
11
star
6

gronn

Growing Neural Network
Rust
9
star
7

green_moon

Green Moon - simple 2D game engine written in Rust
Rust
6
star
8

netcdf-rs

100% pure Rust support for the netCDF file format
Rust
5
star
9

character_twister

OCR software written in Rust
Rust
4
star
10

cr-basic-highlight

Syntax highlighting for CR Basic
Emacs Lisp
4
star
11

rune

Really Unique Interface
Rust
4
star
12

comment_units

Check physical units in source code that are described as comments
Rust
3
star
13

Pecube_D

Pecube_D (University of Tuebingen, ESD workgroup Ehlers)
Fortran
3
star
14

list_of_rust_books

A list of books available for the Rust programming language
2
star
15

panolution

Panorama photo stitcher using evolutionary algorithm
Rust
2
star
16

Snowball_Python

A 2D jump and run game written in Python
Python
2
star
17

sq_noise

A crate for generating noise and random values. Based on the Squirrel3 noise function.
Rust
2
star
18

narvin

Evolutionary algorithms with Nim
Nim
1
star
19

web_container1

1
star
20

green_moon_2d

Green Moon 2D - a simple 2D game engine written in Rust
Rust
1
star
21

ice_data_extractor

Python
1
star
22

mini_magnets

A smal puzzle game written in Rust
Rust
1
star
23

msg_box

A message box system
Rust
1
star
24

math_term

Mathematical terms in Rust
Rust
1
star
25

parasnake

Distributed number crunching with Python
Python
1
star
26

radar-rs

Process radar data with Rust
Rust
1
star
27

pecube_conv

Converter for Pecube binary files
Rust
1
star
28

andromeda_chess

Chess game with variations
Rust
1
star
29

Matlab_Kurs

Unterlagen für einen Matlabkurs (Geowissenschaften Uni Tübingen)
TeX
1
star
30

topo_scaler

Scale Topographic Data
Rust
1
star
31

stl_3d

STL 3D (text and binary) format parser for Rust written with nom
Rust
1
star
32

xls_grep

A simple (quick and dirty) tool to search for a given text through a bunch of Excel files
Python
1
star
33

iridium_weatherstation

A small data processing tool written in Rust for one of the campbell iridium weather stations
Rust
1
star
34

terra_data_server

A webserver for managing all the data for the Terra project.
Python
1
star