AnyLogic
Развернуть
Размер шрифта

Переход

Переход означает переключение управления диаграммы состояний, ее переход из одного состояния в другое. Переход означает, что если происходит заданное событие срабатывания перехода, и выполняется заданное дополнительное условие, то диаграмма состояний переключается из одного состояния в другое и выполняет заданные действия. Когда это происходит, мы говорим, что срабатывает переход.

Начальная точка перехода лежит на границе исходного состояния перехода. Конечная точка перехода лежит на границе того состояния, которое должно стать активным при срабатывании перехода. Переход может пересекать границы как простых, так и сложных состояний. Если начальная точка перехода лежит на границе состояния или внутри него, а конечная точка перехода лежит за пределами состояния, то по этому переходу диаграмма состояний будет покидать это состояние. При срабатывании такого перехода будет выполняться действие при выходе из покидаемого состояния. Если начальная точка перехода лежит за пределами состояния, а конечная точка перехода лежит внутри или на границе состояния, то по этому переходу диаграмма состояний будет входить в это состояние. При срабатывании такого перехода будет выполняться действие при входе в состояние, которое будет становиться текущим. Если переход пересекает состояние, но и начальная и конечная точки этого перехода лежат за пределами состояния, то считается, что это состояние не участвует в процессе смен состояний диаграммы состояний, и ни действие при входе, ни действие при выходе из этого состояния выполняться не будут.

Внутренние переходы

Есть специальный тип перехода, называемый внутренним переходом. Внутренний переход лежит внутри состояния, причем как начальная, так и конечная точки этого перехода лежат на границе этого состояния. Поскольку внутренний переход не покидает состояние, то не выполняются ни действия, которые должны выполняться при выходе из этого состояния, ни действия, выполняемые при входе в него. Более того, не изменяется и текущее простое состояние этого сложного состояния. Поэтому внутренний переход очень удобен для выполнения фоновых задач, которые не должны прерывать основную активность сложного состояния.

Демо-модель: Cell Phone User Statechart with Internal Transitions Открыть страницу модели в AnyLogic Cloud. Там можно запустить модель или скачать ее по ссылке Исходные файлы модели.

Чтобы нарисовать переход

  1. Перетащите элемент Переход  из палитры Диаграмма состояний в то место графического редактора, где вы хотите его нарисовать.
  2. Однако иногда (особенно в случае переходов сложной формы) удобнее создавать переходы в режиме рисования. Чтобы перейти в этот режим, сделайте двойной щелчок мышью по элементу Переход  в палитре (при этом его значок должен поменяться на этот: ). Теперь вы можете рисовать переход, последовательными щелчками мыши добавляя в нужных вам местах диаграммы начальную точку перехода, затем точки его изгиба и, наконец, двойным щелчком — конечную точку перехода.
Свойства

Имя — Имя перехода. Имя используется для идентификации перехода.

Отображать имя — Если опция выбрана, то имя перехода будет отображаться в графическом редакторе.

Исключить — Если опция выбрана, то переход будет исключен из модели.

Происходит — Выберите здесь тип события, при происхождении которого переход сработает.

По таймауту — переход будет активирован, если истечет время заданного таймаута.
С заданной интенсивностью — переход будет активироваться с заданной интенсивностью.
При выполнении условия — переход будет активирован, когда будет выполнено заданное логическое условие.
При получении сообщения — переход будет активирован по прибытии сообщения в соединенный с диаграммой состояний порт.
По прибытию агента — переход будет активирован, когда агент (чье поведение задается этой диаграммой состояний) достигнет точки назначения.

Таймаут — [Только для перехода, происходящего по таймауту] Таймаут, по истечении которого сработает переход.

Интенсивность — [Только для перехода, происходящего с заданной интенсивностью] Интенсивность, с которой будет срабатывать данный переход. Переход активируется по таймауту, вычисленному согласно экспоненциальному распределению с параметром, равном заданной Интенсивности (таймаут отсчитывается от момента входа управления в состояние, из которого выходит данный переход). То есть, если интенсивность равна 5, то переход будет срабатывать в среднем 5 раз в единицу модельного времени.

Условие — [Только для перехода, происходящего при выполнении условия] Логическое условие, при выполнении которого будет активирован переход.

