Подтвердить что ты не робот

Как реализовать гауссовский оператор мутации для генетического алгоритма в Java

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

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

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

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

Итак,

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

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

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

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

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

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

4b9b3361

Ответ 1

Чтобы ответить на вопрос a, все, что вам нужно сделать, округляется до ближайшего 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
}

Ответ 2

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

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

Соответственно, я предлагаю вам рассмотреть реализацию Mersenne twister. В частности, я использую реализацию 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.

Ответ 3

Чтобы изменить "точность" числа, сделайте следующее:

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

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

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

Ответ 4

Здесь вы можете создать случайное число между 0 и n:

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

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