Стейтчарт life отражает "динамику жизни" агента. Фактически, он отслеживает переход из состояния его жизни к состоянию его смерти (рис. 10.12). Эта динамика определяется собранными статистическими данными о смертности (т. е. таблицей DeathRate). Однако напрямую использование интен-сивностей, представленных в этой таблице, неудобно.
Действительно, собранная статистика состоит из конечного числа пар вида <уеа ri, ri >, где yeari — это текущий i-й год "жизни" агента, а Ri — вероятность смерти в этом возрасте (см. рис. 10.8). Такие данные позволяют построить стейтчарт (рис. 10.12, а) так, что по истечении каждой единицы модельного времени, соответствующей одному году жизни, из текущего состояния year, агент с вероятностью ri перейдет в состояние dead, и с вероятностью (1— ri) перейдет в состояние yeari+1
Вместо такого громоздкого стейтчарта, однако, можно построить стейтчарт всего из двух состояний, в котором переход из начального состояния "жив" в заключительное состояние "умер" для каждого агента будет выполняться после истечения таймаута, который является реализацией случайной величины, отражающей продолжительность жизни агента. Распределение этой случайной величины можно построить по таблице DeathRate. Именно эту операцию для любой таблицы, задающей интенсивности переходов, выполняет алгоритмическая функция rateToDistribution, определенная для активного объекта Agent.
Функция rateToDistribution для любой таблично заданной функции, определяющей интенсивность (в процентах) наступления некоторого события от времени, вычисляет вероятностное распределение времени наступления этого события. Тип этой функции Distrcustom (см. Справочник классов). Функции подобного типа возвращают реализацию случайной величины, которая имеет данное распределение. Использование ключевого слова static в объявлении этой функции говорит о том, что она является одной и той же во всех экземплярах класса Agent. В поле Дополнительный код класса окна Код активного объекта Agent с помощью указанной функции все таблично заданные интенсивности (таблица интенсивностей смертности и пять таблиц интенсивностей использования алкоголя) преобразуются в распределения. Поскольку все эти распределения будут одни и те же для всех экземпляров класса Agent, они также определены с ключевым словом static
Очевидно, что каждый агент в модели должен иметь свое собственное распределение продолжительности жизни в зависимости от его собственной
истории алкогольной зависимости. В модели реальзована следующая концепция: у каждого агента определяется его личное распределение продолжительности жизни, названное distrActualDeath. Вначале это распределение совпадает с исходным распределением продолжительности жизни distrDeath (она объявлена в поле Дополнительный код класса окна Код активного объекта Agent). В тот момент, когда конкретный экземпляр агента переходит от одной стадии алкогольной зависимости к другой, его личное распределение продолжительности жизни distrActuaiDeath должно пересчитаться, и в дальнейшем именно оно будет определять "жизнь" этого агента.
Стейтчарты агента
Динамику "жизни" агентов представляют стейтчарты life и alcohoiusage. Стейтчарт life (рис. 10.13) в отличие от рис. 10.12, б имеет дополнительный переход из состояния alive в себя (именно здесь пересчитывается распределение distrActuaiDeath) и дополнительное состояние. Это состояние необходимо для того, чтобы заставить стейтчарт alcohoiusage выйти из своего состояния alive и тем самым корректно считать число агентов, находящихся в той или иной стадии алкогольной зависимости. При переходе в состояние dead агент инициирует у своего владельца group операцию уничтожения объекта:
group.dispose_agents(Agent.this);
Пересчет распределения distrActuaiDeath производится в стейтчарте life по получении любого события (поэтому в поле Событие перехода gets
addict or quits СТОИТ?Object). Эти события (ADDICTED ИЛИ QUITTED) ИНИЦИИРУЮТСЯ в стейтчарте alcohoiusage соответственно при входе и выходе из состояния addict. Пересчет осуществляется умножением интенсивностей
смертности на коэффициент, зависящий от соответствующей стадии алкогольной зависимости. Переходы между этими стадиями определяются стейтчартом alcoholUsage. При входе и выходе из каждого элементарного состояния в группе, включающей данного агента, соответственно увеличивается и уменьшается общее количество агентов, находящихся в текущий момент в соответствующей стадии. Иерархическая структура описываемого стейтчарта определяет возможный переход из фазы 1 в фазу 4, минуя фазу 3 алкогольной зависимости.
Параметры
Агент имеет единственный параметр intervened логического типа. Истинное его значение определяет членов группы, подвергшейся акции пропаганды, ложное значение этого параметра будет установлено для членов контрольной группы. Фактически, параметр intervened определяет то распределение, по которому будет генерироваться случайная величина временного интервала перехода в стейтчарте alcohoiusage в первую и в последнюю стадии алкогольной зависимости. Так, переход initiates стейтчарта alcohoiusage производится по таймауту, который определяется так: intervened? distrAlcoholInitiationlntervened.get(): distrAlcoholInitiation.get()
Соответственно определен и переход quits этого стейтчарта:
intervened? distrAlcoholQuitIntervened.get(): distrAlcoholQuit.get()
10.6.5. Активный объект AgentGroup
Сюда включен реплицированный экземпляр класса Agent, множество агентов с именем agents. Их число установлено в 1000. Значение булевского параметра intervened включенных в группу агентов определено как значение параметра intervened активного объекта AgentGroup. В этом активном объекте определены также две группы переменных. Первая группа — скалярные переменные, которые подсчитывают интересующие значения в текущем году. nNeverUser, nRecreationalUser, nAddict И nQuitter — Количества агентов, находящихся в текущий момент в соответствующей стадии алкогольной зависимости. Значения этих переменных изменяют составляющие группу агенты при входе и выходе из соответствующих состояний своего стейтчарта alcohoiusage.
Кроме того, AgentGroup содержит статический таймер, который циклически с интервалом 1 (что соответствует одному году жизни общества) активизирует действие подсчета стоимости cost лечения членов группы за текущий год, а также запоминание подсчитанных скалярных значений всех величин
В тех элементах массивов histNeverUser, histRecreationalUser, histAddict, histQuitter и histcost, которые соответствуют текущему году.
начиная с года 0 и кончая годом 100. Здесь принято, что в год на каждого человека, находящегося на первой стадии алкогольной зависимости, тратится $1К, на второй стадии — $50К и на третьей — $5К:
cost = nRecreationalUser*1000 + nAddict*50000 + nQuitter*5000;
В результате работы модели, за 100 прошедших единиц модельного времени, в группе агентов будут сформированы массивы, хранящие по годам количества членов группы, находящихся в четырех указанных ранее стадиях алкогольной зависимости, подсчитаны затраты по годам на лечение всех членов группы, а также общие затраты (totalcost) и количество лет (totalyears). которые жили все члены группы.
10.6.6. Активный объект Model
Этот активный объект содержит две группы — экземпляры класса AgentGroup. В одной из них параметр intervened установлен в false — это контрольная группа, в другой он установлен в true — это группа, подвергшаяся влиянию акции (уменьшение вдвое интенсивности перехода к первой стадии и увеличение вдвое интенсивности перехода к третьей стадии алкогольной зависимости).
Анимация
Анимация здесь позволяет наблюдать эффект влияния акции (рис. 10.14). Этот эффект представлен различием в графиках, показывающих изменение числа членов группы, продолжительность жизни членов и затраты для двух групп агентов.
Для класса AgentGroup анимация представляет собой графики, которые
формируются на основании массивов histNeverUser, histRecreationalUser,
histAddict, histQuitter и histcost, заполняемых по мере хода моделирования. Рассмотрим, как формируется график затрат на лечение по годам (синяя линия) по массиву histcost. График представлен ломаной, динамическое значение числа точек которой задано константой 101 — от О до 100 года возможной жизни членов группы. Координаты X точек ломаной определяются через номер точки (index) с масштабом по оси X поля анимации, а координата Y — тоже с масштабом — значениями массива histcost [index]. Чуть более сложно определяются графики числа членов группы, находящихся в различных стадиях алкогольной зависимости. Графики задаются ломаной с 102 точками, из которых первые 101 определяют координаты кривой, а последняя имеет координаты (0, 0) для того, чтобы построить замкнутую ломаную, которую можно залить цветом. Кривые строятся в приращениях для каждой стадии, чтобы можно было наблюдать на одном графике в каждом году и общее число членов группы.
Использование средств библиотеки деловой графики (Business Graphics) позволяет значительно упростить представление результатов в этой модели. Мы применяли здесь базовые средства AnyLogic для построения сложных графиков в порядке упражнения.
Заключение
Фактически, имитационное моделирование часто является единственным средством, которое может помочь принятию разумного решения в условиях неопределенности. Имитационное моделирование таких систем связано с имитацией случайных явлений и генерацией дискретных и непрерывных случайных величин с заданными законами распределения. Поэтому умение строить модели для анализа систем в условиях неопределенности включает в себя базовые знания теории вероятностей и статистики. В данной главе мы рассмотрели общие принципы анализа систем в условиях неопределенности и средства AnyLogic, позволяющие выполнять такой анализ.
AnyLogic включает множество средств, облегчающих разработку и анализ стохастических моделей. В первую очередь, это богатое разнообразие распределений случайных величин. Разработчик моделей на AnyLogic может также создать свое собственное распределение по своим экспериментальным данным. Для создания своего распределения пользователь должен создать новый класс и унаследовать его от базового класса Distr, как это показано В Приведенном примере модели Alcogol Use Dynamics.
Глава 11
Организация
взаимодействия AnyLogic с другими приложениями 1