fix: cargo fmt
This commit is contained in:
@@ -1,50 +1,44 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
use super::Distance;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Euclidian {
|
||||
}
|
||||
pub struct Euclidian {}
|
||||
|
||||
impl Euclidian {
|
||||
pub fn squared_distance<T: FloatExt>(x: &Vec<T>,y: &Vec<T>) -> T {
|
||||
pub fn squared_distance<T: FloatExt>(x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
if x.len() != y.len() {
|
||||
panic!("Input vector sizes are different.");
|
||||
}
|
||||
|
||||
|
||||
let mut sum = T::zero();
|
||||
for i in 0..x.len() {
|
||||
sum = sum + (x[i] - y[i]).powf(T::two());
|
||||
}
|
||||
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T: FloatExt> Distance<Vec<T>, T> for Euclidian {
|
||||
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
Euclidian::squared_distance(x, y).sqrt()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn squared_distance() {
|
||||
let a = vec![1., 2., 3.];
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
let l2: f64 = Euclidian{}.distance(&a, &b);
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
assert!((l2 - 5.19615242).abs() < 1e-8);
|
||||
}
|
||||
let l2: f64 = Euclidian {}.distance(&a, &b);
|
||||
|
||||
}
|
||||
assert!((l2 - 5.19615242).abs() < 1e-8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,40 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
use super::Distance;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Hamming {
|
||||
}
|
||||
pub struct Hamming {}
|
||||
|
||||
impl<T: PartialEq, F: FloatExt> Distance<Vec<T>, F> for Hamming {
|
||||
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> F {
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> F {
|
||||
if x.len() != y.len() {
|
||||
panic!("Input vector sizes are different");
|
||||
}
|
||||
|
||||
|
||||
let mut dist = 0;
|
||||
for i in 0..x.len() {
|
||||
if x[i] != y[i]{
|
||||
if x[i] != y[i] {
|
||||
dist += 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
F::from_i64(dist).unwrap() / F::from_usize(x.len()).unwrap()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn minkowski_distance() {
|
||||
let a = vec![1, 0, 0, 1, 0, 0, 1];
|
||||
let b = vec![1, 1, 0, 0, 1, 0, 1];
|
||||
|
||||
let h: f64 = Hamming{}.distance(&a, &b);
|
||||
|
||||
let b = vec![1, 1, 0, 0, 1, 0, 1];
|
||||
|
||||
let h: f64 = Hamming {}.distance(&a, &b);
|
||||
|
||||
assert!((h - 0.42857142).abs() < 1e-8);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::linalg::Matrix;
|
||||
pub struct Mahalanobis<T: FloatExt, M: Matrix<T>> {
|
||||
pub sigma: M,
|
||||
pub sigmaInv: M,
|
||||
t: PhantomData<T>
|
||||
t: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: FloatExt, M: Matrix<T>> Mahalanobis<T, M> {
|
||||
@@ -23,7 +23,7 @@ impl<T: FloatExt, M: Matrix<T>> Mahalanobis<T, M> {
|
||||
Mahalanobis {
|
||||
sigma: sigma,
|
||||
sigmaInv: sigmaInv,
|
||||
t: PhantomData
|
||||
t: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,21 +33,30 @@ impl<T: FloatExt, M: Matrix<T>> Mahalanobis<T, M> {
|
||||
Mahalanobis {
|
||||
sigma: sigma,
|
||||
sigmaInv: sigmaInv,
|
||||
t: PhantomData
|
||||
t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FloatExt, M: Matrix<T>> Distance<Vec<T>, T> for Mahalanobis<T, M> {
|
||||
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
let (nrows, ncols) = self.sigma.shape();
|
||||
if x.len() != nrows {
|
||||
panic!("Array x[{}] has different dimension with Sigma[{}][{}].", x.len(), nrows, ncols);
|
||||
panic!(
|
||||
"Array x[{}] has different dimension with Sigma[{}][{}].",
|
||||
x.len(),
|
||||
nrows,
|
||||
ncols
|
||||
);
|
||||
}
|
||||
|
||||
if y.len() != nrows {
|
||||
panic!("Array y[{}] has different dimension with Sigma[{}][{}].", y.len(), nrows, ncols);
|
||||
panic!(
|
||||
"Array y[{}] has different dimension with Sigma[{}][{}].",
|
||||
y.len(),
|
||||
nrows,
|
||||
ncols
|
||||
);
|
||||
}
|
||||
|
||||
println!("{}", self.sigmaInv);
|
||||
@@ -56,7 +65,7 @@ impl<T: FloatExt, M: Matrix<T>> Distance<Vec<T>, T> for Mahalanobis<T, M> {
|
||||
let mut z = vec![T::zero(); n];
|
||||
for i in 0..n {
|
||||
z[i] = x[i] - y[i];
|
||||
}
|
||||
}
|
||||
|
||||
// np.dot(np.dot((a-b),VI),(a-b).T)
|
||||
let mut s = T::zero();
|
||||
@@ -67,31 +76,29 @@ impl<T: FloatExt, M: Matrix<T>> Distance<Vec<T>, T> for Mahalanobis<T, M> {
|
||||
}
|
||||
|
||||
s.sqrt()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
use crate::linalg::naive::dense_matrix::*;
|
||||
|
||||
#[test]
|
||||
fn mahalanobis_distance() {
|
||||
let data = DenseMatrix::from_array(&[
|
||||
&[ 64., 580., 29.],
|
||||
&[ 66., 570., 33.],
|
||||
&[ 68., 590., 37.],
|
||||
&[ 69., 660., 46.],
|
||||
&[ 73., 600., 55.]]);
|
||||
|
||||
&[64., 580., 29.],
|
||||
&[66., 570., 33.],
|
||||
&[68., 590., 37.],
|
||||
&[69., 660., 46.],
|
||||
&[73., 600., 55.],
|
||||
]);
|
||||
|
||||
let a = data.column_mean();
|
||||
let b = vec![66., 640., 44.];
|
||||
|
||||
let mahalanobis = Mahalanobis::new(&data);
|
||||
|
||||
let mahalanobis = Mahalanobis::new(&data);
|
||||
|
||||
println!("{}", mahalanobis.distance(&a, &b));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,38 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
use super::Distance;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Manhattan {
|
||||
}
|
||||
pub struct Manhattan {}
|
||||
|
||||
impl<T: FloatExt> Distance<Vec<T>, T> for Manhattan {
|
||||
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
if x.len() != y.len() {
|
||||
panic!("Input vector sizes are different");
|
||||
}
|
||||
|
||||
|
||||
let mut dist = T::zero();
|
||||
for i in 0..x.len() {
|
||||
dist = dist + (x[i] - y[i]).abs();
|
||||
}
|
||||
|
||||
for i in 0..x.len() {
|
||||
dist = dist + (x[i] - y[i]).abs();
|
||||
}
|
||||
|
||||
dist
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn manhattan_distance() {
|
||||
let a = vec![1., 2., 3.];
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
let l1: f64 = Manhattan{}.distance(&a, &b);
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
assert!((l1 - 9.0).abs() < 1e-8);
|
||||
}
|
||||
let l1: f64 = Manhattan {}.distance(&a, &b);
|
||||
|
||||
}
|
||||
assert!((l1 - 9.0).abs() < 1e-8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
@@ -6,58 +6,52 @@ use super::Distance;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Minkowski<T: FloatExt> {
|
||||
pub p: T
|
||||
pub p: T,
|
||||
}
|
||||
|
||||
impl<T: FloatExt> Distance<Vec<T>, T> for Minkowski<T> {
|
||||
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
fn distance(&self, x: &Vec<T>, y: &Vec<T>) -> T {
|
||||
if x.len() != y.len() {
|
||||
panic!("Input vector sizes are different");
|
||||
}
|
||||
if self.p < T::one() {
|
||||
panic!("p must be at least 1");
|
||||
}
|
||||
|
||||
|
||||
let mut dist = T::zero();
|
||||
for i in 0..x.len() {
|
||||
let d = (x[i] - y[i]).abs();
|
||||
dist = dist + d.powf(self.p);
|
||||
}
|
||||
|
||||
dist.powf(T::one()/self.p)
|
||||
}
|
||||
dist = dist + d.powf(self.p);
|
||||
}
|
||||
|
||||
dist.powf(T::one() / self.p)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn minkowski_distance() {
|
||||
let a = vec![1., 2., 3.];
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
let l1: f64 = Minkowski{p: 1.0}.distance(&a, &b);
|
||||
let l2: f64 = Minkowski{p: 2.0}.distance(&a, &b);
|
||||
let l3: f64 = Minkowski{p: 3.0}.distance(&a, &b);
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
let l1: f64 = Minkowski { p: 1.0 }.distance(&a, &b);
|
||||
let l2: f64 = Minkowski { p: 2.0 }.distance(&a, &b);
|
||||
let l3: f64 = Minkowski { p: 3.0 }.distance(&a, &b);
|
||||
|
||||
assert!((l1 - 9.0).abs() < 1e-8);
|
||||
assert!((l2 - 5.19615242).abs() < 1e-8);
|
||||
assert!((l2 - 5.19615242).abs() < 1e-8);
|
||||
assert!((l3 - 4.32674871).abs() < 1e-8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "p must be at least 1")]
|
||||
fn minkowski_distance_negative_p() {
|
||||
let a = vec![1., 2., 3.];
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
let _: f64 = Minkowski{p: 0.0}.distance(&a, &b);
|
||||
let b = vec![4., 5., 6.];
|
||||
|
||||
let _: f64 = Minkowski { p: 0.0 }.distance(&a, &b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+10
-11
@@ -1,32 +1,31 @@
|
||||
pub mod euclidian;
|
||||
pub mod minkowski;
|
||||
pub mod manhattan;
|
||||
pub mod hamming;
|
||||
pub mod mahalanobis;
|
||||
pub mod manhattan;
|
||||
pub mod minkowski;
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
pub trait Distance<T, F: FloatExt>{
|
||||
pub trait Distance<T, F: FloatExt> {
|
||||
fn distance(&self, a: &T, b: &T) -> F;
|
||||
}
|
||||
|
||||
pub struct Distances{
|
||||
}
|
||||
pub struct Distances {}
|
||||
|
||||
impl Distances {
|
||||
pub fn euclidian() -> euclidian::Euclidian{
|
||||
pub fn euclidian() -> euclidian::Euclidian {
|
||||
euclidian::Euclidian {}
|
||||
}
|
||||
|
||||
pub fn minkowski<T: FloatExt>(p: T) -> minkowski::Minkowski<T>{
|
||||
minkowski::Minkowski {p: p}
|
||||
pub fn minkowski<T: FloatExt>(p: T) -> minkowski::Minkowski<T> {
|
||||
minkowski::Minkowski { p: p }
|
||||
}
|
||||
|
||||
pub fn manhattan() -> manhattan::Manhattan{
|
||||
pub fn manhattan() -> manhattan::Manhattan {
|
||||
manhattan::Manhattan {}
|
||||
}
|
||||
|
||||
pub fn hamming() -> hamming::Hamming{
|
||||
pub fn hamming() -> hamming::Hamming {
|
||||
hamming::Hamming {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user