Сохранение и восстановление состояния модели

AnyLogic Professional предоставляет возможность сохранения в файл всей информации о текущем состоянии модели во время ее выполнения с возможностью последующего ее восстановления и возобновления моделирования с того самого момента времени, когда было сохранено состояние.

Обучающее видео: Saving and restoring simulation state

Эта часто требуется для достижения следующих целей:

Реализация сохранения и восстановления состояния модели AnyLogic основана на механизме сериализации Java.

Сохранение состояния модели

Чтобы сохранить состояние модели

  1. Для начала убедитесь, что ваша модель поддерживает механизм сериализации, т.е. состояния всех элементов модели можно сохранить, и следовательно, всю информацию о текущем состоянии модели можно сохранить в файл состояния модели. Чтобы проверить свою модель, выберите ее в панели Проекты, а затем выберите Инструменты > Проверить возможность сохранения состояния из главного меню. Если в модели обнаружатся элементы, не поддерживающие сериализацию, исправьте их, прежде чем продолжить.
  2. Состояние модели может быть сохранено только в тот момент, когда выполнение модели приостановлено. Запустите модель и щелкните по кнопке панели управления Приостановить выполнение в тот момент, когда вы захотите сохранить состояние модели.

  3. Вам понадобятся команды управления файлами состояний модели. Они расположены в панели разработчика. Откройте панель разработчика в окне модели, щелкнув крайний справа элемент управления Показать / скрыть панель разработчика .

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

  5. Щелкните по кнопке Сохранить снэпшот. Состояние модели будет сохранено в файле.

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

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

Восстановление сохраненного состояния модели

Чтобы восстановить сохраненное состояние модели

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

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

  3. Щелкните по кнопке Загрузить снэпшот. Откроется диалоговое окно, где вы сможете выбрать файл, из которого вы хотите загрузить состояние модели.

  4. Выберите файл и щелкните по кнопке Открыть.

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

Программное сохранение и восстановление состояния модели

Сохранение / восстановление состояния модели из всех экспериментов, кроме нестандартного

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

Программное сохранение и восстановление состояния модели из нестандартного эксперимента

Сохранить и восстановить состояния модели из нестандартного эксперимента можно с помощью следующих функций исполняющего модуля:

Примеры:

После создания, нестандартный эксперимент содержит код, сгенерированный по умолчанию (см. секцию Код свойств нестандартного эксперимента) со следующей строчкой: Engine engine = createEngine();

Этот код создает исполняющий модуль и хранит его в локальной переменной engine. Используйте его, чтобы вызывать вышеописанные функции. Напишите следующий код для вызова функции:

engine.saveRootObjectSnapshot("C:ModelModel.als");

Main root = (Main)engine.loadRootObjectSnapshot("C:Model\Model.als");

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

Загрузка агента верхнего уровня эксперимента из файла сохраненного состояния модели

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

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

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

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

Чтобы загрузить агента верхнего уровня эксперимента из файла сохраненного состояния модели

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

Нестандартные механизмы сериализации

В 99% случаев ваши модели будут поддерживать механизм сериализации (поскольку этот механизм поддерживают все объекты AnyLogic, в том числе и библиотечные объекты), а значит, вы сможете сохранять и восстанавливать состояния таких моделей во время моделирования, не выполняя никаких дополнительных действий. Однако же не исключаются те редкие ситуации, когда вам нужно будет самостоятельно внести в модель небольшие изменения для того, чтобы эта модель полностью поддерживала сериализацию.

Как вы знаете, AnyLogic позволяет использовать в моделях объекты любых Java классов. На такие объекты могут ссылаться:

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

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

Сбросив этот флажок, вы говорите AnyLogic, что соответствующий элемент модели не должен сохраняться в файле состояния посредством стандартного механизма сериализации. Вы можете затем задать свой механизм сериализации для таких элементов, объявив две функции в Дополнительном коде типа агентов - владельца этих элементов:

Обратите внимание, что если вы используете для какого-то поля нестандартный механизм сериализации, реализованный в поле Дополнительный код класса (т.e. не графически, и у которого нет флажка Сохранять при сохранении состояния модели, который вы можете сбросить), то вам нужно добавить к объявлению этих полей слово transient (перед именем поля).

У мастера создания нового Java класса теперь есть опция Добавить возможность сохранения в файле состояния - реализовать java.io.Serializable. Если этот флажок будет установлен, то новый класс будет реализовывать интерфейсjava.io.Serializable и содержать следующую строку кода:

private static final long serialVersionUID = <какое-то значение>;

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

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

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

Некоторые классы требуют дополнительной нестандартной десериализации для своих объектов, если они были созданы вручную (т.e. в коде) и сохранены в сериализуемых полях (например, в простых переменных или в коллекциях). Такими классами являются:

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

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

private void writeObject(java.io.ObjectOutputStream out)

throws IOException;

private void readObject(java.io.ObjectInputStream in)

throws IOException, ClassNotFoundException;

Следующее описание заимствовано из документации стандартного Java интерфейса java.io.Serializable:

Ограничения

Некоторые объекты Java, например, объекты класса BufferedImage, не могут быть сериализованы. Переменные таких типов должны быть исключены из стандартного механизма сериализации, используемого при сохранении состояния модели. Если же вы все-таки хотите сохранять и восстанавливать состояние таких объектов, то вы можете написать свой собственный код в методах writeCustomData и readCustomData. Этот код должен выполнять нестандартную сериализацию и восстановление основного содержимого несериализуемого объекта.

Например, в случае класса BufferedImage, основным его содержимым являются: высота, ширина, параметры типа изображения (которые используются в конструкторе) и массив int[] цветов пикселей (который может быть получен путем вызова метода getRGB). Код, восстанавливающий объект BufferedImage (в методе readCustomData), должен создавать экземпляр этого класса посредством вызова конструктора с вышеперечисленными параметрами и последующего вызова метода setRGB для восстановления изображения.

Открытые соединения с базами данных и открытые файлы не могут сохранять и восстанавливать свои состояния. Поэтому после восстановления состояния модели файлы и соединения с базами данных будут в закрытом состоянии. Это не означает, что вы не можете продолжать работать с ними. Например, если модель записывает информацию в файл журнала, то вы можете продолжать записывать туда нужные вам данные при условии, что соответствующий текстовый файл находится в режиме "запись с добавлением в конец". Объекты связи с базами данных установят свои соединения при первом доступе к базе данных (как и обычно). Но объекты Statement и ResultSet (если есть таковые) не могут быть включены в сохраняемое состояние модели (они несериализуемы). Рекомендуется открывать объекты ResultSet, работать с ними и закрывать их в теле одной и той же функции (или в коде одного и того же кодового свойства элемента модели). Не рекомендуется хранить ссылки на объекты типа Statement и ResultSet в переменных агента. Также обратите внимание, что файлы состояния не могут влиять на внешние источники данных и в некоторых случаях может потребоваться ручное сохранение и восстановление баз данных.

В настоящий момент исполняющий модуль оптимизатора OptQuest не поддерживает сериализацию, поэтому вы не можете сохранять и восстанавливать состояние оптимизационных экспериментов. Это станет возможно, как только OptTek выпустит версию OptQuest, которая будет поддерживать сериализацию.