Skip to main content

rusty_alto/
score.rs

1//! Rule-weight scoring conventions for Viterbi and A* algorithms.
2
3/// Maps raw rule weights to the score algebra used by one-best algorithms.
4///
5/// `Explicit` stores the raw weights it was built with. Algorithms that combine
6/// many weights use a scorer to decide how to interpret those raw values.
7pub trait WeightScorer {
8    /// Score for an impossible derivation.
9    fn zero(&self) -> f64;
10
11    /// Score for an empty product.
12    fn one(&self) -> f64;
13
14    /// Convert one raw rule weight into this scorer's representation.
15    fn rule_score(&self, weight: f64) -> f64;
16
17    /// Combine two scores along one derivation.
18    fn times(&self, left: f64, right: f64) -> f64;
19
20    /// Convert a final score back to a conventional raw weight.
21    fn score_to_weight(&self, score: f64) -> f64;
22
23    /// Return whether `candidate` is strictly better than `current`.
24    #[inline]
25    fn better(&self, candidate: f64, current: f64) -> bool {
26        candidate > current
27    }
28}
29
30/// Interpret raw weights as ordinary multiplicative weights.
31#[derive(Clone, Copy, Debug, Default)]
32pub struct ProbabilityScorer;
33
34impl WeightScorer for ProbabilityScorer {
35    #[inline]
36    fn zero(&self) -> f64 {
37        0.0
38    }
39
40    #[inline]
41    fn one(&self) -> f64 {
42        1.0
43    }
44
45    #[inline]
46    fn rule_score(&self, weight: f64) -> f64 {
47        weight
48    }
49
50    #[inline]
51    fn times(&self, left: f64, right: f64) -> f64 {
52        left * right
53    }
54
55    #[inline]
56    fn score_to_weight(&self, score: f64) -> f64 {
57        score
58    }
59}
60
61/// Interpret raw weights as probabilities and combine them in log space.
62#[derive(Clone, Copy, Debug, Default)]
63pub struct LogProbabilityScorer;
64
65impl WeightScorer for LogProbabilityScorer {
66    #[inline]
67    fn zero(&self) -> f64 {
68        f64::NEG_INFINITY
69    }
70
71    #[inline]
72    fn one(&self) -> f64 {
73        0.0
74    }
75
76    #[inline]
77    fn rule_score(&self, weight: f64) -> f64 {
78        if weight == 0.0 {
79            f64::NEG_INFINITY
80        } else {
81            weight.ln()
82        }
83    }
84
85    #[inline]
86    fn times(&self, left: f64, right: f64) -> f64 {
87        left + right
88    }
89
90    #[inline]
91    fn score_to_weight(&self, score: f64) -> f64 {
92        score.exp()
93    }
94}