use crate::DType;
use numr::autograd::Var;
use numr::error::Result as NumrResult;
use numr::runtime::Runtime;
use numr::tensor::Tensor;
use crate::optimize::error::OptimizeResult;
use crate::optimize::minimize::TensorMinimizeResult;
#[derive(Debug, Clone)]
pub struct NewtonCGOptions {
pub max_iter: usize,
pub max_cg_iter: Option<usize>,
pub g_tol: f64,
pub f_tol: f64,
pub x_tol: f64,
pub cg_tol: f64,
pub trust_radius: Option<f64>,
}
impl Default for NewtonCGOptions {
fn default() -> Self {
Self {
max_iter: 100,
max_cg_iter: None,
g_tol: 1e-8,
f_tol: 1e-8,
x_tol: 1e-8,
cg_tol: 0.1, trust_radius: None,
}
}
}
#[derive(Debug, Clone)]
pub struct NewtonCGResult<R: Runtime<DType = DType>> {
pub x: Tensor<R>,
pub fun: f64,
pub iterations: usize,
pub nfev: usize,
pub ngrad: usize,
pub nhvp: usize,
pub converged: bool,
pub grad_norm: f64,
}
impl<R: Runtime<DType = DType>> From<NewtonCGResult<R>> for TensorMinimizeResult<R> {
fn from(result: NewtonCGResult<R>) -> Self {
TensorMinimizeResult {
x: result.x,
fun: result.fun,
iterations: result.iterations,
nfev: result.nfev + result.ngrad + result.nhvp, converged: result.converged,
}
}
}
pub trait NewtonCGAlgorithms<R: Runtime<DType = DType>> {
fn newton_cg<F>(
&self,
f: F,
x0: &Tensor<R>,
options: &NewtonCGOptions,
) -> OptimizeResult<NewtonCGResult<R>>
where
F: Fn(&Var<R>, &Self) -> NumrResult<Var<R>>;
}