spdkit/
lib.rs

1// [[file:../spdkit.note::*header][header:1]]
2//===============================================================================#
3//   DESCRIPTION:  spdkit: Structure Predication Development Kit
4//
5//       OPTIONS:  ---
6//  REQUIREMENTS:  ---
7//         NOTES:  rewrite my python codes using rust
8//        AUTHOR:  Wenping Guo <ybyygu@gmail.com>
9//       LICENCE:  GPL version 2 or upper
10//       CREATED:  <2018-06-14 Thu 20:52>
11//       UPDATED:  <2022-06-14 Tue 10:56>
12//===============================================================================#
13// header:1 ends here
14
15// [[file:../spdkit.note::3ac79127][3ac79127]]
16use gut::prelude::*;
17
18// FIXME: remove?
19
20#[macro_use]
21extern crate lazy_static;
22
23pub mod common {
24    pub use gut::prelude::*;
25
26    // Arbitrarily decide the order of NaNs
27    macro_rules! local_float_cmp {
28        ($fi:ident, $fj:ident) => {
29            match ($fi.is_nan(), $fj.is_nan()) {
30                (true, false) => std::cmp::Ordering::Greater,
31                (false, true) => std::cmp::Ordering::Less,
32                (true, true) => std::cmp::Ordering::Equal,
33                (false, false) => unreachable!(),
34            }
35        };
36    }
37
38    // https://stackoverflow.com/questions/43921436/extend-iterator-with-a-mean-method
39    pub trait FloatIteratorExt
40    where
41        Self: std::marker::Sized,
42    {
43        fn fmax(mut self) -> Option<f64> {
44            todo!()
45        }
46        fn fmin(mut self) -> Option<f64> {
47            todo!()
48        }
49        fn imax(mut self) -> Option<(usize, f64)> {
50            todo!()
51        }
52        fn imin(mut self) -> Option<(usize, f64)> {
53            todo!()
54        }
55    }
56
57    impl<F, T> FloatIteratorExt for T
58    where
59        T: Iterator<Item = F>,
60        F: std::borrow::Borrow<f64>,
61        Self: std::marker::Sized,
62    {
63        /// Returns the minimum element of an iterator. Return None if the
64        /// iterator is empty.
65        fn fmax(mut self) -> Option<f64> {
66            if let Some(value) = self.next() {
67                let f = self.fold(*value.borrow(), |a, b| a.max(*b.borrow()));
68                Some(f)
69            } else {
70                None
71            }
72        }
73
74        fn fmin(mut self) -> Option<f64> {
75            if let Some(value) = self.next() {
76                let f = self.fold(*value.borrow(), |a, b| a.min(*b.borrow()));
77                Some(f)
78            } else {
79                None
80            }
81        }
82
83        /// Find maximum value and the corresponding index. Return None if the
84        /// iterator is empty.
85        fn imax(mut self) -> Option<(usize, f64)> {
86            if let Some(value) = self.next() {
87                let value = *value.borrow();
88                let value = (1..).zip(self).fold((0, value), |a, b| {
89                    let (ia, fa) = a;
90                    let (ib, fb) = b;
91                    let fb = *fb.borrow();
92
93                    if fb > fa {
94                        (ib, fb)
95                    } else {
96                        (ia, fa)
97                    }
98                });
99                Some(value)
100            } else {
101                None
102            }
103        }
104
105        /// Find minimum value and the corresponding index. Return None if the
106        /// iterator is empty.
107        fn imin(mut self) -> Option<(usize, f64)> {
108            if let Some(value) = self.next() {
109                let value = *value.borrow();
110                let value = (1..).zip(self).fold((0, value), |a, b| {
111                    let (ia, fa) = a;
112                    let (ib, fb) = b;
113                    let fb = *fb.borrow();
114
115                    if fb < fa {
116                        (ib, fb)
117                    } else {
118                        (ia, fa)
119                    }
120                });
121                Some(value)
122            } else {
123                None
124            }
125        }
126    }
127
128    /// For sort values in maximum first order.
129    pub fn float_ordering_maximize(fi: &f64, fj: &f64) -> std::cmp::Ordering {
130        fj.partial_cmp(&fi).unwrap_or_else(|| local_float_cmp!(fi, fj))
131    }
132
133    /// For sort values in minimum first order.
134    pub fn float_ordering_minimize(fi: &f64, fj: &f64) -> std::cmp::Ordering {
135        fi.partial_cmp(&fj).unwrap_or_else(|| local_float_cmp!(fi, fj))
136    }
137
138    #[test]
139    fn test_float_ordering() {
140        let mut values = vec![1.0, -1.0, std::f64::NAN, 0.5, 2.0];
141        let m = values.iter().fmax();
142        assert_eq!(m, Some(2.0));
143
144        let m = values.iter().fmin();
145        assert_eq!(m, Some(-1.0));
146
147        let m = values.iter().imax();
148        assert_eq!(m, Some((4, 2.0)));
149
150        let m = values.iter().imin();
151        assert_eq!(m, Some((1, -1.0)));
152
153        values.sort_by(|a, b| float_ordering_maximize(&a, &b));
154        assert_eq!(values[0], 2.0);
155        assert!(values[4].is_nan());
156
157        values.sort_by(|a, b| float_ordering_minimize(&a, &b));
158        assert_eq!(values[0], -1.0);
159        assert!(values[4].is_nan());
160    }
161}
162// 3ac79127 ends here
163
164// [[file:../spdkit.note::1e9e2348][1e9e2348]]
165#[macro_use]
166pub mod random; // the mod order is important for get_rng! macro
167
168pub mod encoding;
169pub mod engine;
170pub mod fitness;
171pub mod gears;
172pub mod individual;
173pub mod operators;
174pub mod population;
175pub mod termination;
176
177mod annealing;
178mod fingerprint;
179mod graph6;
180mod vars;
181// 1e9e2348 ends here
182
183// [[file:../spdkit.note::4ccc7fd1][4ccc7fd1]]
184pub mod prelude {
185    pub use crate::engine::Evolve;
186    pub use crate::fitness::EvaluateFitness;
187    pub use crate::gears::Breed;
188    pub use crate::gears::Survive;
189    pub use crate::individual::EvaluateObjectiveValue;
190    pub use crate::operators::*;
191    pub use crate::population::SortMember;
192    pub use crate::random::*;
193
194    pub use crate::encoding::Mutate;
195    pub use crate::fingerprint::FingerPrintExt;
196}
197// 4ccc7fd1 ends here
198
199// [[file:../spdkit.note::*exports][exports:1]]
200pub use crate::engine::{Engine, EvolutionAlgorithm};
201pub use crate::gears::GeneticBreeder;
202pub use crate::gears::Survivor;
203pub use crate::gears::Valuer;
204pub use crate::individual::{Genome, Individual};
205pub use crate::population::Population;
206// exports:1 ends here