13

Intento aprender e implementar una biblioteca de algoritmo genético simple para mi proyecto. En este momento, la evolución, la selección de población está lista, y estoy tratando de implementar un buen operador de mutación simple como el Gaussian mutation operator (GMO) para mi motor de evolución genética en Java y Scala.Cómo implementar el operador de mutación gaussiana para un algoritmo genético en Java

encuentro alguna información sobre el operador de mutación de Gauss (OGM) en el papel A mutation operator based on a Pareto ranking for multi-objective evolutionary algorithms (PM Mateo, Alberto I.), página 6 y 7.

pero tengo algunos problemas para encontrar otra información sobre cómo para implementar este operador de mutación gaussiana y otras variantes útiles de este operador en Java. ¿Que debería hacer?

estoy usando la función random.nextGaussian() de Util de Java al azar, pero este método sólo devuelve un número aleatorio entre 0 y 1.

Así,

a) ¿Cómo puedo modificar la precisión de la devolución número en este caso? (Por ejemplo, quiero conseguir un número doble aleatorio entre 0 y 1 con paso igual a 0,00001.)

b) y cómo puedo especificar mu y sigma para esta función, porque quiero buscar localmente alrededor de un valor de mi genoma, no entre -1 y 1. ¿Cómo puedo ajustar esa investigación local en torno al valor de mi genoma?

Editar 1: Después de investigar, encontré una respuesta para la pregunta b). Parece que puedo desplazar el número aleatorio gaussiano como esto:

newGenomeValue = oldGenomeValue + ((gaussiandRndNumber * sigma) + mean) 

donde mean = valor de mi genoma.

(. Método Cfr del pie de página en How can I generate random numbers with a normal or Gaussian distribution?)

+0

¿Qué es exactamente lo que quiere decir con "precisión del número de retorno"? – NPE

+0

Los números del número después de la coma: http://en.wikipedia.org/wiki/Double_precision_floating-point_format – reyman64

+0

¿De qué manera desea "modificar" "los números del número después de la coma"? 'nextGaussian' te da un' doble'. ¿Estás diciendo que eso no es suficiente para tus necesidades? – NPE

Respuesta

4

Para responder a la pregunta a, todo lo que tienes que hacer es redondear al 0.00001 más cercano para obtener tu respuesta en esas unidades. Por ejemplo:

step = 0.00001; 
    quantized_x = step * Math.rint(x/step); 

Ahora, para la parte b, tiene la idea correcta y debería funcionar el código que presentó. Todo lo que necesita hacer es cambiar la escala de su variable al rango deseado. Lo único que puedo añadir es que la razón subyacente que esto funciona es el cambio de variables teorema del cálculo: http://en.wikipedia.org/wiki/Integration_by_substitution

Si usted se resuelve esta fórmula en el caso de una distribución gaussiana con 0 media y la desviación estándar de 1, siendo transformados por un cambio lineal y un cambio de escala, entonces verás que lo que escribiste fue realmente correcto.

Poniendo todo junto, aquí es un código que debe hacer el truco:

double next_gaussian() 
{ 
    double x = rng.nextGaussian(); //Use whichever method you like 
            //here to generate an initial [-1,1] gaussian distribution 

    y = (x * 0.5) + 0.5;    //Rescale to [0,1] 

    return Math.rint(y * 100000.0) * 0.00001; //Quantize to step size 0.00001 
} 
-2

Así es como se puede generar un número aleatorio entre 0 y n:

public static double random(int n) 
{ 
    return Math.random() * n; 
} 

Si necesita un entero, echarlo a int pero agregar uno a n, es decir, (int)random(n + 1)

+0

¿Quién rechazó - por qué? – Bohemian

3

Sugiero fuertemente a DO NO utilice el generador de números aleatorios de Java. Se utiliza el linear congruential generator, que ha conocido limitaciones:

Si se necesitan números aleatorios de mayor calidad, y hay suficiente memoria disponible (~ 2 kilobytes), entonces el algoritmo Mersenne Twister proporciona un período muy largo (219937-1) y varia la uniformidad. [9] El tornado de Mersenne genera una mayor calidad se desvía que casi cualquier LCG. [Cita requerida] Una aplicación de Mersenne twister común, curiosamente, utiliza un LCG para generar datos de semillas. * (De Wikipedia)

En consecuencia, le sugiero considerar una implementación de Twister de Mersenne. En particular, estoy usando la implementación del ECJ, que también tiene la capacidad de generar números gaussianos.

Si necesita compatibilidad con la interfaz Random de Java, use http://code.google.com/p/ecj/source/browse/trunk/ecj/ec/util/MersenneTwister.java.

http://code.google.com/p/ecj/source/browse/trunk/ecj/ec/util/MersenneTwisterFast.java es más rápido, pero no implementa la interfaz Aleatoria.

+1

Olvidé decir que ... el próximoGaussian devuelve una muestra de una distribución Normal. Como quiera cambiar la media y la Varianza, debe aplicar las transformaciones estándar que mencionaba en su comentario. Para obtener información adicional, consulte http://people.math.sfu.ca/~cschwarz/Stat-301/Handouts/node70.html – Matteo

+0

Thx para obtener ayuda, yo ' m usando un generador aleatorio de lecuyer en la biblioteca SSJ y math.commons (apac el fundamento) como WEll. No tengo respuesta sobre generar más pequeñas variaciones en mi doble aleatorio:/En realidad, estoy usando un aleatorio (int) entre 1 y 1E6 para dividir mi aleatorio (doble) ... – reyman64

-1

Para cambiar la "precisión" de la serie, hacer algo como:

((int)(100*rand))/100.0 

Esto redondear las variables rand a 2 decimales. Por supuesto, tendrá que tener cuidado con los pequeños errores de redondeo de coma flotante, por lo que no será necesariamente exacto.

En cuanto a la implementación de la GMO, el documento describe cómo hacerlo con bastante precisión. No estoy seguro de cómo podría explicarse más claro. Supongo que tiene un x y un sigma en algún lugar de su código y simplemente lo transforma utilizando la operación matemática descrita.

Cuestiones relacionadas