using System; using CenterSpace.NMath.Core; namespace CenterSpace.NMath.Examples.CSharp { /// <summary> /// A .NET example in C# showing how to create streams of independent random numbers. /// </summary> class IndependentStreamsExample { static void Main( string[] args ) { // NMath provides classes for generating several independent streams of random // numbers using the leapfrog and skip-ahead (blocksplitting) methods. // IMPORTANT NOTE: // Skip-ahead and leapfrog streams are only supported for basic random number // generator types which provide a more efficient algorithm than generation // of that full sequence to pick out a required subsequence. The static variable // SkipAheadStream.SupportedGeneratorTypes contains a list of the supported // types for SkipAheadStream. int seed = 0x124; var genType = RandomNumberStream.BasicRandGenType.MultiplicativeCongruent31; // Create a SkipAheadRandomStreams object for generating 10 independent random number streams, // each of length 100, using the Skip Ahead method. int numberOfStreams = 5; int streamLength = 1000; var indStreams = new SkipAheadRandomStreams( seed, genType, numberOfStreams, streamLength ); // Create a streamLength x numberOfStreams matrix A and use the SkipAheadRandomStreams object // created above to fill it with random numbers. Each of the numberOfStreams columns // in the resulting matrix will contain streamLength random deviates distributed // uniformly in the interval (0, 1). Each column of random numbers will // be independent from the others. var dist = new DoubleRandomUniformDistribution(); var A = new DoubleMatrix( streamLength, numberOfStreams ); indStreams.Fill( dist, A ); // Print out the correlation matrix for the sample to test // independence. Correlations should be near zero for independent // samples. DoubleSymmetricMatrix correlationMatrix = RankCorrelation( A, true ); Console.WriteLine(); Console.WriteLine( "Spearmans Rank Correlation for independent random samples:" ); for ( int i = 0; i < correlationMatrix.Rows; i++ ) { for ( int j = 0; j < i; j++ ) { Console.WriteLine( "Correlation between column {0} and row {1} is {2}", i, j, correlationMatrix[i, j].ToString( "G6" ) ); } } // You can also generate independent streams from different probability // distributions. Here we generate 3 streams each with a different // distribution using the leapfrog technique. numberOfStreams = 3; var leapfrogIndStreams = new LeapfrogRandomStreams( seed, genType, numberOfStreams, streamLength ); var distributions = new IRandomNumberDistribution<double>[numberOfStreams]; distributions[0] = new DoubleRandomBetaDistribution(); distributions[1] = new DoubleRandomExponentialDistribution(); distributions[2] = new DoubleRandomLogNormalDistribution(); DoubleMatrix C = leapfrogIndStreams.Next( distributions ); // Print out the rank correlation matrix for the sample to test // independence. Correlations should be near zero for independent // samples. correlationMatrix = RankCorrelation( C, true ); Console.WriteLine( "\nSpearmans Rank Correlation for samples from different distributions:" ); for ( int i = 0; i < correlationMatrix.Rows; i++ ) { for ( int j = 0; j < i; j++ ) { Console.WriteLine( "Correlation between column {0} and row {1} is {2}", i, j, correlationMatrix[i, j].ToString( "G6" ) ); } } // Independent streams from discrete distributions are also supported. streamLength = 5; genType = RandomNumberStream.BasicRandGenType.WinchannHillCombined; leapfrogIndStreams = new LeapfrogRandomStreams( genType, numberOfStreams, streamLength ); var discreteDistributions = new IRandomNumberDistribution<int>[numberOfStreams]; discreteDistributions[0] = new IntRandomBernoulliDistribution( .6 ); discreteDistributions[1] = new IntRandomGeometricDistribution( .2 ); discreteDistributions[2] = new IntRandomPoissonDistribution( .8 ); int[][] discreteRandomSamples = leapfrogIndStreams.Next<int>( discreteDistributions ); // The ith independent stream is in the array discreteRandomSamples[i]. for ( int i = 0; i < numberOfStreams; i++ ) { Console.WriteLine( "\nDistribution: {0}", discreteDistributions[i].GetType() ); for ( int j = 0; j < discreteRandomSamples[i].Length; j++ ) { Console.Write( discreteRandomSamples[i][j] ); Console.WriteLine(); } } Console.WriteLine(); Console.WriteLine( "Press Enter Key" ); Console.Read(); } /// <summary> /// Computes the Spearman rank correlation matrix for a set of random inputs. The random /// inputs are taken to be the columns of the input matrix. The symmetric, /// positive definite matrix whose i,j entry is the Spearman correlation coefficient /// between the inputs in column i and column j is computed and returned. /// </summary> /// <param name="A">Matrix whose columns are the inputs whose Spearman rank correlation /// coefficient is computed.</param> /// <param name="useMidRankForTies">If true mid ranks are used for ranking ties. /// </param> /// <returns>The symmetric, positive definite matrix whose row i, column j /// entry is the correlation coefficient between the inputs in column i and column j /// </returns> static DoubleSymmetricMatrix RankCorrelation( DoubleMatrix A, bool useMidRankForTies ) { int N = A.Rows; var sortedData = new double[N]; var indices = new int[N]; var xRanks = new DoubleVector( N ); var yRanks = new DoubleVector( N ); var R = new DoubleSymmetricMatrix( A.Cols ); for ( int i = 0; i < A.Cols; i++ ) { for ( int j = i; j < A.Cols; j++ ) { if ( i == j ) { R[i, j] = 1.0; } else { RankData( A.Col( i ), sortedData, indices, xRanks, useMidRankForTies ); RankData( A.Col( j ), sortedData, indices, yRanks, useMidRankForTies ); R[i, j] = RankCorrelationFromRanks( xRanks, yRanks ); } } } return R; } static void RankData( DoubleVector data, double[] sortedData, int[] Indices, DoubleVector ranks, bool useMidRankForTies ) { if ( data.Length != sortedData.Length ) { throw new InvalidArgumentException( "data and sortedData arrays do not have the same length in RankData" ); } if ( data.Length != Indices.Length ) { throw new InvalidArgumentException( "data and Indices arrays do not have the same length in RankData" ); } for ( int i = 0; i < Indices.Length; i++ ) { sortedData[i] = data[i]; Indices[i] = i; } Array.Sort<double, int>( sortedData, Indices ); for ( int i = 0; i < sortedData.Length; i++ ) { ranks[i] = Array.IndexOf<int>( Indices, i ) + 1; } if ( useMidRankForTies ) { ApplyMidranks( sortedData, ranks ); } } static void ApplyMidranks( double[] data, DoubleVector ranks ) { for ( int i = 1; i < data.Length; i++ ) { if ( data[i] == data[i - 1] ) { int start = i - 1; int count = 0; double rankSum = 0; while ( start + count < data.Length && data[start] == data[start + count] ) { rankSum += ranks[start + count]; ++count; } double midrank = rankSum / (double) count; for ( int s = 0; s < count; s++ ) { ranks[start + s] = midrank; } i = start + count; } } } static double RankCorrelationFromRanks( DoubleVector xRanks, DoubleVector yRanks ) { int N = xRanks.Length; if ( yRanks.Length != N ) { throw new InvalidArgumentException( "All arrays must have same length in RankCorreleation" ); } double sum = 0; for ( int i = 0; i < N; i++ ) { double d = xRanks[i] - yRanks[i]; sum += ( d * d ); } return ( 1.0 - ( ( 6 * sum ) / ( N * ( N * N - 1 ) ) ) ); } } // class } // namespace← All NMath Code Examples