AC-Random

De Wikihaskell
Saltar a: navegación, buscar
AC-Random
AC-Random
Lenguaje Haskell
Biblioteca AC-Random
Autores Jesús María Lozano Romero
Natalia Partera Jaime
Maripaz Oteo Meseguer

Contenido

Introducción

El lenguaje Haskell no permite la generación de números aleatorios. El paquete AC-Random es un generador de números pseudo-aleatorios. Diseñado para reemplazar el estándar '98 PRNG del paquete random.

Permite generar resultados repetibles comenzando con un generador de números aleatorios inicial especificado, u obtener resultados diferentes en cada ejecución mediante un sistema generador inicializado o proporcionando una semilla de alguna otra fuente.

Podemos dividir este paquete en dos capas:

  • Un núcleo generador de números aleatorios proporciona un suministro de bits. La clase RandomGen proporciona una interfaz común para dichos generadores. La biblioteca ofrece una instancia de RandomGen, tipo abstracto de datos StdGen.
  • Proporciona una manera de extraer valores de un tipo concreto de un generador de números aleatorios. Por ejemplo: generar valores aleatorio de tipo Float.


Nota: Los programadores pueden hacer uso de sus propios RandomGen.

Propiedades

  • Mejor API que random. Soporta todos los tamaños de enteros, por ejemplo.
  • Mucho más rápido que Random.
  • Calidad similar a Random. Ambas bibliotecas pasan el test "Die Harder" con resultados parecidos.
  • 100% código Haskell '98. Sin características específicas del compilador. Sin dependencias externas.Genera en todas partes.
  • Funciones puras y ADTs simples. Estados no mutables, E/S no mónadas.

Instalación

Para instalar cualquier librería de Haskell, previamente es necesario tener instalado el sistema "Cabal". Dicho sistema describe cómo interactúan cada una de ellas con el lenguaje, así como implementaciones para dar soporte a las mismas. Además, para los desarrolladores, permite construir y empaquetar librerías, facilitando así su distribución.

Instalación en Ubuntu

Para instalar Cabal:

$  sudo apt-get install cabal-install

Una vez instalado, es necesario realizar una actualización de la lista de paquetes:

$  cabal update

Por último, para instalar la presente librería:

$  cabal install ac-random

Instalación en Windows

Tal y como se comenta anteriormente, para la instalación de AC-Random es necesaria la instalación de Cabal sea cual sea el sistema utilizado. En el caso de que el sistema utilizado sea Windows es necesaria, además, la instalación de Haskell Platform.

Una vez descargados ambos requisitos, debemos seguir los siguientes pasos:

1. Si no tenemos instalado Haskell, instalamos Haskell Platform.

2. Vamos a nuestra terminal (Símbolo de sistema) y nos situamos en el directorio donde se encuentre nuestro ejecutable "cabal.exe".

3. Actualizamos nuestra lista de paquetes. Para ello, introducimos ejecutamos en la terminal:

  $ cabal update

4. Por último, instalamos el módulo que deseemos. En nuestro caso, AC-Random

  $ cabal install AC-Random

Módulos

Random.MWC.Primitive

Este módulo contiene el algoritmo que genera números aleatorios. Es recomendable el uso del API Random.MWC.Pure para un mejor funcionamiento.

Semillas aleatorias

Tipo de datos Seed

El paquete AC-Random pone a disposición el tipo de datos 'Seed' para la generación de números aleatorios. Los elementos declarados del tipo de dato 'Seed' representan semillas inmutables para la generación de números aleatorios.

Además, sobre el tipo de datos 'Seed' están definidas las relaciones de orden y de igualdad.

Instancias:

  • Eq Seed
  • Ord Seed

Método seed

La función seed recibe una lista de valores enteros de 32 bits sin signo y devuelve una semilla aleatoria del tipo 'seed'. En el caso de que la lista de enteros esté vacía, devuelve un valor por defecto. En las demás situaciones, cada elemento de la lista afecta a la semilla que se genera. La lista de elementos debe de ser finita para que el método seed no entre en un bucle infinito.

La cabecera de este método es la siguiente:

   seed :: [Word32] -> Seed

Generación de números aleatorios

El paquete AC-Random incluye también un método para la generación de números aleatorios con la siguiente cabecera:

   next_word :: Seed -> (Word32, Seed)