Тип сообщения — [Только для перехода, происходящего по прибытии сообщения] Здесь вы выбираете тип сообщения, при получении которого сработает переход. Вы можете выбрать один из наиболее часто используемых типов (int, double, boolean, String), выбрав соответствующую опцию справа, либо же задать любой другой Java класс, выбрав опцию Другой и введя имя класса в поле справа.

Осуществлять переход — [Только для перехода, происходящего по прибытии сообщения] Здесь вы можете задать дополнительное условие, выполнение которого будет требоваться для срабатывания перехода.

Безусловно — Выберите эту опцию, если вы не хотите производить проверку типа сообщения.
При получении заданного сообщения — Если опция выбрана, то переход будет срабатывать только по приходе сообщений, удовлетворяющих заданному в поле ниже дескриптору.
Если выполняется условие — Здесь вы можете ввести код сложной проверки содержимого сообщения в поле Выражение (только что полученное сообщение доступно здесь как локальная переменная msg).

Действие — Последовательность выражений Java, выполняемых при срабатывании перехода.

Доп. условие — Логическое выражение, разрешающее (если оно истинно, т.е. равно true) или запрещающее (если равно false) срабатывание перехода. Если условие не задано, то подразумевается true.

Свойства переходов, исходящих из ветвлений, отличаются от свойств обычных переходов:

Свойства переходов, ведущих из ветвления

При выполнении условия — Если опция выбрана, то этот переход будет срабатывать, если заданное в поле Условие логическое условие будет истинно.
По умолчанию (выбирается, если все остальные условия не выполняются) — Если опция выбрана, то этот переход будет выбираться в том случае, если условия всех остальных переходов, ведущих из состояния ветвления, не выполняются.
Если вы не зададите переход по умолчанию, и при переходе управления в ветвление все исходящие из ветвления переходы окажутся закрыты (не будет выполняться Условие ни одного перехода), то возникнет ошибка.
Пожалуйста, обратите внимание, что переходы, исходящие из ветвлений, не имеют Дополнительных условий.

Срабатывание перехода

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

Переход может сработать в результате происхождения различных событий, а именно:

По истечении заданного таймаута
С заданной интенсивностью
При выполнении заданного условия
При получении сообщения
По прибытию агента

Тип триггера задается в свойстве перехода Происходит.

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

Переход, срабатывающий по таймауту

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

Чтобы сделать переход срабатывающим по таймауту

  1. Выделите переход в графическом редакторе.
  2. В панели Свойства выберите По таймауту из выпадающего списка Происходит.
  3. Введите значение таймаута в расположенном ниже поле Таймаут.

Программное управление переходами

Функция Описание
boolean isActive() Возвращает true, если данный переход запланирован. В противном случае возвращает false.
double getRest() Возвращает время (в единицах модельного времени), оставшееся до запланированного перехода или Double.POSITIVE_INFINITY, если переход не запланирован.
double getRest(TimeUnits units) Возвращает время, оставшееся до запланированного перехода в заданных единицах времени, или Double.POSITIVE_INFINITY, если событие не запланировано.

units — константа единиц измерения времени
Пример: transition.getRest(MINUTE) возвращает время в минутах, оставшееся до запланированного перехода.

Переход, срабатывающий с заданной интенсивностью

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

Чтобы сделать переход срабатывающим с заданной интенсивностью

  1. Выделите переход в графическом редакторе.
  2. В панели Свойства выберите С заданной интенсивностью из выпадающего списка Происходит.
  3. Введите значение интенсивности в расположенном ниже поле Интенсивность.

Если значение интенсивности изменяется динамически, то время срабатывания перехода будет каждый раз вычисляться заново; такие изменения могут быть обнаружены переходом только при вызове метода onChange() соответствующего агента.

Программное управление переходами

Функция Описание
boolean isActive() Возвращает true, если данный переход запланирован. В противном случае возвращает false.
double getRest() Возвращает время (в единицах модельного времени), оставшееся до запланированного перехода или Double.POSITIVE_INFINITY, если переход не запланирован.
double getRest(TimeUnits units) Возвращает время, оставшееся до запланированного перехода в заданных единицах времени, или Double.POSITIVE_INFINITY, если событие не запланировано.

