Modelling Language

Apart from the action language, the Modelverse also has a modelling language. With this language, models (i.e., data) can be defined in addition to the algorithms.

This language is still work in progress, but should be decent enough to construct simple models. All models have the extension *.mvc, indicating that they are models and should be compiled as such. There is no constraint that this extension is mandatory.

First, we show an example on how to create a simple PetriNet model. To take into account action language in the example model, we will also show an example for Finite State Automata afterwards.

Example: Petri Nets

Creating a simple Petri Net is easy using the Modelverse modelling language. An example is given below, which contains some places and transitions, with some connections between them:

Place p1 {
    name = "place 1"
    tokens = 1
}

Place p2 {
    name = "place 2"
    tokens = 2
}

Transition t1 {
    name = "transition"
}

P2T p2t (p1, t1) {
    weight = 1
}

T2P t2p (t1, p2) {
    weight = 2
}

The name immediately after the type (e.g., p1), is the identifier used throughout the textual representation. All identification of the element at the model-level should happen based on defined attributes. The identifiers can also be overwritten internally, in which case the latest definition is used. Do note that there is no concept of scope here, so identifiers stay visible throughout the whole file. It is possible to have anonymous identifiers, but only if the identifier is not used in the remainder of the file (e.g., not the source of an association). For example, the two arcs could just as well have been defined as follows

P2T (p1, t1) {
    weight = 1
}

T2P (t1, p2) {
    weight = 2
}

Example: Finite State Automata

Next we use a simple Finite State Automata example model. This will introduce some new concepts: hierarchy, long strings, and code attributes.

Hierarchy

The Modelverse does not natively support a notion of hierarchy, but its modelling language can easily be used to represent hierarchy. Models can be indented, which means that a link is created from the container to the containee. If only one link type is allowed between both, the type is automatically selected. If multiple link types are possible, it is ambiguous and the model will fail to compile. For example, if we consider a hierarchical state:

CompositeState s1 {
    name = "state 1"

    CompositeState s2 {
        name = "state 2"

        State s3 {
            name = "state 3"
        }
    }
}

State s4 {
    name = "state 4"
}

When the only allowed links between a CompositeState and any other state is this, the model will compile fine as it is. However, we also want to define transitions, which can go from a CompositeState to a normal State as well. As such, we must update the model as follows, specifying the association type:

CompositeState s1 {
    name = "state 1"

    {Contains} CompositeState s2 {
        name = "state 2"

        {Contains} State s3 {
            name = "state 3"
        }
    }
}

State s4 {
    name = "state 4"
}

As there is no difference between Contains and Transition, there is nothing that prevents you from creating something like:

State s1 {
    name = "state 1"

    {Transition} State {
        name = "state 2"
    }

    {Contains} State {
        name = "state 3"
    }
}

In this case, the state state 1 and state 2 are actually at the same level, with a transition between them. This can get rather confusing, and is therefore discouraged.

Long string attributes

Sometimes longer string values are required in attributes, for example as code blocks or descriptions of elements. In this case, three double quotes are used to delimit this string, similar to Python. Note that an ordinary double quote is not allowed within this long string attribute, due to limitations of the parser:

State s1 {
    description = """
    This is a lenghty description of the state.
    In this state, the execution will start.
    """
}

Code

Using code in the model definition is easy, and merely requires the use of the $ symbol around the text, instead of the usual ” symbols. For example, to define a Transition with an action:

State s1 {
    name = "state 1"
}

State s2 {
    name = "state 2"
}

Transition (s1, s2) {
    action = $
        include "primitives.alh"
        Void function action(model : Element):
            log("Test!")
            return !
        $
}

In this case, it is impossible to use code defined externally. All code between $ symbols is passed on as-is to the action language compiler.

Note the import statements, which will likely be repeated in each and every code block. It is possible to define include statements at the top of the model, in which case the include is automatically prepended in each and every code block:

include "primitives.alh"

State s1 {
    name = "state 1"
}

State s2 {
    name = "state 2"
}

Transition (s1, s2) {
    action = $
        Void function action(model : Element):
            log("Test!")
            return !
        $
}

As mentioned before, the Action Language does not allow for subfunctions, but it is possible for there to be multiple functions between the dollar tags. In that case, the function with name main is executed first, or, if no such function exists, the topmost function is chosen.

Using the Model Representation

The question remains how to use this model representation with the Modelverse. The model_add operation can be extended with an additional parameter, specifying a textual model. It will then create a new model and initialize it with the model specified textually:

>>> model_add("models/my_pn", "formalisms/PetriNets", open("my_pn.mvc", "r").read())

Another function that can be used, is the model_overwrite function, which overwrites an existing model with the content of the provided textual model:

>>> model_overwrite("models/my_pn", "formalisms/PetriNets", open("my_pn.mvc", "r").read())