← All NMath Code Examples
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