units — константа единиц измерения времени
Пример: transition.getRest(MINUTE) возвращает время в минутах, оставшееся до запланированного перехода.

Переход, срабатывающий при выполнении условия

Такой переход будет разрешен, когда заданное логическое условие станет истинным (т.е. равно true). Если у агента есть непрерывно изменяющиеся переменные, то численный решатель будет постоянно отслеживать выполнение заданного условия. В чисто дискретных моделях условие проверяется при каком-либо изменении, произошедшем в типе агента, т.e. при вызове метода onChange().

Чтобы сделать переход срабатывающим при выполнении заданного условия

  1. Выделите переход в графическом редакторе.
  2. В панели Свойства выберите При выполнении условия из выпадающего списка Происходит.
  3. Введите условие в расположенном ниже поле Условие.

Если ко времени передачи управления исходному состоянию этого перехода это выражение уже истинно (равно true), то этот переход сработает немедленно. Иначе этот переход сработает как только заданное выражение станет истинным — например, в результате решения уравнений, поскольку условие может содержать переменные, непрерывно изменяющиеся согласно заданным дифференциальным уравнениям. Точка переключения — момент, когда условие станет истинным, будет определяться AnyLogic с заданной вами точностью.

Важно понимать, когда модель производит проверку условия, по которому должен сработать переход. Проверка производится в следующих случаях:

  • Если у агента есть непрерывно изменяющиеся переменные, то численный решатель постоянно отслеживает выполнение условия, т.e. условие проверяется на каждом шаге решателя численных уравнений.
  • В чисто дискретных моделях условие проверяется, если в агенте происходят какие-то изменения, например:
    • если в этом агенте происходит какое-то событие, например, срабатывает переход, происходит какое-то другое событие, вызывается Действие при изменении параметра, в порт агента приходит сообщение и т.д.
    • если пользователь явно вызовет метод onChange() агента.
    Если изменения происходят во вложенном агенте, то условие при этом не проверяется!

    Если вам нужно проверять условия во вложенных агентах или популяциях, то вы можете установить периодическую проверку таких условий следующим образом. Выберите опцию Выполнять шаги в секции свойств Пространство и сеть агента верхнего уровня, на диаграмме которого заданы эти агенты. Добавьте вызов функции onChange(); в поле Действие на шаге (в секции свойств Действия агента) того вложенного агента, где вы хотите проверять условия с заданной периодичностью. Это будет более эффективным решением по сравнению с добавлением циклически срабатывающего события с вызовом функции onStep() в каждого такого агента.

При задании условия срабатывания перехода вы должны учитывать так называемую проблему чувствительности. Пусть переход ожидает выполнения условия x>=5, а переменная x непрерывно изменяет свое значение, как показано на приведенном ниже рисунке:

Проблема чувствительности

Поскольку решатель численных уравнений работает по шагам, то может произойти ситуация, когда значение переменной x успеет между двумя шагами моделирования как превзойти значение заданного порога 5, так и стать снова меньше этого значения. В этом случае факт происхождения события не будет обнаружен. Вы должны учитывать возможность таких ситуаций при моделировании систем, в которых такие ошибки достаточно критичны. Если вы вдруг столкнетесь с такой проблемой, то вам будет нужно задать более высокую точность численных методов.

Переход, срабатывающий при получении сообщения

Такой переход сработает, когда диаграмма состояний получит сообщение (значение примитивного типа Java или объект заданного Java класса, удовлетворяющий заданному дескриптору сообщения).

Чтобы послать сообщение от одного агента к другим, вызовите одну из функций send() этого агента, подробнее о функциях можно прочесть здесь.

Когда сообщение будет получено в диаграмме состояний:

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

Вы можете выполнять проверку содержимого сообщения и принимать только те сообщения, которые удовлетворяют заданным критериям проверки:

  • Это может быть проверка типа сообщения, то есть будут приниматься только сообщения заданного типа.
  • Или же это может быть проверка содержимого сообщения - вы можете указать, чему должно быть равно входящее сообщение, или же задать условие, которое будет анализировать содержимое сообщение и выдавать в качестве результата вердикт - будет ли это сообщение принято диаграммой состояний или нет.

