genetic_algorithm_fn/
function.rs

1use std::fmt;
2/// Custom error that can occur with the Function class defined below.
3#[derive(Debug, PartialEq)]
4pub enum FunctionError {
5    /// The Function could not compute the function value because the
6    /// Vector provided does not have the right number of arguments.
7    WrongNumberOfEntries {
8        /// Expected number of arguments.
9        expected_number_of_entries: usize,
10        /// Actual number of arguments.
11        actual_number_of_entries: usize,
12    },
13}
14impl fmt::Display for FunctionError {
15    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16        match self {
17            FunctionError::WrongNumberOfEntries {
18                expected_number_of_entries,
19                actual_number_of_entries,
20            } => write!(
21                f,
22                "Expected {} entries, but got {}",
23                expected_number_of_entries, actual_number_of_entries
24            ),
25        }
26    }
27}
28
29/// A representation of a f64 based distance matrix.
30#[derive(Debug)]
31pub struct Function {
32    fun: fn(Vec<f64>) -> Result<f64, FunctionError>,
33}
34
35impl Function {
36    /// Create a new function.
37    ///
38    /// # Arguments
39    ///
40    /// * `fun` - The function that should be computed in this struct.
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use genetic_algorithm_fn::function;
46    ///
47    /// let function_to_optimize = function::Function::new(
48    ///     |x| match x.len() {
49    ///         3 => Ok(x[0] * x[1] * x[2]),
50    ///         _ => Err(function::FunctionError::WrongNumberOfEntries {
51    ///             actual_number_of_entries: x.len(),
52    ///             expected_number_of_entries: 3,
53    ///         }),
54    ///     }
55    /// );
56    ///
57    /// ```
58    pub fn new(fun: fn(Vec<f64>) -> Result<f64, FunctionError>) -> Self {
59        Function { fun }
60    }
61    /// Compute the function value for a Solution.
62    ///
63    /// # Arguments
64    ///
65    /// * `solution` - The solution for which the function value should be computed.
66    ///
67    /// # Examples
68    ///
69    /// ```
70    /// use genetic_algorithm_fn::function;
71    ///
72    /// let function_to_optimize = function::Function::new(
73    ///     |x| match x.len() {
74    ///         3 => Ok(x[0] * x[1] * x[2]),
75    ///         _ => Err(function::FunctionError::WrongNumberOfEntries {
76    ///             actual_number_of_entries: x.len(),
77    ///             expected_number_of_entries: 3,
78    ///         }),
79    ///     }
80    /// );
81    /// println!("{}", function_to_optimize.get_function_value(vec![3.0, 4.0, 5.0]).unwrap());
82    ///
83    /// ```
84    pub fn get_function_value(&self, function_values: Vec<f64>) -> Result<f64, FunctionError> {
85        (self.fun)(function_values)
86    }
87}
88
89#[cfg(test)]
90mod test_distance_mat {
91    use super::*;
92    use crate::test_objects;
93    #[test]
94    fn test_constructor() {
95        let _ = Function::new(|x| match x.len() {
96            3 => Ok(x[0] * x[1] * x[2]),
97            _ => Err(FunctionError::WrongNumberOfEntries {
98                actual_number_of_entries: x.len(),
99                expected_number_of_entries: 3,
100            }),
101        });
102    }
103    #[test]
104    fn test_simple_computation() {
105        let my_func = Function::new(test_objects::triple_multiplication());
106
107        assert_eq!(my_func.get_function_value(vec![1.0, 2.0, 3.0]), Ok(6.0));
108    }
109    #[test]
110    fn test_simple_computation_wrong_arguments() {
111        let my_func = Function::new(test_objects::triple_multiplication());
112        assert_eq!(
113            my_func.get_function_value(vec![1.0, 2.0]),
114            Err(FunctionError::WrongNumberOfEntries {
115                expected_number_of_entries: 3,
116                actual_number_of_entries: 2
117            })
118        );
119    }
120}