extern crate eigenvalues;
extern crate nalgebra as na;
use streaming_iterator::*;
use iterative_methods::conjugate_gradient::ConjugateGradient;
use iterative_methods::utils::make_3x3_pd_system_2;
use iterative_methods::*;
use ndarray::{rcarr1, ArcArray1};
pub type V = ArcArray1<f64>;
fn residual_l2(result: &ConjugateGradient) -> f64 {
let res = result.a.dot(&result.solution) - &result.b;
res.dot(&res).sqrt()
}
fn a_distance(result: &ConjugateGradient, optimum: V) -> f64 {
let error = &result.solution - &optimum;
error.dot(&result.a.dot(&error)).sqrt()
}
fn residual_linf(result: &ConjugateGradient) -> f64 {
(result.a.dot(&result.solution) - &result.b).fold(0.0, |m, e| m.max(e.abs()))
}
fn cg_demo() {
let p = make_3x3_pd_system_2();
let optimum = rcarr1(&[-4.0, 6., -4.]);
let cg_iter = ConjugateGradient::for_problem(&p);
let cg_iter = cg_iter.take(80);
let cg_iter = time(cg_iter);
let cg_iter = assess(cg_iter, |TimedResult { result, .. }| {
(
residual_l2(result),
residual_linf(result),
a_distance(result, optimum.clone()),
)
});
fn small_residual((euc, linf, _): &(f64, f64, f64)) -> bool {
euc < &1e-3 && linf < &1e-3
}
let mut cg_iter = take_until(cg_iter, |ar| small_residual(&ar.annotation));
while let Some(AnnotatedResult {
annotation: (euc, linf, a_dist),
result:
TimedResult {
result,
start_time,
duration,
},
}) = cg_iter.next()
{
println!(
"{:8} : {:6} | ||Ax - b||_2 = {:.3}, ||Ax - b||_inf = {:.3}, ||x-x*||_A = {:.3}, for x = {:.4}",
start_time.as_nanos(), duration.as_nanos(),
euc, linf, a_dist, result.solution
);
}
}
fn main() {
cg_demo();
}