qrlew/expr/
rewriting.rs

1use crate::{expr::Expr, namer};
2use std::f64::consts::PI;
3
4impl Expr {
5    /// Gaussian noise based on [Box Muller transform](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform)
6    pub fn gaussian_noise() -> Self {
7        Expr::multiply(
8            Expr::sqrt(Expr::multiply(
9                Expr::val(-2.0),
10                Expr::ln(Expr::random(namer::new_id("GAUSSIAN_NOISE"))),
11            )),
12            Expr::cos(Expr::multiply(
13                Expr::val(2.0 * PI),
14                Expr::random(namer::new_id("GAUSSIAN_NOISE")),
15            )),
16        )
17    }
18    /// Gaussian noise based on [Box Muller transform](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform)
19    pub fn add_gaussian_noise(self, sigma: f64) -> Self {
20        Expr::plus(
21            self,
22            Expr::multiply(Expr::val(sigma), Expr::gaussian_noise()),
23        )
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30    use crate::{
31        builder::WithoutContext,
32        data_type::{function::Function as _, value::Value},
33        display::Dot,
34    };
35
36    #[test]
37    fn test_gaussian_noise() {
38        //TODO not great to have stateful functions, fix it
39        let x = Expr::gaussian_noise();
40        println!("gaussian noise = {x}");
41        println!(
42            "gaussian noise value = {}",
43            x.value(&Value::structured_from_values(vec![])).unwrap()
44        );
45        x.with(Value::structured_from_values(vec![]))
46            .display_dot()
47            .unwrap();
48    }
49
50    #[test]
51    fn test_add_gaussian_noise() {
52        //TODO not great to have stateful functions, fix it
53        let g = Expr::col("mu").add_gaussian_noise(1.);
54        println!("mu plus gaussian noise = {g}");
55        g.with(Value::structured(vec![("mu", Value::from(1.0))]))
56            .display_dot()
57            .unwrap();
58    }
59}