pmcore/routines/initialization/
latin.rs1use anyhow::Result;
2use faer::Mat;
3use rand::prelude::*;
4use rand::rngs::StdRng;
5use rand::Rng;
6
7use crate::prelude::Parameters;
8use crate::structs::theta::Theta;
9
10pub fn generate(parameters: &Parameters, points: usize, seed: usize) -> Result<Theta> {
23 let params: Vec<(String, f64, f64, bool)> = parameters
24 .iter()
25 .map(|p| (p.name.clone(), p.lower, p.upper, p.fixed))
26 .collect();
27
28 let random_params: Vec<(String, f64, f64)> = params
30 .iter()
31 .filter(|(_, _, _, fixed)| !fixed)
32 .map(|(name, lower, upper, _)| (name.clone(), *lower, *upper))
33 .collect();
34
35 let mut rng = StdRng::seed_from_u64(seed as u64);
37
38 let mut intervals = Vec::new();
40 for _ in 0..random_params.len() {
41 let mut param_intervals: Vec<f64> = (0..points).map(|i| i as f64).collect();
42 param_intervals.shuffle(&mut rng);
43 intervals.push(param_intervals);
44 }
45
46 let rand_matrix = Mat::from_fn(points, random_params.len(), |i, j| {
47 let interval = intervals[j][i];
49 let random_offset = rng.random::<f64>();
50 let unscaled = (interval + random_offset) / points as f64;
52 let (_name, lower, upper) = random_params.get(j).unwrap(); lower + unscaled * (upper - lower)
55 });
56
57 let fixed_params: Vec<(String, f64)> = params
59 .iter()
60 .filter(|(_, _, _, fixed)| *fixed)
61 .map(|(name, lower, upper, _)| (name.clone(), (upper - lower) / 2.0))
62 .collect();
63
64 let theta = Theta::from_parts(rand_matrix, random_params, fixed_params);
65
66 Ok(theta)
67}