VB Independent Streams Example

← All NMath Code Examples

 

Imports System

Imports CenterSpace.NMath.Core
Imports CenterSpace.NMath.Matrix

Namespace CenterSpace.NMath.Core.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