Принцип работы программы

Рассмотрим структуры, которые описывают окружащую среду, агентов и другие объекты.

Характеристики агента:

- тип (травоядное или хищник)

- уровень энергии

- координаты (x и y)

- массив inputs (значение входов в нейронную сеть на этапе восприятия окружеющей среды)

- массив actions (значения выходов, действия)

- массив weight_oi

- массив biasso (смещения)

Входной массив задаёт входы как объект и область (например, хищное животное и область «лево»). Чтобы дать агенту возможность различать эти элементы, для каждого из них определяется отдельный вход в нейронную сеть. Выходы также связаны с отдельными выходными ячейками выходного вектора, который представляет одно действие.

Мир агентов двумерный, для агентов доступно три плоскости, причём каждую плоскость занимает агент одного типа, три измерения применяются для более эффективного подсчёта присутствующих объектов.

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

Теперь рассмотрим ход выполнения программы.

int main( int argc, char *argv[] )

{

< .>

init();

for (i = 0 ; i < MAX_STEPS ; i++) {

emitLandscape();

simulate();

< .>

}

Функция main инициализирует модель, а затем выполняет в цикле итерации, количество которых указано в заговолочном файле.

Функция init инициализирует среду и объекты в ней. Сначала инициализируется плоскость растений (функция growPlans), для этого создаются растения в количестве, заданном константой. Далее инициализируются агенты (initAgent); чтобы создать максимальное количество агентов (указано константой) каждый раз резервируется половина пространства. Сначала инициализируются травоядные, потом хищники.

Функций growPlans находит пустое место на плоскости растений и помещает в эту ячейку новое растение. Гарантируется, что растение будет помещено только в пустую ячейку.

В ходе инициализации плоскостей агентов программа в цикле проходит по массиву, содержащему типы агентов. Сначала инициализируется поле energy, энергия устанавливается в значение, равное половине от максимального. С помощью findEmptySpot() определяется начальное положение агента, эта находит пустую ячейку в заданной плоскости и сохраняет координаты агента в его структуре. Наконец, инициализируются веса и смещения для нейронной сети агента.

Теперь, после рассмотрения инициализации модели, рассмотрим непосредственно симуляцию. Функция simulate() позволяет каждому агенту выполнить одно действие в окружающей среде за один вызов. Травоядные получают небольшое преимущество, так как они создаются перед хищниками, но так как им предстоит противостоять и голоду, и хищникам, такое преимущество лишь немного выравнивает шансы агентов.

void simulate()

{

int i, type;

// Первыми действуют травоядные

for (type = TYPE_HERBIVORE ; type <= TYPE_CARNIVORE ; type++) {

for (i = 0 ; i < MAX_AGENTS ; i++) {

if (agents[i].type == type) {

simulateAgent( &agents[i] );

}

}

}

}

Функция simulate вызывает функцию simulateAgent для просчёта и выполнения одного действия агентом. Она может быть разбита на четыре отдельные части: восприятие, обработка полученных данных об окружающей среде, выбор действия и проверка энергии агента.

Для того, чтобы агент чувствовал среду ему сначала нужно идентифицировать координаты сетки, которые составляют его поле зрения (на основании направления движения), а затем разбить данную область на четыре отдельные зоны. Каждый вызов функции percept суммирает объекты в определённой зоне. При вызове в неё передаются текущие координаты агента, из массива inputs выбираются нужные данные о значениях на входах нейронной сети агента, а также список координат offset и их смещений. Если агент смотрит на север, то в функцию передаётся набор координат north<zone>, а если на юг, то передаётся тот же набор координт, но со смещением -1, аналогично и области для west<zone>. Смещения координат в каждой зоне определяются выбранным направлением, но они могут быть изменены на координаты противоположного направления. Для лучшего понимания приведу листинг:

Перейти на страницу:
1 2 3