Skip to content

Commit 3a8520c

Browse files
authored
Merge pull request #338 from rust-ndarray/test-fixed-seed
Fix PRNG seed for random vectors and matrices in tests
2 parents f3a9f4c + 4ea4f36 commit 3a8520c

26 files changed

+302
-192
lines changed

ndarray-linalg/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ paste = "1.0.5"
5151
criterion = "0.3.4"
5252
# Keep the same version as ndarray's dependency!
5353
approx = { version = "0.4.0", features = ["num-complex"] }
54+
rand_pcg = "0.3.1"
5455

5556
[[bench]]
5657
name = "truncated_eig"

ndarray-linalg/src/lobpcg/lobpcg.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,8 @@ mod tests {
460460
/// Test the `sorted_eigen` function
461461
#[test]
462462
fn test_sorted_eigen() {
463-
let matrix: Array2<f64> = generate::random((10, 10)) * 10.0;
463+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
464+
let matrix: Array2<f64> = generate::random_using((10, 10), &mut rng) * 10.0;
464465
let matrix = matrix.t().dot(&matrix);
465466

466467
// return all eigenvectors with largest first
@@ -476,7 +477,8 @@ mod tests {
476477
/// Test the masking function
477478
#[test]
478479
fn test_masking() {
479-
let matrix: Array2<f64> = generate::random((10, 5)) * 10.0;
480+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
481+
let matrix: Array2<f64> = generate::random_using((10, 5), &mut rng) * 10.0;
480482
let masked_matrix = ndarray_mask(matrix.view(), &[true, true, false, true, false]);
481483
close_l2(
482484
&masked_matrix.slice(s![.., 2]),
@@ -488,7 +490,8 @@ mod tests {
488490
/// Test orthonormalization of a random matrix
489491
#[test]
490492
fn test_orthonormalize() {
491-
let matrix: Array2<f64> = generate::random((10, 10)) * 10.0;
493+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
494+
let matrix: Array2<f64> = generate::random_using((10, 10), &mut rng) * 10.0;
492495

493496
let (n, l) = orthonormalize(matrix.clone()).unwrap();
494497

@@ -509,7 +512,8 @@ mod tests {
509512
assert_symmetric(a);
510513

511514
let n = a.len_of(Axis(0));
512-
let x: Array2<f64> = generate::random((n, num));
515+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
516+
let x: Array2<f64> = generate::random_using((n, num), &mut rng);
513517

514518
let result = lobpcg(|y| a.dot(&y), x, |_| {}, None, 1e-5, n * 2, order);
515519
match result {
@@ -553,7 +557,8 @@ mod tests {
553557
#[test]
554558
fn test_eigsolver_constructed() {
555559
let n = 50;
556-
let tmp = generate::random((n, n));
560+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
561+
let tmp = generate::random_using((n, n), &mut rng);
557562
//let (v, _) = tmp.qr_square().unwrap();
558563
let (v, _) = orthonormalize(tmp).unwrap();
559564

@@ -570,7 +575,8 @@ mod tests {
570575
fn test_eigsolver_constrained() {
571576
let diag = arr1(&[1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]);
572577
let a = Array2::from_diag(&diag);
573-
let x: Array2<f64> = generate::random((10, 1));
578+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
579+
let x: Array2<f64> = generate::random_using((10, 1), &mut rng);
574580
let y: Array2<f64> = arr2(&[
575581
[1.0, 0., 0., 0., 0., 0., 0., 0., 0., 0.],
576582
[0., 1.0, 0., 0., 0., 0., 0., 0., 0., 0.],

ndarray-linalg/src/lobpcg/svd.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ mod tests {
214214

215215
#[test]
216216
fn test_truncated_svd_random() {
217-
let a: Array2<f64> = generate::random((50, 10));
217+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
218+
let a: Array2<f64> = generate::random_using((50, 10), &mut rng);
218219

219220
let res = TruncatedSvd::new(a.clone(), Order::Largest)
220221
.precision(1e-5)

ndarray-linalg/src/solve.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@
55
//! Solve `A * x = b`:
66
//!
77
//! ```
8-
//! #[macro_use]
9-
//! extern crate ndarray;
10-
//! extern crate ndarray_linalg;
11-
//!
128
//! use ndarray::prelude::*;
139
//! use ndarray_linalg::Solve;
14-
//! # fn main() {
1510
//!
1611
//! let a: Array2<f64> = array![[3., 2., -1.], [2., -2., 4.], [-2., 1., -2.]];
1712
//! let b: Array1<f64> = array![1., -2., 0.];
1813
//! let x = a.solve_into(b).unwrap();
1914
//! assert!(x.abs_diff_eq(&array![1., -2., -2.], 1e-9));
20-
//!
21-
//! # }
2215
//! ```
2316
//!
2417
//! There are also special functions for solving `A^T * x = b` and
@@ -29,21 +22,18 @@
2922
//! the beginning than solving directly using `A`:
3023
//!
3124
//! ```
32-
//! # extern crate ndarray;
33-
//! # extern crate ndarray_linalg;
34-
//!
3525
//! use ndarray::prelude::*;
3626
//! use ndarray_linalg::*;
37-
//! # fn main() {
3827
//!
39-
//! let a: Array2<f64> = random((3, 3));
28+
//! /// Use fixed algorithm and seed of PRNG for reproducible test
29+
//! let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
30+
//!
31+
//! let a: Array2<f64> = random_using((3, 3), &mut rng);
4032
//! let f = a.factorize_into().unwrap(); // LU factorize A (A is consumed)
4133
//! for _ in 0..10 {
42-
//! let b: Array1<f64> = random(3);
34+
//! let b: Array1<f64> = random_using(3, &mut rng);
4335
//! let x = f.solve_into(b).unwrap(); // Solve A * x = b using factorized L, U
4436
//! }
45-
//!
46-
//! # }
4737
//! ```
4838
4939
use ndarray::*;

ndarray-linalg/src/solveh.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,8 @@
88
//! Solve `A * x = b`, where `A` is a Hermitian (or real symmetric) matrix:
99
//!
1010
//! ```
11-
//! #[macro_use]
12-
//! extern crate ndarray;
13-
//! extern crate ndarray_linalg;
14-
//!
1511
//! use ndarray::prelude::*;
1612
//! use ndarray_linalg::SolveH;
17-
//! # fn main() {
1813
//!
1914
//! let a: Array2<f64> = array![
2015
//! [3., 2., -1.],
@@ -24,29 +19,25 @@
2419
//! let b: Array1<f64> = array![11., -12., 1.];
2520
//! let x = a.solveh_into(b).unwrap();
2621
//! assert!(x.abs_diff_eq(&array![1., 3., -2.], 1e-9));
27-
//!
28-
//! # }
2922
//! ```
3023
//!
3124
//! If you are solving multiple systems of linear equations with the same
3225
//! Hermitian or real symmetric coefficient matrix `A`, it's faster to compute
3326
//! the factorization once at the beginning than solving directly using `A`:
3427
//!
3528
//! ```
36-
//! # extern crate ndarray;
37-
//! # extern crate ndarray_linalg;
3829
//! use ndarray::prelude::*;
3930
//! use ndarray_linalg::*;
40-
//! # fn main() {
4131
//!
42-
//! let a: Array2<f64> = random((3, 3));
32+
//! /// Use fixed algorithm and seed of PRNG for reproducible test
33+
//! let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
34+
//!
35+
//! let a: Array2<f64> = random_using((3, 3), &mut rng);
4336
//! let f = a.factorizeh_into().unwrap(); // Factorize A (A is consumed)
4437
//! for _ in 0..10 {
45-
//! let b: Array1<f64> = random(3);
38+
//! let b: Array1<f64> = random_using(3, &mut rng);
4639
//! let x = f.solveh_into(b).unwrap(); // Solve A * x = b using the factorization
4740
//! }
48-
//!
49-
//! # }
5041
//! ```
5142
5243
use ndarray::*;

ndarray-linalg/tests/arnoldi.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use ndarray_linalg::{krylov::*, *};
33

44
#[test]
55
fn aq_qh_mgs() {
6-
let a: Array2<f64> = random((5, 5));
7-
let v: Array1<f64> = random(5);
6+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
7+
let a: Array2<f64> = random_using((5, 5), &mut rng);
8+
let v: Array1<f64> = random_using(5, &mut rng);
89
let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9);
910
println!("A = \n{:?}", &a);
1011
println!("Q = \n{:?}", &q);
@@ -18,8 +19,9 @@ fn aq_qh_mgs() {
1819

1920
#[test]
2021
fn aq_qh_householder() {
21-
let a: Array2<f64> = random((5, 5));
22-
let v: Array1<f64> = random(5);
22+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
23+
let a: Array2<f64> = random_using((5, 5), &mut rng);
24+
let v: Array1<f64> = random_using(5, &mut rng);
2325
let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9);
2426
println!("A = \n{:?}", &a);
2527
println!("Q = \n{:?}", &q);
@@ -33,8 +35,9 @@ fn aq_qh_householder() {
3335

3436
#[test]
3537
fn aq_qh_mgs_complex() {
36-
let a: Array2<c64> = random((5, 5));
37-
let v: Array1<c64> = random(5);
38+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
39+
let a: Array2<c64> = random_using((5, 5), &mut rng);
40+
let v: Array1<c64> = random_using(5, &mut rng);
3841
let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9);
3942
println!("A = \n{:?}", &a);
4043
println!("Q = \n{:?}", &q);
@@ -48,8 +51,9 @@ fn aq_qh_mgs_complex() {
4851

4952
#[test]
5053
fn aq_qh_householder_complex() {
51-
let a: Array2<c64> = random((5, 5));
52-
let v: Array1<c64> = random(5);
54+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
55+
let a: Array2<c64> = random_using((5, 5), &mut rng);
56+
let v: Array1<c64> = random_using(5, &mut rng);
5357
let (q, h) = arnoldi_mgs(a.clone(), v, 1e-9);
5458
println!("A = \n{:?}", &a);
5559
println!("Q = \n{:?}", &q);

ndarray-linalg/tests/cholesky.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ macro_rules! cholesky {
66
paste::item! {
77
#[test]
88
fn [<cholesky_ $elem>]() {
9-
let a_orig: Array2<$elem> = random_hpd(3);
9+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
10+
let a_orig: Array2<$elem> = random_hpd_using(3, &mut rng);
1011
println!("a = \n{:?}", a_orig);
1112

1213
let upper = a_orig.cholesky(UPLO::Upper).unwrap();
@@ -79,7 +80,8 @@ macro_rules! cholesky_into_lower_upper {
7980
paste::item! {
8081
#[test]
8182
fn [<cholesky_into_lower_upper_ $elem>]() {
82-
let a: Array2<$elem> = random_hpd(3);
83+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
84+
let a: Array2<$elem> = random_hpd_using(3, &mut rng);
8385
println!("a = \n{:?}", a);
8486
let upper = a.cholesky(UPLO::Upper).unwrap();
8587
let fac_upper = a.factorizec(UPLO::Upper).unwrap();
@@ -106,7 +108,8 @@ macro_rules! cholesky_into_inverse {
106108
paste::item! {
107109
#[test]
108110
fn [<cholesky_inverse_ $elem>]() {
109-
let a: Array2<$elem> = random_hpd(3);
111+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
112+
let a: Array2<$elem> = random_hpd_using(3, &mut rng);
110113
println!("a = \n{:?}", a);
111114
let inv = a.invc().unwrap();
112115
assert_close_l2!(&a.dot(&inv), &Array2::eye(3), $rtol);
@@ -134,7 +137,8 @@ macro_rules! cholesky_det {
134137
paste::item! {
135138
#[test]
136139
fn [<cholesky_det_ $elem>]() {
137-
let a: Array2<$elem> = random_hpd(3);
140+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
141+
let a: Array2<$elem> = random_hpd_using(3, &mut rng);
138142
println!("a = \n{:?}", a);
139143
let ln_det = a
140144
.eigvalsh(UPLO::Upper)
@@ -168,8 +172,9 @@ macro_rules! cholesky_solve {
168172
paste::item! {
169173
#[test]
170174
fn [<cholesky_solve_ $elem>]() {
171-
let a: Array2<$elem> = random_hpd(3);
172-
let x: Array1<$elem> = random(3);
175+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
176+
let a: Array2<$elem> = random_hpd_using(3, &mut rng);
177+
let x: Array1<$elem> = random_using(3, &mut rng);
173178
let b = a.dot(&x);
174179
println!("a = \n{:?}", a);
175180
println!("x = \n{:?}", x);

ndarray-linalg/tests/convert.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use ndarray_linalg::*;
33

44
#[test]
55
fn generalize() {
6-
let a: Array3<f64> = random((3, 2, 4).f());
6+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
7+
let a: Array3<f64> = random_using((3, 2, 4).f(), &mut rng);
78
let ans = a.clone();
89
let a: Array3<f64> = convert::generalize(a);
910
assert_eq!(a, ans);

ndarray-linalg/tests/det.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,23 +136,45 @@ fn det() {
136136
assert_rclose!(result.1, ln_det, rtol);
137137
}
138138
}
139+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
139140
for rows in 1..5 {
140-
det_impl(random_regular::<f64>(rows), 1e-9);
141-
det_impl(random_regular::<f32>(rows), 1e-4);
142-
det_impl(random_regular::<c64>(rows), 1e-9);
143-
det_impl(random_regular::<c32>(rows), 1e-4);
144-
det_impl(random_regular::<f64>(rows).t().to_owned(), 1e-9);
145-
det_impl(random_regular::<f32>(rows).t().to_owned(), 1e-4);
146-
det_impl(random_regular::<c64>(rows).t().to_owned(), 1e-9);
147-
det_impl(random_regular::<c32>(rows).t().to_owned(), 1e-4);
141+
det_impl(random_regular_using::<f64, _>(rows, &mut rng), 1e-9);
142+
det_impl(random_regular_using::<f32, _>(rows, &mut rng), 1e-4);
143+
det_impl(random_regular_using::<c64, _>(rows, &mut rng), 1e-9);
144+
det_impl(random_regular_using::<c32, _>(rows, &mut rng), 1e-4);
145+
det_impl(
146+
random_regular_using::<f64, _>(rows, &mut rng)
147+
.t()
148+
.to_owned(),
149+
1e-9,
150+
);
151+
det_impl(
152+
random_regular_using::<f32, _>(rows, &mut rng)
153+
.t()
154+
.to_owned(),
155+
1e-4,
156+
);
157+
det_impl(
158+
random_regular_using::<c64, _>(rows, &mut rng)
159+
.t()
160+
.to_owned(),
161+
1e-9,
162+
);
163+
det_impl(
164+
random_regular_using::<c32, _>(rows, &mut rng)
165+
.t()
166+
.to_owned(),
167+
1e-4,
168+
);
148169
}
149170
}
150171

151172
#[test]
152173
fn det_nonsquare() {
153174
macro_rules! det_nonsquare {
154175
($elem:ty, $shape:expr) => {
155-
let a: Array2<$elem> = random($shape);
176+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
177+
let a: Array2<$elem> = random_using($shape, &mut rng);
156178
assert!(a.factorize().unwrap().det().is_err());
157179
assert!(a.factorize().unwrap().sln_det().is_err());
158180
assert!(a.factorize().unwrap().det_into().is_err());

ndarray-linalg/tests/deth.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ fn deth_zero_nonsquare() {
7272
fn deth() {
7373
macro_rules! deth {
7474
($elem:ty, $rows:expr, $atol:expr) => {
75-
let a: Array2<$elem> = random_hermite($rows);
75+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
76+
let a: Array2<$elem> = random_hermite_using($rows, &mut rng);
7677
println!("a = \n{:?}", a);
7778

7879
// Compute determinant from eigenvalues.

ndarray-linalg/tests/eigh.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ fn fixed_t_lower() {
7979

8080
#[test]
8181
fn ssqrt() {
82-
let a: Array2<f64> = random_hpd(3);
82+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
83+
let a: Array2<f64> = random_hpd_using(3, &mut rng);
8384
let ans = a.clone();
8485
let s = a.ssqrt(UPLO::Upper).unwrap();
8586
println!("a = {:?}", &ans);
@@ -92,7 +93,8 @@ fn ssqrt() {
9293

9394
#[test]
9495
fn ssqrt_t() {
95-
let a: Array2<f64> = random_hpd(3).reversed_axes();
96+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
97+
let a: Array2<f64> = random_hpd_using(3, &mut rng).reversed_axes();
9698
let ans = a.clone();
9799
let s = a.ssqrt(UPLO::Upper).unwrap();
98100
println!("a = {:?}", &ans);
@@ -105,7 +107,8 @@ fn ssqrt_t() {
105107

106108
#[test]
107109
fn ssqrt_lower() {
108-
let a: Array2<f64> = random_hpd(3);
110+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
111+
let a: Array2<f64> = random_hpd_using(3, &mut rng);
109112
let ans = a.clone();
110113
let s = a.ssqrt(UPLO::Lower).unwrap();
111114
println!("a = {:?}", &ans);
@@ -118,7 +121,8 @@ fn ssqrt_lower() {
118121

119122
#[test]
120123
fn ssqrt_t_lower() {
121-
let a: Array2<f64> = random_hpd(3).reversed_axes();
124+
let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5);
125+
let a: Array2<f64> = random_hpd_using(3, &mut rng).reversed_axes();
122126
let ans = a.clone();
123127
let s = a.ssqrt(UPLO::Lower).unwrap();
124128
println!("a = {:?}", &ans);

0 commit comments

Comments
 (0)