Skip to content

Commit

Permalink
feat: update documentation
Browse files Browse the repository at this point in the history
- add function level docs with examples
- update version in lib.rs
Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>
  • Loading branch information
king-11 committed Sep 3, 2021
1 parent 380f8ea commit bc1f31e
Show file tree
Hide file tree
Showing 15 changed files with 264 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -72,7 +72,7 @@
//! Add this to your `Cargo.toml`:
//! ```toml
//! [dependencies]
//! genx = "0.1.0"
//! genx = "0.2.3"
//! ```
//! If you are not using Rust 2018 edition add this to your crate root:
//! ```rust
Expand Down
25 changes: 25 additions & 0 deletions src/mutation/flipping.rs
@@ -1,5 +1,30 @@
use rand::{rngs::StdRng, SeedableRng, Rng};

/**
## Description
Flipping mutation is a mutation only for binary encoded individuals.
Given the `mutation_probability` and `individual` it iterates through the boolean vector of `individual`
and generates a random number between `0.0` and `1.0`. If the number is less than `mutation_probability`
then we _flip_ the value at that index else it remains the same.
_Note: The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results._
## Return
The return value is a `Result<(), &'static str>` which will return error only if the `mutation_probability` is greater than `1`
## Example
```rust
use genx::mutation::flipping_mutation;
let mut individual = vec![false, true, false, false,
true, true, true, false, false, true, false,
false, true, false, false, true];
let original_individual = individual.clone();
match flipping_mutation(&mut individual, 0.5, Some(42)) {
Ok(_) => (),
Err(error) => panic!("{:?}", error)
};
assert_ne!(original_individual, individual);
```
*/
pub fn flipping_mutation(individual: &mut Vec<bool>, mutation_probability: f32, seed: Option<u64>) -> Result<(), &'static str> {
if mutation_probability < 0.0 || mutation_probability > 1.0 {
return Err("mutation_probability should lie between 0.0 and 1.0 inclusive");
Expand Down
19 changes: 19 additions & 0 deletions src/mutation/inversion.rs
Expand Up @@ -2,6 +2,25 @@ use std::{mem::swap};

use rand::{Rng, SeedableRng, rngs::StdRng};

/**
## Description
Inversion mutation is a mutation only for binary encoded individuals.
Given the `individual` it randomly generates two indices and then inverts
the value between those indices of the individual.
_Note: The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results._
## Example
```rust
use genx::mutation::inversion_mutation;
let mut individual = vec![false, true, false, false,
true, true, true, false, false, true, false,
false, true, false, false, true];
let original_individual = individual.clone();
inversion_mutation(&mut individual, Some(42));
assert_ne!(original_individual, individual);
```
*/
pub fn inversion_mutation(individual: &mut Vec<bool>, seed: Option<u64>) {
let mut prng = match seed {
Some(val) => StdRng::seed_from_u64(val),
Expand Down
3 changes: 2 additions & 1 deletion src/mutation/mod.rs
Expand Up @@ -14,7 +14,8 @@
//!
//! All the mutation functions for binary encoded schema
//! take in atleast an argument of mutable reference to
//! the boolean vector of individual to mutate.
//! the boolean vector of individual to mutate. Hence they
//! change the actual boolean Vector.
//!
//! Only those functions where, there is a need to constrain
//! range of values that can be provided as argument will return
Expand Down
23 changes: 23 additions & 0 deletions src/mutation/polynomial.rs
@@ -1,5 +1,28 @@
use rand::{Rng, rngs::StdRng, SeedableRng};

/**
## Description
Polynomial mutation is a mutation only for real encoded individuals.
Given the `individual`, `distribution_index` and `max_perturbation` it generates a closure
which is an exponential polynomial function using the `distribution_index`. Given a randomly generated value
in range `0.0..1.0` to the closure it returns the `perturbation_factor`.
### Note
- A large value for `distribution_index` will make stark mutation for only a few values whereas a small `distribution_index` will cause uniform mutation for all randomly generated values (undesirable).
- The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results.
## Return
Finally returned value is `individual + calculate_perturbation_factor(random_value)*max_perturbation`
## Example
```rust
use genx::mutation::polynomial_mutation;
let individual = 29.11;
let result = polynomial_mutation(individual, 4.2, 4.0, Some(42));
assert_ne!(individual, result);
```
*/
pub fn polynomial_mutation(individual: f32, distribution_index: f32, max_perturbation: f32, seed: Option<u64>) -> f32 {
let random_value = (match seed {
Some(val) => StdRng::seed_from_u64(val),
Expand Down
22 changes: 22 additions & 0 deletions src/mutation/random.rs
@@ -1,5 +1,27 @@
use rand::{Rng, rngs::StdRng, SeedableRng};

/**
## Description
Random mutation is a mutation only for real encoded individuals.
Given the `individual` and `perturbation_factor` it generates a random value
in range `0.0..1.0` which is then used to linearly mutate the individual.
#### Note
- A large value for `perturbation_factor` will make stark mutation for all values.
- The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results.
## Return
Finally returned value is `individual + (2.0*random_value - 1.0)*perturbation_factor`
## Example
```rust
use genx::mutation::random_mutation;
let individual = 29.11;
let result = random_mutation(individual, 4.2, Some(42));
assert_ne!(individual, result);
```
*/
pub fn random_mutation(individual: f32, perturbation_factor: f32, seed: Option<u64>) -> f32 {
let random_value = (match seed {
Some(val) => StdRng::seed_from_u64(val),
Expand Down
19 changes: 19 additions & 0 deletions src/mutation/scramble.rs
Expand Up @@ -2,6 +2,25 @@ use std::{mem::swap};

use rand::{Rng, SeedableRng, rngs::StdRng, seq::SliceRandom};

/**
## Description
Scramble mutation is a mutation only for binary encoded individuals.
Given the `individual` it randomly generates two indices and then
shuffles the values between those two indices.
_Note: The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results._
## Example
```rust
use genx::mutation::scramble_mutation;
let mut individual = vec![false, true, false, false,
true, true, true, false, false, true, false,
false, true, false, false, true];
let original_individual = individual.clone();
scramble_mutation(&mut individual, Some(42));
assert_ne!(original_individual, individual);
```
*/
pub fn scramble_mutation(individual: &mut Vec<bool>, seed: Option<u64>) {
let mut prng = match seed {
Some(val) => StdRng::seed_from_u64(val),
Expand Down
18 changes: 18 additions & 0 deletions src/mutation/swap.rs
@@ -1,5 +1,23 @@
use rand::{rngs::StdRng, SeedableRng, seq::SliceRandom};

/**
## Description
Swap mutation is a mutation only for binary encoded individuals.
Given the `individual` it randomly generates two indices and then swaps the value at those two indices.
_Note: The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results._
## Example
```rust
use genx::mutation::swap_mutation;
let mut individual = vec![false, true, false, false,
true, true, true, false, false, true, false,
false, true, false, false, true];
let original_individual = individual.clone();
swap_mutation(&mut individual, Some(11));
assert_ne!(original_individual, individual);
```
*/
pub fn swap_mutation(individual: &mut Vec<bool>, seed: Option<u64>) -> Result<(), &'static str> {
let mut prng = match seed {
Some(val) => StdRng::seed_from_u64(val),
Expand Down
2 changes: 2 additions & 0 deletions src/selection/mod.rs
Expand Up @@ -15,6 +15,8 @@
//! point values that contains fitness values of individuals, and
//! number of individuals to select. Finally functions return indices of
//! selected individuals.
//!
//! You can read more about selection schemas and their working from the [wikipedia page](https://en.wikipedia.org/wiki/Selection_(genetic_algorithm))

pub mod random;

Expand Down
21 changes: 21 additions & 0 deletions src/selection/random.rs
@@ -1,5 +1,26 @@
use rand::{rngs::StdRng, SeedableRng, Rng};

/**
## Description
Random Selection is the simplest form of selection which randomly
generates an index from the provided `fitness_values` vector and that
is the selection. Same procedure is done until we have `num_parents` selected individuals.
_Note: The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results._
## Return
The return value is a `Vec<usize>` pointing to the selected indices.
## Example
```rust
use genx::selection::random_selection;
let num_parents:usize = 10;
let fitness_values = vec![10.0,0.2,9.0,4.8,7.7,8.4,3.2,9.4,9.0,11.0,4.5];
let result = random_selection(&fitness_values, num_parents, None);
```
*/
pub fn random_selection(fitness_values: &Vec<f32>, num_parents: usize, seed: Option<u64>) -> Vec<usize> {
let population_size = fitness_values.len();
let mut prng = match seed {
Expand Down
24 changes: 24 additions & 0 deletions src/selection/rank.rs
@@ -1,6 +1,30 @@
use std::cmp::Ordering;
use rand::{rngs::StdRng, SeedableRng, Rng};

/**
## Description
Rank Selection is a form of proportionate selection. It generates a roulette wheel where area occupied by a particular individual is proportional to its rank in fitness vector when sorted in non decreasing order.
For each of the `num_parents` iterations a random number between `0.0..1.0` is generated which then decides the location at which roulette wheel will stop and that particular individual's index is added to vector of selected individuals.
### Note
- Individuals with same fitness value are given the same ranks.
- The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results.
## Return
The return value is a `Vec<usize>` pointing to the selected indices.
## Example
```rust
use genx::selection::rank_selection;
let num_parents:usize = 10;
let fitness_values = vec![10.0,0.2,9.0,4.8,7.7,8.4,3.2,9.4,9.0,11.0,4.5];
let result = rank_selection(&fitness_values, num_parents, None);
```
*/
pub fn rank_selection(fitness_values: &Vec<f32>, num_parents: usize, seed: Option<u64>) -> Vec<usize> {
let mut fitness_values_with_index : Vec<(f32, usize)> = Vec::new();
for (i, &value) in fitness_values.iter().enumerate() {
Expand Down
24 changes: 24 additions & 0 deletions src/selection/roulette_wheel.rs
@@ -1,5 +1,29 @@
use rand::{rngs::StdRng, SeedableRng, Rng};

/**
## Description
Roulette Wheel Selection is a form of proportionate selection. It generates a roulette wheel where area occupied by a particular individual is proportional to its fitness values.
For each of the `num_parents` iterations a random number between `0.0..1.0` is generated which then decides the location at which roulette wheel will stop and that particular individual's index is added to vector of selected individuals.
### Note
- Individuals with same fitness value occupy same area on roulette wheel.
- The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results.
## Return
The return value is a `Vec<usize>` pointing to the selected indices.
## Example
```rust
use genx::selection::roulette_wheel_selection;
let num_parents:usize = 10;
let fitness_values = vec![10.0,0.2,9.0,4.8,7.7,8.4,3.2,9.4,9.0,11.0,4.5];
let result = roulette_wheel_selection(&fitness_values, num_parents, None);
```
*/
pub fn roulette_wheel_selection(fitness_values: &Vec<f32>, num_parents: usize, seed: Option<u64>) -> Vec<usize> {
let sum_of_fitness = fitness_values.iter().sum::<f32>();
let normalized_probabilities = fitness_values.iter().map(|&a| a/sum_of_fitness).collect::<Vec<f32>>();
Expand Down
19 changes: 19 additions & 0 deletions src/selection/steady_state.rs
@@ -1,5 +1,24 @@
use std::cmp::{Ordering, min};

/**
## Description
Steady State Selection is a sorting based selection method. It will always select the top `num_parents` in terms of fitness value from the pool of individuals.
_Note: If `num_parents` is greater than length of `fitness_values` vector (n), then only indices from `0..n-1` will be returned._
## Return
The return value is a `Vec<usize>` pointing to the selected indices.
## Example
```rust
use genx::selection::steady_state_selection;
let num_parents:usize = 10;
let fitness_values = vec![10.0,0.2,9.0,4.8,7.7,8.4,3.2,9.4,9.0,11.0,4.5];
let result = steady_state_selection(&fitness_values, num_parents);
```
*/
pub fn steady_state_selection(fitness_values: &Vec<f32>, num_parents: usize) -> Vec<usize> {
let mut fitness_values_with_index : Vec<(f32, usize)> = Vec::new();
let population_size = fitness_values.len();
Expand Down
23 changes: 23 additions & 0 deletions src/selection/stochastic_universal.rs
@@ -1,5 +1,28 @@
use rand::{rngs::StdRng, SeedableRng, Rng};

/**
## Description
Stochastic Universal Selection/Sampling is also a proportionate selection method very much like roulette wheel selection. The major differences is that it selects the required number of individuals (`num_parents`) in a single spin of the wheel which allows for population diversity.
To know more about stochastic universal sampling refer the [wikipedia page](https://en.wikipedia.org/wiki/Stochastic_universal_sampling)
### Note
- Individuals with same fitness value occupy same area on roulette wheel.
- The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results.
## Return
The return value is a `Vec<usize>` pointing to the selected indices.
## Example
```rust
use genx::selection::stochastic_universal_selection;
let num_parents:usize = 10;
let fitness_values = vec![10.0,0.2,9.0,4.8,7.7,8.4,3.2,9.4,9.0,11.0,4.5];
let result = stochastic_universal_selection(&fitness_values, num_parents, None);
```
*/
pub fn stochastic_universal_selection(fitness_values: &Vec<f32>, num_parents: usize, seed: Option<u64>) -> Vec<usize> {
let sum_of_fitness = fitness_values.iter().sum::<f32>();
let mut fitness_scale:Vec<f32> = Vec::new();
Expand Down
22 changes: 22 additions & 0 deletions src/selection/tournament.rs
@@ -1,6 +1,28 @@
use rand::{seq::SliceRandom, rngs::StdRng, SeedableRng};
use std::cmp::{Ordering, min};

/**
## Description
Tournament Selection is a randomized sorting based selection method. We conduct `num_parents` tournaments where we randomly select `tournament_size` individuals. Out of those selected for a particular tournament, the fittest one is added to the vector of selected indices.
### Note:
- If `tournament_size` is greater than length of `fitness_values` vector (n), then overall fittest individual gets selected from all the tournaments.
- The function can also take in an optional `seed` value of type `Option<u64>` for deterministic results.
## Return
The return value is a `Vec<usize>` pointing to the selected indices.
## Example
```rust
use genx::selection::tournament_selection;
let num_parents:usize = 10;
let fitness_values = vec![10.0,0.2,9.0,4.8,7.7,8.4,3.2,9.4,9.0,11.0,4.5];
let result = tournament_selection(&fitness_values, num_parents, 4, None);
```
*/
pub fn tournament_selection(fitness_values: &Vec<f32>, num_parents: usize, tournament_size: usize, seed: Option<u64>) -> Vec<usize> {
let mut fitness_values_with_index : Vec<(f32, usize)> = Vec::new();
for (i, &value) in fitness_values.iter().enumerate() {
Expand Down

0 comments on commit bc1f31e

Please sign in to comment.