Este método recibe una semilla inicial con la que genera un valor entero sin signo y una nueva semilla. Dada una semilla, next_word devolverá siempre el mismo valor pseudoaleatorio, por eso devuelve también otra semilla.

El valor generado se encuentra comprendido entre los valores 0x00000000 y 0xFFFFFFFF (ambos inclusive) y siguiendo una distribución uniforme, por lo que todos los valores posibles tienen la misma probabilidad de ser generados.

Random.MWC.Pure

Este módulo del paquete AC-Random engloba las funciones puras para la generación de números aleatorios.

Para ello, se utiliza como base el módulo anterior Random.MWC.Primitive, por tanto usa el tipo de datos 'Seed' para la generación de número aleatorios y mantienen las propiedades ya definidas:

  • Existe una relación de igualdad
   Eq Seed
  • Existe una relación de orden
   Ord Seed
  • Las semillas son inmutables para dicha generación de números aleatorios

Así pues, a través de este nuevo módulo, conseguimos subir el nivel de abstracción mediante la definición de nuevos métodos que se añaden al ya definido en el módulo Random.MWC.Primitive:

   next_word :: Seed -> (Word32, Seed) 


Generación de números aleatorios

Se definen las siguientes clases con sus respectivos métodos:

Clase BoundedRandom

Permite generar número aleatorios dentro un de un rango limitado tanto inferior como superior. Así pues, los tipos de datos que pueden utilizar esta clase, deben pertenecer a su vez a la clase Bounded, donde se definen los límites inferior y superior de cada tipo de datos.

Definición:

   class Bounded x => BoundedRandom x

Método bounded_random

   bounded_random :: Seed -> (x, Seed)

Dada una semilla, devuelve un valor al azar dentro de un rango y una nueva semilla.

El valor se obtiene de forma pseudo-aleatoria (con la misma semilla siemre se obtendrá el mismo valor) y con una distribución uniforme, es decir, todos los valores tienen la misma probabilidad. El rango vendrá definido por el tipo de dato elegido.

Instancias:

  • BoundedRandom Bool
  • BoundedRandom Int
  • BoundedRandom Int8
  • BoundedRandom Int16
  • BoundedRandom Int32
  • BoundedRandom Int64
  • BoundedRandom Word
  • BoundedRandom Word8
  • BoundedRandom Word16
  • BoundedRandom Word32
  • BoundedRandom Word64

Por tanto se puede utilizar con los siguientes tipos de datos: Bool, Int, Int8, Int16, Int32, Int64, Word, Word8, Word16, Word32, Word64.

Clase UnitRandom

Esta clase permite la generación de número aleatorios comprendidos entre cero y uno. Para ello es necesario que los tipos de datos pertenezcan a la clase Ord, es decir, que posean una relación de orden.

Definición:

   class Ord x => UnitRandom x

Método unit_random

   unit_random :: Seed -> (x, Seed)

Dada una semilla, devuelve un valor aleatorio entre cero y uno, así como una nueva semilla. El valor se obtiene igualmente de forma pseudo-aleatoria y con una distribución uniforme.

Instancias:

  • UnitRandom Double
  • UnitRandom Float

Los tipos de datos que representan a los números decimales y pertenecen a la clase Ord son: Double y Float

Clase RangeRandom

Permite la generación de números aleatorios en un intervalo dado. Al igual que sucedía con la clase UnitRandom, los tipos de datos deben pertenecer a la clase Ord.

Definición:

   class Ord x => RangeRandom x

Instancias:

  • RangeRandom Double
  • RangeRandom Float
  • RangeRandom Int
  • RangeRandom Int8
  • RangeRandom Int16
  • RangeRandom Int32
  • RangeRandom Int64
  • RangeRandom Word
  • RangeRandom Word8
  • RangeRandom Word16
  • RangeRandom Word32
  • RangeRandom Word64


Los tipos de datos que cumplen los requisitos son: Double, Float, Int, Int8, Int16, Int32, Int64, Word, Word8, Word16, Word32, Word64.


Método range_random

   range_random :: (x, x) -> Seed -> (x, Seed)


Dado un intervalo (representado por un par) y una semilla, devuelve un valor pseudo-aleatorio dentro del intervalo dado y con una distribución uniforme.

Método random_list

   random_list :: (Seed -> (x, Seed)) -> Int -> Seed -> ([x], Seed)

