--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kernels/linear.rs Tue Dec 31 09:25:45 2024 -0500 @@ -0,0 +1,94 @@ +//! Implementation of the linear function + +use numeric_literals::replace_float_literals; +use serde::Serialize; +use alg_tools::types::*; +use alg_tools::norms::*; +use alg_tools::loc::Loc; +use alg_tools::sets::Cube; +use alg_tools::bisection_tree::{ + Support, + Bounds, + LocalAnalysis, + GlobalAnalysis, + Bounded, +}; +use alg_tools::mapping::{Mapping, Instance}; +use alg_tools::maputil::array_init; +use alg_tools::euclidean::Euclidean; + +/// Representation of the hat function $f(x)=1-\\|x\\|\_1/ε$ of `width` $ε$ on $ℝ^N$. +#[derive(Copy,Clone,Serialize,Debug,Eq,PartialEq)] +pub struct Linear<F : Float, const N : usize> { + /// The parameter $ε>0$. + pub v : Loc<F, N>, +} + +#[replace_float_literals(F::cast_from(literal))] +impl<F : Float, const N : usize> Mapping<Loc<F, N>> for Linear<F, N> { + type Codomain = F; + + #[inline] + fn apply<I : Instance<Loc<F, N>>>(&self, x : I) -> Self::Codomain { + x.eval(|x| self.v.dot(x)) + } +} + + +#[replace_float_literals(F::cast_from(literal))] +impl<'a, F : Float, const N : usize> Support<F, N> for Linear<F, N> { + #[inline] + fn support_hint(&self) -> Cube<F,N> { + array_init(|| [F::NEG_INFINITY, F::INFINITY]).into() + } + + #[inline] + fn in_support(&self, _x : &Loc<F,N>) -> bool { + true + } + + /*fn fully_in_support(&self, _cube : &Cube<F,N>) -> bool { + todo!("Not implemented, but not used at the moment") + }*/ + + #[inline] + fn bisection_hint(&self, _cube : &Cube<F,N>) -> [Option<F>; N] { + [None; N] + } +} + + +#[replace_float_literals(F::cast_from(literal))] +impl<'a, F : Float, const N : usize> +GlobalAnalysis<F, Bounds<F>> +for Linear<F, N> { + #[inline] + fn global_analysis(&self) -> Bounds<F> { + Bounds(F::NEG_INFINITY, F::INFINITY) + } +} + +impl<'a, F : Float, const N : usize> +LocalAnalysis<F, Bounds<F>, N> +for Linear<F, N> { + #[inline] + fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> { + let (lower, upper) = cube.iter_corners() + .map(|x| self.apply(x)) + .fold((F::INFINITY, F::NEG_INFINITY), |(lower, upper), v| { + (lower.min(v), upper.max(v)) + }); + Bounds(lower, upper) + } +} + +#[replace_float_literals(F::cast_from(literal))] +impl<'a, F : Float, const N : usize> +Norm<F, Linfinity> +for Linear<F, N> { + #[inline] + fn norm(&self, _ : Linfinity) -> F { + self.bounds().upper() + } +} +