Skip to main content

radiate_core/objectives/
score.rs

1use radiate_error::RadiateError;
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4use std::fmt::Debug;
5use std::hash::Hash;
6use std::iter::Sum;
7use std::ops::{Add, Div, Index, Mul, Sub};
8use std::sync::Arc;
9
10/// A trait for types that can be scored.
11/// We can use this for a common interface for all scored types.
12pub trait Scored {
13    fn score(&self) -> Option<&Score>;
14}
15
16/// A [Score] is a value that can be used to compare the fitness of two individuals and represents
17/// the 'fitness' of an individual within the genetic algorithm.
18/// The [Score] can be a single value or multiple values, depending on the problem being solved.
19/// For ease of use the [Score] struct provides methods
20/// to convert the score to a single value, an integer, a string, or a vector of `f32` values.
21///
22/// Note: The reason it is a Vec is for multi-objective optimization problems. This allows for multiple
23/// fitness values to be returned from the fitness function.
24#[derive(Clone, PartialEq, Default)]
25#[repr(transparent)]
26pub struct Score {
27    values: Arc<[f32]>,
28}
29
30impl Score {
31    pub fn from_vec(values: Vec<f32>) -> Self {
32        Score {
33            values: Arc::from(values),
34        }
35    }
36
37    pub fn is_multi_objective(&self) -> bool {
38        self.values.len() > 1
39    }
40
41    pub fn is_single_objective(&self) -> bool {
42        self.values.len() == 1
43    }
44
45    pub fn objective(&self, idx: usize) -> Option<&f32> {
46        self.values.get(idx)
47    }
48
49    #[inline]
50    pub fn first(&self) -> Option<f32> {
51        self.values.first().cloned()
52    }
53
54    pub fn as_slice(&self) -> &[f32] {
55        &self.values
56    }
57
58    pub fn as_f32(&self) -> f32 {
59        self.values.first().cloned().unwrap_or(f32::NAN)
60    }
61
62    pub fn as_f64(&self) -> f64 {
63        self.values.first().cloned().unwrap_or(f32::NAN) as f64
64    }
65
66    pub fn as_i32(&self) -> i32 {
67        self.values[0] as i32
68    }
69
70    pub fn as_string(&self) -> String {
71        self.values[0].to_string()
72    }
73
74    pub fn as_usize(&self) -> usize {
75        self.values[0] as usize
76    }
77
78    pub fn iter(&self) -> impl Iterator<Item = &f32> + '_ {
79        self.values.iter()
80    }
81
82    pub fn len(&self) -> usize {
83        self.values.len()
84    }
85
86    pub fn is_empty(&self) -> bool {
87        self.values.is_empty()
88    }
89}
90
91impl AsRef<[f32]> for Score {
92    fn as_ref(&self) -> &[f32] {
93        &self.values
94    }
95}
96
97impl PartialOrd for Score {
98    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
99        self.values.partial_cmp(&other.values)
100    }
101}
102
103impl Debug for Score {
104    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        write!(f, "{:?}", self.values)
106    }
107}
108
109impl Hash for Score {
110    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
111        let mut hash: usize = 0;
112
113        for value in self.values.iter() {
114            let value_hash = value.to_bits();
115            hash = hash.wrapping_add(value_hash as usize);
116        }
117
118        hash.hash(state);
119    }
120}
121
122impl Index<usize> for Score {
123    type Output = f32;
124    fn index(&self, index: usize) -> &Self::Output {
125        &self.values[index]
126    }
127}
128
129impl From<Score> for Vec<f32> {
130    fn from(score: Score) -> Vec<f32> {
131        score.values.to_vec()
132    }
133}
134
135impl From<f32> for Score {
136    fn from(value: f32) -> Self {
137        Score {
138            values: Arc::from(vec![value]),
139        }
140    }
141}
142
143impl TryFrom<i16> for Score {
144    type Error = RadiateError;
145
146    fn try_from(value: i16) -> Result<Self, Self::Error> {
147        Ok(Score {
148            values: Arc::from(vec![value as f32]),
149        })
150    }
151}
152
153impl From<f64> for Score {
154    fn from(value: f64) -> Self {
155        Score {
156            values: Arc::from(vec![value as f32]),
157        }
158    }
159}
160
161impl From<i32> for Score {
162    fn from(value: i32) -> Self {
163        Score {
164            values: Arc::from(vec![value as f32]),
165        }
166    }
167}
168
169impl From<i64> for Score {
170    fn from(value: i64) -> Self {
171        Score {
172            values: Arc::from(vec![value as f32]),
173        }
174    }
175}
176
177impl From<usize> for Score {
178    fn from(value: usize) -> Self {
179        Score {
180            values: Arc::from(vec![value as f32]),
181        }
182    }
183}
184
185impl From<String> for Score {
186    fn from(value: String) -> Self {
187        Score {
188            values: Arc::from(vec![
189                value.parse::<f32>().expect("Failed to parse string to f32"),
190            ]),
191        }
192    }
193}
194
195impl From<&str> for Score {
196    fn from(value: &str) -> Self {
197        Score {
198            values: Arc::from(vec![
199                value.parse::<f32>().expect("Failed to parse string to f32"),
200            ]),
201        }
202    }
203}
204
205impl From<Vec<f32>> for Score {
206    fn from(value: Vec<f32>) -> Self {
207        Score::from_vec(value)
208    }
209}
210
211impl From<Vec<f64>> for Score {
212    fn from(value: Vec<f64>) -> Self {
213        Score::from_vec(value.into_iter().map(|v| v as f32).collect())
214    }
215}
216
217impl From<Vec<i32>> for Score {
218    fn from(value: Vec<i32>) -> Self {
219        Score::from_vec(value.into_iter().map(|v| v as f32).collect())
220    }
221}
222
223impl From<Vec<i64>> for Score {
224    fn from(value: Vec<i64>) -> Self {
225        Score::from_vec(value.into_iter().map(|v| v as f32).collect())
226    }
227}
228
229impl From<Vec<usize>> for Score {
230    fn from(value: Vec<usize>) -> Self {
231        Score::from_vec(value.into_iter().map(|v| v as f32).collect())
232    }
233}
234
235impl From<Vec<String>> for Score {
236    fn from(value: Vec<String>) -> Self {
237        Score::from_vec(
238            value
239                .into_iter()
240                .map(|v| v.parse::<f32>().unwrap())
241                .collect(),
242        )
243    }
244}
245
246impl From<Vec<&str>> for Score {
247    fn from(value: Vec<&str>) -> Self {
248        Score::from_vec(
249            value
250                .into_iter()
251                .map(|v| v.parse::<f32>().unwrap())
252                .collect(),
253        )
254    }
255}
256
257impl Add for Score {
258    type Output = Self;
259
260    fn add(self, other: Self) -> Self {
261        if self.values.is_empty() {
262            return other;
263        }
264
265        let mut values = Vec::with_capacity(self.values.len());
266
267        for i in 0..self.values.len() {
268            values.push(self.values[i] + other.values[i]);
269        }
270
271        Score {
272            values: Arc::from(values),
273        }
274    }
275}
276
277impl Add<f32> for Score {
278    type Output = Self;
279
280    fn add(self, other: f32) -> Self {
281        if self.values.is_empty() {
282            return Score::from(other);
283        }
284
285        let mut values = Vec::with_capacity(self.values.len());
286        for i in 0..self.values.len() {
287            values.push(self.values[i] + other);
288        }
289
290        Score {
291            values: values.into(),
292        }
293    }
294}
295
296impl Sub for Score {
297    type Output = Self;
298
299    fn sub(self, other: Self) -> Self {
300        if self.values.is_empty() {
301            return other;
302        }
303
304        let mut values = Vec::with_capacity(self.values.len());
305
306        for i in 0..self.values.len() {
307            values.push(self.values[i] - other.values[i]);
308        }
309
310        Score {
311            values: Arc::from(values),
312        }
313    }
314}
315
316impl Sub<f32> for Score {
317    type Output = Self;
318
319    fn sub(self, other: f32) -> Self {
320        if self.values.is_empty() {
321            return Score::from(-other);
322        }
323
324        let mut values = Vec::with_capacity(self.values.len());
325        for i in 0..self.values.len() {
326            values.push(self.values[i] - other);
327        }
328
329        Score {
330            values: Arc::from(values),
331        }
332    }
333}
334
335impl Mul for Score {
336    type Output = Self;
337
338    fn mul(self, other: Self) -> Self {
339        if self.values.is_empty() {
340            return other;
341        }
342
343        let mut values = Vec::with_capacity(self.values.len());
344        for i in 0..self.values.len() {
345            values.push(self.values[i] * other.values[i]);
346        }
347
348        Score {
349            values: Arc::from(values),
350        }
351    }
352}
353
354impl Mul<f32> for Score {
355    type Output = Self;
356
357    fn mul(self, other: f32) -> Self {
358        if self.values.is_empty() {
359            return Score::from(other);
360        }
361
362        let mut values = Vec::with_capacity(self.values.len());
363        for i in 0..self.values.len() {
364            values.push(self.values[i] * other);
365        }
366
367        Score {
368            values: Arc::from(values),
369        }
370    }
371}
372
373impl Mul<Score> for f32 {
374    type Output = Score;
375
376    fn mul(self, other: Score) -> Score {
377        if other.values.is_empty() {
378            return Score::from(self);
379        }
380
381        let mut values = Vec::with_capacity(other.values.len());
382        for i in 0..other.values.len() {
383            values.push(other.values[i] * self);
384        }
385
386        Score {
387            values: Arc::from(values),
388        }
389    }
390}
391
392impl Div for Score {
393    type Output = Self;
394
395    fn div(self, other: Self) -> Self {
396        if self.values.is_empty() {
397            return other;
398        }
399
400        let mut values = Vec::with_capacity(self.values.len());
401        for i in 0..self.values.len() {
402            values.push(self.values[i] / other.values[i]);
403        }
404
405        Score {
406            values: Arc::from(values),
407        }
408    }
409}
410
411impl Div<f32> for Score {
412    type Output = Self;
413
414    fn div(self, other: f32) -> Self {
415        if self.values.is_empty() {
416            return Score::from(other);
417        }
418
419        let mut values = Vec::with_capacity(self.values.len());
420        for i in 0..self.values.len() {
421            values.push(self.values[i] / other);
422        }
423
424        Score {
425            values: Arc::from(values),
426        }
427    }
428}
429
430impl Sum for Score {
431    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
432        let mut values = vec![];
433
434        for score in iter {
435            for (i, value) in score.values.iter().enumerate() {
436                if values.len() <= i {
437                    values.push(*value);
438                } else {
439                    values[i] += value;
440                }
441            }
442        }
443
444        Score {
445            values: Arc::from(values),
446        }
447    }
448}
449
450impl<'a> Sum<&'a Score> for Score {
451    fn sum<I: Iterator<Item = &'a Score>>(iter: I) -> Self {
452        let mut values = vec![];
453
454        for score in iter {
455            for (i, value) in score.values.iter().enumerate() {
456                if values.len() <= i {
457                    values.push(*value);
458                } else {
459                    values[i] += value;
460                }
461            }
462        }
463
464        Score {
465            values: Arc::from(values),
466        }
467    }
468}
469
470#[cfg(feature = "serde")]
471impl Serialize for Score {
472    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
473    where
474        S: serde::Serializer,
475    {
476        self.values.as_ref().serialize(serializer)
477    }
478}
479
480#[cfg(feature = "serde")]
481impl<'de> Deserialize<'de> for Score {
482    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
483    where
484        D: serde::Deserializer<'de>,
485    {
486        let vec = Vec::<f32>::deserialize(deserializer)?;
487        for value in &vec {
488            if value.is_nan() {
489                return Err(serde::de::Error::custom("Score value cannot be NaN"));
490            }
491        }
492
493        Ok(Score {
494            values: Arc::from(vec),
495        })
496    }
497}
498
499#[cfg(test)]
500mod tests {
501    use super::*;
502
503    #[test]
504    fn test_score_from_vec() {
505        let score = Score::from(vec![1.0, 2.0, 3.0]);
506        assert_eq!(score.values.len(), 3);
507    }
508
509    #[test]
510    fn test_score_from_usize() {
511        let score = Score::from(3);
512        assert_eq!(score.values.len(), 1);
513        assert_eq!(score.as_f32(), 3.0);
514        assert_eq!(score.as_i32(), 3);
515    }
516
517    #[test]
518    fn test_score_from_f32() {
519        let score = Score::from(1.0);
520        assert_eq!(score.as_f32(), 1.0);
521        assert_eq!(score.as_i32(), 1)
522    }
523
524    #[test]
525    fn test_score_from_i32() {
526        let score = Score::from(-5);
527        assert_eq!(score.as_f32(), -5.0);
528        assert_eq!(score.as_i32(), -5);
529    }
530
531    #[test]
532    fn test_score_add() {
533        let score1 = Score::from(vec![1.0, 2.0, 3.0]);
534        let score2 = Score::from(vec![4.0, 5.0, 6.0]);
535        let score3 = score1 + score2;
536
537        assert_eq!(score3.values.len(), 3);
538        assert_eq!(score3.as_f32(), 5.0);
539        assert_eq!(score3[0], 5.0);
540        assert_eq!(score3[1], 7.0);
541        assert_eq!(score3[2], 9.0);
542    }
543
544    #[test]
545    fn test_score_sub() {
546        let score1 = Score::from(vec![5.0, 7.0, 9.0]);
547        let score2 = Score::from(vec![4.0, 5.0, 6.0]);
548        let score3 = score1 - score2;
549        assert_eq!(score3.values.len(), 3);
550        assert_eq!(score3.as_f32(), 1.0);
551        assert_eq!(score3[0], 1.0);
552        assert_eq!(score3[1], 2.0);
553        assert_eq!(score3[2], 3.0);
554    }
555
556    #[test]
557    fn test_score_mul() {
558        let score1 = Score::from(vec![1.0, 2.0, 3.0]);
559        let score2 = Score::from(vec![4.0, 5.0, 6.0]);
560        let score3 = score1 * score2;
561        assert_eq!(score3.values.len(), 3);
562        assert_eq!(score3.as_f32(), 4.0);
563        assert_eq!(score3[0], 4.0);
564        assert_eq!(score3[1], 10.0);
565        assert_eq!(score3[2], 18.0);
566    }
567
568    #[test]
569    fn test_score_div() {
570        let score1 = Score::from(vec![4.0, 8.0, 12.0]);
571        let score2 = Score::from(vec![2.0, 4.0, 6.0]);
572        let score3 = score1 / score2;
573        assert_eq!(score3.values.len(), 3);
574        assert_eq!(score3.as_f32(), 2.0);
575        assert_eq!(score3[0], 2.0);
576        assert_eq!(score3[1], 2.0);
577        assert_eq!(score3[2], 2.0);
578    }
579
580    #[test]
581    #[cfg(feature = "serde")]
582    fn test_score_can_serialize() {
583        let score = Score::from(vec![1.0, 2.0, 3.0]);
584        let serialized = serde_json::to_string(&score).expect("Failed to serialize Score");
585        let deserialized: Score =
586            serde_json::from_str(&serialized).expect("Failed to deserialize Score");
587        assert_eq!(score, deserialized);
588    }
589}