VB Independent Streams Example

← All NMath Code Examples

 

Imports System

Imports CenterSpace.NMath.Core


Namespace CenterSpace.NMath.Examples.VisualBasic

  A .NET example in Visual Basic showing how to create streams of independent random numbers.
  Module IndependentStreamsExample

    Sub Main()

      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.

      Dim Seed As Integer = &H124
      Dim GenType As RandomNumberStream.BasicRandGenType = RandomNumberStream.BasicRandGenType.MultiplicativeCongruent31

      Create a SkipAheadRandomStreams object for generating 10 independent random number streams, 
      each of length 100, using the Skip Ahead method.
      Dim NumberOfStreams As Integer = 5
      Dim StreamLength As Integer = 1000
      Dim IndStreams As 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.
      Dim Dist As New DoubleRandomUniformDistribution()
      Dim A As New DoubleMatrix(StreamLength, NumberOfStreams)
      IndStreams.Fill(Dist, A)

      Console.WriteLine()

      Print out the correlation matrix for the sample to test
      independence. Correlations should be near zero for independent
      samples.
      Dim CorrelationMatrix As DoubleSymmetricMatrix = RankCorrelation(A, True)
      Console.WriteLine("Spearmans Rank Correlation for independent random samples:")
      Dim I, J As Integer
      For I = 0 To CorrelationMatrix.Rows - 1
        For J = 0 To I - 1
          Console.WriteLine("Correlation between column {0} and row {1} is {2}", I, J, CorrelationMatrix(I, J).ToString("G6"))
        Next
      Next

      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
      Dim LeapfrogIndStreams As New LeapfrogRandomStreams(Seed, GenType, NumberOfStreams, StreamLength)
      Dim Distributions(NumberOfStreams) As IRandomNumberDistribution(Of Double)
      Distributions(0) = New DoubleRandomBetaDistribution()
      Distributions(1) = New DoubleRandomExponentialDistribution()
      Distributions(2) = New DoubleRandomLogNormalDistribution()
      Dim C As DoubleMatrix = 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()
      Console.WriteLine("Spearmans Rank Correlation for samples from different distributions:")
      For I = 0 To CorrelationMatrix.Rows - 1
        For J = 0 To I - 1
          Console.WriteLine("Correlation between column {0} and row {1} is {2}", I, J, CorrelationMatrix(I, J).ToString("G6"))
        Next
      Next

      Independent streams from discrete distributions are also supported.
      StreamLength = 5
      GenType = RandomNumberStream.BasicRandGenType.WinchannHillCombined
      LeapfrogIndStreams = New LeapfrogRandomStreams(GenType, NumberOfStreams, StreamLength)
      Dim DiscreteDistributions(NumberOfStreams) As IRandomNumberDistribution(Of Integer)
      DiscreteDistributions(0) = New IntRandomBernoulliDistribution(0.6)
      DiscreteDistributions(1) = New IntRandomGeometricDistribution(0.2)
      DiscreteDistributions(2) = New IntRandomPoissonDistribution(0.8)
      Dim DiscreteRandomSamples()() As Integer = LeapfrogIndStreams.Next(Of Integer)(DiscreteDistributions)
      The ith independent stream is in the array discreteRandomSamples[i].
      For I = 0 To NumberOfStreams - 1
        Console.WriteLine()
        Console.WriteLine("Distribution: {0}", DiscreteDistributions(I).GetType())
        For J = 0 To DiscreteRandomSamples(I).Length - 1
          Console.Write("{0}{1}", DiscreteRandomSamples(I)(J), If(J = DiscreteRandomSamples(I).Length, "\n", ", "))
        Next
      Next

      Console.WriteLine()
      Console.WriteLine()
      Console.WriteLine("Press Enter Key")
      Console.Read()
    End Sub

    <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>
    Function RankCorrelation(ByVal A As DoubleMatrix, ByVal useMidRankForTies As Boolean) As DoubleSymmetricMatrix

      Console.WriteLine("A.Rows " & A.Rows)
      Console.WriteLine("A.Cols " & A.Cols)

      Dim N As Integer = A.Rows
      Console.WriteLine(N)
      Dim SortedData(N - 1) As Double
      Console.WriteLine(SortedData.Length)
      Dim Indices(N - 1) As Integer
      Console.WriteLine(Indices.Length)

      Dim XRanks As New DoubleVector(N)
      Dim YRanks As New DoubleVector(N)

      Dim R As New DoubleSymmetricMatrix(A.Cols)

      For I = 0 To A.Cols - 1
        For J = 0 To A.Cols - 1
          If (I = J) Then
            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)
          End If
        Next
      Next
      Return R
    End Function

    Sub RankData(ByVal Data As DoubleVector, ByVal SortedData() As Double, ByVal Indices() As Integer, ByVal Ranks As DoubleVector, ByVal useMidRankForTies As Boolean)

      Console.WriteLine("data: " & Data.Length & " sorted " & SortedData.Length)

      If (Data.Length <> SortedData.Length) Then
        Throw New InvalidArgumentException("data and sortedData arrays do not have the same length in RankData")
      End If

      If (Data.Length <> Indices.Length) Then
        Throw New InvalidArgumentException("data and indices arrays do not have the same length in RankData")
      End If

      For I = 0 To Indices.Length - 1
        SortedData(I) = Data(I)
        Indices(I) = I
      Next

      Array.Sort(Of Double, Integer)(SortedData, Indices)

      For I = 0 To SortedData.Length - 1
        Ranks(I) = Array.IndexOf(Of Integer)(Indices, I) + 1
      Next

      If (useMidRankForTies) Then
        ApplyMidranks(SortedData, Ranks)
      End If

    End Sub

    Sub ApplyMidranks(ByRef Data() As Double, ByRef Ranks As DoubleVector)

      For I = 1 To Data.Length - 1
        If (Data(I) = Data(I - 1)) Then
          Dim Start As Integer = I - 1
          Dim Count As Integer = 0
          Dim Ranksum As Double = 0

          While (Start + Count < Data.Length & Data(Start) = Data(Start + Count))
            Ranksum += Ranks(Start + Count)
            Count = Count + 1
          End While

          Dim MidRanks As Double = Ranksum / CType(Count, Double)
          For S = 0 To Count - 1
            Ranks(Start + S) = MidRanks
          Next
          I = Start + Count
        End If
      Next
    End Sub

    Function RankCorrelationFromRanks(ByRef xRanks As DoubleVector, ByRef yRanks As DoubleVector) As Double

      Dim N As Integer = xRanks.Length
      If (yRanks.Length <> N) Then
        Throw New InvalidArgumentException("All arrays must have same length in RankCorreleation")
      End If

      Dim Sum As Double = 0 

      For I = 0 To N - 1

        Dim D As Double = xRanks(I) - yRanks(I)
        Sum += (D * D)
      Next
      Return (1.0 - ((6 * Sum) / (N * (N * N - 1))))
    End Function

  End Module
End Namespace

← All NMath Code Examples
Top