2. Актуальность
— Необходимость генерации и изменения алгоритма по
заданным разработчиком требованиям.
Например, для автоматического изменения фильтров от
спама, при новой тактике рассылки рекламы.
— Необходимость максимальной гибкости алгоритма при
изменении условий.
Например, при поломке автономного робота.
2
3. Постановка задачи
Сгенерировать такой алгоритм A, чтобы
оценочная функция T(A) была максимальной.
Алгоритм А разработчику неизвестен. Оценочная функция T(A) —
программа, результат которой максимизируется. Она предоставляется
разработчиком в соответствии с требованиями к алгоритму.
Генератор планируется использовать для изучения автоматической
генерации программ, поэтому алгоритм A должен быть закодирован
максимально понятным способом. Например, в виде современных языков
программирования.
Возможные варианты решения:
— полный перебор;
— различные методы, накладывающие ограничения на T(A);
— генетический алгоритм.
3
4. Генетический алгоритм
Основная проблема генерации программы с
помощью генетического алгоритма:
Выбор схемы кодирования алгоритма.
Начальная популяция Если базироваться на обычных язык
программирования, то мутацию сложно
a
реализовать из-за иерархичных операторов
if, while, for и излишнего множества команд.
Размножение
На текущий момент чаще всего применяются
a aaa нейронные сети, но при беглом взгляде на
нейронную сеть нельзя понять её алгоритм.
Отбор Мутация
abc
4
5. 2
Язык D NA
Язык D2NA создан для представления алгоритма в форме, удобной для
мутации и смешивания в генетическом алгоритме. Чтобы быть понятным
человеку он базируется на современных языках программирования:
1. Только целочисленные переменные (их имена с прописной буквы).
2. С внешним миром обмен идёт сигналами (их имена с заглавной буквы).
3. Перед именами переменных и сигналов идёт двоеточие.
4. Только три команды:
4.1. послать сигнал;
4.2. увеличить переменную на 1;
4.3. уменьшить переменную на 1.
5. Из операторов только if (без for и while).
Синтаксис: on условие do команды end.
6. Исключается вложенность if’ов.
7. Программа начинается со списка if’ов со всеми возможными условиями.
8. В условии if’а проверяется только:
8.1. поступление сигнала (записывается имя сигнала);
8.2. значение переменной больше 0 (записывается имя переменной).
5
6. 2
Пример программы на языке D NA
Для запуска программы посылается сигнал :Init. На сигнал :Print посылается
исходящий сигнал :Ping. На следующий :Print посылается :Pong и обратно.
on :Init do
up :ping_state
end
on :Print, :ping_state do
send :Ping
down :ping_state
up :pong_state
end
on :Print, :pong_state do
send :Pong
down :pong_state
up :ping_state
end
6
7. 2
Схема генератора D NA-программ
Схема генетического алгоритма с вводом языка D2NA:
Размножение
начальная популяция
Разработчик
Генератор
оценочная функция
Отбор Мутация
Результаты D2NA-код
оценочной функции
Виртуальная машина D2NA
7
8. Реализация на языке Ruby
2
генератора D NA-программ
Метрики: Генератор опубликован в Интернете
11 классов под свободной лицензией GNU GPL:
84 метода http://github.com/ai/d2na
110 правок в истории проекта
по системе контроля версий Диаграмма классов:
487 строк комментариев
2 261 строка кода d2na/evolution
Population
Язык Ruby:
— интерпретируемый
с JIT-компиляцией; Evolution d2na/vm
— кроссплатформенный;
— с динамической типизаций;
— с автоматическим управлением Tests MutableCode Code
памятью и сборщиком мусора; Rule
— с объектной модель Smalltalk;
— в нём всё является объектом, даже Rule
число и класс; …
— имеет замыкания и гибкий
синтаксис.
8
9. Отладка и тестирование
— 177 модульных тестов (1 015 строк кода).
— 100% покрытие кода тестами по C0 (по строкам).
— 4 интеграционных теста.
— Тесты писались до реализации (методология TDD).
— Было исправлено около 16 ошибок
во время интеграционного тестирования.
Пример. В D2NA, при клонировании кода, условные операторы копируются,
только если в клоне их изменили (копирование при записи, copy-on-write).
В начале клонирование было неправильным, так как метод clone() клонирует
только сам массив, но не создаёт копии его элементов:
def clone_rule(rule)
clone = rule.dup()
clone.commands = clone.commands.clone()
↓
def clone_rule(rule)
clone = rule.dup()
clone.commands = deep_clone(clone.commands)
9
10. Результаты
Созданный программный притотип «Использования генетических алгоритмов для
автоматизированного написания программ» был проверен на задаче
«Повторяющейся дилеммы заключённого» из теории игр:
Идёт следствие, обвиняются два подельника А и Б по одному преступлению. Каждому
предлагает предать сообщника или молчать. Общаться между собой они не могут. В
зависимости от своих действий, А и Б получат срок:
А молчит А предаёт Б
А: 0,5 года А: свободен
Б молчит Б: 0,5 года Б: 10 лет
А: 10 лет А: 2 года
Б предаёт А Б: свободен Б: 2 года
Ситуация повторяется несколько раз с запоминанием предыстории.
Цель: минимизация срока А.
Программный прототип генератора должен найти оптимальную стратегию для А.
Лучшую стратегию «Око за око» придумал Анатолий Рапопорт в 1984:
На первом шаге молчим, а далее поступаем так же, как с нами поступили на прошлом шаге.
10
11. Результаты 2
Формализация задачи в виде Автоматически сгенерированное
оценочной функции на языке Ruby: решение на языке D2NA:
protocode do
input :Step, :Keeped, :Betrayed
on :Init do
output :Keep, :Betray send :Keep
end end
end_if { stagnation > 20 }
punishments = {[:Keep, :Keep] => [0.5, 0.5],
on :Step do
[:Betray, :Keep] => [ 0, 10], send :Betray
[:Keep, :Betray] => [ 10, 0], end
[:Betray, :Betray] => [ 2, 2]}
opponents = [proc { :Keep },
proc { :Betray },
on :Keeped do
proc { |p| :Betrayed == p ? :Betray : :Keep }] send :Betray
end
opponents.each do |opponent|
selection do
out_punishment = 0; our_previous_choice = nil Данная программа реализует
10.times do
send :Step оптимальную стратегию
our_choice = out.first «Око за око».
clear_out!
unless our_choice
our_punishment = 100; break
end
opponent_choice = opponent.call(our_previous_choice)
our_previous_choice = input_name(our_choice)
our_punishment += punishments[[our_choice, opponent_choice]].first
end
min our_punishment
end 11
end