Current Crates.io Version

Crates: https://crates.io/crates/easy_ga

Github repository: https://github.com/RubenRubioM/easy_ga

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

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();
}

Logger

The logger is a very usefull tool to measure and retrieve some data from the execution. By default the logger is disabled, you can enable it this way:

use easy_ga::VerbosityLevel; // Verbosity level {DISABLED, LOW, MID, HIGH}
use easy_ga::VerbosityType; // Verbosity type {LOG, SAVE, LOG_AND_SAVE}
use easy_ga::LOG_verbosity; // Sets the verbosity level.
use easy_ga::LOG_verbosity_type; // Sets the verbosity type.

LOG_verbosity(VerbosityLevel::LOW); // VerbosityLevel::DISABLED by default
LOG_verbosity_type(VerbosityType::LOG_AND_SAVE); // VerbosityType::LOG by default
  • VerbosityLevel:
    • DISABLED: The logs are disabled.
    • LOW: Only very usefull information.
    • MID: Maybe not to desired information but also usefull.
    • HIGH: All logs are avaliable including tracing logs.
  • VerbosityType:
    • LOG: Only terminal logs.
    • SAVE: Saves the logs into target/tmp/.
    • SAVE_AND_LOG: Both.

Benchmarking

Benchmarking was added in the version 1.1.0 and you can run them donwloading the repository and running cargo bench from the command-line. The benchmarks are placed inside the benches/ folder.

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
  • Add benchmarks ✔

License

Easy_GA is licensed under Mozilla Public License 2.0.


1 Comment

Dayna Venzor · April 22, 2022 at 19:30

Having read this I believed it was extremely informative. I appreciate you taking the time and effort to put this informative article together. I once again find myself personally spending a significant amount of time both reading and leaving comments. But so what, it was still worth it!

Leave a Reply

Your email address will not be published.