RUST genetic algorithms library

Codacy Badge CircleCI

Description

This library provides a simple framework to implement genetic algorithms (GA) with Rust.

Table of content

Features

Traits

This version uses traits for generic implementations.

These traits are within the traits module:

Operators

Within the module operations we have the following operators:

Population

In genetic algorithms, operators are applied over a population of individuals, and over a set of rules (not yet implemented). Within the population module, Population structure will define the population.

Runner

Because genetic algorithms run over different generations, in this library there is a start function within module ga that facilitates the process. This function will need the GaConfiguration structure which contains the operators to use, the maximum number of generations, and the problem solver (Maximization or Minimization), and the Population structure, which is in the population module.

Example

A simple example of use could be the minimization of a genotype whose gene has only an id.

Creation of the gene and genotype structure

Use the traits. use use genetic_algorithms::{ga::{GaConfiguration, ProblemSolving, run}, operations::{Selection, Crossover, Mutation, Survivor}, population::Population, traits::GenotypeT};

Define the gene structure.

```

[derive(Debug, Copy, Clone, Default, PartialEq)]

pub struct Gene{ pub id: i32, } impl GeneT for Gene{ fn new()->Gene{ return Gene{id: -1}; } fn get_id(&self) -> &i32{ return &self.id; } } ```

Define the genotype structure, and the phenotype calculation.

```

[derive(Debug, Clone, Default, PartialEq)]

pub struct Genotype{ pub dna: Vec, pub phenotype: f64, pub age: i32, } impl GenotypeT for Genotype{ fn getdna(&self) -> &Vec { &self.dna } fn getdnamut(&mut self) -> &mut Vec { &mut self.dna } fn getphenotype(&self) -> &f64 { return &self.phenotype; } fn getagemut(&mut self) -> &mut i32 { &mut self.age } fn getage(&self) -> &i32 { &self.age } fn calculatephenotype(&mut self) {

    self.phenotype = 0.0;
    let mut position = 0;

    for i in &self.dna{
        let phenotype = f64::from(i.get_id()*position);
        self.phenotype += phenotype;
        position += 1;
    }
}
fn new() -> Self {
    return Genotype{
        dna: Vec::new(),
        phenotype: 0.0,
        age: 0,
    }
}

} ```

Define the configuration of the GA.

let configuration = GaConfiguration{ problem_solving: ProblemSolving::Maximization, max_generations: 100, selection: Selection::Random, crossover: Crossover::Cycle, mutation: Mutation::Swap, survivor: Survivor::Fitness, };

Define the DNA, the individuals and the population.

``` let dna1 = vec![Gene{id:1}, Gene{id:2}, Gene{id:3}, Gene{id:4}]; let dna2 = vec![Gene{id:2}, Gene{id:3}, Gene{id:4}, Gene{id:1}]; let dna3 = vec![Gene{id:3}, Gene{id:4}, Gene{id:1}, Gene{id:2}]; let dna4 = vec![Gene{id:4}, Gene{id:1}, Gene{id:2}, Gene{id:3}]; let dna5 = vec![Gene{id:2}, Gene{id:1}, Gene{id:3}, Gene{id:4}]; let dna6 = vec![Gene{id:1}, Gene{id:3}, Gene{id:4}, Gene{id:2}]; let dna7 = vec![Gene{id:3}, Gene{id:4}, Gene{id:2}, Gene{id:1}]; let dna8 = vec![Gene{id:4}, Gene{id:2}, Gene{id:1}, Gene{id:3}]; let dna9 = vec![Gene{id:2}, Gene{id:1}, Gene{id:4}, Gene{id:3}]; let dna10 = vec![Gene{id:1}, Gene{id:4}, Gene{id:3}, Gene{id:2}];

let individuals = vec![Genotype{dna: dna1, phenotype: 1.0, age: 0}, Genotype{dna: dna2, phenotype: 2.0, age: 0}, Genotype{dna: dna3, phenotype: 3.0, age: 0}, Genotype{dna: dna4, phenotype: 4.0, age: 0}, Genotype{dna: dna5, phenotype: 5.0, age: 0}, Genotype{dna: dna6, phenotype: 6.0, age: 0}, Genotype{dna: dna7, phenotype: 7.0, age: 0}, Genotype{dna: dna8, phenotype: 8.0, age: 0}, Genotype{dna: dna9, phenotype: 9.0, age: 0}, Genotype{dna: dna10, phenotype: 10.0, age: 0}];

let mut population = Population::new(individuals);

```

Finally, run the GA.

population = run(population, configuration);

Usage

Add this to your Cargo.toml:

toml [dependencies] genetic_algorithms = "0.2.0"