Реагирующую систему (reactive system) А. Пнуэли в [Р86] определил как сис-тему, постоянно ожидающую внешних или внутренних событий и реагирующую на них. Реагирующие системы являются типичными системами дискретно-событийного типа: события происходят в дискретные моменты времени, реакция системы на события состоит в изменении переменных состояния этих систем и формально такая реакция является мгновенной.
При задании реагирующих систем оказалось удобным использовать стейтчарты (или карты состояний), простейший вариант которых был использован нами в главе 4. Стейтчарты представляют собой графический язык диаграмм (фактически, расширение обычных графов переходов). Язык стейтчартов, впервые введенный Д. Харелом [Н87], в настоящее время широко применяется для спецификации, моделирования, верификации и про-тотипирования протоколов коммуникации, встроенных систем управления в авиации, на транспорте, в бытовой и научной электронике. Они также являются средством определения поведения объектов в UML.
Стейтчарты строятся из состояний и переходов между ними. Система может находиться в каждый момент только в одном состоянии. Переходы из состояния в состояние случаются, если происходит событие, связанное с этим переходом, и условие, связанное с переходом (если оно есть), выполнено. На диаграмме рис. 6.3. система из состояния а переходит в состояние в, если наступит событие а и при этом условие р будет выполнено. Событием может быть, например, истечение таймаута, переключение в истину предиката (условия), определенного на переменных модели и т. п. Графически состояния представляются прямоугольниками или овалами, а переходы — лугами. Короткая стрелка-указатель, входящая в состояние а, говорит о том, чго это состояние начальное: в начальный момент времени система будет находиться именно в этом состоянии. Очевидно, что у системы может быть
ровно одно начальное состояние. С каждым переходом может быть связано некоторое действие — изменение переменных, посылка сигнала и т. п. С каждым состоянием также могут быть связаны действия. Одно действие выполняется в момент входа в это состояние, другое действие выполняется при выходе из состояния. На рис. 6.3 y1 и Y2 условно обозначены действия, выполняемые при срабатывании соответствующих переходов.
Рисунок 6.3 представляет простейший стейтчарт с двумя элементарными состояниями. В общем случае в стейтчартах можно дополнительно использовать расширения этой простейшей модели переходов: иерархические состояния (гиперсостояния), исторические состояния, условные переходы и некоторые другие возможности. Рассмотрим их по порядку.
Иерархические состояния или гиперсостояния вводятся для того, чтобы объединить несколько состояний, имеющих одну и ту же реакцию на событие. На рис. 6.4 справа гиперсостояние d позволяет упростить граф переходов, представленный слева: переход в состояние а при наступлении события b происходит вне зависимости от того, в каком из состояний, в или с находилась система. Иными словами, два стейтчарта на рис. 6.4 эквивалентны.
Каждое гиперсостояние требует, чтобы точно одно из включенных в него состояний было помечено как начальное. Это позволяет трактовать переход из состояния а при наступлении события а в гиперсостояние d как переход из а в элементарное состояние в. На рис. 6.4 начальным состоянием систе-мы является состояние а, а состояние в является начальным только для множества состояний {в, о, входящих в гиперсостояние о.
Историческое состояние хранит то состояние внутри данного гиперсостоя-ния. в котором система находилась последний раз.
На рис. 6.5 при наступлении события а система вернется в то состояние из множества состояний {А, в, о, в котором она была последний раз (независимо от того, какими переходами связаны эти состояния). Исторические состояния удобны, например, для описания продолжения функционирования системы после прерываний.
Условные состояния позволяют отложить проверку логического условия. Такая отложенная проверка удобна, например, в том случае, если определить дальнейшие действия системы можно только после реакции на событие. Например, пусть событием является приход сообщения, а реакция на него зависит от содержимого этого сообщения. На рис. 6.6 представлен фрагмент
Стейтчарта, описывающего эту ситуацию. По приходе сообщения (событие а) если система находилась в состоянии а, то она перейдет в состояние с только в том случае, если условие р выполнено. Если условие р не выпол-нено, система перейдет в состояние d. В этом примере удобно использовать именно условное состояние, в котором система не задерживается, а после приема сообщения мгновенно определяет, в какое состояние перейти.
В качестве примера использования всех этих расширений рассмотрим спе-цификацию процесса доступа к среде протокола IEEE 802.12 обмена сообщениями в высокоскоростной локальной сети (рис. 6.7). В сети работает множество станций, и в каждой из них активизирован свой процесс доступа к сети. Все процессы идентичны.
Каждый процесс начинает свою работу в элементарном состоянии тренировка ГИПерсоСТОЯНИЯ Активен. В СОСТОЯНИИ Тренировка ВЫПОЛНЯЮТСЯ операции по идентификации данной рабочей станции, проверке каната и верхнего уровня. Если идентификация выполнилась без ошибок, процесс переходит в состояние Старт, в котором ожидает очередной пакет, сгенерированный пользователем данной рабочей станции. Когда пакет для передачи сгенерирован, процесс переходит в состояние пакет, посылая верхнему уровню сигнал о наличии пакета. В этом состоянии процесс ждет от верхнего уровня разрешения послать пакет в канал, и когда разрешение получено, процесс переходит в состояние посылка пакета. По завершении пересылки процесс возвращается в состояние Старт. В любом из двух состояний (Старт И Пакет) ГИПерсоСТОЯНИЯ Ожидание процесс может быть прерван приходом сигнала идет пакет от верхнего уровня. Этот сигнал извещает каждую станцию локальной сети о том, что в сети начал передаваться пакет, адресату необходимо подготовиться к его приему. Поскольку имя
адресата находится в заголовке пакета, пакет начинают принимать все процессы. После приема пакета (или после обнаружения, что пакет чужой по-сле приема заголовка) процесс возвращается в то состояние, включенное в гиперсостояние ожидание, из которого он был прерван сигналом идет пакет. В любом из обсуждавшихся ранее состояний процесс может быть прерван сигналом Отказ, который заставляет процесс перейти в состояние отказ. После восстановления процесс входит в нормальную работу через состояние Тренировка.
Этот пример показывает, что стейтчарты позволяют наглядно и экономно выразить с помощью графической нотации очень сложное поведение. AnyLogic позволяет задавать алгоритм поведения активных объектов в виде стейтчартов с использованием всех перечисленных здесь расширений.
6.3. Модель пешеходного перехода: переключение состояний в стейтчартах
В качестве простейшего примера применения стейтчартов рассмотрим модель регулируемого пешеходного перехода со светофором, разрешающим или запрещающим движение транспорта.
Постановка проблемы
Светофор, регулирующий движение транспорта на пешеходном переходе, может находиться в следующих состояниях: разрешение движения транс-порта (зеленый), приготовиться к запрещающему сигналу (мигающий зеленый), приготовиться к остановке (желтый), запрет движения (красный) и приготовиться к движению (красный и желтый) (рис. 6.8).
Светофор работает в автоматическом режиме, циклически. В каждом со-стоянии светофор находится определенный постоянный период времени.
Рассматриваемые вопросы
В результате построения этой модели будут рассмотрены следующие новые вопросы:
- построение стейтчартов;
- действия при входе и выходе из состояния, иерархические состояния;
- переход по исчерпании таймаута;
- переход по событию;
- окно наблюдения событий.
Построение модели
Создайте новый проект под названием Pedestriancross и назовите класс корневого активного объекта Model.
Наша модель будет иметь только один активный объект, представляющий светофор, поэтому корневой объект Model будет единственным активным объектом нашей модели. В поле редактора структуры активного объекта Model поместите иконку стейтчарта с инструментальной панели. Спра-
ва появится окно свойств этого нового объекта, в котором в поле имени будет стоять предопределенное имя statechart. Замените это имя на traffic_light (рис. 6.9).
После двойного щелчка мыши на иконке стейтчарта traffic_light откроется окно редактора этого стейтчарта с уже введенным одним состоянием (с именем state) с входящей в него стрелкой, показывющей, что это начальное состояние (рис. 6.10). Имя состояния, как и все другие его параметры, можно редактировать в окне его свойств либо при выделенном состоянии можно нажать клавишу <F2>, что позволяет выделить имя в самом состоянии для его редактирования.
Для того чтобы построить стейтчарт, следует использовать кнопки на инструментальной панели окна редактора, которые становятся активными, если активизировано окно редактора стейтчарта (открыть его можно двойным щелчком по иконке стейтчарта). С помощью кнопки
рисуются состояния (как простые, так и гиперсостояния), кнопка
используется для рисования переходов между состояниями, кнопка определяет начальное состояние как всего стейтчарта, так и в каждом гиперсостоянии. Кнопка используется для рисования состояния, являющегося "финальным" в поведении активного объекта. Графически такое состояние
удобно изображать специальным символом, хотя конкретные действия, определяющие, что нужно делать в этом финальном состоянии, разработчик дол-
жен добавить сам. Комментарии, как обычно, помещаются на поле редактора
с помощью кнопки . Заметьте, что для любого выделенного объекта спра-
ва появляется окно его свойств, в котором можно изменить параметры и,
в частности, имя объекта, если это необходимо. Структурные ошибки при ри-
совании стейтчарта — повисшие переходы, дублированные указатели началь-
ного состояния и т. п. — выделяются в поле редактора красным цветом. Что-
бы имя объекта — состояния или перехода — появилось в поле редактора,
следует выбрать опцию Отображать имя в нижней части окна свойств объекта.
В соответствии с алгоритмом работы светофора кроме начального состояния в модель нужно ввести дополнительные состояния (рис. 6.11). Начальное состояние назовите go (движение транспорту разрешено — горит зеленый), затем светофор переходит в состояния attention (внимание — мигающий зеленый), slow (приготовиться к остановке — горит желтый), остановка транспорта stop (запрет движения — горит красный) и ready (приготовиться к движению — горят красный и желтый). Состояние attention удобно представить гиперсостоянием с парой переключающихся элементарных состояний: в одном из них зеленый горит (состояние а), в другом — нет (состояние в). Постройте все эти состояния и соедините их соответствующими переходами.
Рассмотрим, как задать условия срабатывания переходов. Переходы в нашем автоматическом светофоре выполняются по таймауту, т. е. по истечении интервала времени, который прошел с момента прихода системы в данное состояние. Пусть в состоянии gо светофор должен находиться 25 с, затем 7 с зеленый сигнал мигает, 4 с горит желтый в состоянии slow, в течение 20 с движение запрещено и 4 с светофор находится в состоянии ready. Масштаб времени примем такой: единица модельного времени соответствует 1 с реального физического времени.
Для того чтобы задать такие условия срабатывания переходов, сделайте активным переход t1, в поле Происходит выберите вариант По таймауту, а в поле Таймаут введите 25 (рис. 6.12). Аналогично задайте условия сраба-тывания других переходов. Между состояниями а и в пусть переходы срабатывают через 1 единицу времени (1 с горит зеленый свет, затем 1 с не го-рит). Заметьте, что переход срабатывает (в модельном времени) мгновенно.
Запустите модель на выполнение. Чтобы можно было наблюдать переходы между состояниями стейтчарта при работе модели, откройте окно стейтчарта двойным щелчком левой кнопки мыши на его изображении в окне кор-невого объекта модели с именем root. Активное в данный момент состоя-ние подсвечивается красным. Проведите эксперименты с моделью при раз-дичных масштабах времени. Ваша модель должна быть похожа на модель Pedestriancross1, которая находится в папке Model Examples\Part II.
В каждом состоянии светофора должен гореть вполне определенный сигнал: всостоянии до должен гореть зеленый, в состоянии ready должны гореть красный и желтый одновременно и т. п. Откройте окно редактора структуры объекта Model. Определите три переменные логического (boolean) типа red, yellow и green, которые будут принимать истинное значение тогда, когда у светофора должен гореть соответствующий "глаз": красный, желтый и зеленый (рис. 6.13). Начальные значения этих булевых переменных можно не задавать: по умолчанию они будут равны false.
Наш стейтчарт построен именно для управления значениями этих переменных, каждое состояние отвечает за зажигание своего света или комбинации светов. Например, в состоянии go должен гореть зеленый, при входе в со-стояние stop должен загореться красный свет (а остальные гореть не должны), а в состоянии ready должны гореть красный и желтый и т. п. Именно это мы и должны определить.
Откройте окно свойств состояния go и в поле Действие при входе запишите green=true;, а в поле Действие при выходе запишите green=false; (рис. 6.14). То же самое нужно определить для состояния в, а у состояния а эти поля нужно оставить без изменения — когда светофор находится в этом состоянии, он вообще не горит (все переменные имеют значения false). Аналогично, в состоянии slow нужно включить желтый сигнал, т. е. при входе в это состояние установить переменную yellow в true, а при выходе из этого состояния установить ее в false. Для состояния stop то же нужно сделать с переменной red, а для состояния ready следует обе переменные — red и yellow — установить в true при входе и установить в false при выходе из него.
Запустите модель на выполнение при различных масштабах времени. В окне root в дереве переменных и параметров модели переменные green, yellow и red будут переключаться между значениями истина и ложь (представляемыми здесь 1 и 0) в соответствии с алгоритмом переключения све-тофора.
Создание анимации
Анимация для этой модели весьма просто строится средствами AnyLogic (рис. 6.15). Все графические объекты в анимации имеют статические харак-теристики, кроме цвета сигналов светофора. Светофор строится из трех эл-дипсов, статически повернутых на 45 градусов (поле Поворот вкладки Общие окна свойств овала). Динамическое значение цвета верхнего сигнала светофора необходимо установить так: если переменная red истинна, то цвет должен быть color.red, в противном случае его цвет нужно установить Color.gray (серый). Это записывается следующим выражением— также фрагментом кода языка Java:
red? Color.red: Color.gray
Цвет среднего и нижнего овалов, представляющих сигналы светофора, следует установить в поле их динамических значений соответственно так:
yellow? Color.yellow: Color.gray green? Color.green: Color.gray
Из материала следующей главы будет ясно, что здесь color — класс Java, a gray — предопределенная в этом классе константа, обозначающая серый цвет.
Сравните вашу модель с моделью PedestrianCross2. Запустите модель. На рис. 6.15 зафиксирован момент выполнения модели в состоянии ready. Переход из этого состояния в состояние go будет выполнен следующим, он подсвечен красным.