Skip to main content

score_set/
set.rs

1use crate::float::Float;
2use crate::member::Members;
3use crate::value::NormalizedContainer;
4use core::marker::PhantomData;
5
6// ---------------------------------------------------------------------------
7// ScoreSet — normalized weighted set of scoring operators
8// ---------------------------------------------------------------------------
9
10/// A static weighted set of scoring operators with normalized weights.
11///
12/// Construct via [`score_set!`](crate::score_set!) or
13/// [`ScoreSet::normalize`]. Call [`.score()`](ScoreSet::score) to enter the
14/// scoring stage.
15pub struct ScoreSet<T: Float, Members> {
16    pub(crate) members: Members,
17    _phantom: PhantomData<T>,
18}
19
20impl<T: Float, Members> ScoreSet<T, Members>
21where
22    Members: crate::Members<T>,
23{
24    /// Normalize raw weights and validate the resulting set.
25    pub fn normalize(raw: Members::Raw) -> Result<Self, &'static str> {
26        let raw_weights = Members::extract_raw_weights(&raw);
27        let sum: T = raw_weights.iter().fold(T::zero(), |a, &b| a + b);
28        let normalized: Vec<T> = raw_weights.iter().map(|&w| w / sum).collect();
29        let container = NormalizedContainer::witness(normalized)?;
30        Ok(ScoreSet {
31            members: Members::from_raw_with_weights(raw, &container),
32            _phantom: PhantomData,
33        })
34    }
35
36    /// Enter the scoring stage.
37    #[inline]
38    pub fn score(&self) -> ScoreStage<'_, T, Members> {
39        ScoreStage {
40            members: &self.members,
41            _phantom: PhantomData,
42        }
43    }
44}
45
46// ---------------------------------------------------------------------------
47// ScoreStage — user-provided scoring closure
48// ---------------------------------------------------------------------------
49
50/// The scoring stage, created by [`ScoreSet::score`].
51///
52/// Call [`.by(closure)`](ScoreStage::by) to evaluate the set with an
53/// arbitrary composition of its members.
54pub struct ScoreStage<'a, T: Float, Members> {
55    members: &'a Members,
56    _phantom: PhantomData<T>,
57}
58
59impl<'a, T: Float, Members> ScoreStage<'a, T, Members> {
60    /// Score the set using a user-provided closure.
61    #[inline]
62    pub fn by<F, R>(self, f: F) -> R
63    where
64        F: FnOnce(&Members) -> R,
65    {
66        f(self.members)
67    }
68}
69
70#[cfg(test)]
71mod tests_for_set;