Added golden section search
This commit is contained in:
parent
5f56865f33
commit
6134559471
2 changed files with 78 additions and 7 deletions
36
src/main.rs
36
src/main.rs
|
|
@ -1,6 +1,7 @@
|
|||
extern crate colored;
|
||||
use colored::Colorize;
|
||||
mod univariate_solvers;
|
||||
mod univariate_minimizers;
|
||||
|
||||
/// x sin(x)
|
||||
/// e + ──────
|
||||
|
|
@ -43,7 +44,7 @@ fn check_result(x : f64, x_true : f64, tol : f64, test_name: &str, verbose: bool
|
|||
return 1;
|
||||
} else {
|
||||
if verbose {
|
||||
println!("{}\t: x = {}\tf(x) = {}\t{} (expected {})", test_name_padded, format!("{:<20}", x), format!("{:<40}", fct(x)), "failed".red(), x_true);
|
||||
println!("{}\t: x = {}\tf(x) = {}\t{} (expected {}, delta = {})", test_name_padded, format!("{:<20}", x), format!("{:<40}", fct(x)), "failed".red(), x_true, (x - x_true));
|
||||
} else {
|
||||
println!("{} {} : expected {}, got {}", test_name_padded, "failed".red(), x_true, x);
|
||||
}
|
||||
|
|
@ -60,18 +61,18 @@ fn print_test_results(num_tests_passed: u32, num_tests_total: u32) {
|
|||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Testing Rust numerical solvers.");
|
||||
let mut num_tests_passed : u32 = 0;
|
||||
let num_tests_total : u32 = 7;
|
||||
let verbose : bool = true;
|
||||
fn test_univariate_solvers(verbose: bool) {
|
||||
println!("Testing univariate numerical solvers.");
|
||||
let x0 : f64 = 1.0;
|
||||
let tol : f64 = 1e-10;
|
||||
let max_iter : u32 = 100;
|
||||
let dx_num : f64 = 1e-6;
|
||||
let mut num_tests_passed : u32 = 0;
|
||||
let num_tests_total : u32 = 7;
|
||||
|
||||
let x_mathematica: f64 = -3.26650043678562449167148755288;// 30 digits of precision
|
||||
let x_mathematica_2: f64 = -6.27133405258685307845641527902;// 30 digits of precision
|
||||
let x_mathematica_3: f64 = -9.42553801930504142668603949182;// 30 digits of precision
|
||||
// let x_mathematica_3: f64 = -9.42553801930504142668603949182;// 30 digits of precision
|
||||
let x_newton: f64 = univariate_solvers::newton_solve(&(fct as fn(f64) -> f64), &(dfct as fn(f64) -> f64), x0, tol, max_iter);
|
||||
let x_newton_num: f64 = univariate_solvers::newton_solve_num(&(fct as fn(f64) -> f64), x0, tol, dx_num, max_iter);
|
||||
let x_halley: f64 = univariate_solvers::halley_solve(&(fct as fn(f64) -> f64), &(dfct as fn(f64) -> f64), &(ddfct as fn(f64) -> f64), x0, tol, max_iter, false).unwrap();
|
||||
|
|
@ -89,3 +90,24 @@ fn main() {
|
|||
|
||||
print_test_results(num_tests_passed, num_tests_total);
|
||||
}
|
||||
|
||||
fn test_univariate_optimizers(verbose: bool) {
|
||||
let tol : f64 = 1e-10;
|
||||
let max_iter : u32 = 100;
|
||||
let dx_num : f64 = 1e-6;
|
||||
let mut num_tests_passed : u32 = 0;
|
||||
let num_tests_total : u32 = 1;
|
||||
|
||||
let x_mathematica: f64 = -4.54295618675514754103476876324;// 30 digits of precision
|
||||
let y_mathematica: f64 = -0.206327079359226884630654987440;// 30 digits of precision
|
||||
let x_golden_section: f64 = univariate_minimizers::golden_section_minimize(&(fct as fn(f64) -> f64), -7.0, -1.0, tol);
|
||||
num_tests_passed += check_result(x_golden_section, x_mathematica, tol*1e2, "Golden section search", verbose);
|
||||
print_test_results(num_tests_passed, num_tests_total);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Testing Rust numerical solvers.");
|
||||
let verbose : bool = true;
|
||||
test_univariate_solvers(verbose);
|
||||
test_univariate_optimizers(verbose);
|
||||
}
|
||||
|
|
|
|||
49
src/univariate_minimizers.rs
Normal file
49
src/univariate_minimizers.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/// Golden section search for minimizing a function f(x)
|
||||
/// @param f function to minimize
|
||||
/// @param a left bracket
|
||||
/// @param b right bracket
|
||||
/// @param tol tolerance
|
||||
/// @return solution
|
||||
/// @note The interval [a, b] must bracket the minimum, and the function must have f''(x) > 0 over the interval [a, b] to garantee convergence.
|
||||
pub fn golden_section_minimize<F>(f : F, mut a: f64, mut b: f64, tol: f64) -> f64
|
||||
where F : Fn(f64) -> f64
|
||||
{
|
||||
let invphi: f64 = (f64::sqrt(5.0) - 1.0) / 2.0; // 1 / phi
|
||||
let invphi2: f64 = (3.0 - f64::sqrt(5.0)) / 2.0; // 1 / phi^2
|
||||
|
||||
a = f64::min(a, b);
|
||||
b = f64::max(a, b);
|
||||
let mut h: f64 = b - a;
|
||||
if h <= tol {
|
||||
return (a + b)/2.0;
|
||||
}
|
||||
|
||||
// Required steps to achieve tolerance
|
||||
let n: u32 = (f64::ceil(f64::ln(tol / h) / f64::ln(invphi))) as u32;
|
||||
|
||||
let mut c: f64 = a + invphi2 * h;
|
||||
let mut d: f64 = a + invphi * h;
|
||||
let mut yc: f64 = f(c);
|
||||
let mut yd: f64 = f(d);
|
||||
|
||||
for _ in 0..n {
|
||||
if yc < yd { // yc > yd to find the maximum
|
||||
b = d;
|
||||
d = c;
|
||||
yd = yc;
|
||||
h = invphi * h;
|
||||
c = a + invphi2 * h;
|
||||
yc = f(c);
|
||||
} else {
|
||||
a = c;
|
||||
c = d;
|
||||
yc = yd;
|
||||
h = invphi * h;
|
||||
d = a + invphi * h;
|
||||
yd = f(d);
|
||||
}
|
||||
}
|
||||
|
||||
if yc < yd { return (a + d)/2.0; }
|
||||
else { return (c + b)/2.0; }
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue