Saving and Restoring the Model Snapshot

In AnyLogic Professional Edition you are able to save the full state of a model (the snapshot) during runtime to a file, restore it at a later time and continue running simulation from the same point.

How-To video: Saving and restoring simulation state

This feature may be useful in several cases:

AnyLogic model snapshot implementation is based on Java serialization mechanism.

Saving a model snapshot

To save a snapshot of a model

  1. First, check that your model is serializable, i.e. states of all model elements can be saved, and therefore all the information about the current state of the model can be saved in a model snapshot file. To check this, select the model item (e.g. Model) in the Projects view, and then select Tools > Check for Snapshot Compatibility from the main menu. If there are some unserializable elements in your model, fix this, and then continue.

  2. Snapshots can be saved and restored only when the model execution is paused. Run the model and then pause the execution by clicking the Pause control.
  3. Now you will need the snapshot management commands. The snapshot commands are located in the developer panel. To open the developer panel click the rightmost Open developer panel control, located in the model window.
  4. By default, the snapshot commands are hidden. To see them, click the show/hide snapshot options control in the topmost line of the developer panel.
  5. Click the save snapshot toolbar button.
  6. The Save model snapshot dialog box will open.
  7. Specify the name and location of the snapshot file and click the Save button when finished.
  8. The model state is saved. You can now continue the simulation, stop, close it, or even shut down your computer.

Restoring a saved model snapshot

To restore a snapshot of a model

  1. To restore the saved model state you first need to run the same experiment (you do not need to actually run the simulation, it is sufficient just to launch the experiment).
  2. Now you will need snapshot management commands. Snapshot commands are located in the developer panel. To open the developer panel, in the model window, click the rightmost control Open developer panel .
  3. By default, the snapshot commands are hidden. To see them, click the show/hide snapshot options control in the topmost line of the developer panel.
  4. Click the restore snapshot toolbar button.
  1. The Open model snapshot dialog box will open.
  2. Choose the snapshot file you want to restore and click the Open button when finished.
  3. The model state saved in that file will be restored and the model will be put in the paused state.

Saving and restoring model snapshots via API

Saving / restoring model snapshot from all experiments except for the custom experiment

You can save and restore model snaphots using API functions which both take one parameter – the name of the snapshot file. Call them as follows:

Saving / restoring model snapshot from custom experiment

You can also save and restore model snapshots from custom experiment code using the following functions of Engine:

Examples:

