ceres_solver/
parameter_block.rs

1//! Parameter block and related structures for [NllsProblem](crate::nlls_problem::NllsProblem).
2
3use crate::error::ParameterBlockStorageError;
4
5use std::pin::Pin;
6
7/// Parameter vector representation to use with [NllsProblem](crate::nlls_problem::NllsProblem).
8pub struct ParameterBlock {
9    values: Pin<Vec<f64>>,
10    pointer: *mut f64,
11    lower_bounds: Option<Vec<Option<f64>>>,
12    upper_bounds: Option<Vec<Option<f64>>>,
13}
14
15#[allow(clippy::len_without_is_empty)]
16impl ParameterBlock {
17    // Create a new parameter vector.
18    pub fn new(values: impl Into<Vec<f64>>) -> Self {
19        let mut values = Pin::new(values.into());
20        assert!(!values.is_empty());
21        let pointer = values.as_mut_ptr();
22        Self {
23            values,
24            pointer,
25            lower_bounds: None,
26            upper_bounds: None,
27        }
28    }
29
30    /// Add lower bounds to the parameter vector. [None] means no lower bound.
31    pub fn set_lower_bounds(&mut self, lower_bounds: impl Into<Vec<Option<f64>>>) -> &mut Self {
32        let lower_bounds = lower_bounds.into();
33        assert_eq!(lower_bounds.len(), self.len());
34        self.lower_bounds = Some(lower_bounds);
35        self
36    }
37
38    /// Add upper bounds to the parameter vector. [None] means no upper bound.
39    pub fn set_upper_bounds(&mut self, upper_bounds: impl Into<Vec<Option<f64>>>) -> &mut Self {
40        let upper_bounds = upper_bounds.into();
41        assert_eq!(upper_bounds.len(), self.len());
42        self.upper_bounds = Some(upper_bounds);
43        self
44    }
45
46    /// Add lower bounds to the parameter vector.
47    pub fn set_all_lower_bounds(&mut self, lower_bounds: impl Into<Vec<f64>>) -> &mut Self {
48        let lower_bounds = lower_bounds.into();
49        assert_eq!(lower_bounds.len(), self.len());
50        self.set_lower_bounds(lower_bounds.into_iter().map(Some).collect::<Vec<_>>())
51    }
52
53    /// Add upper bounds to the parameter vector.
54    pub fn set_all_upper_bounds(&mut self, upper_bounds: impl Into<Vec<f64>>) -> &mut Self {
55        let upper_bounds = upper_bounds.into();
56        assert_eq!(upper_bounds.len(), self.len());
57        self.set_upper_bounds(upper_bounds.into_iter().map(Some).collect::<Vec<_>>())
58    }
59
60    /// Number of parameters.
61    pub fn len(&self) -> usize {
62        self.values.len()
63    }
64
65    /// Lower bounds of the parameters, if any. [None] means no lower bound.
66    pub fn lower_bounds(&self) -> Option<&[Option<f64>]> {
67        self.lower_bounds.as_deref()
68    }
69
70    /// Upper bounds of the parameters, if any. [None] means no upper bound.
71    pub fn upper_bounds(&self) -> Option<&[Option<f64>]> {
72        self.upper_bounds.as_deref()
73    }
74
75    /// Components of the parameter.
76    pub fn values(&self) -> &[f64] {
77        &self.values
78    }
79
80    pub(crate) fn pointer_mut(&self) -> *mut f64 {
81        self.pointer
82    }
83
84    /// Convert to vector of parameters, each parameter is vector of floats.
85    pub fn to_values(self) -> Vec<f64> {
86        Pin::into_inner(self.values)
87    }
88}
89
90impl From<Vec<f64>> for ParameterBlock {
91    fn from(values: Vec<f64>) -> Self {
92        Self::new(values)
93    }
94}
95
96pub enum ParameterBlockOrIndex {
97    Block(ParameterBlock),
98    Index(usize),
99}
100
101impl From<ParameterBlock> for ParameterBlockOrIndex {
102    fn from(block: ParameterBlock) -> Self {
103        Self::Block(block)
104    }
105}
106
107impl From<usize> for ParameterBlockOrIndex {
108    fn from(index: usize) -> Self {
109        Self::Index(index)
110    }
111}
112
113impl From<Vec<f64>> for ParameterBlockOrIndex {
114    fn from(values: Vec<f64>) -> Self {
115        Self::Block(ParameterBlock::new(values))
116    }
117}
118
119pub struct ParameterBlockStorage {
120    storage: Vec<ParameterBlock>,
121}
122
123impl ParameterBlockStorage {
124    pub fn new() -> Self {
125        Self {
126            storage: Vec::new(),
127        }
128    }
129
130    pub fn extend<P>(
131        &mut self,
132        parameter_blocks: impl IntoIterator<Item = P>,
133    ) -> Result<Vec<usize>, ParameterBlockStorageError>
134    where
135        P: Into<ParameterBlockOrIndex>,
136    {
137        let mut indices = Vec::new();
138        for parameter_block in parameter_blocks {
139            let parameter_block = parameter_block.into();
140            let len = self.storage.len();
141            match parameter_block {
142                ParameterBlockOrIndex::Block(block) => {
143                    indices.push(len);
144                    self.storage.push(block);
145                }
146                ParameterBlockOrIndex::Index(index) => {
147                    if index >= self.storage.len() {
148                        return Err(ParameterBlockStorageError::IndexOutOfBounds { index, len });
149                    }
150                    indices.push(index);
151                }
152            }
153        }
154        Ok(indices)
155    }
156
157    #[inline]
158    pub fn blocks(&self) -> &[ParameterBlock] {
159        &self.storage
160    }
161
162    #[inline]
163    pub fn get_block(&self, index: usize) -> Result<&ParameterBlock, ParameterBlockStorageError> {
164        self.storage
165            .get(index)
166            .ok_or(ParameterBlockStorageError::IndexOutOfBounds {
167                index,
168                len: self.storage.len(),
169            })
170    }
171
172    pub fn to_values(self) -> Vec<Vec<f64>> {
173        self.storage.into_iter().map(|p| p.to_values()).collect()
174    }
175}
176
177impl Default for ParameterBlockStorage {
178    fn default() -> Self {
179        Self::new()
180    }
181}