Чтобы сделать переход срабатывающим при получении сообщения

  1. Выделите переход в графическом редакторе.
  2. В панели Свойства выберите При получении сообщения из выпадающего списка Происходит.
  3. Если вы хотите выполнять фильтрацию сообщений по типу, то с помощью выпадающего списка Тип сообщения нужно будет выбрать, сообщения какого типа будут приниматься (если вы хотите задать какой-то из не перечисленных здесь Java классов, выберите опцию Другой и введите имя класса в поле справа. В этом случае переход сможет сработать только при получении сообщений заданного здесь Java класса.
  4. Если же вы не хотите выполнять такую фильтрацию сообщений, оставьте выбранной опцию Другой и введите Object в этом поле.
  5. Теперь можете задать дополнительные условия проверки содержимого сообщения с помощью группы кнопок Осуществлять переход.
  6. Если вы не хотите задавать никаких условий — просто выберите Безусловно.
  7. Если вы хотите задать принимать сообщения только с заданным содержимым, выберите опцию При получении заданного сообщения и задайте дескриптор сообщения в поле Сообщение ниже. Такая проверка будет работать следующим образом: при получении сообщения, AnyLogic вызовет метод equals() дескриптора, передав методу сообщение в качестве параметра. Если метод equals() вернет true, то такое сообщение будет принято. Если false - то это будет означать, что соответствия не найдено, и сообщение будет проигнорировано. Примеры дескрипторов: "STOP!" для сообщения типа String; 5.0 для сообщения типа Double.
  8. Если же вы хотите задать сложный механизм проверки содержимого сообщения с помощью логического условия, выберите опцию Если выполняется условие. Введите условие в расположенном ниже поле Выражение. Только что полученное сообщение доступно здесь как переменная msg.
  9. Введите код, который будет выполняться при срабатывании перехода, в поле Действие.
  10. Введите дополнительное условие, которое должно быть выполнено для того, чтобы было разрешено срабатывание этого перехода, в поле Доп. условие.

Очередь диаграммы состояний

Иногда вам может понадобиться добавлять поступающие в диаграмму состояний сообщения в очередь. Очередь нужна для того, чтобы диаграмма состояний могла принимать сообщения, в те моменты, когда она не может их обработать (например, когда выполняется переход диаграммы состояний).

Добавить сообщение в очередь диаграммы состояний можно путем вызова метода диаграммы состояний fireEvent().

Очередь событий обрабатывается диаграммой состояний при происхождении любой активности в этой диаграмме или при вызове метода fireEvent(). При этом происходит последовательная проверка всех сообщений в очереди, начиная с самого "старого" в соответствии со следующим алгоритмом:

  • Если из текущего простого состояния или из сложных состояний, в которые входит это простое состояние, исходит один или несколько переходов, условия срабатывания которых соответствуют проверяемому сообщению, то такие переходы считаются разрешенными, т.e. один из этих переходов (если выполнится его дополнительное условие) сработает. В этом случае это событие, а также все события, предшествующие ему в очереди диаграммы состояний, будут удалены из очереди.После этого будет обрабатываться следующее сообщение очереди.
  • Если таких переходов не будет, то будет обрабатываться следующее сообщение очереди.

Диаграмма состояний может последовательно обработать сразу несколько сообщений из очереди (это занимает нулевое модельное время).

Переход, срабатывающий по прибытию агента

Переход такого типа срабатывает, когда агент (чье поведение задается с помощью этой диаграммы состояний) прибывает в место назначения.

Переход срабатывает, если агент существует в непрерывном пространстве или ГИС-пространстве, а его перемещение было инициировано вызовом функции moveTo() агента, одной из схожих функций перемещения или с помощью блока MoveTo Библиотеки моделирования процессов.

Переход, срабатывающий по прибытию агента, обозначается в диаграмме состояний с помощью значка .

Чтобы сделать переход срабатывающим по прибытию агента

  1. Выделите переход в графическом редакторе или в панели Проекты.
  2. В панели Свойства из выпадающего списка Происходит выберите опцию По прибытию агента.
  3. В расположенном ниже поле Действие вы можете ввести Java код, который должен выполняться, когда срабатывает этот переход.
Как мы можем улучшить эту статью?