Как реализовать оператор мутации Гаусса для генетического алгоритма в Java - PullRequest
13 голосов
/ 08 июня 2011

Я пытаюсь изучить и реализовать простую библиотеку генетических алгоритмов для моего проекта.На данный момент эволюция, отбор популяции готов, и я пытаюсь реализовать простой хороший оператор мутации, такой как Гауссов оператор мутации (GMO), для моего механизма генетической эволюции в Java и Scala.

Я нахожу некоторую информацию об операторе мутации Гаусса (GMO) в статье Оператор мутации, основанный на ранжировании по Парето для многоцелевых эволюционных алгоритмов (PM Mateo, I.Альберто), стр. 6 и 7.

Но у меня есть некоторая проблема, чтобы найти другую информацию о том, как реализовать этот гауссов оператор мутации и другие полезные варианты этого оператора в Java.Что мне делать?

Я использую random.nextGaussian() функцию случайного Java-утилиты, но этот метод возвращает случайное число только от 0 до 1.

Итак,

а) Как я могу изменить точность номера возврата в этом случае?(Например, я хочу получить случайное двойное число от 0 до 1 с шагом, равным 0,00001.)

b) и как я могу указать mu и sigma для этой функции, потому что я хочулокально искать значение моего генома, а не от -1 до 1. Как я могу настроить локальное исследование вокруг моего значения генома?

После исследования я нашел ответ на вопрос б).Кажется, я могу сместить гауссово случайное число следующим образом:

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

, где mean = значение моего генома.

(см. Метод нижней страницы в Как я могугенерировать случайные числа с нормальным или гауссовым распределением? .)

Ответы [ 4 ]

5 голосов
/ 25 июня 2011

Чтобы ответить на вопрос а, все, что вам нужно сделать, это округлить до ближайшего 0,00001, чтобы получить ответ в этих единицах.Например:

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

Теперь для части b у вас есть правильная идея, и код, который вы представили, должен работать.Все, что вам нужно сделать, это изменить масштаб вашей переменной до желаемого диапазона.Единственное, что я могу добавить, это то, что основная причина этой работы - это теорема об изменении переменных из исчисления: http://en.wikipedia.org/wiki/Integration_by_substitution

Если вы разработаете эту формулу в случае гауссовского распределения со средним 0 и стандартным отклонением1, будучи преобразованным линейным сдвигом и масштабированием, вы увидите, что то, что вы написали, действительно было правильным.

Собирая все это вместе, вот код, который должен добиться цели:

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
}
3 голосов
/ 17 июня 2011

Я настоятельно рекомендую НЕ использовать генератор случайных чисел Java. Он использует линейный конгруэнтный генератор , который имеет известные ограничения:

Если нужны случайные числа более высокого качества и достаточно памяти (~ 2 килобайта), тогда алгоритм твистера Мерсенна обеспечивает значительно более длительный период (219937-1) и однородность вариаций. [9] Твистер Mersenne генерирует отклонения более высокого качества, чем почти любая LCG. [Цитата необходима] Обычная реализация твистера Mersenne, достаточно интересно, использует LCG для генерации начальных данных. * (Из Википедии)

Соответственно, я предлагаю вам рассмотреть реализацию твистера Мерсенна. В частности, я использую реализацию ECJ, которая также имеет возможность генерировать гауссовых чисел .

Если вам нужна совместимость с Java-интерфейсом Random, используйте 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 быстрее, но не реализует интерфейс Random.

0 голосов
/ 23 июня 2011

Чтобы изменить «точность» числа, сделайте что-то вроде:

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

Это округлит переменную rand до 2 десятичных знаков.Конечно, вы должны быть осторожны с небольшими ошибками округления с плавающей запятой, чтобы они не обязательно были точными.

Что касается реализации ГМО, в статье описывается, как это сделать довольно точно.Я не уверен, как это можно объяснить более четко.Я предполагаю, что у вас есть x и sigma где-то в вашем коде, и вы просто преобразуете его, используя описанную математическую операцию.

0 голосов
/ 13 июня 2011

Вот как вы можете сгенерировать случайное число от 0 до n:

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

Если вам нужно целое число, приведите его к int, но добавьте к n, то есть (int)random(n + 1)

...