rsgenetic/sim/select/
max.rs

1// file: max.rs
2//
3// Copyright 2015-2017 The RsGenetic Developers
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// 	http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#![allow(deprecated)]
18
19use super::*;
20use pheno::{Fitness, Phenotype};
21
22/// Selects best performing phenotypes from the population.
23#[derive(Clone, Copy, Debug)]
24#[deprecated(
25    note = "The `MaximizeSelector` has bad performance due to sorting. For better performance with potentially different results, \
26                   use the `UnstableMaximizeSelector`.",
27    since = "1.7.7"
28)]
29pub struct MaximizeSelector {
30    count: usize,
31}
32
33impl MaximizeSelector {
34    /// Create and return a maximizing selector.
35    ///
36    /// Such a selector selects only the `count` best performing phenotypes
37    /// as parents.
38    ///
39    /// * `count`: must be larger than zero, a multiple of two and less than the population size.
40    pub fn new(count: usize) -> MaximizeSelector {
41        MaximizeSelector { count }
42    }
43}
44
45impl<T, F> Selector<T, F> for MaximizeSelector
46where
47    T: Phenotype<F>,
48    F: Fitness,
49{
50    fn select<'a>(&self, population: &'a [T]) -> Result<Parents<&'a T>, String> {
51        if self.count == 0 || self.count % 2 != 0 || self.count * 2 >= population.len() {
52            return Err(format!(
53                "Invalid parameter `count`: {}. Should be larger than zero, a \
54                 multiple of two and less than half the population size.",
55                self.count
56            ));
57        }
58
59        let mut borrowed: Vec<&T> = population.iter().collect();
60        borrowed.sort_by(|x, y| y.fitness().cmp(&x.fitness()));
61        let mut index = 0;
62        let mut result: Parents<&T> = Vec::new();
63        while index < self.count {
64            result.push((borrowed[index], borrowed[index + 1]));
65            index += 2;
66        }
67        Ok(result)
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use pheno::*;
74    use sim::select::*;
75    use test::Test;
76
77    #[test]
78    fn test_count_zero() {
79        let selector = MaximizeSelector::new(0);
80        let population: Vec<Test> = (0..100).map(|i| Test { f: i }).collect();
81        assert!(selector.select(&population).is_err());
82    }
83
84    #[test]
85    fn test_count_odd() {
86        let selector = MaximizeSelector::new(5);
87        let population: Vec<Test> = (0..100).map(|i| Test { f: i }).collect();
88        assert!(selector.select(&population).is_err());
89    }
90
91    #[test]
92    fn test_count_too_large() {
93        let selector = MaximizeSelector::new(100);
94        let population: Vec<Test> = (0..100).map(|i| Test { f: i }).collect();
95        assert!(selector.select(&population).is_err());
96    }
97
98    #[test]
99    fn test_result_size() {
100        let selector = MaximizeSelector::new(20);
101        let population: Vec<Test> = (0..100).map(|i| Test { f: i }).collect();
102        assert_eq!(20, selector.select(&population).unwrap().len() * 2);
103    }
104
105    #[test]
106    fn test_result_ok() {
107        let selector = MaximizeSelector::new(20);
108        let population: Vec<Test> = (0..100).map(|i| Test { f: i }).collect();
109        // The greatest fitness should be 99.
110        assert_eq!(selector.select(&population).unwrap()[0].0.fitness().f, 99);
111    }
112
113    #[test]
114    fn test_contains_best() {
115        let selector = MaximizeSelector::new(2);
116        let population: Vec<Test> = (0..100).map(|i| Test { f: i }).collect();
117        let parents = selector.select(&population).unwrap()[0];
118        assert_eq!(
119            parents.0.fitness(),
120            population
121                .iter()
122                .max_by_key(|x| x.fitness())
123                .unwrap()
124                .fitness()
125        );
126    }
127}