Dicho método recibe:

  • Una función que recibe una semilla y devuelve un número aleatorio junto con una nueva semilla.
  • Un entero (n)
  • Una semilla

Y devuelve una lista de n valores pseudo-aleatorios con una distribución uniforme, así como una nueva semilla.

Random.MWC.Monadic

Haskell hace uso de mónadas para impimir un número aleatorio. La propiedad de transparencia referencial no nos permite que una función devuelva un resultado distinto cada vez que se llama a la misma, es por esto que necesitamos un mecanismo para poder utilizar números aleatorios o E/S en Haskell.

El uso de mónadas nos permite encapsular un dato de manera que para el sistema lo que recibe o devuelve es una mónada de un tipo.

Debido a que conseguir manualmente el valor correcto de la semilla es tedioso y propenso a errores, un enfoque común es el uso de un estado oculto. Este módulo proporciona funciones prácticas para hacer esto sencillo, simplemente hay que escribir una instancia de RandomM acorde a nuestra mónada, y podremos generar números aleatorios facilmente.

Tal y como hemos comentado anteriormente, los elementos declarados del tipo de dato Seed representan semillas inmutables para la generación de números aleatorios.

  • Existe una relación de igualdad
   Eq Seed
  • Existe una relación de orden
   Ord Seed

Clase Monads

La clase mónadas (Monad) posee una sola semilla aleatoria dentro de su estado.

Definición:

   class Monad m => RandomM m where

Método get_random_seed

   get_random_seed :: m Seed

Método set_random_sed

   set_random_seed :: Seed -> m ()

Operaciones con mónadas

Método bounded_randomM

   bounded_randomM :: (RandomM m, BoundedRandom x) => m x

Es el análogo monádico de bounded_random.

Devuelve un valor elegido al azar entre minBound y maxBound. Utiliza el valor actual de la semilla de la mónada, actualiza de manera automática el valor de la semilla. Así, llamando repetidamente a esta función producirá diferentes valores sucesivos.

Método unit_randomM

   unit_randomM :: (RandomM m, UnitRandom x) => m x

Análogo monádico de unit_random.

Este método devuelve un valor entre cero y uno al azar. Al igual que el anterior método, utiliza el valor de la semilla para así acualizar de manera automática su valor. Es por esto, que llamando de manera repetida a esta función producirá la generación de diferentes valores.

Método range_randomM

   range_randomM :: (RandomM m, RangeRandom x) => (x, x) -> m x

El análogo monádico de range_random.

Devuelve un valor escogido de forma aleatoria a partir de una gama especificada por el usuario (inclusive). Al igual que sus métodos hermanos actualiza de manera automática el valor de la semilla que se encuentra actualmente en la mónada, para así con la llamada repetida a esta función se produzcan la generación de diferentes valores.

Ejemplos de Uso

Creación de una semilla

 > Seed 1 2 3 4 5
   Seed {word1 = 1, word2 = 2, word3 = 3, word4 = 4, carry = 5}

Generar un número aleatorio

Utilizando el método más básico del módulo Random.MWC.Primitive, next_word, sería de la siguiente manera:

   > next_word seed0
    (13352297,Seed {word1 = 13352297, word2 = 2378237609, word3 = 1123982241, word4 = 42253450, carry = 0})

Así pues, el número pseudo-aleatorio generado ha sido el 13352297. Siendo seed0 una semilla ya definida en el módulo con el tipo de datos Word32:

   seed0 =  Seed 0x8DC106A9 0x42FE9BA1 0x0284BC8A 0xABA48CE2 0x5935B28D

Aplicando la semilla creada en el apartado anterior:

   > next_word (Seed 1 2 3 4 5)
   (4294966589,Seed {word1 = 4294966589, word2 = 1, word3 = 2, word4 = 3, carry = 0})

El número generado ha sido el 4294966589, además de la creación de una nueva semilla: Seed {word1 = 4294966589, word2 = 1, word3 = 2, word4 = 3, carry = 0}.

Tal y como se ha mencionado varias veces, la generación se realiza de forma pseudo-aleatoria, por lo que si utilizamos de nuevo el método next_word con la misma semilla, obtendriamos el mismo número.

Referencias

http://hackage.haskell.org/package/AC-Random
http://www.haskell.org/cabal/


Herramientas personales