polysim_core/distribution/
schulz_zimm.rs1use rand::RngCore;
2use rand_distr::{Distribution, Gamma};
3
4use super::ChainLengthDistribution;
5
6pub struct SchulzZimm;
16
17impl ChainLengthDistribution for SchulzZimm {
18 fn sample(
19 &self,
20 mn: f64,
21 pdi: f64,
22 m0: f64,
23 num_chains: usize,
24 rng: &mut dyn RngCore,
25 ) -> Vec<usize> {
26 let xn = (mn / m0).max(1.0);
27 let pdi_clamped = pdi.max(1.0 + 1e-9);
28 let k = (1.0 / (pdi_clamped - 1.0)).min(1e6);
29 let theta = xn / k;
30
31 let gamma = Gamma::new(k, theta).expect("valid gamma parameters");
32 (0..num_chains)
33 .map(|_| {
34 let x: f64 = gamma.sample(rng);
35 (x.round() as usize).max(1)
36 })
37 .collect()
38 }
39
40 fn name(&self) -> &'static str {
41 "schulz_zimm"
42 }
43}