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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//! Optimization algorithms:
//! - Levenberg-Marquardt algorithm for:
//! - solving nonlinear equation system
//! - fitting data
//! LM uses analytical Jacobian matrix
//! - H.P.Gavin's Levenberg-Marquardt algorithm
//! - scalar root finding:
//! - bisection method
//! - Newton-Raphson method
//! - secant method
//! - Brent's method
//!
/// not production ready
///here is main loop for solving nonlinear equation system with Levenberg-Marquardt algorithm
/// some special cases of fitting
/// main function to solve nonlinear equation system with Levenberg-Marquardt algorithm
/// some linear algebra functions for solving nonlinear equation system
/// nonlinear equation system solver implementation for fittting data. Fiitting function is symbolic expression.
///
/// Example#1
/// ```
/// use approx::assert_relative_eq;
/// use RustedSciThe::numerical::optimization::sym_fitting::Fitting;
/// // creating test data to fit
/// let x_data = (0..20).map(|x| x as f64).collect::<Vec<f64>>();
/// let exp_function = |x: f64| (1e-1 * x).exp() + 10.0;
/// let y_data = x_data
/// .iter()
/// .map(|&x| exp_function(x))
/// .collect::<Vec<f64>>();
/// let initial_guess = vec![1.0, 1.0];
/// let unknown_coeffs = vec!["a".to_string(), "b".to_string()];
/// let eq = " exp(a*x) + b".to_string();
/// let mut sym_fitting = Fitting::new();
/// sym_fitting.fitting_generate_from_str(
/// x_data,
/// y_data,
/// eq,
/// Some(unknown_coeffs),
/// "x".to_string(),
/// initial_guess,
/// None,
/// None,
/// None,
/// None,
/// None,
/// );
/// sym_fitting.eq_generate();
/// sym_fitting.solve();
/// let map_of_solutions = sym_fitting.map_of_solutions.unwrap();
/// assert_relative_eq!(map_of_solutions["a"], 1e-1, epsilon = 1e-6);
/// assert_relative_eq!(map_of_solutions["b"], 10.0, epsilon = 1e-6);
///```
/// Example#2
/// ```
/// use approx::assert_relative_eq;
/// use RustedSciThe::numerical::optimization::sym_fitting::Fitting;
/// let x_data = (0..100).map(|x| x as f64).collect::<Vec<f64>>();
/// let quadratic_function = |x: f64| 5.0 * x * x + 2.0 * x + 100.0;
/// let y_data = x_data
/// .iter()
/// .map(|&x| quadratic_function(x))
/// .collect::<Vec<f64>>();
/// let initial_guess = vec![1.0, 1.0, 1.0];
/// let unknown_coeffs = vec!["a".to_string(), "b".to_string(), "c".to_string()];
/// let eq = "a * x^2.0 + b * x + c".to_string();
/// let mut sym_fitting = Fitting::new();
/// sym_fitting.easy_fitting(
/// x_data,
/// y_data,
/// eq,
/// Some(unknown_coeffs),
/// "x".to_string(),
/// initial_guess,
/// );
/// let map_of_solutions = sym_fitting.map_of_solutions.unwrap();
/// assert_relative_eq!(map_of_solutions["a"], 5.0, epsilon = 1e-6);
/// assert_relative_eq!(map_of_solutions["b"], 2.0, epsilon = 1e-6);
/// assert_relative_eq!(map_of_solutions["c"], 100.0, epsilon = 1e-6);
///```
/// solver of nonlinear equation system with Levenberg-Marquardt algorithm is
/// used with residual functions that are symbolic expressions and jacobian functions that are calculated analytically
///
/// Example#1
/// ```
/// use approx::assert_relative_eq;
/// use RustedSciThe::numerical::optimization::sym_wrapper::LM;
/// let vec_of_str = vec!["x^2 + y^2 - 1".to_string(), "x - y".to_string()];
/// let initial_guess = vec![0.5, 0.5];
/// let values = vec!["x".to_string(), "y".to_string()];
/// let mut LM = LM::new();
/// LM.eq_generate_from_str(
/// vec_of_str,
/// Some(values),
/// initial_guess,
/// None,
/// None,
/// None,
/// None,
/// None,
/// );
/// LM.eq_generate();
/// LM.solve();
/// ```
/// trust region subproblem solver for Levenberg-Marquardt algorithm
/// some utility functions for solving nonlinear equation system with Levenberg-Marquardt algorithm
/// Piecewise polynomial interpolation
/// rewritten in Rust from SciPy's PPoly class
/// interpolation and extrapolation of data
/// H.P.Gavin's Levenberg-Marquardt algorithm
///
/// Example#1
/// ```
/// use RustedSciThe::numerical::optimization::lm_gavin2::{LevenbergMarquardt, PolynomialModel};
/// use nalgebra::DVector;
/// use nalgebra::dvector;
/// use crate::RustedSciThe::numerical::optimization::lm_gavin2::ObjectiveFunction;
/// // you can define your own objective function
/// let model = PolynomialModel::new(2); // Quadratic
/// let mut lm = LevenbergMarquardt::new(model);
///
/// let t = DVector::from_vec((0..10).map(|i| i as f64).collect());
/// let p_true = dvector![1.0, 2.0, 0.5]; // 1 + 2x + 0.5x^2
/// let y_true = lm.objective_fn.evaluate(&t, &p_true);
///
/// let p_initial = dvector![0.8, 1.8, 0.4];
///
/// match lm.lm(p_initial, &t, &y_true) {
/// Ok((p_fitted, red_x2, _sigma_p, _sigma_y, _corr_p, _r_sq, _cvg_hst)) => {
/// println!("Fitted polynomial parameters: {:?}", p_fitted);
/// println!("Reduced chi-squared: {}", red_x2);
/// assert!(red_x2 < 1e-10);
/// }
/// Err(e) => panic!("Polynomial LM fitting failed: {}", e),
/// }
/// ```
/// using Bisection, Secant, Newton, and Brent methods to find the minimum of a scalar function of one variable
///
/// Example#1
/// ```
/// use RustedSciThe:: numerical::optimization::minimize_scalar::{ScalarRootFinder, RootFindingMethod, approx_equal};
/// let solver = ScalarRootFinder::new();
///
/// // Solve x^3 - x - 1 = 0, root approximately at x = 1.324717957
/// let result = solver
/// .solve_symbolic_str(
/// "x^3 - (x + 1)",
/// "x",
/// RootFindingMethod::Bisection,
/// 1.5, // initial guess
/// Some((-10.0, 3.0)), // search range
/// None,
/// )
/// .unwrap();
/// println!("result.root: {}", result.root);
/// let expected_root = 1.324717957244746;
/// assert!(approx_equal(result.root, expected_root, 1e-9));
/// assert!(result.converged);
/// ```
///
/// Example#2
/// ```
/// use RustedSciThe::numerical::optimization::minimize_scalar::{ScalarRootFinder, RootFindingMethod, approx_equal};
/// let solver = ScalarRootFinder::new();
///
/// // Solve exp(x) - 2 = 0, root at x = ln(2)
/// let result = solver
/// .solve_symbolic_str(
/// "exp(x) - 2",
/// "x",
/// RootFindingMethod::NewtonRaphson,
/// 1.0, // initial guess
/// None,
/// None,
/// )
/// .unwrap();
///
/// let expected_root = 2.0_f64.ln();
/// assert!(approx_equal(result.root, expected_root, 1e-10));
/// assert!(result.converged);
///
/// ```
pub use ;