easy_ga 1.0.0

Library to implement genetic algorithms
Documentation

Easy_GA

Current Crates.io Version

Easy_GA is a genetic algorithm library made for Rust projects. It provides full customization for your own genotypes definitions and a geneticAlgorithm implementation to wrap all the common logic within a genetic algorithm.

All the changes will be updated in the CHANGELOG.md

Features

  • trait Gene: Definition to implement for your custom genotypes.
  • trait Selection: Definition for your custom selection algorithms.
    • Roulette: Selection algorithm already implemented.
    • Tournament: Selection algorithm implementation with n members on it.
  • GeneticAlgorithm: The main class to wrap the business logic in the genetic algorithm execution.

Usage

In your Cargo.tml you have to add the Easy_GA dependency

[dependencies]
easy_ga = "*"

Now I will show you a basic example of Easy_GA that you can find on main.rs

Files to include in order to use features:

use easy_ga::Gene; // For defining our own gene.
use easy_ga::GeneticAlgorithm; // To create a GeneticAlgorithm.
use easy_ga::SelectionAlgorithms; // To specity a concrete SelectionAlgorithm.

Definition of a custom Gene implementing easy_ga::Gene trait:

#[derive(Clone, Copy)]
struct MyGene {
    // Fields.
    fitness: f64 // Recomended to avoid recalculate fitness on `get_fitness`
}

impl Gene for MyGene {
    fn init() -> Self {
        // Gene constructor.
    }

    fn calculate_fitness(&mut self) -> f64 {
        // Fitness function.
    }

    fn crossover(&self, other: &Self) -> Self {
        // Crossover implementation.
    }

    fn mutate(&mut self) {
        // Mutation implementation.
    }

    fn get_fitness(&self) -> f64 {
        // Returns the fitness
    }
}

At this moment, we need to implement the Clone & Copy traits for our Gene. I will try to avoid that in a future versions.


Initialization of our GeneticAlgorithm:

let genetic_algorithm = GeneticAlgorithm::<MyGene>::new()
            .population_size(20)
            .iterations(50)
            .mutation_rate(0.10)
            .selection_rate(0.90)
            .selection_algorithm(Box::new(SelectionAlgorithms::Tournament(10)))
            .fitness_goal(100.0)
            .init().unwrap();

We have other ways to initializate our GeneticAlgorithm such as GeneticAlgorithm::new_with_values if we don't want the chain calling method.


Now that we have defined our genotype and have initializate our GeneticAlgorhtm we have 2 ways of running it:

  • GeneticAlgorithm::run: This method runs the algorithm until the end and returns a tuple with (Gene, StopCriteria) that represents the best Gene in the execution and the reason to stop the execution.
let (gene, stop_criteria) = genetic_algorithm.run();
  • Iteration by iteration: We have the posibilty of running the algorithm generation by generation and make modification while the execution is running.
while genetic_algorithm.is_running() {
    let new_generation: &Vec<MyGene> = genetic_algorithm.next_iteration();
}

Next steps

This is a personal side project mainly for me so any further implementations will be done in my spare time as a good way to teach me more about Rust.

  • Multithreading
  • Add verbosity for debugging
  • More unit testing and system testing
  • New default Selection algorithms
  • CSV and JSON result export
  • Fix some quality of life problems with references and chain calling

License

Easy_GA is licensed under Mozilla Public License 2.0.