const offsetPairType northProx[]=
{{0,-1}, {-1,-1}, {-1,0}, {-1,1}, {0,1}, {9,9}};
// Сетка смещений (восток-запад)
const offsetPairType westFront[]=
{{2,-2}, {1,-2}, {0,-2}, {-1,-2}, {-2,-2}, {9,9}};
const offsetPairType westLeft[]={{2,0}, {2,-1}, {9,9}};
const offsetPairType westRight[]={{-2,0}, {-2,-1}, {9,9}};
const offsetPairType westProx[]=
{{1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {9,9}};
Здесь представлены два набора координат для векторов смещения. Предположим, что агент имеет координаты (7,9) в среде (используя систему координат (х,у)). Используя вектор northRight в качестве смещения координат, программа рассчитывает две новые пары координат: (7,11) и (6,11) (координаты (9,9) представляют конец списка). Данные координаты отображают два положения в правой зоне для агента, который смотрит на север. Если бы агент смотрел на юг, программа бы инвертировала координаты northRight перед тем, как добавить их к текущему положению. В результате получилось бы следующее: (7,7) и (8,7). Эти координаты представляют два положения в правой зоне при условии, что агент смотрит на юг.
Продолжим изучение трёх других частей функции simulateAgent. Следующий этап заключается в том, чтобы провести переменные inputs, полученные на предыдущей стадии, в выходные ячейки нейронной сети агента. Результатом является набор значений выходных ячеек, которые рассчитаны на основании входных сигналов с использованием весов соединений между нейронами в сети. Затем (базируясь на том, какая ячейка имеет наибольшее значение) программа выбирает действие, которое будет выполнено агентом, по принципу «победитель получает всё». Для выполнения действия используется оператор case, для выбора доступны следующие действия: повернуть налево, повернуть направо, съесть, продвинуться вперёд на одну ячейку.
Последний этап симуляции агента — проверка его энергии. На каждом этапе агент теряет часть своей энергии (количество потерянной энергии различно для травоядных и хищников). Если энергия агента падает до нуля, то он умирает от голода и выбывает из симуляции.
Рассмотрим функции, используемые simulateAgent в порядке их вызова (percept, turn, move, eat и killAgent).
Функция percept использует цикл для изучения всех плоскостей и рассчитывает суммы на основании информации о соответствующей плоскости. Дляодин объект.
Функция turn изменяет направление, в которое агент смотрит. В зависимости от текущего направления агента и направления для поворота устанавливается новое направление.
Функция move немного сложнее. Используя набор смещений для установки нового положения по осям координат, а также направление, которое помогает определить нужную пару смещений программа рассчитывает новый набор координат. Перед движением агента изменяется плоскость, его содержащая, чтобы отобразить движение. После перемещения плоскость снова изменяется, чтобы показать, что агент находится на другой ячейке на заданной плоскости.
Выволнение функции eat разбито на два этапа: поиск объекта для съедения в области «близости» агента и, если таковой существует, запись об удалении съеденного объекта.
Суть первого этапа заключается в том, чтобы выбирается плоскость для поиска. Выбор основывается на типе текущего агента. Если агент является травоядным, то поиск ведётся на плоскости растений, в противном случае — на плоскости травоядных (для хищников). Далее, используя направление движения агента, программа вызывает функцию ChooseObject, чтобы вернуть координаты объекта интереса на нужную плоскость. В этой функции вновь задействованы пары смещения, но внимание уделяется только области близости — в напралении движения агента. Если объект был найден, функция ChooseObject возвращает значение, которое не равно нулю, и заполняет координаты x и y в соотвествии с функцией eat.
Функция ChooseObject очень похожа на функцию percept, однако вместо того, чтобы суммировать объекты, расположенные в плоскости данной зоны, она возвращает координаты первого найденного объекта.
Следующий этап — съедение объекта. Если подходящий объект был найден, программа проверяет плоскость, в которой он был обнаружен. Для плоскости растений выполняется поиск в массиве plants, после чего растение удаляется из массива landscape, затем создаётся новое растение, которое будет помещено в произвольную пустую ячейку. Для плоскости травоядных животных программа убивает съедаемое травоядное с помощью функции killAgent. Благодаря съедению объекта увеличивается уровень текущего объекта.
Наконец, если объект достиг уровня энергии, который необходим для воспроизводства, вызывается функция reproduceAgent, чтобы позволить агенту «родить» нового агента данного типа.
После уничтожения агента программа определяет, нужно ли инициализировать нового случайного агента данного типа вместо уничтоженного. Решение зависит от количества агентов данного типа, присутствующих в модели. Поскольку эволюционный аспект симуляции является самым интересным, требуется сохранить количество открытых позиций для агентов, чтобы любой агент при достижении определённого уровня энергии мог воспроизвести себя, поэтому новому случайному агенту позволяется занять место уничтоженного агента только если популяция данного типа агентов составляет менее 25% от общего количества агентов. Это позволяет сохранять 25% мест для агентов одного типа свободными для следующего воспроизведения.
Последняя функция симуляции, reproduceAgent , является самой интересной, поскольку она вносит в модель аспект эволюции Ламарка. Когда агент воспроизводит себя, он передает свою нейронную сеть ребенку. Ребенок наследует нейронную сеть родителя, а потом производится с небольшой вероятностью мутация
Сначала необходимо определить, есть ли свободное место для ребенка, проверив, заполнено пространство для агентов данного типа на 50% или нет. Если для ребенка было найдено свободное место, структура агента-родителя копируется для ребёнка, а затем отыскивается свободная ячейка, которую займёт ребёнок. Далее посредством мутации изменяется один из весов в нейронной сети агента. Затем выполняется запись, а энергия родителя делится поровну между ним и ребёнком, что заставляет их двигаться по среде в поисках пищи, пока они не наберут нужного количества энергии для следующего воспроизведения.
Функция emitLandscape сканирует все три плоскости и выводит на экран текущее положение всех объектов.
Заключение
В своей курсовой работе понятие «искусственная жизнь» я рассматривал на примере моделирования пищевой цепочки. Искусственная жизнь предлагает платформу для изучения различных феноменов в биологических и и социальных системах. Преимущество искусственной жизни в теории синтетического поведение — возможность играть в ролевые игры, изменяя параметры модели и отслеживая результаты. В данной курсовой концепции синтетической теории поведения были продемонстрированы с помощью несложной симуляции хищник/жертва. Можно увидеть, что и хищники, и жертвы выработали ряд интересных стратегий поведения, например:
- инстинкт стада для травоядных
Травоядное будет следовать за травоядным, если оно находится в области фронта. Сила травоядных в их количестве, конечно, если это не то травоядное, которое идёт впереди.
- хищники поджидают травоядных возле растений
Эта стратегия была успешной до тех пор, пока травоядные не научились избегать хищников, даже при условии, что растение находится в области видимости.
Мной была создана очень упрощённая модель пищевой цепочки, но даже на её основе можно ставить эксперименты, изменяя параметры окружающей среды, максимальный уровень энергии агентов и максимальное количество агентов того или иного типа, путём редактирования исходных кодов программы данную пищевую цепочку можно усложнять, превращая, к примеру, мёртвых хищников в растения или добавляя различные режимы симуляции.
Список литературы
1. М. Тим Джонс, «Программирование ИИ в приложениях», ДМК Пресс, Москва, 2006 г.
2. В. Г. Редько, курс лекций «Эволюционная кибернетика».
3. С. Осовский, «Нейронные сети для обработки информации», Финансы и статистика, Москва, 2002 г.