darwin_rs/simulation_builder.rs
1//! This module defines helper functions (builder pattern) to create a valid simulation.
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 simulation::{Simulation, SimulationType, SimulationResult};
19use individual::{Individual};
20use population::Population;
21
22/// This is a helper struct in order to build (configure) a valid simulation.
23/// See builder pattern: https://en.wikipedia.org/wiki/Builder_pattern
24///
25/// Maybe use phantom types, see https://github.com/willi-kappler/darwin-rs/issues/9
26pub struct SimulationBuilder<T: Individual + Send + Sync> {
27 /// The actual simulation.
28 simulation: Simulation<T>,
29}
30
31error_chain! {
32 errors {
33 EndIterationTooLow
34 }
35}
36
37/// This implementation contains all the helper method to build (configure) a valid simulation.
38impl<T: Individual + Send + Sync> SimulationBuilder<T> {
39 /// Start with this method, it must always be called as the first one.
40 /// It creates a default simulation with some dummy (but invalid) values.
41 pub fn new() -> SimulationBuilder<T> {
42 SimulationBuilder {
43 simulation: Simulation {
44 type_of_simulation: SimulationType::EndIteration(10),
45 num_of_threads: 2,
46 habitat: Vec::new(),
47 total_time_in_ms: 0.0,
48 simulation_result: SimulationResult {
49 improvement_factor: std::f64::MAX,
50 original_fitness: std::f64::MAX,
51 fittest: Vec::new(),
52 iteration_counter: 0
53 },
54 share_fittest: false,
55 num_of_global_fittest: 10,
56 output_every: 10,
57 output_every_counter: 0,
58 share_every: 10,
59 share_counter: 0
60 },
61 }
62 }
63
64 /// Set the total number of iterations for the simulation and thus sets the simulation
65 /// type to `EndIteration`. (Only usefull in combination with `EndIteration`).
66 pub fn iterations(mut self, iterations: u32) -> SimulationBuilder<T> {
67 self.simulation.type_of_simulation = SimulationType::EndIteration(iterations);
68 self
69 }
70
71 /// Set the improvement factor stop criteria for the simulation and thus sets the simulation
72 /// type to `EndFactor`. (Only usefull in combination with `EndFactor`).
73 pub fn factor(mut self, factor: f64) -> SimulationBuilder<T> {
74 self.simulation.type_of_simulation = SimulationType::EndFactor(factor);
75 self
76 }
77
78 /// Set the minimum fitness stop criteria for the simulation and thus sets the simulation
79 /// type to `EndFitness`. (Only usefull in combination with `EndFactor`).
80 pub fn fitness(mut self, fitness: f64) -> SimulationBuilder<T> {
81 self.simulation.type_of_simulation = SimulationType::EndFitness(fitness);
82 self
83 }
84
85 /// Sets the number of threads in order to speed up the simulation.
86 pub fn threads(mut self, threads: usize) -> SimulationBuilder<T> {
87 self.simulation.num_of_threads = threads;
88 self
89 }
90
91 /// Add a population to the simulation.
92 pub fn add_population(mut self, population: Population<T>) -> SimulationBuilder<T> {
93 self.simulation.habitat.push(population);
94 self
95 }
96
97 /// Add multiple populations to the simulation.
98 pub fn add_multiple_populations(mut self, multiple_populations: Vec<Population<T>>) -> SimulationBuilder<T> {
99 for population in multiple_populations {
100 self.simulation.habitat.push(population);
101 }
102 self
103 }
104
105 /// If this option is enabled (default: off), then the fittest individual of all populations
106 /// is shared between all populations.
107 pub fn share_fittest(mut self) -> SimulationBuilder<T> {
108 self.simulation.share_fittest = true;
109 self
110 }
111
112 /// How many global fittest should be kept ? (The size of the "high score list")
113 pub fn num_of_global_fittest(mut self, num_of_global_fittest: usize) -> SimulationBuilder<T> {
114 self.simulation.num_of_global_fittest = num_of_global_fittest;
115 self
116 }
117
118 /// Do not output every time a new individual is found, only every nth time.
119 /// n == output_every
120 pub fn output_every(mut self, output_every: u32) -> SimulationBuilder<T> {
121 self.simulation.output_every = output_every;
122 self
123 }
124
125 /// If share fittest is enabled and the number share_every of iteration has passed then
126 /// the fittest individual is shared between all populations
127 pub fn share_every(mut self, share_every: u32) -> SimulationBuilder<T> {
128 self.simulation.share_every = share_every;
129 self
130 }
131
132 /// This checks the configuration of the simulation and returns an error or Ok if no errors
133 /// where found.
134 pub fn finalize(self) -> Result<Simulation<T>> {
135 match self.simulation {
136 Simulation { type_of_simulation: SimulationType::EndIteration(0...9), .. } => {
137 Err(ErrorKind::EndIterationTooLow.into())
138 }
139 _ => Ok(self.simulation),
140 }
141 }
142}