1#![warn(missing_docs)]
2#![warn(missing_doc_code_examples)]
3
4use rand::Rng;
9use rand::seq::SliceRandom;
10
11pub mod functions;
12
13pub struct Settings {
28 pub population_size: u32,
30 pub number_of_generations: u32,
32 pub crossover_probability: f64,
34 pub mutation_probability: f64,
36 pub verbose: bool,
38 pub elitism: bool,
40 pub elitism_fraction: f64,
42 pub maximize_fitness: bool,
44 pub number_of_dimensions: u32,
46 pub upper_bound: Vec<f64>,
48 pub lower_bound: Vec<f64>,
50 pub fitness_function: Box<dyn FnMut(Vec<f64>) -> f64>,
52}
53
54impl Default for Settings {
56 fn default() -> Self {
57 Self {
58 fitness_function: Box::new(crate::functions::summation),
59 population_size: 100,
60 number_of_generations: 100,
61 crossover_probability: 0.8,
62 mutation_probability: 0.1,
63 verbose: true,
64 elitism: true,
65 elitism_fraction: 0.2,
66 maximize_fitness: true,
67 number_of_dimensions: 2,
68 upper_bound: vec![ 1.0, 1.0],
69 lower_bound: vec![-1.0, -1.0],
70 }
71 }
72}
73
74impl Settings {
75 pub fn set_fitness_function<F: 'static + FnMut(Vec<f64>) -> f64>(&mut self, f: F) {
100 self.fitness_function = Box::new(f);
101 }
102}
103
104
105pub struct Optimizer {
116 settings: Settings,
117 current_population: Population,
118 new_population: Population,
119 best_fitness: f64,
120 best_representation: Vec<f64>
121}
122
123impl Optimizer {
124
125 pub fn new(mut settings: Settings) -> Self {
127 Self {
128 current_population: Population::new(&mut settings),
129 new_population: Population::empty(),
130 settings: settings,
131 best_fitness: -f64::INFINITY,
132 best_representation: vec![]
133 }
134 }
135
136 pub fn solve(&mut self) {
138 for _ in 0..self.settings.number_of_generations {
139 self.iterate();
140 }
141 }
142
143 pub fn report(&self) {
145 println!("{}", self.best_fitness);
146 }
147
148 fn check_bounds(&self, x: Individual) -> bool {
149 let mut state = true;
150 for i in 0..self.settings.number_of_dimensions as usize{
151 if x.representation[i] < self.settings.lower_bound[i] ||
152 x.representation[i] > self.settings.upper_bound[i] {
153 state = false;
154 }
155 }
156 state
157 }
158
159 fn iterate(&mut self) {
160 self.implement_elitism();
162
163 self.implement_crossover();
165
166 self.implement_mutation();
168
169 self.fill_population();
171
172 self.current_population = self.new_population.copy();
174 if self.current_population.get_best() > self.best_fitness {
175 self.best_fitness = self.current_population.get_best();
176 }
177
178 self.current_population.sort();
180 self.new_population = Population::empty();
181 self.report();
182 }
183
184 fn implement_elitism(&mut self) {
185 if self.settings.elitism {
187 let number_of_elites: f64 = self.settings.elitism_fraction * self.settings.population_size as f64;
188 for i in (self.settings.population_size as usize - number_of_elites as usize)..self.settings.population_size as usize{
189 self.new_population.individuals.push(self.current_population.individuals[i].clone())
190 }
191 }
192 }
193
194 fn implement_crossover(&mut self) {
195 let number_of_crosses: f64 = self.settings.crossover_probability * self.settings.population_size as f64;
196 for i in (self.settings.population_size as usize - number_of_crosses as usize)..self.settings.population_size as usize{
197 let thingone = self.current_population.get_random();
198 let thingtwo = self.current_population.get_random();
199 self.new_population.individuals.push(thingone.cross(thingtwo))
200 }
201 }
202
203 fn implement_mutation(&mut self) {
204 for i in 0..self.settings.population_size as usize {
205 let mut rng = rand::thread_rng();
206 if rng.gen::<f64>() < self.settings.mutation_probability {
207 self.new_population.individuals.push(self.current_population.individuals[i].mutate())
208 }
209 }
210 }
211
212 fn fill_population(&mut self) {
213 while self.new_population.individuals.len() < self.settings.population_size as usize {
214 self.new_population.individuals.push(Individual::new(&mut self.settings));
215 }
216 }
217}
218
219
220struct Population {
224 individuals: Vec<Individual>,
225}
226
227impl Population {
228 fn new(mut settings: &mut Settings) -> Self {
229 let mut pop = vec![];
230 for _ in 0..settings.population_size {
231 pop.push(Individual::new(&mut settings))
232 }
233 Self {
234 individuals: pop,
235 }
236 }
237
238 fn empty() -> Self {
239 Self {
240 individuals: vec![],
241 }
242 }
243
244 fn copy(&self) -> Self {
245 let mut pop = Population::empty();
246 for indi in &self.individuals {
247 pop.individuals.push((*indi).clone());
248 }
249 pop
250 }
251
252 fn get_best(&self) -> f64 {
253 let mut best_fitness = -f64::INFINITY;
254 for i in 0..(*self).individuals.len() {
255 if self.individuals[i].fitness > best_fitness {
256 best_fitness = self.individuals[i].fitness;
257 }
258 }
259 best_fitness
260 }
261
262 fn get_mean(&self) {
263
264 }
265
266 fn get_std(&self) {
267
268 }
269
270 fn get_random(&mut self) -> Individual {
271 let option = self.individuals.choose_mut(&mut rand::thread_rng());
272 match option {
273 Some(x) => (*x).clone(),
274 None => self.individuals[self.individuals.len()-1].clone()
275 }
276
277 }
278
279 fn sort(&mut self) {
280 self.individuals.sort_unstable_by(|x, y| x.fitness.partial_cmp(&y.fitness).unwrap());
281 }
282}
283
284
285#[cfg(test)]
286mod population_tests {
287 use super::*;
288
289 #[test]
290 fn basic_inst() {
291 let x = Population::new(&mut Settings::default());
292 }
293
294 #[test]
295 fn empty_inst() {
296 let x = Population::empty();
297 }
298
299 #[test]
300 fn sort_check() {
301 let mut x = Population::new(&mut Settings::default());
302 x.sort();
303 }
304
305 #[test]
306 fn stat_check() {
307 let x = Population::new(&mut Settings::default());
308 x.get_best();
309 x.get_mean();
310 x.get_std();
311 }
312}
313
314pub struct Individual {
316 representation: Vec<f64>,
317 fitness: f64,
318}
319
320impl Individual {
321 fn new(sets: &mut crate::Settings) -> Self {
323 let mut rng = rand::thread_rng();
324 let mut v: Vec<f64> = vec![];
325 for i in 0..sets.number_of_dimensions as usize {
326 v.push(rng.gen_range(sets.lower_bound[i], sets.upper_bound[i]));
327 }
328 Self {
329 representation: v.clone(),
330 fitness: (sets.fitness_function)(v.clone())
331 }
332 }
333
334 fn clone(&self) -> Self {
336 Self {
337 representation: self.representation.clone(),
338 fitness: self.fitness,
339 }
340 }
341
342 fn mutate(&self) -> Self {
344 self.clone()
345 }
346
347 fn cross(&self, other_individual: Self) -> Self {
349 let mut v = vec![];
350 let mut rng = rand::thread_rng();
351 for i in 0..self.representation.len() {
352 if rng.gen::<f64>() < 0.5 {
353 v.push(self.representation[i])
354 } else {
355 v.push(other_individual.representation[i])
356 }
357 }
358
359 Self {
360 representation: v,
361 fitness: 0.0
362 }
363
364 }
365}
366
367
368#[cfg(test)]
369mod individual_tests {
370 use super::*;
371
372 #[test]
373 fn basic_inst() {
374 let x = Individual {
375 representation: vec![0.0, 0.0],
376 fitness: 0.0
377 };
378 }
379
380 #[test]
381 fn settings_inst() {
382 let x = Individual::new(&mut crate::Settings::default());
383 }
384
385 #[test]
386 fn clone_check() {
387 let x = Individual::new(&mut crate::Settings::default());
388 let y = x.clone();
389 }
390
391 #[test]
392 fn mutate_check() {
393 let x = Individual::new(&mut crate::Settings::default());
394 let y = x.mutate();
395 }
396}