/// <summary>Generates random numbers following a multivariate normal distribution N_d(\mu, \Sigma), i.e. d-dimensional vectors, where \Sigma = Q * Q' represents the variance-covariance matrix.
            /// </summary>
            /// <param name="n">The number of random values to generate.</param>
            /// <param name="data">The <paramref name="n"/> random numbers following a multivariate normal distribution, i.e. random vectors of size at least <paramref name="dimension"/> * <paramref name="n"/>. The return value
            /// as well as <see cref="GaussianMultivariateDataRepresentation"/> indicates the representation of the data (output).</param>
            /// <param name="dimension">The dimension of the output vectors.</param>
            /// <param name="matrixStorage">The matrix storage schema of <paramref name="pseudoRootOfVarianceCovarianceMatrix" />.</param>
            /// <param name="mu">The mean vector of dimension <paramref name="dimension" />.</param>
            /// <param name="pseudoRootOfVarianceCovarianceMatrix">The elements of the upper triangular matrix Q' passed according to the matrix storage scheme <paramref name="matrixStorage" />, where \Sigma = Q * Q' represents the variance-covariance matrix.</param>
            /// <param name="workspace">A workspace array, perhaps <c>null</c>.</param>
            /// <param name="generationMethod">The optional generation mode.</param>
            /// <returns>The representation of the <paramref name="data"/>; the random vectors (of dimension <paramref name="dimension"/>) are stored column-by-column if <see cref="BLAS.MatrixTransposeState.NoTranspose"/>; otherwise each column contains all realisation of the j'th component (i.e. transposed matrix).</returns>
            public BLAS.MatrixTransposeState GaussianMultivariate(int n, double[] data, int dimension, RandomNumberSequence.MultivariateMatrixStorageType matrixStorage, double[] mu, double[] pseudoRootOfVarianceCovarianceMatrix, double[] workspace = null, RandomNumberSequence.GaussianGenerationMode generationMethod = null)
            {
                int method;

                if (generationMethod != null)
                {
                    if (generationMethod is MklRandomNumberSequence.GaussianGenerationMode)
                    {
                        var vslGaussianGenerationMode = (MklRandomNumberSequence.GaussianGenerationMode)generationMethod;
                        method = vslGaussianGenerationMode.MagicNumber;
                    }
                    else
                    {
                        throw new ArgumentException("Generation mode is not a valid argument", "generationMode");
                    }
                }
                else
                {
                    method = GaussianGenerationMode.InverseCumulativeDistributionFunction.MagicNumber;
                }

                int errorCode;
                int storage = (int)matrixStorage;

                unsafe
                {
                    fixed(double *dataPtr = data, muPtr = mu, pseudoRootPtr = pseudoRootOfVarianceCovarianceMatrix)
                    {
                        errorCode = vdRngGaussianMV(ref method, ref m_Stream.m_Handle, ref n, (IntPtr)dataPtr, ref dimension, ref storage, (IntPtr)muPtr, (IntPtr)pseudoRootPtr);
                    }
                }

                if (errorCode != 0) // execution is not successful
                {
                    throw new InvalidOperationException("MKL: Return value " + errorCode + " in vdRngGaussianmv.");
                }
                return(BLAS.MatrixTransposeState.NoTranspose);
            }
 /// <summary>Gets the length of the workspace array required for optimal performance of <see cref="GaussianMultivariate(int, double[], int, RandomNumberSequence.MultivariateMatrixStorageType, double[], double[], double[], RandomNumberSequence.GaussianGenerationMode)" />.
 /// </summary>
 /// <param name="n">The number of random values to generate.</param>
 /// <param name="dimension">The dimension of the output vectors.</param>
 /// <param name="matrixStorage">The matrix storage schema.</param>
 /// <param name="generationMethod">The optional generation mode.</param>
 /// <returns>The length of the workspace array required for the generation of random numbers following a multivariate normal distribution, perhaps <c>0</c>.</returns>
 public int GaussianMultivariateWorkspaceQuery(int n, int dimension, RandomNumberSequence.MultivariateMatrixStorageType matrixStorage, RandomNumberSequence.GaussianGenerationMode generationMethod = null)
 {
     return(0);
 }
