Process Enactment
=================

A final operation that is useful to modellers, is the enactment of process models.
When enacting a process model, a series of operations on models is automatically executed.

Finding process models
----------------------

To find process models, you can easily query the Modelverse for models that conform to *ProcessModel*.
All such models can be executed, given that the models and operations they refer to, exist.

Enacting process models
-----------------------

To enact the process model, such as *query_state_space*, you must execute the following operation::

    >>> process_execute("models/query_state_space", {"pn": "models/my_pn"}, {})

There are three parameters to this function, the first obviously being the name of the process model.
The second parameter is a mapping between elements in the process and the actual location in the Modelverse.
When executing a process model, models are processed and produced, and when a binding is made to an actual model in the Modelverse, this model is actually stored and made available outside of the process.
For example, in this case we bind the model called *pn* to the model at location *models/my_pn*.
In the process, every occurence of *pn* is therefore processed at that location, both for input models (e.g., when chosing the Petri net to operate on) and output models (e.g., when this is the result).
It is not necessary to define such a mapping, as it is perfectly possible that all models are created inside the process and are intended to stay in there.
For example, in the power window case study, all DSMs are created during the process and we are only interested in the verification result, meaning that no models ``escape`` the process.
If we were to retain the DSMs, for example to push them into another process later on, we could bind all these models to an actual location in the Modelverse.

The third parameter is a dictionary of callbacks.
For each activity, it is possible for users to define a callback function.
This function will be invoked when the specific activity is executed.
For example, a manual operation will require user input, for which this callback function can then serve.
In this case, lets assume that an activity in the process model, termed *refine_petrinet*, is a manual operation and requires user interaction.
The call then becomes::

    >>> def callback(model):
    ...     # Any code required to create the Petrinet
    ...     p = instantiate(model, "Place")
    ...     t = instantiate(model, "Transition")
    ...     instantiate(model, "P2T", (p, t))
    ...     # Alternatively, we could have used raw_input() or so to prompt the user
    ...
    >>> process_execute("models/query_state_space", {}, {"models/refine_petrinet": callback})

When the process executes *refine_petrinet*, the callback function is executed, and the manual operation is terminated when the function terminates.
Other types of operation, such as *model transformations* and *action language* can also have a callback function, but this is usually less important to end users and is therefore not elaborated on here.
