pmcore/model/
parameter_space.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
8pub struct ParameterSpace<T> {
9 pub items: Vec<T>,
10}
11
12impl<T> ParameterSpace<T> {
13 pub fn new() -> Self {
14 Self { items: Vec::new() }
15 }
16
17 pub fn push(&mut self, item: impl Into<T>) {
18 self.items.push(item.into());
19 }
20
21 pub fn len(&self) -> usize {
22 self.items.len()
23 }
24
25 pub fn is_empty(&self) -> bool {
26 self.items.is_empty()
27 }
28
29 pub fn iter(&self) -> std::slice::Iter<'_, T> {
30 self.items.iter()
31 }
32}
33
34impl<T: ParameterMeta> ParameterSpace<T> {
35 pub fn names(&self) -> Vec<String> {
36 self.items.iter().map(|p| p.name().to_string()).collect()
37 }
38}
39
40impl ParameterSpace<BoundedParameter> {
42 pub fn bounded() -> Self {
53 Self::new()
54 }
55
56 #[allow(clippy::should_implement_trait)]
58 pub fn add(mut self, name: impl Into<String>, lower: f64, upper: f64) -> Self {
59 self.items.push(BoundedParameter::new(name, lower, upper));
60 self
61 }
62
63 pub fn finite_ranges(&self) -> Vec<(f64, f64)> {
65 self.items.iter().map(|p| (p.lower, p.upper)).collect()
66 }
67}
68
69impl ParameterSpace<UnboundedParameter> {
71 pub fn unbounded() -> Self {
76 Self::new()
77 }
78
79 #[allow(clippy::should_implement_trait)]
81 pub fn add(mut self, parameter: impl Into<UnboundedParameter>) -> Self {
82 self.items.push(parameter.into());
83 self
84 }
85}
86
87impl<T> FromIterator<T> for ParameterSpace<T> {
88 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
89 Self {
90 items: iter.into_iter().collect(),
91 }
92 }
93}
94
95impl<T> IntoIterator for ParameterSpace<T> {
96 type Item = T;
97 type IntoIter = std::vec::IntoIter<T>;
98
99 fn into_iter(self) -> Self::IntoIter {
100 self.items.into_iter()
101 }
102}
103
104impl<'a, T> IntoIterator for &'a ParameterSpace<T> {
105 type Item = &'a T;
106 type IntoIter = std::slice::Iter<'a, T>;
107
108 fn into_iter(self) -> Self::IntoIter {
109 self.items.iter()
110 }
111}
112
113pub trait ParameterMeta {
115 fn name(&self) -> &str;
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
119pub struct BoundedParameter {
120 pub name: String,
121 pub lower: f64,
122 pub upper: f64,
123}
124
125impl BoundedParameter {
126 pub fn new(name: impl Into<String>, lower: f64, upper: f64) -> Self {
127 Self {
128 name: name.into(),
129 lower,
130 upper,
131 }
132 }
133}
134
135impl ParameterMeta for BoundedParameter {
136 fn name(&self) -> &str {
137 &self.name
138 }
139}
140
141impl From<BoundedParameter> for UnboundedParameter {
143 fn from(p: BoundedParameter) -> Self {
144 UnboundedParameter {
145 name: p.name,
146 scale: ParameterScale::Logit {
147 lower: p.lower,
148 upper: p.upper,
149 },
150 initial: None,
151 estimate: true,
152 }
153 }
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
158pub struct UnboundedParameter {
159 pub name: String,
160 pub scale: ParameterScale,
161 pub initial: Option<f64>,
162 pub estimate: bool,
163}
164
165impl UnboundedParameter {
166 pub fn new(name: impl Into<String>, scale: ParameterScale) -> Self {
168 Self {
169 name: name.into(),
170 scale,
171 initial: None,
172 estimate: true,
173 }
174 }
175
176 pub fn real(name: impl Into<String>) -> Self {
178 Self::new(name, ParameterScale::Identity)
179 }
180
181 pub fn with_initial(mut self, value: f64) -> Self {
183 self.initial = Some(value);
184 self
185 }
186}
187
188impl ParameterMeta for UnboundedParameter {
189 fn name(&self) -> &str {
190 &self.name
191 }
192}
193
194#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Default)]
196pub enum ParameterScale {
197 #[default]
199 Identity,
200 Log,
202 Logit { lower: f64, upper: f64 },
204 Probit { lower: f64, upper: f64 },
206}
207
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
222pub struct Parameter;
223
224impl Parameter {
225 pub fn bounded(name: impl Into<String>, lower: f64, upper: f64) -> BoundedParameter {
227 BoundedParameter::new(name, lower, upper)
228 }
229
230 pub fn real(name: impl Into<String>) -> UnboundedParameter {
232 UnboundedParameter::real(name)
233 }
234
235 pub fn scaled(name: impl Into<String>, scale: ParameterScale) -> UnboundedParameter {
237 UnboundedParameter::new(name, scale)
238 }
239
240 pub fn log(name: impl Into<String>) -> UnboundedParameter {
242 UnboundedParameter::new(name, ParameterScale::Log)
243 }
244
245 pub fn logit(name: impl Into<String>, lower: f64, upper: f64) -> UnboundedParameter {
247 UnboundedParameter::new(name, ParameterScale::Logit { lower, upper })
248 }
249
250 pub fn probit(name: impl Into<String>, lower: f64, upper: f64) -> UnboundedParameter {
252 UnboundedParameter::new(name, ParameterScale::Probit { lower, upper })
253 }
254}