opensrdk_kernel_method/exponential.rs
1use std::ops::{Add, Mul};
2
3use crate::KernelError;
4
5use super::{KernelAdd, KernelMul, PositiveDefiniteKernel};
6use opensrdk_symbolic_computation::Expression;
7
8const PARAMS_LEN: usize = 1;
9
10#[derive(Clone, Debug)]
11pub struct Exponential;
12
13impl PositiveDefiniteKernel for Exponential {
14 fn expression(
15 &self,
16 x: Expression,
17 x_prime: Expression,
18 params: &[Expression],
19 ) -> Result<Expression, KernelError> {
20 if params.len() != PARAMS_LEN {
21 return Err(KernelError::ParametersLengthMismatch.into());
22 }
23 // if x.len() != x_prime.len() {
24 // return Err(KernelError::InvalidArgument.into());
25 // }
26
27 let diff = x - x_prime;
28
29 Ok((-diff
30 .clone()
31 .dot(diff, &[[0, 0]])
32 .pow(Expression::from(1.0 / 2.0))
33 / params[0].clone())
34 .exp())
35 }
36
37 fn params_len(&self) -> usize {
38 1
39 }
40}
41
42impl<R> Add<R> for Exponential
43where
44 R: PositiveDefiniteKernel,
45{
46 type Output = KernelAdd<Self, R>;
47
48 fn add(self, rhs: R) -> Self::Output {
49 KernelAdd::new(self, rhs)
50 }
51}
52
53impl<R> Mul<R> for Exponential
54where
55 R: PositiveDefiniteKernel,
56{
57 type Output = KernelMul<Self, R>;
58
59 fn mul(self, rhs: R) -> Self::Output {
60 KernelMul::new(self, rhs)
61 }
62}
63
64// use super::PositiveDefiniteKernel;
65// use crate::{
66// KernelAdd, KernelError, KernelMul, ParamsDifferentiableKernel, ValueDifferentiableKernel,
67// };
68// use opensrdk_linear_algebra::Vector;
69// use rayon::prelude::*;
70// use std::{ops::Add, ops::Mul};
71
72// const PARAMS_LEN: usize = 1;
73
74// #[derive(Clone, Debug)]
75// pub struct Exponential;
76
77// impl Exponential {
78// fn norm(&self, params: &[f64], x: &Vec<f64>, xprime: &Vec<f64>) -> Result<f64, KernelError> {
79// if params.len() != PARAMS_LEN {
80// return Err(KernelError::ParametersLengthMismatch.into());
81// }
82// if x.len() != xprime.len() {
83// return Err(KernelError::InvalidArgument.into());
84// }
85
86// let v = x
87// .par_iter()
88// .zip(xprime.par_iter())
89// .map(|(x_i, xprime_i)| (x_i - xprime_i).powi(2))
90// .sum::<f64>()
91// .sqrt();
92
93// Ok(v)
94// }
95// }
96
97// impl PositiveDefiniteKernel<Vec<f64>> for Exponential {
98// fn params_len(&self) -> usize {
99// PARAMS_LEN
100// }
101
102// fn value(&self, params: &[f64], x: &Vec<f64>, xprime: &Vec<f64>) -> Result<f64, KernelError> {
103// let norm = self.norm(params, x, xprime)?;
104
105// let fx = (-norm / params[0]).exp();
106
107// Ok(fx)
108// }
109// }
110
111// impl ValueDifferentiableKernel<Vec<f64>> for Exponential {
112// fn ln_diff_value(
113// &self,
114// params: &[f64],
115// x: &Vec<f64>,
116// xprime: &Vec<f64>,
117// ) -> Result<Vec<f64>, KernelError> {
118// let diff = (-2.0 / params[0] * (x.clone().col_mat() - xprime.clone().col_mat())).vec();
119// Ok(diff)
120// }
121// }
122
123// impl ParamsDifferentiableKernel<Vec<f64>> for Exponential {
124// fn ln_diff_params(
125// &self,
126// params: &[f64],
127// x: &Vec<f64>,
128// xprime: &Vec<f64>,
129// ) -> Result<Vec<f64>, KernelError> {
130// let diff1 = 2.0 * params[0].powi(-2) * &self.norm(params, x, xprime).unwrap();
131// let diff = vec![diff1];
132// Ok(diff)
133// }
134// }
135
136// impl<R> Add<R> for Exponential
137// where
138// R: PositiveDefiniteKernel<Vec<f64>>,
139// {
140// type Output = KernelAdd<Self, R, Vec<f64>>;
141
142// fn add(self, rhs: R) -> Self::Output {
143// Self::Output::new(self, rhs)
144// }
145// }
146
147// impl<R> Mul<R> for Exponential
148// where
149// R: PositiveDefiniteKernel<Vec<f64>>,
150// {
151// type Output = KernelMul<Self, R, Vec<f64>>;
152
153// fn mul(self, rhs: R) -> Self::Output {
154// Self::Output::new(self, rhs)
155// }
156// }
157
158// #[cfg(test)]
159// mod tests {
160// use crate::*;
161// #[test]
162// fn it_works() {
163// let kernel = Exponential;
164
165// let test_value = kernel
166// .value(&[1.0], &vec![1.0, 0.0, 0.0], &vec![0.0, 0.0, 0.0])
167// .unwrap();
168
169// assert_eq!(test_value, (-1f64).exp());
170// }
171// }