Beispiel #3
0
        public void NextNumberSequenceGaussianMultivariate_EstimatedMean_ConvidenceInterval(int dimension, int sampleSize, double[] mu, double[] pseudoRootOfVarianceCovarianceMatrix, RandomNumberSequence.MultivariateMatrixStorageType matrixStorageType, RandomNumberSequence.GaussianGenerationMode generatorMode)
        {
            IRandomNumberStream randomStream = GetRandomStream();

            /* do not apply BoxMuller to Pseudo-Random Number Generator: */
            Assume.That(randomStream.Generator is IPseudoRandomNumberGenerator || (string)generatorMode.Name != "BoxMuller", "Box-Muller approach is for Pseudo-Random Number Generators not adequate.");

            var sample          = new double[sampleSize * dimension];
            int workspaceLength = randomStream.NextNumberSequence.GaussianMultivariateWorkspaceQuery(sampleSize, dimension, matrixStorageType, generatorMode);

            double[] workspace = null;
            if (workspaceLength > 0)
            {
                workspace = new double[workspaceLength];
            }
            var outputRepresentation = randomStream.NextNumberSequence.GaussianMultivariate(sampleSize, sample, dimension, matrixStorageType, mu, pseudoRootOfVarianceCovarianceMatrix, workspace, generatorMode);

            for (int j = 0; j < dimension; j++)
            {
                // check the mean of the j'te component etc.:
                double[] projectedSample = null;

                switch (outputRepresentation)
                {
                case Basics.BLAS.MatrixTransposeState.NoTranspose:
                    projectedSample = sample.Skip(j).Where((x, k) => k % dimension == 0).ToArray();      // the relevant sample, i.e. realisations of a normal-distributed random number
                    break;

                case Basics.BLAS.MatrixTransposeState.Transpose:
                case Basics.BLAS.MatrixTransposeState.Hermite:
                    projectedSample = sample.Skip(j * sampleSize).Where((x, k) => k < sampleSize).ToArray();
                    break;

                default:
                    throw new NotImplementedException();
                }
                Assert.That(projectedSample.Length >= sampleSize, String.Format("Length : {0}", projectedSample.Length));

                double expectedMean  = mu[j];
                double estimatedMean = projectedSample.Average();

                double estimatedStandardDeviation = GetEstimatedStandardDeviation(projectedSample, sampleSize, estimatedMean);
                double epsilon = 2.0 * estimatedStandardDeviation / Math.Sqrt(sampleSize); // size of the confidence interval w.r.t. normal distribution N{-1}(0.975) \approx 1.96 \approx 2.0

                /* test whether E(X) \in [ estimatedMean - \epsilon, estimatedMean + \epsilon], where \epsilon = \sigma/\sqrt(n} */
                Assert.That(estimatedMean + epsilon, Is.GreaterThanOrEqualTo(expectedMean), String.Format("Component: {0}; expected Mean: {1}; estimated Mean: {2}; lower Confidence Interval bound: {3}; upper Confidence Interval bound: {4}.", j, expectedMean, estimatedMean, estimatedMean - epsilon, estimatedMean + epsilon));
                Assert.That(estimatedMean - epsilon, Is.LessThanOrEqualTo(expectedMean), String.Format("Component: {0}; expected Mean: {1}; estimated Mean: {2}; lower Confidence Interval bound: {3}; upper Confidence Interval bound: {4}.", j, expectedMean, estimatedMean, estimatedMean - epsilon, estimatedMean + epsilon));
            }
        }
