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
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:
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 aNextSobolNumber()
, 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 deSobolNumber
en lugar de utilizar un loop.