Skip to main content

score_set/
set.rs

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