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
10pub trait Scored {
13 fn score(&self) -> Option<&Score>;
14}
15
16#[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}