Адаптация генетического алгоритма для минимизации полиномиальных представлений булевых функций Аспирант Б.П. Ильин Любую булеву функцию можно представить в виде полинома. Например: f ( x1 , x2 , x3 ) = x1 ⋅ x2 ⋅ x 3 ⊕ x1 ⋅ x 2 ⋅ x 3 ⊕ x1 ⋅ x 2 ⋅ x 3 В теории и на практике зачастую возникает задача нахождения минимального представления булевых функций в виде полинома. Для решения этой задачи применяются различные методы. Одним из таких методов является метод минимизации полиномиального представления булевых функций с использованием библиотек (ссылка?). Этот метод основывается на том, что достаточно хранить только сложности функций от n–1 числа переменных. В данном случае под сложностью понимается количество слагаемых по модулю 2 полиномиального представления функции. Такой метод дает точный результат, однако для вычисления сложности функции f ( x1 ,...., x n ) нужно «пробежать» всю библиотеку сложностей функции от n–1 переменных. Поэтому уже для функций 6 переменных это связано с определенными трудностями — необходимо хранить в оперативной памяти 2 Гб данных, а также практически невозможно хранить на жестком диске результирующую библиотеку сложностей. Для преодоления данного рода ограничений могут быть использованы различные приближенные поисковые методы и алгоритмы. Одним из таких алгоритмов выступает генетический алгоритм (ГА). Генетический алгоритм можно определить как эвристический алгоритм поиска, используемый для решения задач оптимизации и моделирования путем последовательного подбора, комбинирования напоминающих и вариации биологическую искомых параметров эволюцию. Является с использованием разновидностью механизмов, эволюционных вычислений. Отличительной особенностью генетического алгоритма является акцент на использование оператора «скрещивания», который производит операцию рекомбинации решений-кандидатов, роль которой аналогична роли скрещивания в живой природе (ссылка). В конце 1960-х годов американским исследователем Джоном Холландом была предложена идея генетических алгоритмов, в основе которых лежит принцип эволюции живых организмов, предложенный Чарльзом Дарвиным. Первый ввел в обиход термин «генетический алгоритм» Д. Багли в своей диссертации в 1967 г. Задача кодируется таким образом, чтобы каждое её решение могло быть представлено в виде вектора («хромосома»). Зачастую хромосомы представляются в виде двоичных векторов. Случайным образом создаётся некоторое количество начальных векторов («начальная популяция») – C11 ... C n1 ... C1k ... C nk . Они оцениваются с использованием «функции приспособленности», в результате чего каждому вектору присваивается определённое значение («приспособленность»), которое определяет вероятность выживания организма, представленного данным вектором. После этого с использованием полученных значений приспособленности выбираются вектора (селекция), допущенные к «скрещиванию». К этим векторам применяются «генетические операторы» (в большинстве случаев «скрещивание» crossover и «мутация» - mutation), создавая таким образом следующее «поколение». Особи следующего поколения также оцениваются, затем производится селекция, применяются генетические операторы и т. д. Так моделируется «эволюционный процесс», продолжающийся несколько жизненных циклов (поколений), пока не будет выполнен критерий останова алгоритма. Таким критерием может быть: • нахождение глобального, либо субоптимального решения; • исчерпание числа поколений, отпущенных на эволюцию; • исчерпание времени, отпущенного на эволюцию. Основной (классический алгоритм) генетический состоит из следующих шагов: 1) инициализация или выбор исходной популяции хромосом; 2) оценка приспособленности хромосом в популяции; 3) проверка условия остановки алгоритма; 4) селекция хромосом; 5) применение генетических операторов; 6) формирование новой популяции; 7) выбор «наилучшей хромосомы». Пункт 1 выполняется один раз в начале выполнения алгоритма, пункт 7 – по его завершении. Шаги с 2 по 6 должны пройти определенное число итераций. Первый шаг состоит в создании случайным образом начальной популяции — данная популяция, является отправной точкой генетического алгоритма. Оценивание приспособленности хромосом в популяции состоит в расчете функции приспособленности для каждой хромосомы этой популяции. Чем больше значение этой функции, тем выше «качество» хромосомы. Форма функции приспособленности зависит от характера решаемой задачи. Проверка условия остановки генетического алгоритма зависит от его конкретного применения. В оптимизационных задачах, если известно максимальное (или минимальное) значение функции приспособленности, то остановка алгоритма может произойти после достижения ожидаемого оптимального значения, возможно — с заданной точностью. Остановка алгоритма также может произойти в случае, когда его выполнения не приводит к улучшению уже достигнутого значения. Алгоритм может быть остановлен по истечении определенного времени выполнения либо после выполнения заданного количества итераций. Если условие остановки выполнено, то производится переход к завершающему этапу выбора «наилучшей хромосомы». В противном случае на следующем шаге выполняется селекция. Селекция хромосом заключается в выборе (по рассчитанной функции приспособленности) тех хромосом, которые будут участвовать в создании потомков для следующей популяции. Такой выбор производится согласно принципу естественного отбора, по которому наибольшие шансы на участие в создании новых особей имеют. Основные методы селекции: • метод рулетки — особенность данного метода заключается в том, что вероятность выбора хромосомы определяется ее приспособленностью. Использование этого метода приводит к тому, что вероятность передачи признаков более приспособленными особями потомкам возрастает. Каждой хромосоме сопоставляется сектор колеса рулетки, величина которого устанавливается пропорционально значению функции приспособленности данной хромосомы. Селекция хромосом таким способом может быть представлена как генерация случайных чисел в виде интервала [0, 100] Выбор родительской хромосомы производится исходя из того, в какой сектор попало данное случайное число. Очевидно, что чем больше сектор, тем больше вероятность «победы» соответствующей хромосомы. 1 8 2 3 1 2 4 3 4 5 6 7 7 5 6 Рис. 1. Метод рулетки. 8 • турнирный метод — реализует n турниров, чтобы выбрать n особей. Каждый турнир построен на выборке k элементов из популяции, и выбора лучшей особи среди них. Наиболее распространен турнирный отбор с k=2 (рис. 2); 0 1 1 0 1 1 0 1 1 1 0 0 1 0 1 0 1 0 0 1 1 0 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 0 5,6 7,2 1,5 3,9 4,7 0,8 2,6 9,1 0 1 0 1 1 1 1 0 1 0 1 1 0 0 0 0 1 1 1 1 0 1 1 0 5,6 7,2 2,6 9,1 Рис. 2. Турнирный метод. • стратегия элитаризма — заключается в том, что особи с наибольшей приспособленностью гарантировано переходят в новую популяцию (рис 3.). Использование элитаризма обычно позволяет ускорить сходимость генетического алгоритма. Недостаток использования стратегии элитаризма в том, что повышается вероятность попадания алгоритма в локальный минимум. 1 1 0 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 1 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 9,1 7,2 5,6 4,7 3,9 2,6 1,5 0,8 Рис.3. Стратегия элитаризма. • ранговый метод — сначала осуществляется сортировка особей по функции приспособленности. Затем процедура выглядит как метод рулетки, за тем исключением, что вероятность выжить, пропорциональна не значению функции приспособленности, а месту, которое заняла гипотеза. 1 1 0 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 1 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 9,1 7,2 5,6 4,7 3,9 2,6 1,5 0,8 Рис. 4. Ранговый метод. Применение генетических операторов к хромосомам, отобранным с помощью селекции, приводит к формированию новой популяции потомков от созданной на предыдущем этапе родительской популяции. В классическом генетическом алгоритме применяются два основных генетических оператора: оператор скрещивания (crossover) и оператор мутации (mutation). Оператор скрещивания выполняется следующим образом — случайным образом выбирается пара хромосом из родительской популяции с вероятностью p c . Далее для каждой пары отобранных таким образом родителей разыгрывается позиция гена в хромосоме, определяющая так называемую точку скрещивания. Эта точка представляет собой натуральное число меньшее L (где L – длина хромосомы), т.е. количество генов в родительской хромосоме (находится в интервале [1, L-1]). В результате скрещивания пары родительских хромосом получается следующая пара потомков (Рис. 5): 1) потомок, хромосома которого на позициях от 1 до l k состоит из генов первого родителя, а на позициях от l k + 1 до L – из генов второго родителя; 2) потомок, хромосома которого на позициях от 1 до l k состоит из генов второго родителя, а на позициях от l k + 1 до L – из генов первого родителя. Модификацией оператора скрещивания или кроссовера является двухточечный кроссовер. Он идентичен одноточечному, однако в нем скрещивание проходит уже по двум точкам. 0 1 1 1 1 0 0 0 0 1 1 0 1 1 1 1 1 0 0 0 0 1 1 0 1 0 0 0 1 1 1 0 1 1 1 1 Рис. 5. Одноточечный кроссовер. Оператор мутации в свою очередь выполняется таким образом — с вероятностью pm меняет значение гена в хромосоме на альтернативное допустимое. Вероятность pm мутации может эмулироваться, например, случайным выбором числа из интервала [0, 1] для каждого гена и отбором для выполнения этой операции тех генов, для которых разыгранное число оказывается меньшим или равным значению pm . 0 1 1 0 1 0 1 1 0 0 1 1 Рис. 6. Оператор мутации. Формирование новой популяции заключается во включении полученных после применения генетических операторов хромосом в состав новой популяции. Она становится текущей популяцией для данной итерации алгоритма. На каждой очередной итерации рассчитываются значения функции приспособленности для всех хромосом этой популяции, после чего проверяется условие остановки алгоритма и либо фиксируется результат, либо осуществляется переход к следующему шагу алгоритма. Выбор «наилучшей» хромосомы выполняется в том случае, если условие остановки алгоритма выполнено. В этом случае следует вывести результат работы, т.е. представить искомое решение задачи. Лучшим решением считается хромосома с наибольшим значением функции приспособленности. Для решения задачи минимизации полиномиального представления булевых функций был реализован ГА с использованием языка C++ (рис. 7). Начало Инициализация начальной популяции Селекция хромосом Кроссовер Оператор мутации Оператор инверсии Оценка приспособленности Формирование новой популяции Проверка условия завершения Выбор наилучшей хромосомы Конец Рис. 7. Схема реализованного генетического алгоритма. Перед тем, как запустить алгоритм, необходимо задать начальные параметры алгоритма: • Функцию, сложность которой определяется; • Количество итераций, которое должен пройти алгоритм; • Количество мутаций, которое произойдет за время выполнения алгоритма; • Количество генов, которые претерпевают мутацию; • Количество инверсий, которое произойдет за время выполнения алгоритма; • Количество генов, которые претерпевают инверсию; • Размер популяции; • Тип генерирования начальной популяции; • Тип кроссовера; • Тип закона распределения при осуществлении выборки особей. Как и в классическом ГА, в виде функций было реализовано несколько генетических операторов. Реализованный алгоритм выполняет следующие стадии: 1. Инициализация начальной популяции — на первом шаге генерируется популяция предков, которая даст в результате выполнения операторов селекции и скрещивания новое потомство. Популяция представляет собой динамический двумерный массив типа unsigned int (один элемент – 32 бита) и, в зависимости от длины функции, состоит из нескольких элементов одной записи массива. Это позволяет легко работать с функциями любой длины. Функция Gen_ind() принимает несколько параметров, главным из которых является тип генерирования первоначальной популяции: 1) Конкретная хромосома представлена набором случайных генов, представляющих собой «0» или «1»; 2) Каждый элемент хромосомы принимает случайное значение от 0 до 232–1 — максимальное значение, которое может принять переменная типа unsigned int. 3) Также как и в п.2, только каждый элемент хромосомы разбивается на 8 частей по 4 бита. 4) Случайный выбор из первых 3-х вариантов. Помимо этого, в первоначальную популяцию было решено добавлять нулевую и единичную остаточную, а также производную исходной функции. 2. Следующим этапом происходит оценивание хромосом. В качестве функции приспособленности выступает сложность булевых функций. Для достижения этой реализована функция AbsMin(), которая возвращает с помощью сокращенной библиотеки (ссылка?) точное значение сложности любой функции 5-ти переменных 3. Оператор селекции Selection() возвращает двух представителей из массива случайным образом. Для этого используются следующие законы распределения вероятностей: 1) Равномерный – вероятность выбора того или иного представителя одинакова. Говорят, что случайная величина имеет непрерывное равномерное распределение на отрезке [a,b], где , если её плотность fX(x) имеет вид: 2) Показательный – случайная величина X имеет показательное (экспоненциальное) распределение с параметром λ > 0, если она непрерывна, принимает только положительные значения, и имеет плотность распределения . 3) Усеченный нормальный – распределение, получаемое из классического нормального, при ограничении интервала возможных значений. f X ( x) = (x − µ)2 exp− 2σ 2 σ 2π 1 Данные законы распределения вероятностей выбора представителей для осуществления селекции и скрещивания выбраны из следующих соображений: • Равномерный закон позволяет выбирать представителей с одинаковой вероятностью, вне зависимости от их функции приспособленности; • Показательный закон позволяет отбирать представителей таким образом, что вероятность выбора того или иного представителя уменьшается с увеличением значения функции приспособленности; • Нормальный закон в первую очередь отбирает наиболее «приспособленных» представителей и только в последнюю очередь отбирает «худших» представителей. Равномерное Показательное Нормальное Рис. 8. Графическое представление законов распределения вероятностей. 4. Оператор скрещивания — кроссовер. Определяет случайным образом одну или две точки скрещивания, в результате чего получает двух новых представителей, с генами от первого и второго родителя. По числу точек скрещивания реализованы: • Одноточечный кроссовер (функция Crossover_1point()); • Двухточечный кроссовер (функция Crossover_2points()). 5. В зависимости от количества мутаций, которое задается, как параметр ГА следующим этапом может выступать оператор мутации (функция mutation()). Подвергаться мутации может как один ген конкретного представителя, так и сразу несколько — это значение, передается как параметр функции. 6. Оператор инверсии (функция Inv()) – зеркально отображает часть генов в хромосоме конкретного представителя. Основной параметр — число генов, которые буду зеркально отображены. 7. Сортировка (функция bubbleSort()) – сортирует представителей по возрастанию функции приспособленности, в качестве которой выступает сложность булевой функции. 8. Завершающим этапом каждой итерации является формирование новой популяции – т.к. и родительская популяция и популяция потомков отсортированы, т.е. упорядочены от «лучших» к «худшим», то в новую родительскую популяцию извлекается половина представителей родительской популяции и половина популяции потомков. Тем самым, качественные решения задачи – потомки, не выпадают в ходе дальнейшего выполнения алгоритма. После выполнения всех этих этапов алгоритм возвращается к п. 2 и продолжается то число раз, которое пользователь задал при запуске данной программы. Генетический алгоритм являет собой достаточно мощное средство, для нахождения точных или приближенных решений различных оптимизационных задач. Однако краеугольным камнем данного класса алгоритмов является подбор параметров ГА. В связи с этим была выдвинута задача отыскания таких параметров алгоритма, при котором сложность любой булевой функции 6-ти можно будет найти за минимальное время, при этом результат будет либо соответствовать точному значению, либо отличаться на единицу. Для этого был предложен следующий путь нахождения оптимальных настроек алгоритма: 1. На первом этапе генерируется 100 функций 6-ти переменных, т.к. длина такой функции равна 64 битам, то начальная популяция была сгенерирована в следующем виде. Популяция была разбита на группы по 10 особей, каждая группа отличалась от соседней на 6 бит. Порядок бит определяется случайным образом. 2. Сгенерированный массив функций оценивается с помощью алгоритма, позволяющего точно оценить сложность функции 6-ти переменных с использованием библиотек (ссылка). 3. Методом прямого перебора перебираются варианты параметров ГА. Параметры, с ограниченным количеством значений (тип кроссовера, тип селекции и т.д.) принимают все возможные варианты значений. Параметры, с неограниченным количеством значений (число итераций, размер популяции и т.д.) принимают значения до определенной границы (зависит от параметра) с заданным шагом. На каждой итерации находится с помощью ГА значение сложности каждой из 100 функций, а также разность между точным значением каждой функции и найденным с помощью ГА. 4. Для каждого набора параметров определяется дельта – сумма разностей между точными значениями сложностей функций и значениями сложности, вычисленной с помощью ГА. 5. Если значения дельты меньше 20, то ее значение и весь набор параметров записываются в файл для дальнейшего анализа. С помощью данного метода были проведены испытания ГА с различными параметрами и были получены следующие выводы: • При небольшом числе итераций наиболее качественные значения алгоритма получены с использованием двухточечного кроссовера, с использованием первого типа генерации начальной совокупности, и достаточно большом размере этой популяции. • Вне зависимости от выбранного закона распределения с увеличением количества итераций наблюдается следующая особенность – независимо от выбранных параметров мутации, генерации первоначальной совокупности представителей, типа селекции генетический алгоритм возвращает максимально точные решения. • Оптимальным числом мутаций – является треть от общего числа итераций, число мутирующих генов – до половины от общей длины функции. • При большем числе итераций увеличение числа мутаций позволяет получить более качественные решения. • Т.к. в дальнейшем планируется использовать генетический алгоритм 6-ти переменных, как промежуточные вычисления, то было бы наиболее эффективным получать наиболее точное решение за минимальное время. Такими параметрами могут быть – 100 итераций, 30 мутаций, 4 мутирующих гена, 160 – размер популяции, тип генерации – 1, тип кроссовера – двухточечный, равномерный закон распределения. Точный алгоритм нахождения сложности полиномиального представления булевых функций 6ти переменных позволил найти наиболее оптимальные параметры для генетического алгоритма. Следующим этапом является нахождение параметров ГА, для поиска наименьшего значения сложности полиномиального представления булевой функции 7-ми переменных. В целом, генетический алгоритм для 7-ми переменных идентичен алгоритму для 6-ти переменных. Однако в нем есть некоторые отличия: • В качестве популяции выступают функции 6-ти переменных; • Оценка приспособленности функций 6-ти переменных использует генетический алгоритм. Схематично генетический алгоритм нахождения сложности булевой функции 7-ми переменных представлен на рис. 1. Промежуточным этапом в этом алгоритме является запуск ГА для 6-ти переменных, который в свою очередь для оценки сложности использует популяцию, состоящую из представителей – функций 5-ти переменных. Сложность этих функций определяется по библиотеке сложностей (ссылка). Начало Инициализация начальной популяции Инициализация начальной популяции Селекция хромосом Селекция хромосом Кроссовер Кроссовер Оператор мутации Оператор мутации Оператор инверсии Оператор инверсии Оценка приспособленности Оценка приспособленности Формирование новой популяции Формирование новой популяции Проверка условия завершения Проверка условия завершения Выбор наилучшей хромосомы Выбор наилучшей хромосомы ГА нахождения сложности функции 6-ти переменных Конец Рис. 9. Схема генетического алгоритма для функции 7-ми переменных.