big_brain/
measures.rs

1//! * A series of
2//!   [Measures](https://en.wikipedia.org/wiki/Measure_(mathematics)) used to
3//!  * weight score.
4
5use bevy::prelude::*;
6
7use crate::prelude::Score;
8
9/// A Measure trait describes a way to combine scores together.
10#[reflect_trait]
11pub trait Measure: std::fmt::Debug + Sync + Send {
12    /// Calculates a score from the child scores
13    fn calculate(&self, inputs: Vec<(&Score, f32)>) -> f32;
14}
15
16/// A measure that adds all the elements together and multiplies them by the
17/// weight.
18#[derive(Debug, Clone, Reflect)]
19pub struct WeightedSum;
20
21impl Measure for WeightedSum {
22    fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
23        scores
24            .iter()
25            .fold(0f32, |acc, (score, weight)| acc + score.0 * weight)
26    }
27}
28
29/// A measure that multiplies all the elements together.
30#[derive(Debug, Clone, Reflect)]
31pub struct WeightedProduct;
32
33impl Measure for WeightedProduct {
34    fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
35        scores
36            .iter()
37            .fold(0f32, |acc, (score, weight)| acc * score.0 * weight)
38    }
39}
40
41/// A measure that returns the max of the weighted child scares based on the
42/// one-dimensional (Chebychev
43/// Distance)[https://en.wikipedia.org/wiki/Chebyshev_distance].
44#[derive(Debug, Clone, Reflect)]
45pub struct ChebyshevDistance;
46
47impl Measure for ChebyshevDistance {
48    fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
49        scores
50            .iter()
51            .fold(0f32, |best, (score, weight)| (score.0 * weight).max(best))
52    }
53}
54
55/// The default measure which uses a weight to provide an intuitive curve.
56#[derive(Debug, Clone, Default, Reflect)]
57pub struct WeightedMeasure;
58
59impl Measure for WeightedMeasure {
60    fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
61        let wsum: f32 = scores.iter().map(|(_score, weight)| weight).sum();
62
63        if wsum == 0.0 {
64            0.0
65        } else {
66            scores
67                .iter()
68                .map(|(score, weight)| weight / wsum * score.get().powf(2.0))
69                .sum::<f32>()
70                .powf(1.0 / 2.0)
71        }
72    }
73}
OSZAR »