use approx::assert_relative_eq;
use ndarray::{arr1, arr2, Array1, Array2};
use nnls::nnls;
#[test]
fn test_nnls_1() {
let a = arr2(&[[1.0, 0.0], [1.0, 0.0], [0.0, 1.0]]);
let b = arr1(&[2.0, 1.0, 1.0]);
let (x, r_norm) = nnls(a.view(), b.view());
assert_relative_eq!(x, arr1(&[1.5, 1.0]), epsilon = 1e-9);
assert_relative_eq!(r_norm, 0.7071067811865475, epsilon = 1e-9);
}
#[test]
fn test_nnls_2() {
let a = arr2(&[[1.0, 0.5, 0.0], [1.0, 0.6, 0.0], [0.9, 0.5, 0.1], [0.0, 0.0, 1.0]]);
let b = arr1(&[2.0, 1.0, 1.0, 0.5]);
let (x, r_norm) = nnls(a.view(), b.view());
assert_relative_eq!(x, arr1(&[1.37279152, 0.0, 0.47173145]), epsilon = 1e-5);
assert_relative_eq!(r_norm, 0.7829905522718629, epsilon = 1e-5);
}
#[test]
fn test_trap() {
let a = arr2(&[
[9.6110e-8, 7.9576e-17, 2.7234e-44, 3.4490e-44],
[7.9576e-17, 2.0449e-7, 7.4360e-44, 9.4173e-44],
[2.7234e-44, 7.4360e-44, 3.1651e-7, 2.9014e-44],
[3.4490e-44, 9.4173e-44, 2.9014e-44, 4.3443e-7],
]);
let b = arr1(&[-2.4678e-17, -6.7118e-17, 3.6306e-44, 4.5923e-44]);
let (x, r_norm) = nnls(a.view(), b.view());
assert_relative_eq!(x, arr1(&[0.0, 0.0, 0.0, 0.0]), epsilon = 1e-5);
assert_relative_eq!(r_norm, 0.0, epsilon = 1e-5);
}
#[test]
fn test_mixture_of_exponentials() {
let mut t0 = Array1::zeros(19);
t0[0] = 2.0;
t0[1] = t0[0] * 2.0f64.sqrt();
for i in 2..t0.len() {
t0[i] = 2.0 * t0[i - 2];
}
let arg_limit = (2.0 * 2.2250738585072014e-308f64).ln();
let a = Array2::from_shape_fn((100, 19), |(i, j)| {
let i = (i + 1) as f64;
let arg = -10.0 * i / t0[j];
if arg > arg_limit {
arg.exp()
} else {
0.0
}
});
let b = Array1::from_shape_fn(100, |i| {
let t = 10.0 * (i + 1) as f64;
100.0 * ((-t / 5.0).exp() + (-t / 50.0).exp() + (-t / 500.0).exp()) - 0.5
});
let (x, r_norm) = nnls(a.view(), b.view());
let mut x_gt = Array1::zeros(19);
x_gt[2] = 146.18289932114504;
x_gt[9] = 82.906587033240356;
x_gt[10] = 18.699400056374593;
x_gt[15] = 13.315689103364351;
x_gt[16] = 87.197680367574506;
assert_relative_eq!(x, x_gt, epsilon = 1e-5);
assert_relative_eq!(r_norm, 0.88433322916388879, epsilon = 1e-5);
}