pmcore/algorithms/
postprob.rs

1use crate::{
2    prelude::algorithms::Algorithms,
3    structs::{
4        psi::{calculate_psi, Psi},
5        theta::Theta,
6    },
7};
8use anyhow::Result;
9use faer::Col;
10use pharmsol::prelude::{
11    data::{Data, ErrorModel},
12    simulator::Equation,
13};
14
15use crate::routines::evaluation::ipm::burke;
16use crate::routines::initialization;
17use crate::routines::output::CycleLog;
18use crate::routines::output::NPResult;
19use crate::routines::settings::Settings;
20
21/// Posterior probability algorithm
22/// Reweights the prior probabilities to the observed data and error model
23pub struct POSTPROB<E: Equation> {
24    equation: E,
25    psi: Psi,
26    theta: Theta,
27    w: Col<f64>,
28    objf: f64,
29    cycle: usize,
30    converged: bool,
31    data: Data,
32    settings: Settings,
33    cyclelog: CycleLog,
34    error_model: ErrorModel,
35}
36
37impl<E: Equation> Algorithms<E> for POSTPROB<E> {
38    fn new(settings: Settings, equation: E, data: Data) -> Result<Box<Self>, anyhow::Error> {
39        Ok(Box::new(Self {
40            equation,
41            psi: Psi::new(),
42            theta: Theta::new(),
43            w: Col::zeros(0),
44            objf: f64::INFINITY,
45            cycle: 0,
46            converged: false,
47            error_model: settings.error().clone().into(),
48            settings,
49            data,
50
51            cyclelog: CycleLog::new(),
52        }))
53    }
54    fn into_npresult(&self) -> NPResult<E> {
55        NPResult::new(
56            self.equation.clone(),
57            self.data.clone(),
58            self.theta.clone(),
59            self.psi.clone(),
60            self.w.clone(),
61            self.objf,
62            self.cycle,
63            self.converged,
64            self.settings.clone(),
65            self.cyclelog.clone(),
66        )
67    }
68    fn get_settings(&self) -> &Settings {
69        &self.settings
70    }
71
72    fn equation(&self) -> &E {
73        &self.equation
74    }
75
76    fn get_data(&self) -> &Data {
77        &self.data
78    }
79
80    fn get_prior(&self) -> Theta {
81        initialization::sample_space(&self.settings).unwrap()
82    }
83
84    fn likelihood(&self) -> f64 {
85        self.objf
86    }
87
88    fn inc_cycle(&mut self) -> usize {
89        0
90    }
91
92    fn get_cycle(&self) -> usize {
93        0
94    }
95
96    fn set_theta(&mut self, theta: Theta) {
97        self.theta = theta;
98    }
99
100    fn get_theta(&self) -> &Theta {
101        &self.theta
102    }
103
104    fn psi(&self) -> &Psi {
105        &self.psi
106    }
107
108    fn convergence_evaluation(&mut self) {}
109
110    fn converged(&self) -> bool {
111        true
112    }
113
114    fn evaluation(&mut self) -> Result<()> {
115        self.psi = calculate_psi(
116            &self.equation,
117            &self.data,
118            &self.theta,
119            &self.error_model,
120            false,
121            false,
122        )?;
123        (self.w, self.objf) = burke(&self.psi).expect("Error in IPM");
124        Ok(())
125    }
126
127    fn condensation(&mut self) -> Result<()> {
128        Ok(())
129    }
130    fn optimizations(&mut self) -> Result<()> {
131        Ok(())
132    }
133
134    fn logs(&self) {}
135
136    fn expansion(&mut self) -> Result<()> {
137        Ok(())
138    }
139}