From 229858bca156eca0b18717445190d9d55c2999c0 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 14 Jan 2019 10:38:55 +0100 Subject: [PATCH 1/8] start implementing Multivariate normal distribution --- ndarray-rand/Cargo.toml | 12 ++++++--- ndarray-rand/src/lib.rs | 2 ++ ndarray-rand/src/multivariatenormal.rs | 37 ++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 ndarray-rand/src/multivariatenormal.rs diff --git a/ndarray-rand/Cargo.toml b/ndarray-rand/Cargo.toml index 1199fee9d..3cacaf5b3 100644 --- a/ndarray-rand/Cargo.toml +++ b/ndarray-rand/Cargo.toml @@ -11,10 +11,14 @@ description = "Constructors for randomized arrays. `rand` integration for `ndarr keywords = ["multidimensional", "matrix", "rand", "ndarray"] -[dependencies] -rand = "0.6.0" -ndarray = { version = "0.12.0", path = ".." } - [package.metadata.release] no-dev-version = true +[features] +normal-dist = ["ndarray-linalg"] + +[dependencies] +rand = "0.6.4" +ndarray = { version = "0.12.0", path = ".." } +ndarray-linalg = { version = "0.10.0", optional = true } + diff --git a/ndarray-rand/src/lib.rs b/ndarray-rand/src/lib.rs index 8349eb14f..68e7ea808 100644 --- a/ndarray-rand/src/lib.rs +++ b/ndarray-rand/src/lib.rs @@ -23,6 +23,8 @@ use ndarray::{ }; use ndarray::ShapeBuilder; +pub mod multivariatenormal; + /// Constructors for n-dimensional arrays with random elements. /// /// This trait extends ndarray’s `ArrayBase` and can not be implemented diff --git a/ndarray-rand/src/multivariatenormal.rs b/ndarray-rand/src/multivariatenormal.rs new file mode 100644 index 000000000..dbce2c685 --- /dev/null +++ b/ndarray-rand/src/multivariatenormal.rs @@ -0,0 +1,37 @@ +//! Implementation of the multiavariate normal distribution. +use super::RandomExt; +use ndarray::Ix1; +use ndarray::{Array1, Array2}; +use rand::Rng; +use rand::distributions::{Distribution, StandardNormal}; + +pub struct MultivariateStandardNormal +{ + shape: Ix1 +} + +impl MultivariateStandardNormal +{ + pub fn new(shape: Ix1) -> Self { + MultivariateStandardNormal { + shape + } + } +} + +impl Distribution> for MultivariateStandardNormal +{ + fn sample(&self, rng: &mut R) -> Array1 { + let shape = self.shape.clone(); + let res = Array1::random_using( + shape, StandardNormal, rng); + res + } +} + +#[cfg(feature = "normal-dist")] +/// The normal distribution `N(mean, covariance)`. +pub struct MultivariateNormal { + mean: Array1, + covariance: Array2 +} From c0df25398443e954346d915c316c88ef11f73db5 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 14 Jan 2019 11:20:40 +0100 Subject: [PATCH 2/8] add dimension test for standard normal --- ndarray-rand/src/multivariatenormal.rs | 47 ++++++++++++++++++++++---- ndarray-rand/tests/tests.rs | 15 +++++++- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/ndarray-rand/src/multivariatenormal.rs b/ndarray-rand/src/multivariatenormal.rs index dbce2c685..7f387ab60 100644 --- a/ndarray-rand/src/multivariatenormal.rs +++ b/ndarray-rand/src/multivariatenormal.rs @@ -1,7 +1,7 @@ //! Implementation of the multiavariate normal distribution. use super::RandomExt; use ndarray::Ix1; -use ndarray::{Array1, Array2}; +use ndarray::Array1; use rand::Rng; use rand::distributions::{Distribution, StandardNormal}; @@ -19,8 +19,7 @@ impl MultivariateStandardNormal } } -impl Distribution> for MultivariateStandardNormal -{ +impl Distribution> for MultivariateStandardNormal { fn sample(&self, rng: &mut R) -> Array1 { let shape = self.shape.clone(); let res = Array1::random_using( @@ -31,7 +30,41 @@ impl Distribution> for MultivariateStandardNormal #[cfg(feature = "normal-dist")] /// The normal distribution `N(mean, covariance)`. -pub struct MultivariateNormal { - mean: Array1, - covariance: Array2 -} +mod advanced_normal { + use rand::Rng; + use rand::distributions::{ + Distribution, StandardNormal + }; + use crate::RandomExt; + use ndarray::{Ix1, Array1, Array2}; + use ndarray_linalg::cholesky::*; + + pub struct MultivariateNormal { + shape: Ix1, + mean: Array1, + covariance: Array2 + } + + impl MultivariateNormal { + pub fn new(mean: Array1, covariance: Array2) -> Self { + let shape = mean.shape() as Ix1; + assert_eq!(shape[0], covariance.shape()[0]); + MultivariateNormal { + shape, mean, covariance + } + } + } + + impl Distribution> for MultivariateNormal { + fn sample(&self, rng: &mut R) -> Array1 { + let shape = self.shape.clone(); + // standard normal distribution + let res = Array1::random_using( + shape, StandardNormal, rng); + // use Cholesky decomposition to obtain a sample of our general multivariate normal + let l: Array2 = self.covariance.view().cholesky(UPLO::Lower).unwrap(); + self.mean.view() + l * res + } + } + +} \ No newline at end of file diff --git a/ndarray-rand/tests/tests.rs b/ndarray-rand/tests/tests.rs index aae89c543..3ac6c37d4 100644 --- a/ndarray-rand/tests/tests.rs +++ b/ndarray-rand/tests/tests.rs @@ -3,9 +3,12 @@ extern crate rand; extern crate ndarray; extern crate ndarray_rand; -use rand::distributions::Uniform; +use rand::distributions::{ + Uniform, Distribution +}; use ndarray::Array; use ndarray_rand::RandomExt; +use ndarray_rand::multivariatenormal::MultivariateStandardNormal; #[test] fn test_dim() { @@ -19,3 +22,13 @@ fn test_dim() { } } } + +#[test] +fn test_standard_normal() { + use ndarray::IntoDimension; + let shape = (2usize,).into_dimension(); + let n = MultivariateStandardNormal::new(shape.into()); + let ref mut rng = rand::thread_rng(); + let s: ndarray::Array1 = n.sample(rng); + assert_eq!(s.shape(), &[2]); +} From bb9ee987923f0f242cc9effea246143b246d16aa Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 14 Jan 2019 11:21:50 +0100 Subject: [PATCH 3/8] edit .gitignore to ignore IntelliJ platform files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1e7caa9ea..1db65aa0b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.idea/ Cargo.lock target/ From f743dad67f9081de879c75ea1915945d63183d02 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 14 Jan 2019 12:33:10 +0100 Subject: [PATCH 4/8] more efficient use of Cholesky --- ndarray-rand/src/lib.rs | 2 ++ ndarray-rand/src/multivariatenormal.rs | 27 +++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ndarray-rand/src/lib.rs b/ndarray-rand/src/lib.rs index 68e7ea808..9f9a03d7c 100644 --- a/ndarray-rand/src/lib.rs +++ b/ndarray-rand/src/lib.rs @@ -11,6 +11,8 @@ //! See [**`RandomExt`**](trait.RandomExt.html) for usage examples. extern crate rand; extern crate ndarray; +#[cfg(feature = "normal-dist")] +extern crate ndarray_linalg; use rand::{thread_rng, Rng, SeedableRng}; use rand::distributions::Distribution; diff --git a/ndarray-rand/src/multivariatenormal.rs b/ndarray-rand/src/multivariatenormal.rs index 7f387ab60..a6e74e6c1 100644 --- a/ndarray-rand/src/multivariatenormal.rs +++ b/ndarray-rand/src/multivariatenormal.rs @@ -36,22 +36,28 @@ mod advanced_normal { Distribution, StandardNormal }; use crate::RandomExt; - use ndarray::{Ix1, Array1, Array2}; - use ndarray_linalg::cholesky::*; + use ndarray::prelude::*; + use ndarray::IntoDimension; + use ndarray_linalg::*; + use ndarray_linalg::error::Result as LAResult; + /// Full multivariate normal distribution, with mean vector and covariance matrix. pub struct MultivariateNormal { shape: Ix1, mean: Array1, - covariance: Array2 + covariance: Array2, + /// Lower triangular Cholesky decomposition of the covariance matrix. + lower_covariance: Array2 } impl MultivariateNormal { - pub fn new(mean: Array1, covariance: Array2) -> Self { - let shape = mean.shape() as Ix1; - assert_eq!(shape[0], covariance.shape()[0]); - MultivariateNormal { - shape, mean, covariance - } + pub fn new(mean: Array1, covariance: Array2) -> LAResult { + use ndarray_linalg::cholesky::*; + let shape = [mean.shape()[0]].into_dimension(); + let l = covariance.cholesky(UPLO::Lower); + Ok(MultivariateNormal { + shape, mean, covariance, lower_covariance: l + }) } } @@ -62,8 +68,7 @@ mod advanced_normal { let res = Array1::random_using( shape, StandardNormal, rng); // use Cholesky decomposition to obtain a sample of our general multivariate normal - let l: Array2 = self.covariance.view().cholesky(UPLO::Lower).unwrap(); - self.mean.view() + l * res + self.mean.clone() + self.lower_covariance.view().dot(&res) } } From 72b23dd0b1f125c78113adf20161d397d5a52822 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Thu, 24 Jan 2019 19:57:37 +0100 Subject: [PATCH 5/8] refactor, add tests for multivariate normal --- ndarray-rand/Cargo.toml | 7 +-- ndarray-rand/src/lib.rs | 6 +-- ndarray-rand/src/multivariatenormal.rs | 75 -------------------------- ndarray-rand/src/normal.rs | 39 ++++++++++++++ ndarray-rand/src/normal/advanced.rs | 51 ++++++++++++++++++ ndarray-rand/tests/tests.rs | 22 ++++++-- 6 files changed, 114 insertions(+), 86 deletions(-) delete mode 100644 ndarray-rand/src/multivariatenormal.rs create mode 100644 ndarray-rand/src/normal.rs create mode 100644 ndarray-rand/src/normal/advanced.rs diff --git a/ndarray-rand/Cargo.toml b/ndarray-rand/Cargo.toml index 3cacaf5b3..492781c9a 100644 --- a/ndarray-rand/Cargo.toml +++ b/ndarray-rand/Cargo.toml @@ -14,11 +14,8 @@ keywords = ["multidimensional", "matrix", "rand", "ndarray"] [package.metadata.release] no-dev-version = true -[features] -normal-dist = ["ndarray-linalg"] [dependencies] rand = "0.6.4" -ndarray = { version = "0.12.0", path = ".." } -ndarray-linalg = { version = "0.10.0", optional = true } - +ndarray = { version = "0.12.1", path = ".." } +ndarray-linalg = { version = "0.10", features = ["openblas"] } diff --git a/ndarray-rand/src/lib.rs b/ndarray-rand/src/lib.rs index 9f9a03d7c..12cbffd1b 100644 --- a/ndarray-rand/src/lib.rs +++ b/ndarray-rand/src/lib.rs @@ -11,7 +11,7 @@ //! See [**`RandomExt`**](trait.RandomExt.html) for usage examples. extern crate rand; extern crate ndarray; -#[cfg(feature = "normal-dist")] +#[cfg(feature = "normaldist")] extern crate ndarray_linalg; use rand::{thread_rng, Rng, SeedableRng}; @@ -25,7 +25,7 @@ use ndarray::{ }; use ndarray::ShapeBuilder; -pub mod multivariatenormal; +pub mod normal; /// Constructors for n-dimensional arrays with random elements. /// @@ -70,7 +70,7 @@ pub trait RandomExt where IdS: Distribution, Sh: ShapeBuilder; - /// Create an array with shape `dim` with elements drawn from + /// Create an array with shape `shape` with elements drawn from /// `distribution`, using a specific Rng `rng`. /// /// ***Panics*** if the number of elements overflows usize. diff --git a/ndarray-rand/src/multivariatenormal.rs b/ndarray-rand/src/multivariatenormal.rs deleted file mode 100644 index a6e74e6c1..000000000 --- a/ndarray-rand/src/multivariatenormal.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Implementation of the multiavariate normal distribution. -use super::RandomExt; -use ndarray::Ix1; -use ndarray::Array1; -use rand::Rng; -use rand::distributions::{Distribution, StandardNormal}; - -pub struct MultivariateStandardNormal -{ - shape: Ix1 -} - -impl MultivariateStandardNormal -{ - pub fn new(shape: Ix1) -> Self { - MultivariateStandardNormal { - shape - } - } -} - -impl Distribution> for MultivariateStandardNormal { - fn sample(&self, rng: &mut R) -> Array1 { - let shape = self.shape.clone(); - let res = Array1::random_using( - shape, StandardNormal, rng); - res - } -} - -#[cfg(feature = "normal-dist")] -/// The normal distribution `N(mean, covariance)`. -mod advanced_normal { - use rand::Rng; - use rand::distributions::{ - Distribution, StandardNormal - }; - use crate::RandomExt; - use ndarray::prelude::*; - use ndarray::IntoDimension; - use ndarray_linalg::*; - use ndarray_linalg::error::Result as LAResult; - - /// Full multivariate normal distribution, with mean vector and covariance matrix. - pub struct MultivariateNormal { - shape: Ix1, - mean: Array1, - covariance: Array2, - /// Lower triangular Cholesky decomposition of the covariance matrix. - lower_covariance: Array2 - } - - impl MultivariateNormal { - pub fn new(mean: Array1, covariance: Array2) -> LAResult { - use ndarray_linalg::cholesky::*; - let shape = [mean.shape()[0]].into_dimension(); - let l = covariance.cholesky(UPLO::Lower); - Ok(MultivariateNormal { - shape, mean, covariance, lower_covariance: l - }) - } - } - - impl Distribution> for MultivariateNormal { - fn sample(&self, rng: &mut R) -> Array1 { - let shape = self.shape.clone(); - // standard normal distribution - let res = Array1::random_using( - shape, StandardNormal, rng); - // use Cholesky decomposition to obtain a sample of our general multivariate normal - self.mean.clone() + self.lower_covariance.view().dot(&res) - } - } - -} \ No newline at end of file diff --git a/ndarray-rand/src/normal.rs b/ndarray-rand/src/normal.rs new file mode 100644 index 000000000..835eb08dc --- /dev/null +++ b/ndarray-rand/src/normal.rs @@ -0,0 +1,39 @@ +//! Implementation of the multiavariate normal distribution. +use crate::RandomExt; +use ndarray::Ix1; +use ndarray::Array1; +use rand::Rng; +use rand::distributions::{Distribution, StandardNormal}; + +pub mod advanced; + +pub struct MultivariateStandardNormal +{ + shape: Ix1 +} + +/// Standard multivariate normal distribution `N(0,1)`. +/// +/// ``` +/// use ndarray; +/// use ndarray_rand::normal::MultivariateStandardNormal; +/// +/// let n = MultivariateStandardNormal(); +/// ``` +impl MultivariateStandardNormal +{ + pub fn new(shape: Ix1) -> Self { + MultivariateStandardNormal { + shape + } + } +} + +impl Distribution> for MultivariateStandardNormal { + fn sample(&self, rng: &mut R) -> Array1 { + let shape = self.shape.clone(); + let res = Array1::random_using( + shape, StandardNormal, rng); + res + } +} diff --git a/ndarray-rand/src/normal/advanced.rs b/ndarray-rand/src/normal/advanced.rs new file mode 100644 index 000000000..95c7d19a2 --- /dev/null +++ b/ndarray-rand/src/normal/advanced.rs @@ -0,0 +1,51 @@ +/// The normal distribution `N(mean, covariance)`. +use rand::Rng; +use rand::distributions::{ + Distribution, StandardNormal +}; + +use ndarray::prelude::*; +use ndarray_linalg::error::Result as LAResult; + +/// Multivariate normal distribution, with mean vector and covariance matrix. +pub struct MultivariateNormal { + shape: Ix1, + mean: Array1, + covariance: Array2, + lower: Array2 +} + +impl MultivariateNormal { + pub fn new(mean: Array1, covariance: Array2) -> LAResult { + let shape: Ix1 = Ix1(mean.shape()[0]); + use ndarray_linalg::cholesky::*; + let lower = covariance.cholesky(UPLO::Lower); + Ok(MultivariateNormal { + shape, mean, covariance, lower + }) + } + + pub fn shape(&self) -> Ix1 { + self.shape + } + + pub fn mean(&self) -> ArrayView1 { + self.mean.view() + } + + pub fn covariance(&self) -> ArrayView2 { + self.covariance.view() + } +} + +impl Distribution> for MultivariateNormal { + fn sample(&self, rng: &mut R) -> Array1 { + let shape = self.shape.clone(); + // standard normal distribution + use crate::RandomExt; + let res = Array1::random_using( + shape, StandardNormal, rng); + // use Cholesky decomposition to obtain a sample of our general multivariate normal + self.mean.view() + self.lower.view().dot(&res) + } +} diff --git a/ndarray-rand/tests/tests.rs b/ndarray-rand/tests/tests.rs index 3ac6c37d4..e57f04423 100644 --- a/ndarray-rand/tests/tests.rs +++ b/ndarray-rand/tests/tests.rs @@ -1,4 +1,3 @@ - extern crate rand; extern crate ndarray; extern crate ndarray_rand; @@ -8,7 +7,7 @@ use rand::distributions::{ }; use ndarray::Array; use ndarray_rand::RandomExt; -use ndarray_rand::multivariatenormal::MultivariateStandardNormal; +use ndarray_rand::normal::MultivariateStandardNormal; #[test] fn test_dim() { @@ -26,9 +25,26 @@ fn test_dim() { #[test] fn test_standard_normal() { use ndarray::IntoDimension; - let shape = (2usize,).into_dimension(); + let shape = (2usize,); let n = MultivariateStandardNormal::new(shape.into()); let ref mut rng = rand::thread_rng(); let s: ndarray::Array1 = n.sample(rng); assert_eq!(s.shape(), &[2]); } + +#[test] +fn test_normal() { + use ndarray::IntoDimension; + use ndarray::{Array1, arr2}; + use ndarray_rand::normal::advanced::MultivariateNormal; + let shape = (2usize,); + let mean = Array1::from_vec([1., 0.]); + let covar = arr2([ + [1., 0.8], [0.8, 1.]]); + let ref mut rng = rand::thread_rng(); + let n = MultivariateNormal::new(mean, covar); + if let Ok(n) = n { + let x = n.sample(rng); + assert_eq!(x.shape(), &[2, 2]); + } +} From 860c780eb62f71437759ca2e29f4520db91ac793 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Fri, 25 Jan 2019 10:32:30 +0100 Subject: [PATCH 6/8] Fixed full normal distribution, re-add feature flag, add tests --- ndarray-rand/Cargo.toml | 10 ++++-- ndarray-rand/src/normal.rs | 47 +++++++++++++++++++---------- ndarray-rand/src/normal/advanced.rs | 8 +++-- ndarray-rand/tests/tests.rs | 7 ++--- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/ndarray-rand/Cargo.toml b/ndarray-rand/Cargo.toml index 492781c9a..b694be32c 100644 --- a/ndarray-rand/Cargo.toml +++ b/ndarray-rand/Cargo.toml @@ -14,8 +14,14 @@ keywords = ["multidimensional", "matrix", "rand", "ndarray"] [package.metadata.release] no-dev-version = true +[features] +normaldist = ["ndarray-linalg"] [dependencies] rand = "0.6.4" -ndarray = { version = "0.12.1", path = ".." } -ndarray-linalg = { version = "0.10", features = ["openblas"] } +ndarray = { version = "0.12.1" } + +[dependencies.ndarray-linalg] +version = "0.10" +optional = true +features = ["openblas"] diff --git a/ndarray-rand/src/normal.rs b/ndarray-rand/src/normal.rs index 835eb08dc..19e01f83d 100644 --- a/ndarray-rand/src/normal.rs +++ b/ndarray-rand/src/normal.rs @@ -1,38 +1,53 @@ //! Implementation of the multiavariate normal distribution. use crate::RandomExt; -use ndarray::Ix1; -use ndarray::Array1; +use ndarray::{Array, IntoDimension, Dimension}; use rand::Rng; use rand::distributions::{Distribution, StandardNormal}; +#[cfg(feature = "normaldist")] pub mod advanced; -pub struct MultivariateStandardNormal -{ - shape: Ix1 -} - -/// Standard multivariate normal distribution `N(0,1)`. +/// Standard multivariate normal distribution `N(0,1)` for any-dimensional arrays. /// /// ``` +/// extern crate rand; +/// extern crate ndarray; +/// extern crate ndarray_rand; +/// +/// use rand; +/// use rand::distributions::Distribution; /// use ndarray; /// use ndarray_rand::normal::MultivariateStandardNormal; -/// -/// let n = MultivariateStandardNormal(); +/// +/// let shape = (2, 3); // create (2,3)-matrix of standard normal variables +/// let n = MultivariateStandardNormal::new(shape); +/// let ref mut rng = rand::thread_rng(); +/// println!("{:?}", n.sample(rng)); /// ``` -impl MultivariateStandardNormal +pub struct MultivariateStandardNormal +where D: Dimension { - pub fn new(shape: Ix1) -> Self { + shape: D +} + +impl MultivariateStandardNormal +where D: Dimension +{ + pub fn new(shape: Sh) -> Self + where Sh: IntoDimension + { MultivariateStandardNormal { - shape + shape: shape.into_dimension() } } } -impl Distribution> for MultivariateStandardNormal { - fn sample(&self, rng: &mut R) -> Array1 { +impl Distribution> for MultivariateStandardNormal +where D: Dimension +{ + fn sample(&self, rng: &mut R) -> Array { let shape = self.shape.clone(); - let res = Array1::random_using( + let res = Array::random_using( shape, StandardNormal, rng); res } diff --git a/ndarray-rand/src/normal/advanced.rs b/ndarray-rand/src/normal/advanced.rs index 95c7d19a2..fa2d82f5c 100644 --- a/ndarray-rand/src/normal/advanced.rs +++ b/ndarray-rand/src/normal/advanced.rs @@ -7,11 +7,13 @@ use rand::distributions::{ use ndarray::prelude::*; use ndarray_linalg::error::Result as LAResult; -/// Multivariate normal distribution, with mean vector and covariance matrix. +/// Multivariate normal distribution for 1D arrays, +/// with mean vector and covariance matrix. pub struct MultivariateNormal { shape: Ix1, mean: Array1, covariance: Array2, + /// Lower triangular matrix (Cholesky decomposition of the coviariance matrix) lower: Array2 } @@ -19,7 +21,7 @@ impl MultivariateNormal { pub fn new(mean: Array1, covariance: Array2) -> LAResult { let shape: Ix1 = Ix1(mean.shape()[0]); use ndarray_linalg::cholesky::*; - let lower = covariance.cholesky(UPLO::Lower); + let lower = covariance.cholesky(UPLO::Lower)?; Ok(MultivariateNormal { shape, mean, covariance, lower }) @@ -46,6 +48,6 @@ impl Distribution> for MultivariateNormal { let res = Array1::random_using( shape, StandardNormal, rng); // use Cholesky decomposition to obtain a sample of our general multivariate normal - self.mean.view() + self.lower.view().dot(&res) + self.mean.clone() + self.lower.view().dot(&res) } } diff --git a/ndarray-rand/tests/tests.rs b/ndarray-rand/tests/tests.rs index e57f04423..64441646a 100644 --- a/ndarray-rand/tests/tests.rs +++ b/ndarray-rand/tests/tests.rs @@ -24,20 +24,19 @@ fn test_dim() { #[test] fn test_standard_normal() { - use ndarray::IntoDimension; - let shape = (2usize,); - let n = MultivariateStandardNormal::new(shape.into()); + let shape = 2usize; + let n = MultivariateStandardNormal::new(shape); let ref mut rng = rand::thread_rng(); let s: ndarray::Array1 = n.sample(rng); assert_eq!(s.shape(), &[2]); } +#[cfg(features = "normaldist")] #[test] fn test_normal() { use ndarray::IntoDimension; use ndarray::{Array1, arr2}; use ndarray_rand::normal::advanced::MultivariateNormal; - let shape = (2usize,); let mean = Array1::from_vec([1., 0.]); let covar = arr2([ [1., 0.8], [0.8, 1.]]); From 5d0d201f69eea1182d4dcae079df1a3d3831b011 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Fri, 25 Jan 2019 11:23:36 +0100 Subject: [PATCH 7/8] Add shape() method on MultivariateStandardNormal --- ndarray-rand/src/normal.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ndarray-rand/src/normal.rs b/ndarray-rand/src/normal.rs index 19e01f83d..490b612e2 100644 --- a/ndarray-rand/src/normal.rs +++ b/ndarray-rand/src/normal.rs @@ -40,6 +40,10 @@ where D: Dimension shape: shape.into_dimension() } } + + pub fn shape(&self) -> D { + self.shape.clone() + } } impl Distribution> for MultivariateStandardNormal From 67fa4769a2aa635fc56a57790eac273d937c69ff Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Sat, 12 Oct 2019 19:15:07 +0200 Subject: [PATCH 8/8] Additional changes post-merge --- ndarray-rand/Cargo.toml | 2 +- ndarray-rand/src/normal.rs | 11 ++++------- ndarray-rand/tests/tests.rs | 1 + 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/ndarray-rand/Cargo.toml b/ndarray-rand/Cargo.toml index 64a543389..1fbbeba2c 100644 --- a/ndarray-rand/Cargo.toml +++ b/ndarray-rand/Cargo.toml @@ -22,7 +22,7 @@ quickcheck = { version = "0.9", default-features = false, optional = true } normaldist = ["ndarray-linalg"] [dependencies.ndarray-linalg] -version = "0.10" +version = "0.11" optional = true features = ["openblas"] diff --git a/ndarray-rand/src/normal.rs b/ndarray-rand/src/normal.rs index 490b612e2..b02effb47 100644 --- a/ndarray-rand/src/normal.rs +++ b/ndarray-rand/src/normal.rs @@ -1,8 +1,9 @@ //! Implementation of the multiavariate normal distribution. use crate::RandomExt; use ndarray::{Array, IntoDimension, Dimension}; -use rand::Rng; -use rand::distributions::{Distribution, StandardNormal}; +use crate::rand::Rng; +use crate::rand::distributions::Distribution; +use crate::rand_distr::{StandardNormal}; #[cfg(feature = "normaldist")] pub mod advanced; @@ -10,12 +11,8 @@ pub mod advanced; /// Standard multivariate normal distribution `N(0,1)` for any-dimensional arrays. /// /// ``` -/// extern crate rand; -/// extern crate ndarray; -/// extern crate ndarray_rand; -/// /// use rand; -/// use rand::distributions::Distribution; +/// use rand_distr::Distribution; /// use ndarray; /// use ndarray_rand::normal::MultivariateStandardNormal; /// diff --git a/ndarray-rand/tests/tests.rs b/ndarray-rand/tests/tests.rs index d3f236811..9ba53ffb7 100644 --- a/ndarray-rand/tests/tests.rs +++ b/ndarray-rand/tests/tests.rs @@ -2,6 +2,7 @@ use ndarray::{Array, Array2, ArrayView1, Axis}; #[cfg(feature = "quickcheck")] use ndarray_rand::rand::{distributions::Distribution, thread_rng}; use ndarray_rand::rand_distr::Uniform; +use ndarray_rand::normal::MultivariateStandardNormal; use ndarray_rand::{RandomExt, SamplingStrategy}; use quickcheck::quickcheck;