/*
 * 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);
        }
    }
}
