Skip to content

Commit

Permalink
v 2.0.8
Browse files Browse the repository at this point in the history
  • Loading branch information
liborty committed Mar 5, 2024
1 parent de6b5d4 commit cec7d5e
Show file tree
Hide file tree
Showing 5 changed files with 8 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rstats"
version = "2.0.7"
version = "2.0.8"
authors = ["Libor Spacek"]
edition = "2021"
description = "Statistics, Information Measures, Data Analysis, Linear Algebra, Clifford Algebra, Machine Learning, Geometric Median, Matrix Decompositions, Mahalanobis Distance, Hulls, Multithreading.."
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ Methods which take an additional generic vector argument, such as a vector of we

## Appendix: Recent Releases

* **Version 2.0.8**' - Changed initial guess in iterative weighted gm methods to weighted mean. This, being more accurate than plain mean, leads to fewer iterations. Updated some dependecies.

* **Version 2.0.7** - Updated to `ran 2.0`.

* **Version 2.0.6** - Added convenience method `medmad` to Stats trait. It packs median and mad into `struct Params`, similarly to `ameanstd` and others. Consequently simplified the printouts in some tests.
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,6 @@ pub trait VecVecg<T, U> {
fn dists(self, v: &[U]) -> Result<Vec<f64>, RE>;
/// Weighted sorted weighted radii magnitudes, normalised
fn wsortedrads(self, ws: &[U], gm: &[f64]) -> Result<Vec<f64>, RE>;
/// Like wgmparts, except only does one iteration from any non-member point g
fn wnxnonmember(self, ws: &[U], g: &[f64]) -> Result<(Vec<f64>, Vec<f64>, f64), RE>;
/// The weighted geometric median to accuracy eps
fn wgmedian(self, ws: &[U], eps: f64) -> Result<Vec<f64>, RE>;
/// Parallel (multithreaded) implementation of the weighted Geometric Median.
Expand Down
32 changes: 4 additions & 28 deletions src/vecvecg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,37 +262,13 @@ impl<T,U> VecVecg<T,U> for &[Vec<T>]
.collect::<Vec<f64>>();
res.muthashsort(noop);
Ok(res)
}

/// Like wgmparts, except only does one iteration from any non-member point g
fn wnxnonmember(self, ws:&[U], g:&[f64]) -> Result<(Vec<f64>,Vec<f64>,f64),RE> {
if self.len() != ws.len() {
return Err(RError::DataError("wnxnonmember and ws lengths mismatch".to_owned())); };
if self[0].len() != g.len() {
return Err(RError::DataError("wnxnonmember self and gm dimensions mismatch".to_owned())); };
// vsum is the sum vector of unit vectors towards the points
let mut vsum = vec![0_f64; self[0].len()];
let mut recip = 0_f64;
for (x,w) in self.iter().zip(ws) {
// |x-p| done in-place for speed. Could have simply called x.vdist(p)
let mag:f64 = x.iter().zip(g).map(|(xi,&gi)|(xi.clone().into()-gi).powi(2)).sum::<f64>();
if mag.is_normal() { // ignore this point should distance be zero
let rec = w.clone().into()/(mag.sqrt()); // reciprocal of distance (scalar)
// vsum increments by components
vsum.iter_mut().zip(x).for_each(|(vi,xi)| *vi += xi.clone().into()*rec);
recip += rec // add separately the reciprocals for final scaling
}
}
Ok(( vsum.iter().map(|vi| vi / recip).collect::<Vec<f64>>(),
vsum,
recip ))
}
}

/// Weighted Geometric Median (gm) is the point that minimises the sum of distances to a given set of points.
fn wgmedian(self, ws:&[U], eps: f64) -> Result<Vec<f64>,RE> {
if self.len() != ws.len() {
return Err(RError::DataError("wgmedian and ws lengths mismatch".to_owned())); };
let mut g = self.acentroid(); // start iterating from the Centre
let mut g = self.wacentroid(ws); // start iterating from the weighted centre
let mut recsum = 0f64;
loop { // vector iteration till accuracy eps is exceeded
let mut nextg = vec![0_f64; self[0].len()];
Expand Down Expand Up @@ -325,7 +301,7 @@ impl<T,U> VecVecg<T,U> for &[Vec<T>]
fn par_wgmedian(self, ws: &[U], eps: f64) -> Result<Vec<f64>,RE> {
if self.len() != ws.len() {
return Err(RError::DataError("wgmedian and ws lengths mismatch".to_owned())); };
let mut g = self.acentroid(); // start iterating from the mean or vec![0_f64; self[0].len()];
let mut g = self.wacentroid(ws); // start iterating from the weighted centre or from vec![0_f64; self[0].len()]
let mut recsum = 0_f64;
loop {
// vector iteration till accuracy eps is exceeded
Expand Down Expand Up @@ -373,7 +349,7 @@ impl<T,U> VecVecg<T,U> for &[Vec<T>]
fn wgmparts(self, ws:&[U], eps: f64) -> Result<(Vec<f64>,Vec<f64>,f64),RE> {
if self.len() != ws.len() {
return Err(RError::DataError("wgmparts and ws lengths mismatch".to_owned())); };
let mut g = self.acentroid(); // start iterating from the Centre
let mut g = self.wacentroid(ws); // start iterating from the weighted centre
let mut recsum = 0f64;
loop { // vector iteration till accuracy eps is exceeded
let mut nextg = vec![0_f64; self[0].len()];
Expand Down
2 changes: 1 addition & 1 deletion tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ fn hulls() -> Result<(), RE> {

let allptsig = zeropts.sigvec(&Vec::from_iter(0..zeropts.len()))?;
println!(
"\nSigvec from all points: {} mod: {}",
"\nSigvec for all points: {} mod: {}",
allptsig.gr(), allptsig.vmag().gr()
);
Ok(())
Expand Down

0 comments on commit cec7d5e

Please sign in to comment.