From b2a1afe3b5a034668f2ef78b3d60251e0c39af6f Mon Sep 17 00:00:00 2001 From: Peter Kalivas Date: Sat, 23 Nov 2024 09:52:24 -0600 Subject: [PATCH] docs --- radiate/src/engines/genome/chromosome.rs | 19 +++++++++++++++++++ radiate/src/engines/genome/genotype.rs | 20 ++++++++++++++++++++ radiate/src/engines/genome/population.rs | 8 +++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/radiate/src/engines/genome/chromosome.rs b/radiate/src/engines/genome/chromosome.rs index 1e2be19..ce1fa43 100644 --- a/radiate/src/engines/genome/chromosome.rs +++ b/radiate/src/engines/genome/chromosome.rs @@ -1,5 +1,23 @@ use super::genes::gene::Gene; +/// The `Chromosome` struct represents a collection of `Gene` instances. The `Chromosome` is part of the +/// genetic makeup of an individual. It is a collection of `Gene` instances, it is essentially a +/// light wrapper around a Vec of `Gene`s. The `Chromosome` struct, however, has some additional +/// functionality and terminology that aligns with the biological concept of a chromosome. +/// +/// In traditional biological terms, a `Chromosome` is a long DNA molecule with part or all of the +/// genetic material of an organism. The `Chromosome` is the 'genetic' part of the individual that is +/// being evolved by the genetic algorithm. +/// +/// We can think of a `Chromosome` as a Vec of structs which implement the `Gene` trait. For example, +/// if we have a `Chromosome` with 3 `Gene`s, it is represented as follows: +/// ```text +/// Chromosome: [Gene, Gene, Gene] +/// ``` +/// +/// # Type Parameters +/// - `G`: The type of gene used in the genetic algorithm, which must implement the `Gene` trait. +/// - `A`: The type of the allele associated with the gene - the gene's "expression". pub struct Chromosome where G: Gene, @@ -12,6 +30,7 @@ impl Chromosome where G: Gene, { + /// Create a new instance of the Chromosome with the given genes. pub fn from_genes(genes: Vec) -> Self { Chromosome { genes, diff --git a/radiate/src/engines/genome/genotype.rs b/radiate/src/engines/genome/genotype.rs index 1734bac..9fbebd8 100644 --- a/radiate/src/engines/genome/genotype.rs +++ b/radiate/src/engines/genome/genotype.rs @@ -1,5 +1,24 @@ use super::{chromosome::Chromosome, genes::gene::Gene}; +/// The `Genotype` struct represents the genetic makeup of an individual. It is a collection of ```Chromosome``` instances, it is +/// essentially a light wrapper around a Vec of ```Chromosome```s. The ```Genotype``` struct, however, has some additional functionality +/// and terminology that aligns with the biological concept of a genotype. +/// In traditional biological terms, a `Genotype` is the set of genes in our DNA that determine a specific trait or set of traits. +/// The ```Genotype``` is the 'genetic' part of the individual that is being evolved by the genetic algorithm. +/// +/// We can think of a ```Genotype``` as a matrix of strucs which implement the ```Gene``` trait where each row is a ```Chromosome```. +/// For example, if we have a ```Genotype``` with 2 ```Chromosome```s, each with 3 ```Gene```s, it is represented as follows: +/// ```text +/// Genotype: +/// [ +/// Chromosome: [Gene, Gene, Gene], +/// Chromosome: [Gene, Gene, Gene] +/// ] +/// ``` +/// +/// # Type Parameters +/// - `G`: The type of gene used in the genetic algorithm, which must implement the `Gene` trait. +/// - `A`: The type of the allele associated with the gene - the gene's "expression". pub struct Genotype where G: Gene, @@ -11,6 +30,7 @@ impl Genotype where G: Gene, { + /// Create a new instance of the Genotype with the given chromosomes. pub fn from_chromosomes(chromosomes: Vec>) -> Self { Genotype { chromosomes } } diff --git a/radiate/src/engines/genome/population.rs b/radiate/src/engines/genome/population.rs index 168a64f..21fb46d 100644 --- a/radiate/src/engines/genome/population.rs +++ b/radiate/src/engines/genome/population.rs @@ -8,7 +8,8 @@ use super::{genes::gene::Gene, phenotype::Phenotype}; /// Note: Although the ```Population``` offers mut methods to mut the individuals in the population, the ```Population``` /// itself offers no way to increase or decrease the number of individuals in the population. As such, the ```Population``` /// should be thought of as an 'immutable' data structure. If you need to add or remove individuals from the population, -/// you should create a new ```Population``` instance with the new individuals. +/// you should create a new ```Population``` instance with the new individuals. To further facilitate this way of +/// thinking, the ```Population``` struct and everyhing it contains implements the ```Clone``` trait. /// /// # Type Parameters /// - `G`: The type of gene used in the genetic algorithm, which must implement the `Gene` trait. @@ -38,6 +39,8 @@ where self.individuals.get(index).expect("Index out of bounds") } + /// Get a mutable reference to the individual at the given index. This will set the is_sorted flag to false + /// because we cannot guarantee that the individual's ```Score``` (fitness) has not changed. pub fn get_mut(&mut self, index: usize) -> &mut Phenotype { self.is_sorted = false; self.individuals @@ -45,6 +48,8 @@ where .expect("Index out of bounds") } + /// Set the individual at the given index. This will set the is_sorted flag to false + /// because we cannot guarantee that the individual is in the correct order. pub fn set(&mut self, index: usize, individual: Phenotype) { self.individuals[index] = individual; self.is_sorted = false; @@ -63,6 +68,7 @@ where self.individuals.len() } + /// Sort the individuals in the population using the given closure. This will set the is_sorted flag to true. pub fn sort_by(&mut self, f: F) where F: FnMut(&Phenotype, &Phenotype) -> std::cmp::Ordering,