Системы называются дискретно-событийными (или просто дискретными), если изменения переменных состояния в них происходят только в явно определенные моменты времени или под влиянием явно определенных собы-тий. Находясь в некотором состоянии, дискретная система сохраняет его (не изменяет своих характеристик) до наступления очередного события, под воздействием которого переменные системы (и, следовательно, ее состояние) изменяются скачком. Например, при построении модели банка со-стояние системы может быть представлено количеством клиентов в помещении банка и числом занятых кассиров. Состояние системы изменяется, если только новый клиент входит в банк или когда освобождается кассир, аэто на некотором уровне абстракции можно считать мгновенными событиями, сопровождаемыми изменением состояния системы.
В данной главе мы рассмотрим примеры дискретно-событийных моделей и средства AnyLogic, позволяющие такие модели разрабатывать.
Порты и сообщения. Дискретная модель счетчика
Разработанная в предыдущей главе модель ContinuousCounter не является удовлетворительной. Действительно, при работе этого счетчика переменные генератора и разрядов растут бесконечно, что не соответствует реальной работе счетчика. В реальном счетчике генератор посылает счетчику не значе-ние общего числа сигналов, а только сам сигнал ("тик"). Каждый разряд десятичного счетчика считает число пришедших на его вход "тиков" по модулю 10 и передает на свой выход сигнал переполнения после прихода на его вход каждого десятого сигнала.
При построении модели такого счетчика нужно использовать новые средст-ва, характерные для моделей дискретно-событийных систем. Здесь нам дос-таточно трех таких средств: (статического) таймера, порта и передаваемых
через порт сообщений. В данной главе мы не будем строить дискретную модель счетчика сами. Вместо этого мы подробно рассмотрим уже разработанную модель с именем counter, находящуюся в папке Model Examples\Part II. Наша задача — объяснить различия между этой моделью и моделью
ContinuousCounter.
Рассматриваемые вопросы
В результате обсуждения модели Counter будут рассмотрены новые средства:
- порты и сообщения;
- действия при получении сообщений.
Структура модели
Структура модели counter совпадает со структурой модели ContinuousCounter. Их внешнее поведение также одинаково. Откройте модель Counter и запустите ее. В этой модели определены три класса активных объектов: Gen (генератор импульсов), counter (одноразрядный десятичный счетчик) и Model (корневой объект, включающий генератор и три разряда счетчика).
Представление сигнала как сообщения
Генератор должен посылать сигналы с заданной частотой. Сигнал можно представить как сообщение, передаваемое между объектами через явно определенный интерфейс — порт. В качестве сообщения в AnyLogic можно передавать любой объект, фактически, экземпляр любого класса. Сообщения в AnyLogic (как и любой класс Java) должны наследоваться от базового класса object. В нашей модели счетчика важен только сам факт передачи или приема сообщений, а содержимое сообщений не важно. В таких случаях сообщения модели можно считать просто экземплярами базового класса object, поскольку это базовый класс Java и нам его не надо расширять специальными переменными. Событие приема такого сообщения будет вызывать выполнение действия по изменению состояния системы (в нашем случае это просто увеличение значения счетчика).
Генератор
Активный объект Gen должен посылать сообщения первому разряду счетчика с заданной частотой. Новым элементом структуры активного объекта Gen в модели дискретного счетчика является порт. Порт — это основной низкоуровневый механизм AnyLogic в коммуникации объектов модели с помощью
передачи сообщений. Сообщения посылаются и передаются через порты. Порты являются двунаправленными, через них сообщения могут и посылаться, и приниматься. Через порт, помещенный на границе прямоугольника, ограничивающего активный объект, этот объект может посылать и принимать сообщения от других активных объектов.
У генератора определен порт с именем tick. Для того чтобы создать такой порт, нужно щелкнуть мышью на кнопке панели инструментов, а затем на границе прямоугольника, представляющего активный объект Gen. Вслед за этим в окне свойств порта нужно установить его параметры. Все параметры порта tick, кроме имени, оставлены неизменными так, как они определены по умолчанию.
Генератор нашей модели периодически с частотой 1/ frequency должен выдавать сообщения (т. е. экземпляры класса object) через порт tick. Внутри прямоугольника Gen помещена иконка статического таймера (рис. 6.1).
Справа в окне свойств таймера указано его предопределенное имя timer, а также параметры таймера: то, что он циклический, что он не срабатывает на старте и что период его срабатывания равен 1/frequency. В поле Действие при срабатывании указывается, что при каждом срабатывании таймера должен делать генератор. Здесь это действие — посылка нового сообщения типа Object через выходной порт с именем tick. Это выражается в AnyLogic следующей строкой:
tick.send(new Object());
Именно эта строка записана в поле Действие при срабатывании окна свойств таймера (рис. 6.1).
Разряд счетчика
Разряд десятичного счетчика представляется как и в модели continuouscounter активным объектом counter. Однако здесь он кроме целой переменной п, хранящей состояние разряда, включает не две интерфейсные переменные, а два порта: tick и overflow. Каждый раз, когда происходит событие получения сообщения в порте tick, переменная п должна увеличиваться на единицу по модулю 10 с извещением по порту overflow о переполнении, если оно наступило. Это значит, что если значение п есть 9 и пришло новое сообщение по порту tick, то переменная п примет значение 0, а через выходной порт будет послан сигнал. В противном случае разряд счетчика увеличивает значение своей переменной п на 1. Именно это записано в поле Действие при получении вкладки Код порта tick (рис. 6.2).
В полях окна свойств порта любое пришедшее в этот порт сообщение доступно по имени msg. В соответствии с данной записью, через порт overflow, таким образом, будет передаваться каждое десятое сообщение, полученное в порт tick.
Приведенная запись в окне Действие при получении окна свойств порта tick — это, в действительности, фрагмент программного кода на языке Java, выражающий логику нужных действий разряда счетчика при получении им сообщения по данному порту. Такую логику невозможно выразить с помощью только графических визуальных средств. Объединение визуальной разработки модели с фрагментами кода является очень удобным приемом, неизмеримо увеличивающим гибкость и мощность среды разработки моделей AnyLogic.
Корневой объект Model и анимация модели
Этот объект аналогичен соответствующему объекту модели Continuouscounter. Он включает один экземпляр генератора и три экземпляра разряда счетчика. Соединение портов включенных объектов выполняется точно так же, как и соединение интерфейсных переменных в модели counter. Чтобы связать интерфейсные переменные и порты не прямой линией, используется иконка панели инструментов. Строить связь с помощью этого графического
элемента нужно так, как строился переход в стейтчарте (рис. 4.16). Анимация модели counter построена точно так же, как анимация модели
ContinuousCounter.