#![allow(clippy::range_plus_one)]
#[macro_use]
pub mod macros;
mod errors;
pub mod executor;
mod iterstate;
mod kv;
mod math;
mod nooperator;
mod observers;
mod opwrapper;
mod result;
mod serialization;
mod termination;
pub use crate::errors::*;
pub use crate::executor::*;
pub use crate::iterstate::*;
pub use crate::kv::ArgminKV;
pub use crate::math::*;
pub use crate::nooperator::*;
pub use crate::observers::*;
pub use crate::opwrapper::*;
pub use crate::result::ArgminResult;
pub use crate::termination::TerminationReason;
pub use failure::Error;
use serde::de::DeserializeOwned;
use serde::Serialize;
pub use serialization::*;
pub mod finitediff {
pub use finitediff::*;
}
pub trait ArgminOp: Clone + Send + Sync + Serialize {
type Param: Clone + Serialize + DeserializeOwned;
type Output: Clone + Serialize + DeserializeOwned;
type Hessian: Clone + Serialize + DeserializeOwned;
type Jacobian: Clone + Serialize + DeserializeOwned;
fn apply(&self, _param: &Self::Param) -> Result<Self::Output, Error> {
Err(ArgminError::NotImplemented {
text: "Method `apply` of ArgminOp trait not implemented!".to_string(),
}
.into())
}
fn gradient(&self, _param: &Self::Param) -> Result<Self::Param, Error> {
Err(ArgminError::NotImplemented {
text: "Method `gradient` of ArgminOp trait not implemented!".to_string(),
}
.into())
}
fn hessian(&self, _param: &Self::Param) -> Result<Self::Hessian, Error> {
Err(ArgminError::NotImplemented {
text: "Method `hessian` of ArgminOp trait not implemented!".to_string(),
}
.into())
}
fn jacobian(&self, _param: &Self::Param) -> Result<Self::Jacobian, Error> {
Err(ArgminError::NotImplemented {
text: "Method `jacobian` of ArgminOp trait not implemented!".to_string(),
}
.into())
}
fn modify(&self, _param: &Self::Param, _extent: f64) -> Result<Self::Param, Error> {
Err(ArgminError::NotImplemented {
text: "Method `modify` of ArgminOp trait not implemented!".to_string(),
}
.into())
}
}
pub trait Solver<O: ArgminOp>: Serialize {
const NAME: &'static str = "UNDEFINED";
fn next_iter(
&mut self,
op: &mut OpWrapper<O>,
state: &IterState<O>,
) -> Result<ArgminIterData<O>, Error>;
fn init(
&mut self,
_op: &mut OpWrapper<O>,
_state: &IterState<O>,
) -> Result<Option<ArgminIterData<O>>, Error> {
Ok(None)
}
fn terminate_internal(&mut self, state: &IterState<O>) -> TerminationReason {
let solver_terminate = self.terminate(state);
if solver_terminate.terminated() {
return solver_terminate;
}
if state.get_iter() >= state.get_max_iters() {
return TerminationReason::MaxItersReached;
}
if state.get_cost() <= state.get_target_cost() {
return TerminationReason::TargetCostReached;
}
TerminationReason::NotTerminated
}
fn terminate(&mut self, _state: &IterState<O>) -> TerminationReason {
TerminationReason::NotTerminated
}
}
#[derive(Clone, Serialize, Debug, Default)]
pub struct ArgminIterData<O: ArgminOp> {
param: Option<O::Param>,
cost: Option<f64>,
grad: Option<O::Param>,
hessian: Option<O::Hessian>,
jacobian: Option<O::Jacobian>,
termination_reason: Option<TerminationReason>,
kv: ArgminKV,
}
impl<O: ArgminOp> ArgminIterData<O> {
pub fn new() -> Self {
ArgminIterData {
param: None,
cost: None,
grad: None,
hessian: None,
jacobian: None,
termination_reason: None,
kv: make_kv!(),
}
}
pub fn param(mut self, param: O::Param) -> Self {
self.param = Some(param);
self
}
pub fn cost(mut self, cost: f64) -> Self {
self.cost = Some(cost);
self
}
pub fn grad(mut self, grad: O::Param) -> Self {
self.grad = Some(grad);
self
}
pub fn hessian(mut self, hessian: O::Hessian) -> Self {
self.hessian = Some(hessian);
self
}
pub fn jacobian(mut self, jacobian: O::Jacobian) -> Self {
self.jacobian = Some(jacobian);
self
}
pub fn kv(mut self, kv: ArgminKV) -> Self {
self.kv = kv;
self
}
pub fn termination_reason(mut self, reason: TerminationReason) -> Self {
self.termination_reason = Some(reason);
self
}
pub fn get_param(&self) -> Option<O::Param> {
self.param.clone()
}
pub fn get_cost(&self) -> Option<f64> {
self.cost
}
pub fn get_grad(&self) -> Option<O::Param> {
self.grad.clone()
}
pub fn get_hessian(&self) -> Option<O::Hessian> {
self.hessian.clone()
}
pub fn get_jacobian(&self) -> Option<O::Jacobian> {
self.jacobian.clone()
}
pub fn get_termination_reason(&self) -> Option<TerminationReason> {
self.termination_reason
}
pub fn get_kv(&self) -> ArgminKV {
self.kv.clone()
}
}
pub trait ArgminLineSearch<P>: Serialize {
fn set_search_direction(&mut self, direction: P);
fn set_init_alpha(&mut self, step_length: f64) -> Result<(), Error>;
}
pub trait ArgminTrustRegion: Clone + Serialize {
fn set_radius(&mut self, radius: f64);
}
pub trait ArgminNLCGBetaUpdate<T>: Serialize {
fn update(&self, nabla_f_k: &T, nabla_f_k_p_1: &T, p_k: &T) -> f64;
}