darwin_rs/population_builder.rs
1//! This module defines helper functions (builder pattern) to create a valid population.
2//!
3//! darwin-rs: evolutionary algorithms with Rust
4//!
5//! Written by Willi Kappler, Version 0.4 (2017.06.26)
6//!
7//! Repository: https://github.com/willi-kappler/darwin-rs
8//!
9//! License: MIT
10//!
11//! This library allows you to write evolutionary algorithms (EA) in Rust.
12//! Examples provided: TSP, Sudoku, Queens Problem, OCR
13//!
14//!
15
16use std;
17
18use individual::{Individual, IndividualWrapper};
19use population::Population;
20
21/// This is a helper struct in order to build (configure) a valid population.
22/// See builder pattern: https://en.wikipedia.org/wiki/Builder_pattern
23///
24/// Maybe use phantom types, see https://github.com/willi-kappler/darwin-rs/issues/9
25pub struct PopulationBuilder<T: Individual> {
26 /// The actual simulation
27 population: Population<T>,
28}
29
30error_chain! {
31 errors {
32 IndividualsTooLow
33 LimitEndTooLow
34 }
35}
36
37/// This implementation contains all the helper method to build (configure) a valid population.
38impl<T: Individual + Clone> PopulationBuilder<T> {
39 /// Start with this method, it must always be called as the first one.
40 /// It creates a default population with some dummy (but invalid) values.
41 pub fn new() -> PopulationBuilder<T> {
42 PopulationBuilder {
43 population: Population {
44 num_of_individuals: 0,
45 population: Vec::new(),
46 reset_limit: 0,
47 reset_limit_start: 1000,
48 reset_limit_end: 10000,
49 reset_limit_increment: 1000,
50 reset_counter: 0,
51 id: 1,
52 fitness_counter: 0
53 }
54 }
55 }
56
57 /// Sets the initial population provided inside a vector, length must be >= 3
58 pub fn initial_population(mut self, individuals: &[T]) -> PopulationBuilder<T> {
59 self.population.num_of_individuals = individuals.len() as u32;
60
61 for individual in individuals {
62 self.population.population.push(IndividualWrapper {
63 individual: (*individual).clone(),
64 fitness: std::f64::MAX,
65 num_of_mutations: 1,
66 id: self.population.id,
67 });
68 }
69
70 self
71 }
72
73 /// Configures the mutation rates (number of mutation runs) for all the individuals
74 /// in the population: The first individual will mutate once, the second will mutate twice,
75 /// the nth individual will Mutate n-times per iteration.
76 pub fn increasing_mutation_rate(mut self) -> PopulationBuilder<T> {
77 let mut mutation_rate = 1;
78
79 for wrapper in &mut self.population.population {
80 wrapper.num_of_mutations = mutation_rate;
81 mutation_rate += 1;
82 }
83
84 self
85 }
86
87 /// Configures the mutation rates (number of mutation runs) for all the individuals in the
88 /// population: Instead of a linear growing mutation rate like in the
89 /// `increasing_mutation_rate` function above this sets an exponention mutation rate for
90 /// all the individuals. The first individual will mutate base^1 times, the second will
91 /// mutate base^2 times, and nth will mutate base^n times per iteration.
92 pub fn increasing_exp_mutation_rate(mut self, base: f64) -> PopulationBuilder<T> {
93 let mut mutation_rate = 1;
94
95 for wrapper in &mut self.population.population {
96 wrapper.num_of_mutations = base.powi(mutation_rate).floor() as u32;
97 mutation_rate += 1;
98 }
99
100 self
101 }
102
103 /// Configures the mutation rates (number of mutation runs) for all the individuals in the
104 /// population: This allows to specify an arbitrary mutation scheme for each individual.
105 /// The number of rates must be equal to the number of individuals.
106 pub fn mutation_rate(mut self, mutation_rate: Vec<u32>) -> PopulationBuilder<T> {
107 // TODO: better error handling
108 assert!(self.population.population.len() == mutation_rate.len());
109
110 for (individual, mutation_rate) in self.population
111 .population
112 .iter_mut()
113 .zip(mutation_rate.into_iter()) {
114 individual.num_of_mutations = mutation_rate;
115 }
116
117 self
118 }
119
120 /// Configures the reset limit for the population. If reset_limit_end is greater than zero
121 /// then a reset counter is increased each iteration. If that counter is greater than the
122 /// limit, all individuals will be resetted, the limit will be increased by 1000 and the
123 /// counter is set back to zero. Default value for reset_limit_start is 1000.
124 pub fn reset_limit_start(mut self, reset_limit_start: u32) -> PopulationBuilder<T> {
125 self.population.reset_limit_start = reset_limit_start;
126 self.population.reset_limit = reset_limit_start;
127 self
128 }
129
130 /// Configures the end value for the reset_limit. If the reset_limit >= reset_limit_end
131 /// then the reset_limit will be resetted to the start value reset_limit_start.
132 /// Default value for reset_limit_end is 100000.
133 /// If reset_limit_end == 0 then the reset limit feature will be disabled.
134 pub fn reset_limit_end(mut self, reset_limit_end: u32) -> PopulationBuilder<T> {
135 self.population.reset_limit_end = reset_limit_end;
136 self
137 }
138
139 /// Configure the increment for the reset_limit. If the reset_limit is reached, its value
140 /// is incrementet by the amount of reset_limit_increment.
141 pub fn reset_limit_increment(mut self, reset_limit_increment: u32) -> PopulationBuilder<T> {
142 self.population.reset_limit_increment = reset_limit_increment;
143 self
144 }
145
146 /// Set the population id. Currently this is only used for statistics.
147 pub fn set_id(mut self, id: u32) -> PopulationBuilder<T> {
148 for individual in &mut self.population.population {
149 individual.id = id;
150 }
151
152 self.population.id = id;
153 self
154 }
155
156 /// This checks the configuration of the simulation and returns an PopError or Ok if no PopErrors
157 /// where found.
158 pub fn finalize(self) -> Result<Population<T>> {
159 match self.population {
160 Population { num_of_individuals: 0...2, ..} => {
161 Err(ErrorKind::IndividualsTooLow.into())
162 }
163 Population { reset_limit_start: start,
164 reset_limit_end: end, ..} if (end > 0) && (start >= end) => {
165 Err(ErrorKind::LimitEndTooLow.into())
166 }
167 _ => Ok(self.population)
168 }
169 }
170}