When you create a custom experiment, the experiment has default auto-generated code (see the custom experiment's properties, Code section) containing this line of code: Engine engine = createEngine();

This code creates engine and stores it in the local variable engine. Use it to call the functions mentioned above. To call the functions, write the following code:

engine.saveRootObjectSnapshot("C:\Model\Model.als");

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

Or, instead of typing the code, you can automatically insert the load snapshot function call while creating a custom experiment, by selecting the checkbox Load top-level agent from snapshot on the second page of the New Experiment wizard.

Loading a top-level agent from snapshot into an experiment

There is one more use case of model snapshots. You can load a top-level agent from a snapshot into an experiment. It can be any experiment - possibly of even another type than the one that was launched when you have saved the model snaphot. The only self-evident restriction is that the model should be the same.

Loading a top-level agent from a snapshot into an experiment, you load the saved state of a model from the snapshot file. The experiment will be started from the time when the model state was saved.

Unlike restoring snapshots, when loading a top-level agent from a snapshot, experiment settings are not taken from the saved snaphot.

To load a top-level agent from a snapshot into an experiment

  1. In the Projects view, select the required experiment.
  2. Open the Advanced section of the experiment's Properties.
  3. Select the Load root agent from snapshot checkbox.
  4. Choose the snapshot file, which top-level agent's state you want to load into the experiment. Type the full path to the snapshot file in the edit box to the right of the checkbox. You can browse to the required file using the Browse button.

How to ensure your model is serializable

For 99% of models you do not have to do anything to enable their serialization, i.e. saving their state at runtime: all AnyLogic objects are serializable, including all standard library objects. However, there are things you should be aware of.

As you know, AnyLogic allows you to use arbitrary Java classes in your model, namely in:

If you wish all the objects to be saved and restored, you have to either use only serializable classes, or define custom serialization, or exclude them from the snapshot at all.

In the properties of Parameter, Variable and Collection you will find the checkbox Save in Snapshot that is checked by default. If you leave that checkbox checked AnyLogic will take care of serialization, but the type of parameter, variable or a collection element should then be one of:

By unchecking that checkbox you tell AnyLogic to exclude the corresponding object from standard serialization. You may then specify custom serialization for it by defining two functions in the agent's Additional class code:

Please note that if you are defining custom serialization for a field defined in the Additional class code (i.e. not graphically and for which there is no Save in snapshot checkbox that you can uncheck) you need to declare them as transient by adding this word before the field name.

The wizard for creating a new Java class within AnyLogic IDE now has an option Enable saving this class in model snapshots. If it is checked, the new class will be generated as implementing java.io.Serializable interface and contain the code line

private static final long serialVersionUID = <some_value> ;

where <some_value> is a kind of class fingerprint which normally should be changed when class structure changes (e.g. when some fields are added to (removed from) the class). Please note that in the models created earlier the Java classes were not implementing that interface by default and you may need to add the corresponding code manually. Same applies to the inner classes if there are any.

The Java classes used as statechart transition messages MUST be serializable.

Also, there is one common recommendation for making advanced structures Serializable. All user-defined cross-object links except links to the embedded objects must have custom serialization (and Save in snapshot checkbox should be unchecked for the corresponding model elements). An example of one-level-links is field “next” of some object, which stores reference to the object of the same class and thus also having field “next” with reference to third object and so on. Link to owner is link from one object located inside another object, to its parent.

Some classes require additional custom deserialization code for their instances, if any are created manually (i.e. in the code) and stored in the serializable fields (e.g. in collections or variables) of model objects. These classes are:

Note, that custom deserialization code is automatically generated for all elements added from the Palette in the AnyLogic graphical editor.

Java Classes which need custom serialization, i.e. require special handling during the serialization and deserialization process must implement special functions with these exact signatures:

private void writeObject(java.io.ObjectOutputStream out)

throws IOException

private void readObject(java.io.ObjectInputStream in)

throws IOException, ClassNotFoundException;

The following description is borrowed from API JavaDoc of standard Java interface java.io.Serializable:

Restrictions

Static elements

The following AnyLogic elements can be declared as static:

Please note that static elements are not saved into a snaphot file.

If you do not alter the value of a static element in your model, the state of the restored model will be exactly the same as the previously saved state. However, if you somehow change the value of a static element (e.g. in agent's On startup code), the modified value won't be saved into a snapshot, and therefore the restored state of the model will differ from the state you have previously saved.

There is one more case to be mentioned with the static constant variable and some other variable inside a model referring to the same Java object. As a result, when you check the constant and the variable for equality, you will get true. However, if you save the model state into a snapshot, the constant and the variable in the restored model will refer to different objects, and they won't be considered as equal anymore, thus the restored model behavior will differ.

The general conclusion is to avoid using static elements if you plan to save/restore your model state using the AnyLogic snapshot feature.

Non-serializable objects

Some Java objects cannot be serialized, for example objects of class BufferedImage. Variables of such types should be excluded from standard snapshot serialization. If you wish to save and restore these objects anyway, you can write some code in the functions writeCustomData and readCustomData. This code should take care of custom serialization and loading of some base content of a given non-serializable object (of course, it is possible to obtain that base content from the object and setup it back in the future).

For example, for the BufferedImage base content could be: width, height, image type parameters (which are used in the constructor) and int[] array of pixel colors (which can be retrieved by calling getRGB function). The code restoring BufferedImage (in the readCustomData function) should create an instance by invoking constructor with above parameters and then call setRGB function to restore the picture.

Open database connections and open files cannot save and restore their states. Therefore after restoring the snapshot the connections and files will be in closed state. This does not mean you cannot continue accessing them. For example, if the model writes to a kind of a log file, it can continue writing there, provided the file is in “append” mode. Connectivity objects will create their connections on first access, as they usually do. But Statement and ResultSet objects (if any are opened) cannot be included in the snapshot (they are not serializable). It is recommended to open ResultSets, access and close them entirely within the code of some function body (or any code section). Storing references to Statement and ResultSet in the variables of agent is not recommended. Also, note that snapshot cannot affect external data sources and in some cases manual database backup and restore may be required.

At the moment OptQuest optimization engine cannot save and restore its state, therefore you cannot save snapshots of Optimization experiments. In the future however OptTek will release a serializable version of OptQuest.