Beispiel #4
0
        public void NextNumberSequenceGaussianMultivariate_EstimatedVariance_ConvidenceInterval(int dimension, int sampleSize, double[] mu, double[] pseudoRootOfVarianceCovarianceMatrix, RandomNumberSequence.MultivariateMatrixStorageType matrixStorageType, double lowerCriticalValueOfChiSquaredDistribution, double upperCriticalValueOfChiSquaredDistribution, RandomNumberSequence.GaussianGenerationMode generatorMode)
        {
            IRandomNumberStream randomStream = GetRandomStream();

            /* do not apply BoxMuller to Pseudo-Random Number Generator: */
            Assume.That(randomStream.Generator is IPseudoRandomNumberGenerator || (string)generatorMode.Name != "BoxMuller", "Box-Muller approach is for Pseudo-Random Number Generators not adequate.");


            var sample          = new double[sampleSize * dimension];
            int workspaceLength = randomStream.NextNumberSequence.GaussianMultivariateWorkspaceQuery(sampleSize, dimension, matrixStorageType, generatorMode);

            double[] workspace = null;
            if (workspaceLength > 0)
            {
                workspace = new double[workspaceLength];
            }
            var outputRepresentation = randomStream.NextNumberSequence.GaussianMultivariate(sampleSize, sample, dimension, matrixStorageType, mu, pseudoRootOfVarianceCovarianceMatrix, workspace, generatorMode);

            int triangularPackagedMatrixStartIndex = 0;

            for (int j = 0; j < dimension; j++)
            {
                // check the variance of the j'te component
                double[] projectedSample = null;

                switch (outputRepresentation)
                {
                case Basics.BLAS.MatrixTransposeState.NoTranspose:
                    projectedSample = sample.Skip(j).Where((x, k) => k % dimension == 0).ToArray();      // the relevant sample, i.e. realisations of a normal-distributed random number
                    break;

                case Basics.BLAS.MatrixTransposeState.Transpose:
                case Basics.BLAS.MatrixTransposeState.Hermite:
                    projectedSample = sample.Skip(j * sampleSize).Where((x, k) => k < sampleSize).ToArray();
                    break;

                default:
                    throw new NotImplementedException();
                }
                Assert.That(projectedSample.Length >= sampleSize, String.Format("Length : {0}", projectedSample.Length));

                double expectedMean  = mu[j];
                double estimatedMean = projectedSample.Average();

                double estimatedVariance = GetEstimatedVariance(projectedSample, sampleSize, estimatedMean);

                double expectedVariance = 0.0;
                switch (matrixStorageType)
                {
                case RandomNumberSequence.MultivariateMatrixStorageType.Diagonal:
                    expectedVariance = pseudoRootOfVarianceCovarianceMatrix[j] * pseudoRootOfVarianceCovarianceMatrix[j];
                    break;

                case RandomNumberSequence.MultivariateMatrixStorageType.Full:

                    // compute [Q * Q']_{j,j], where Q' is one of the arguments
                    for (int k = 0; k < dimension; k++)
                    {
                        double temp = pseudoRootOfVarianceCovarianceMatrix[k + dimension * j];
                        expectedVariance += temp * temp;
                    }
                    break;

                case RandomNumberSequence.MultivariateMatrixStorageType.TriangularPackaged:

                    for (int k = 0; k <= j; k++)
                    {
                        double temp = pseudoRootOfVarianceCovarianceMatrix[triangularPackagedMatrixStartIndex + k];
                        expectedVariance += temp * temp;
                    }
                    triangularPackagedMatrixStartIndex += j + 1;
                    break;

                default:
                    throw new NotImplementedException();
                }

                /* check whether the (theoretical) variance is inside
                 *
                 * [ (n-1) * S^2 / \chi^2_{\alpha/2, n-1}, (n-1)*S^2 / \chi^2_{1.0 - \alpha/2, n-1} ],
                 *
                 * where \chi^2_{\alpha, n} is the quantile of the chi-square distribution with degree n and parameter \alpha.
                 */
                Assert.That(estimatedVariance * (sampleSize - 1) / upperCriticalValueOfChiSquaredDistribution, Is.GreaterThanOrEqualTo(expectedVariance), String.Format("Component: {0}; sampleSize: {1}, theor. Variance: {2}, estimated mean: {3}, estimated Variance: {4}, upper-Chi Squared quantile: {5}", j, sampleSize, expectedVariance, estimatedMean, estimatedVariance, upperCriticalValueOfChiSquaredDistribution));
                Assert.That(estimatedVariance * (sampleSize - 1) / lowerCriticalValueOfChiSquaredDistribution, Is.LessThanOrEqualTo(expectedVariance), String.Format("Component: {0}; sampleSize: {1}, theor. Variance: {2}, estimated mean: {3}, estimated Variance: {4}, upper-Chi Squared quantile: {5}", j, sampleSize, expectedVariance, estimatedMean, estimatedVariance, upperCriticalValueOfChiSquaredDistribution));
            }
        }
