blob: 64829a7e606ce7a1219a9e9cb352e99355d3f073 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.legacy.random;
import java.util.Arrays;
import java.util.function.Supplier;
import org.junit.Test;
import org.junit.Assert;
import org.apache.commons.rng.simple.RandomSource;
import org.apache.commons.math4.legacy.TestUtils;
import org.apache.commons.math4.legacy.linear.Array2DRowRealMatrix;
import org.apache.commons.math4.legacy.linear.MatrixUtils;
import org.apache.commons.math4.legacy.linear.RealMatrix;
import org.apache.commons.math4.legacy.stat.correlation.StorelessCovariance;
import org.apache.commons.math4.legacy.stat.descriptive.moment.VectorialCovariance;
import org.apache.commons.math4.legacy.stat.descriptive.moment.VectorialMean;
import org.apache.commons.math4.legacy.core.jdkmath.AccurateMath;
public class CorrelatedVectorFactoryTest {
private double[] mean;
private RealMatrix covariance;
private Supplier<double[]> generator;
public CorrelatedVectorFactoryTest() {
mean = new double[] { 0.0, 1.0, -3.0, 2.3 };
final RealMatrix b = MatrixUtils.createRealMatrix(4, 3);
int counter = 0;
for (int i = 0; i < b.getRowDimension(); ++i) {
for (int j = 0; j < b.getColumnDimension(); ++j) {
b.setEntry(i, j, 1.0 + 0.1 * ++counter);
}
}
final RealMatrix bbt = b.multiply(b.transpose());
covariance = MatrixUtils.createRealMatrix(mean.length, mean.length);
for (int i = 0; i < covariance.getRowDimension(); ++i) {
covariance.setEntry(i, i, bbt.getEntry(i, i));
for (int j = 0; j < covariance.getColumnDimension(); ++j) {
double s = bbt.getEntry(i, j);
covariance.setEntry(i, j, s);
covariance.setEntry(j, i, s);
}
}
generator = new CorrelatedVectorFactory(mean,
covariance,
1e-12 * covariance.getNorm())
.gaussian(RandomSource.KISS.create());
}
@Test
public void testMath226() {
final double[] mean = { 1, 1, 10, 1 };
final double[][] cov = {
{ 1, 3, 2, 6 },
{ 3, 13, 16, 2 },
{ 2, 16, 38, -1 },
{ 6, 2, -1, 197 }
};
final RealMatrix covRM = MatrixUtils.createRealMatrix(cov);
final Supplier<double[]> sg = new CorrelatedVectorFactory(mean, covRM, 1e-5)
.gaussian(RandomSource.WELL_1024_A.create());
final double[] min = new double[mean.length];
Arrays.fill(min, Double.POSITIVE_INFINITY);
final double[] max = new double[mean.length];
Arrays.fill(max, Double.NEGATIVE_INFINITY);
for (int i = 0; i < 10; i++) {
double[] generated = sg.get();
for (int j = 0; j < generated.length; ++j) {
min[j] = AccurateMath.min(min[j], generated[j]);
max[j] = AccurateMath.max(max[j], generated[j]);
}
}
for (int j = 0; j < min.length; ++j) {
Assert.assertTrue(max[j] - min[j] > 2.0);
}
}
@Test
public void testMeanAndCovariance() {
final VectorialMean meanStat = new VectorialMean(mean.length);
final VectorialCovariance covStat = new VectorialCovariance(mean.length, true);
for (int i = 0; i < 5000; ++i) {
final double[] v = generator.get();
meanStat.increment(v);
covStat.increment(v);
}
final double[] estimatedMean = meanStat.getResult();
final RealMatrix estimatedCovariance = covStat.getResult();
for (int i = 0; i < estimatedMean.length; ++i) {
Assert.assertEquals(mean[i], estimatedMean[i], 0.07);
for (int j = 0; j <= i; ++j) {
Assert.assertEquals(covariance.getEntry(i, j),
estimatedCovariance.getEntry(i, j),
1e-1 * (1 + AccurateMath.abs(mean[i])) * (1 + AccurateMath.abs(mean[j])));
}
}
}
@Test
public void testSampleWithZeroCovariance() {
final double[][] covMatrix1 = new double[][]{
{0.013445532, 0.010394690, 0.009881156, 0.010499559},
{0.010394690, 0.023006616, 0.008196856, 0.010732709},
{0.009881156, 0.008196856, 0.019023866, 0.009210099},
{0.010499559, 0.010732709, 0.009210099, 0.019107243}
};
final double[][] covMatrix2 = new double[][]{
{0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.013445532, 0.010394690, 0.009881156, 0.010499559},
{0.0, 0.010394690, 0.023006616, 0.008196856, 0.010732709},
{0.0, 0.009881156, 0.008196856, 0.019023866, 0.009210099},
{0.0, 0.010499559, 0.010732709, 0.009210099, 0.019107243}
};
final double[][] covMatrix3 = new double[][]{
{0.013445532, 0.010394690, 0.0, 0.009881156, 0.010499559},
{0.010394690, 0.023006616, 0.0, 0.008196856, 0.010732709},
{0.0, 0.0, 0.0, 0.0, 0.0},
{0.009881156, 0.008196856, 0.0, 0.019023866, 0.009210099},
{0.010499559, 0.010732709, 0.0, 0.009210099, 0.019107243}
};
testSampler(covMatrix1, 10000, 1e-3);
testSampler(covMatrix2, 10000, 1e-3);
testSampler(covMatrix3, 10000, 1e-3);
}
private Supplier<double[]> createSampler(double[][] cov) {
final RealMatrix matrix = new Array2DRowRealMatrix(cov);
final double small = 1e-12 * matrix.getNorm();
return new CorrelatedVectorFactory(matrix, small)
.gaussian(RandomSource.WELL_1024_A.create());
}
private void testSampler(final double[][] covMatrix,
int samples,
double epsilon) {
final Supplier<double[]> sampler = createSampler(covMatrix);
final StorelessCovariance cov = new StorelessCovariance(covMatrix.length);
for (int i = 0; i < samples; ++i) {
cov.increment(sampler.get());
}
final double[][] sampleCov = cov.getData();
for (int r = 0; r < covMatrix.length; ++r) {
TestUtils.assertEquals(covMatrix[r], sampleCov[r], epsilon);
}
}
}