radiate_core/objectives/
score.rs1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3use std::fmt::Debug;
4use std::hash::Hash;
5use std::iter::Sum;
6use std::ops::{Add, Div, Mul, Sub};
7use std::sync::Arc;
8
9pub trait Scored {
10 fn score(&self) -> Option<&Score>;
11}
12
13#[derive(Clone, PartialEq, Default)]
22#[repr(transparent)]
23pub struct Score {
24 pub values: Arc<[f32]>,
25}
26
27impl Score {
28 pub fn from_vec(values: Vec<f32>) -> Self {
29 for value in &values {
30 if value.is_nan() {
31 panic!("Score value cannot be NaN")
32 }
33 }
34
35 Score {
36 values: Arc::from(values),
37 }
38 }
39
40 pub fn as_f32(&self) -> f32 {
41 self.values.get(0).cloned().unwrap_or(f32::NAN)
42 }
43
44 pub fn as_i32(&self) -> i32 {
45 self.values[0] as i32
46 }
47
48 pub fn as_string(&self) -> String {
49 self.values[0].to_string()
50 }
51
52 pub fn as_usize(&self) -> usize {
53 self.values[0] as usize
54 }
55}
56
57impl AsRef<[f32]> for Score {
58 fn as_ref(&self) -> &[f32] {
59 &self.values
60 }
61}
62
63impl PartialOrd for Score {
64 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
65 self.values.partial_cmp(&other.values)
66 }
67}
68
69impl Debug for Score {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 write!(f, "{:?}", self.values)
72 }
73}
74
75impl Hash for Score {
76 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
77 let mut hash: usize = 0;
78
79 for value in self.values.iter() {
80 let value_hash = value.to_bits();
81 hash = hash.wrapping_add(value_hash as usize);
82 }
83
84 hash.hash(state);
85 }
86}
87
88impl From<f32> for Score {
89 fn from(value: f32) -> Self {
90 if value.is_nan() {
91 panic!("Score value cannot be NaN")
92 }
93
94 Score {
95 values: Arc::from(vec![value]),
96 }
97 }
98}
99
100impl From<i32> for Score {
101 fn from(value: i32) -> Self {
102 Score {
103 values: Arc::from(vec![value as f32]),
104 }
105 }
106}
107
108impl From<usize> for Score {
109 fn from(value: usize) -> Self {
110 Score {
111 values: Arc::from(vec![value as f32]),
112 }
113 }
114}
115
116impl From<String> for Score {
117 fn from(value: String) -> Self {
118 Score {
119 values: Arc::from(vec![
120 value.parse::<f32>().expect("Failed to parse string to f32"),
121 ]),
122 }
123 }
124}
125
126impl From<&str> for Score {
127 fn from(value: &str) -> Self {
128 Score {
129 values: Arc::from(vec![
130 value.parse::<f32>().expect("Failed to parse string to f32"),
131 ]),
132 }
133 }
134}
135
136impl From<Vec<f32>> for Score {
137 fn from(value: Vec<f32>) -> Self {
138 Score::from_vec(value)
139 }
140}
141
142impl From<Vec<i32>> for Score {
143 fn from(value: Vec<i32>) -> Self {
144 Score::from_vec(value.into_iter().map(|v| v as f32).collect())
145 }
146}
147
148impl From<Vec<usize>> for Score {
149 fn from(value: Vec<usize>) -> Self {
150 Score::from_vec(value.into_iter().map(|v| v as f32).collect())
151 }
152}
153
154impl From<Vec<String>> for Score {
155 fn from(value: Vec<String>) -> Self {
156 Score::from_vec(
157 value
158 .into_iter()
159 .map(|v| v.parse::<f32>().unwrap())
160 .collect(),
161 )
162 }
163}
164
165impl From<Vec<&str>> for Score {
166 fn from(value: Vec<&str>) -> Self {
167 Score::from_vec(
168 value
169 .into_iter()
170 .map(|v| v.parse::<f32>().unwrap())
171 .collect(),
172 )
173 }
174}
175
176impl Add for Score {
177 type Output = Self;
178
179 fn add(self, other: Self) -> Self {
180 if self.values.is_empty() {
181 return other;
182 }
183 let values = self
184 .values
185 .iter()
186 .zip(other.values.iter())
187 .map(|(a, b)| a + b)
188 .collect();
189
190 Score { values }
191 }
192}
193
194impl Add<f32> for Score {
195 type Output = Self;
196
197 fn add(self, other: f32) -> Self {
198 if self.values.is_empty() {
199 return Score::from(other);
200 }
201
202 let values = self.values.iter().map(|a| a + other).collect();
203
204 Score { values }
205 }
206}
207
208impl Sub for Score {
209 type Output = Self;
210
211 fn sub(self, other: Self) -> Self {
212 if self.values.is_empty() {
213 return other;
214 }
215
216 let values = self
217 .values
218 .iter()
219 .zip(other.values.iter())
220 .map(|(a, b)| a - b)
221 .collect();
222
223 Score { values }
224 }
225}
226
227impl Sub<f32> for Score {
228 type Output = Self;
229
230 fn sub(self, other: f32) -> Self {
231 if self.values.is_empty() {
232 return Score::from(-other);
233 }
234
235 let values = self.values.iter().map(|a| a - other).collect();
236
237 Score { values }
238 }
239}
240
241impl Mul for Score {
242 type Output = Self;
243
244 fn mul(self, other: Self) -> Self {
245 if self.values.is_empty() {
246 return other;
247 }
248
249 let values = self
250 .values
251 .iter()
252 .zip(other.values.iter())
253 .map(|(a, b)| a * b)
254 .collect();
255
256 Score { values }
257 }
258}
259
260impl Mul<f32> for Score {
261 type Output = Self;
262
263 fn mul(self, other: f32) -> Self {
264 if self.values.is_empty() {
265 return Score::from(other);
266 }
267
268 let values = self.values.iter().map(|a| a * other).collect();
269
270 Score { values }
271 }
272}
273
274impl Div for Score {
275 type Output = Self;
276
277 fn div(self, other: Self) -> Self {
278 if self.values.is_empty() {
279 return other;
280 }
281
282 let values = self
283 .values
284 .iter()
285 .zip(other.values.iter())
286 .map(|(a, b)| a / b)
287 .collect();
288
289 Score { values }
290 }
291}
292
293impl Div<f32> for Score {
294 type Output = Self;
295
296 fn div(self, other: f32) -> Self {
297 if self.values.is_empty() {
298 return Score::from(other);
299 }
300
301 let values = self.values.iter().map(|a| a / other).collect();
302
303 Score { values }
304 }
305}
306
307impl Sum for Score {
308 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
309 let mut values = vec![];
310
311 for score in iter {
312 for (i, value) in score.values.iter().enumerate() {
313 if values.len() <= i {
314 values.push(*value);
315 } else {
316 values[i] += value;
317 }
318 }
319 }
320
321 Score {
322 values: Arc::from(values),
323 }
324 }
325}
326
327impl<'a> Sum<&'a Score> for Score {
328 fn sum<I: Iterator<Item = &'a Score>>(iter: I) -> Self {
329 let mut values = vec![];
330
331 for score in iter {
332 for (i, value) in score.values.iter().enumerate() {
333 if values.len() <= i {
334 values.push(*value);
335 } else {
336 values[i] += value;
337 }
338 }
339 }
340
341 Score {
342 values: Arc::from(values),
343 }
344 }
345}
346
347#[cfg(feature = "serde")]
348impl Serialize for Score {
349 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
350 where
351 S: serde::Serializer,
352 {
353 self.values.as_ref().serialize(serializer)
354 }
355}
356
357#[cfg(feature = "serde")]
358impl<'de> Deserialize<'de> for Score {
359 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
360 where
361 D: serde::Deserializer<'de>,
362 {
363 let vec = Vec::<f32>::deserialize(deserializer)?;
364 for value in &vec {
365 if value.is_nan() {
366 return Err(serde::de::Error::custom("Score value cannot be NaN"));
367 }
368 }
369
370 Ok(Score {
371 values: Arc::from(vec),
372 })
373 }
374}
375
376#[cfg(test)]
377mod tests {
378 use super::*;
379
380 #[test]
381 fn test_score_from_vec() {
382 let score = Score::from(vec![1.0, 2.0, 3.0]);
383 assert_eq!(score.values.len(), 3);
384 }
385
386 #[test]
387 fn test_score_from_usize() {
388 let score = Score::from(3);
389 assert_eq!(score.values.len(), 1);
390 assert_eq!(score.as_f32(), 3.0);
391 assert_eq!(score.as_i32(), 3);
392 }
393
394 #[test]
395 fn test_score_from_f32() {
396 let score = Score::from(1.0);
397 assert_eq!(score.as_f32(), 1.0);
398 assert_eq!(score.as_i32(), 1)
399 }
400
401 #[test]
402 fn test_score_from_i32() {
403 let score = Score::from(-5);
404 assert_eq!(score.as_f32(), -5.0);
405 assert_eq!(score.as_i32(), -5);
406 }
407
408 #[test]
409 #[cfg(feature = "serde")]
410 fn test_score_can_serialize() {
411 let score = Score::from(vec![1.0, 2.0, 3.0]);
412 let serialized = serde_json::to_string(&score).expect("Failed to serialize Score");
413 let deserialized: Score =
414 serde_json::from_str(&serialized).expect("Failed to deserialize Score");
415 assert_eq!(score, deserialized);
416 }
417}