Beispiel #5
0
            /// <summary>Generates random numbers following a multivariate normal distribution N_d(\mu, \Sigma), i.e. d-dimensional vectors, where \Sigma = Q * Q' represents the variance-covariance matrix.
            /// </summary>
            /// <param name="n">The number of random values to generate.</param>
            /// <param name="data">The <paramref name="n"/> random numbers following a multivariate normal distribution, i.e. random vectors of size at least <paramref name="dimension"/> * <paramref name="n"/>. The return value
            /// as well as <see cref="GaussianMultivariateDataRepresentation"/> indicates the representation of the data (output).</param>
            /// <param name="dimension">The dimension of the output vectors.</param>
            /// <param name="matrixStorage">The matrix storage schema of <paramref name="pseudoRootOfVarianceCovarianceMatrix" />.</param>
            /// <param name="mu">The mean vector of dimension <paramref name="dimension" />.</param>
            /// <param name="pseudoRootOfVarianceCovarianceMatrix">The elements of the upper triangular matrix Q' passed according to the matrix storage scheme <paramref name="matrixStorage" />, where \Sigma = Q * Q' represents the variance-covariance matrix.</param>
            /// <param name="workspace">A workspace array, perhaps <c>null</c>.</param>
            /// <param name="generationMethod">The optional generation mode.</param>
            /// <returns>The representation of the <paramref name="data"/>; the random vectors (of dimension <paramref name="dimension"/>) are stored column-by-column if <see cref="BLAS.MatrixTransposeState.NoTranspose"/>; otherwise each column contains all realisation of the j'th component (i.e. transposed matrix).</returns>
            public BLAS.MatrixTransposeState GaussianMultivariate(int n, double[] data, int dimension, RandomNumberSequence.MultivariateMatrixStorageType matrixStorage, double[] mu, double[] pseudoRootOfVarianceCovarianceMatrix, double[] workspace = null, RandomNumberSequence.GaussianGenerationMode generationMethod = null)
            {
                // for this implementation one has to calculate the covariance matrix:
                if ((workspace == null) || (workspace.Length < dimension * dimension))
                {
                    workspace = new double[dimension * dimension];
                }

                switch (matrixStorage)
                {
                case RandomNumberSequence.MultivariateMatrixStorageType.Full:
                    BLAS.Level3.dgemm(dimension, dimension, dimension, 1.0, pseudoRootOfVarianceCovarianceMatrix, pseudoRootOfVarianceCovarianceMatrix, 0.0, workspace, BLAS.MatrixTransposeState.Transpose);
                    break;

                case RandomNumberSequence.MultivariateMatrixStorageType.Diagonal:
                    BLAS.Level1.dscal(dimension * dimension, 0.0, workspace); // set coVarianceMatrix = 0
                    for (int j = 0; j < dimension; j++)                       // the input is just the diagonal matrix (column-by-column representation)
                    {
                        workspace[j * dimension + j] = pseudoRootOfVarianceCovarianceMatrix[j] * pseudoRootOfVarianceCovarianceMatrix[j];
                    }
                    break;

                case RandomNumberSequence.MultivariateMatrixStorageType.TriangularPackaged:
                    int startIndexMatrixQ = 0;     // the null-based index of the first index [in packaged representation] of matrix Q w.r.t. to the (i,j)-component of Q*Q'

                    for (int i = 0; i < dimension; i++)
                    {
                        startIndexMatrixQ += i;

                        for (int j = 0; j <= i; j++)
                        {
                            /* j is the start index of Matrix Q' and one has to calculate j + 1 multiplications: */
                            double value = 0.0;

                            for (int k = 0; k < j + 1; k++)
                            {
                                value += pseudoRootOfVarianceCovarianceMatrix[startIndexMatrixQ + k] * pseudoRootOfVarianceCovarianceMatrix[j + k];
                            }
                            workspace[i + j * dimension] = workspace[j + i * dimension] = value;
                        }
                    }
                    break;

                default:
                    throw new ArgumentException(matrixStorage.ToFormatString());
                }
                int errorCode = 0;

                _acml_MultiNormalNumbers(ref n, ref dimension, mu, workspace, ref dimension, m_RandomNumberStream.m_State, data, ref n, ref errorCode);
                if (errorCode != 0) // execution is not successful
                {
                    throw new InvalidOperationException("ACML: Return value " + errorCode + " in DRANDMULTINORMAL.");
                }
                return(BLAS.MatrixTransposeState.Transpose);
            }