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}