pmcore/algorithms/parametric/mod.rs
1//! Parametric algorithm implementations.
2//!
3//! Parametric algorithms estimate the population distribution as a parametric model (for
4//! example a multivariate normal) whose parameters are fitted to the data.
5//!
6//! # Algorithm Selection
7//!
8//! Use the [`ParametricAlgorithm`] enum to select and configure an algorithm. Each variant
9//! wraps its algorithm-specific configuration struct (e.g. [`SaemConfig`]).
10//!
11//! Note: the parametric fitting machinery is not yet implemented. Constructing a problem and
12//! calling [`fit_with`](crate::estimation::EstimationProblem::fit_with) with a
13//! [`ParametricAlgorithm`] type-checks today, but running it will panic until the SAEM solver
14//! is implemented.
15
16pub mod saem_config;
17
18pub use saem_config::SaemConfig;
19
20use crate::algorithms::Algorithm;
21use crate::estimation::{EstimationProblem, Parametric};
22use crate::results::ParametricResult;
23use anyhow::Result;
24use pharmsol::prelude::simulator::Equation;
25
26/// The parametric algorithms supported by PMcore.
27///
28/// Use the constructors to select an algorithm with its default configuration:
29///
30/// ```no_run
31/// use pmcore::prelude::*;
32///
33/// // Default SAEM configuration.
34/// let algorithm = ParametricAlgorithm::saem();
35/// ```
36///
37/// To customize an algorithm, build its configuration struct (which exposes only the
38/// setters valid for that algorithm) and pass it directly to
39/// [`fit_with`](crate::estimation::EstimationProblem::fit_with):
40///
41/// ```no_run
42/// use pmcore::prelude::*;
43///
44/// // SAEM with a custom iteration schedule and seed.
45/// let config = SaemConfig::new()
46/// .k1_iterations(500)
47/// .k2_iterations(200)
48/// .seed(42);
49/// // `problem.fit_with(config)` accepts the config directly.
50/// ```
51///
52/// [`SaemConfig`] implements [`Algorithm`] by delegating to the matching enum variant, so
53/// configs can be passed to `fit_with` without converting them first.
54#[derive(Debug, Clone)]
55pub enum ParametricAlgorithm {
56 /// Stochastic Approximation Expectation-Maximization.
57 Saem(SaemConfig),
58}
59
60impl Default for ParametricAlgorithm {
61 fn default() -> Self {
62 Self::saem()
63 }
64}
65
66impl From<SaemConfig> for ParametricAlgorithm {
67 fn from(config: SaemConfig) -> Self {
68 Self::Saem(config)
69 }
70}
71
72impl ParametricAlgorithm {
73 /// The Stochastic Approximation Expectation-Maximization (SAEM) algorithm with its
74 /// default configuration.
75 pub fn saem() -> Self {
76 Self::Saem(SaemConfig::default())
77 }
78}
79
80impl<E: Equation + Send + 'static> Algorithm<E, Parametric> for ParametricAlgorithm {
81 type Output = ParametricResult<E>;
82
83 fn fit(self, _problem: EstimationProblem<E, Parametric>) -> Result<Self::Output> {
84 match self {
85 Self::Saem(_config) => {
86 unimplemented!("SAEM fitting is not yet implemented")
87 }
88 }
89 }
90}
91
92// `SaemConfig` delegates to the matching `ParametricAlgorithm` variant so it can be passed
93// directly to `fit_with`, keeping its setters compile-time checked.
94impl<E: Equation + Send + 'static> Algorithm<E, Parametric> for SaemConfig {
95 type Output = ParametricResult<E>;
96
97 fn fit(self, problem: EstimationProblem<E, Parametric>) -> Result<Self::Output> {
98 ParametricAlgorithm::from(self).fit(problem)
99 }
100}