1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::{
traits::{ProgressStatus, Status, StatusMessage},
DMatrix, DVector, Float,
};
use serde::{Deserialize, Serialize};
/// A status message struct containing all information about a minimization result.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GradientStatus {
/// A [`StatusMessage`] that can be set by [`Algorithm`](crate::traits::Algorithm)s.
pub message: StatusMessage,
/// The current parameters of the minimization.
pub x: DVector<Float>,
/// The current value of the minimization problem function at [`GradientStatus::x`].
pub fx: Float,
/// The number of function evaluations (approximately, this is left up to individual
/// [`Algorithm`](crate::traits::Algorithm)s to correctly compute and may not be exact).
pub n_f_evals: usize,
/// The number of gradient evaluations (approximately, this is left up to individual
/// [`Algorithm`](crate::traits::Algorithm)s to correctly compute and may not be exact).
pub n_g_evals: usize,
/// The number of Hessian evaluations (approximately, this is left up to individual
/// [`Algorithm`](crate::traits::Algorithm)s to correctly compute and may not be exact).
pub n_h_evals: usize,
/// The Hessian matrix at the end of the fit ([`None`] if not computed yet)
pub hess: Option<DMatrix<Float>>,
/// Covariance matrix at the end of the fit ([`None`] if not computed yet)
pub cov: Option<DMatrix<Float>>,
/// Errors on parameters at the end of the fit ([`None`] if not computed yet)
pub err: Option<DVector<Float>>,
}
impl Status for GradientStatus {
fn reset(&mut self) {
self.message = Default::default();
self.x = DVector::zeros(self.x.len());
self.fx = Default::default();
self.n_f_evals = Default::default();
self.n_g_evals = Default::default();
self.n_h_evals = Default::default();
self.hess = Default::default();
self.cov = Default::default();
self.err = Default::default();
}
fn message(&self) -> &StatusMessage {
&self.message
}
fn set_message(&mut self) -> &mut StatusMessage {
&mut self.message
}
}
impl GradientStatus {
/// Updates the [`GradientStatus::x`] and [`GradientStatus::fx`] fields and sets the status
/// message to an initialized state.
pub fn initialize(&mut self, pos: (DVector<Float>, Float)) {
self.set_message()
.succeed_with_message(&format!("f(x) = {}", pos.1));
self.x = pos.0;
self.fx = pos.1;
}
/// Updates the [`GradientStatus::x`] and [`GradientStatus::fx`] fields and sets the status
/// message to a step state.
pub fn set_position(&mut self, pos: (DVector<Float>, Float)) {
self.set_message()
.step_with_message(&format!("f(x) = {}", pos.1));
self.x = pos.0;
self.fx = pos.1;
}
/// Updates the [`GradientStatus::x`] and [`GradientStatus::fx`] fields and marks the status as
/// initialized without formatting a message payload.
pub fn initialize_silent(&mut self, pos: (DVector<Float>, Float)) {
self.set_message().initialize();
self.x = pos.0;
self.fx = pos.1;
}
/// Updates the [`GradientStatus::x`] and [`GradientStatus::fx`] fields and marks the status as
/// a step without formatting a message payload.
pub fn set_position_silent(&mut self, pos: (DVector<Float>, Float)) {
self.set_message().step();
self.x = pos.0;
self.fx = pos.1;
}
/// Increments [`GradientStatus::n_f_evals`] by `1`.
pub fn inc_n_f_evals(&mut self) {
self.n_f_evals += 1;
}
/// Increments [`GradientStatus::n_g_evals`] by `1`.
pub fn inc_n_g_evals(&mut self) {
self.n_g_evals += 1;
}
/// Increments [`GradientStatus::n_h_evals`] by `1`.
pub fn inc_n_h_evals(&mut self) {
self.n_h_evals += 1;
}
/// Updates the [`GradientStatus::err`] field.
pub fn set_cov(&mut self, covariance: Option<DMatrix<Float>>) {
if let Some(cov_mat) = &covariance {
self.err = Some(cov_mat.diagonal().map(Float::sqrt));
}
self.cov = covariance;
}
/// Updates the [`GradientStatus::hess`] field and computes [`GradientStatus::cov`] and [`GradientStatus::err`].
pub fn set_hess(&mut self, hessian: &DMatrix<Float>) {
use crate::core::utils::hessian_to_covariance;
self.hess = Some(hessian.clone());
let covariance = hessian_to_covariance(hessian);
if let Some(cov_mat) = &covariance {
self.err = Some(cov_mat.diagonal().map(Float::sqrt));
}
self.cov = covariance;
}
}
impl ProgressStatus for GradientStatus {
fn write_progress(&self, out: &mut String) -> std::fmt::Result {
use std::fmt::Write;
write!(out, "status={} fx={}", self.message, self.fx)
}
}