es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Obtención de valor en IEnumerable.

Una secuencia de Sobol, una serie de números aleatorios de baja discrepancia en el rango [0,1], se puede generar primero inicializando un vector de números de dirección:

Dim V(31) As ULong
For i = 1 To 31
  V(i-1) = 2 ^ (32 - i)
Next

y luego enumerando los elementos generados por una función Sobol() (proporcionada a continuación) como:

For Each lnumber As ULong In Sobol(V)
   MessageBox.Show(lnumber / 2 ^ 32)
Next

Esto se puede hacer siempre y cuando haya menos de 2^32 valores generados, el período típico de un generador congruencial lineal.

La pregunta es, ¿cómo se pueden extraer números individuales de Sobol de Sobol() sin usar un bucle, y en su lugar obtener un número a la vez a partir de una única llamada a la función? La idea sería instanciar una clase pública, en cualquier lugar de mi código, como

Dim ran As New SobolNumber()

y luego llamar al siguiente número usando, por ejemplo:

Dim x as Double
x = ran.NextSobolNumber

La función Sobol() y la función Ruler() requerida se enumeran a continuación:

Public Iterator Function Sobol(ByVal v() As ULong) As IEnumerable(Of ULong)
    Dim s As ULong = 0
    For Each r In Ruler()
        Yield s = s Xor v(r)
    Next r
End Function

Public Iterator Function Ruler() As IEnumerable(Of Integer)
    Yield 0
    For Each r In Ruler()
        Yield r + 1
        Yield 0
    Next r
End Function
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para extraer números individuales de Sobol() sin utilizar un loop, la función Sobol puede ser modificada para mantener un estado y generar un sólo número a la vez. La función modificada puede ser diseñada de la siguiente manera:

    Public Class SobolNumber
        Private v() As ULong
        Private s As ULong = 0
        Private r As IEnumerator(Of Integer)
    
        Public Sub New()
            ReDim v(31)
            For i = 1 To 31
                v(i - 1) = 2 ^ (32 - i)
            Next
    
            r = Ruler().GetEnumerator()
        End Sub
    
        Public Function NextSobolNumber() As Double
            r.MoveNext()
            s = s Xor v(r.Current)
            Return CDbl(s) / CDbl(2 ^ 32)
        End Function
    
        Private Iterator Function Ruler() As IEnumerable(Of Integer)
            Yield 0
            For Each r In Ruler()
                Yield r + 1
                Yield 0
            Next r
        End Function
    End Class
    

    La clase SobolNumber mantiene los vectores de dirección (v), el estado actual(s), y un enumerador para la secuencia Ruler (r). Cuando se llama a NextSobolNumber(), la secuencia Ruler se avanza una vez y el vector de dirección correspondiente se aplica para actualizar el estado de la secuencia Sobol. La función entonces devuelve el número de Sobol generado como un doble en el rango [0,1].

    Esta función modificada permite generar números individuales de Sobol llamando a NextSobolNumber() en una instancia de SobolNumber en lugar de utilizar un loop.

Comments are closed.