Modelling ========= Modelling is the core activity in the Modelverse. A model is based on a meta-model, or a language, which, for the sake of this tutorial, assume to exist. Throughout this tutorial, we will focus on how to instantiate a simple Petri Net model. We assume that our language has a notion of *Place*, *Transition*, *P2T* arc, and *T2P* arc. The *Place* has a *name* and *tokens*, the *Transition* has a *name*. Both the *P2T* and *T2P*"arcs have a *weight*. This information is stored in the metamodel, which we will define later on. For now, assume that the metamodel is stored in the Modelverse using the name *PetriNets*. Creating a model ---------------- Creating a new instance of PetriNets is simple, and can be done using the *model_add* operation of the wrapper:: >>> model_add("my_pn", "PetriNets") The first parameter of the operation indicates the name that we would like to give to our newly created model. This name is available to all users, and is therefore a unique identifier. The second parameter is the metamodel that we want to use to conform to. The value needs to be a name that is available in the Modelverse, and readable to the current user. To get a list of currently available models, users can query the Modelverse with the *model_list* operation:: >>> model_list() [("PetriNets", "SimpleClassDiagrams"), ("SimpleClassDiagrams", "SimpleClassDiagrams"), ("ProcessModel", "SimpleClassDiagrams"), ...] This list contains the various models, and the metamodel of these models. Note that this operation does not specify anything about the permissions of the supplied models. Modifying a model ----------------- Now that we have created our model, we can start modifying it. To do so, we have access to several operations offered by the Modelverse. We categorize them by their effects on the Modelverse: create, read, or delete. Create and delete operations are only allowed when the user has write permission to the model, which users have by default on their own models. Create ^^^^^^ 1. *instantiate* creates a new instance in the model, for example a new PetriNet place:: >>> instantiate("my_pn", "Place") __12345 The operation requires the model on which we are working, and the type of the element you want to instantiate. When successful, the operation returns the identifier that can be used in future operations. This identifier has no value within the model, and should only be used as a handle to that specific model element. When instantiating an edge, the optional *edge* parameter must be passed with the identifiers to connect:: >>> instantiate("my_pn", "Place") p1 >>> instantiate("my_pn", "Transition") t1 >>> instantiate("my_pn", "P2T", edge=("p1", "t1")) p2t1 2. *attr_assign* assigns attributes of a specific model element. For example, it specifies the name and number of tokens of our PetriNet place:: >>> instantiate("my_pn", "Place") p1 >>> attr_assign("my_pn", "p1", "name", "place 1") >>> attr_assign("my_pn", "p1", "tokens", 2) The value of the attribute can be any simple primitive: string, integer, float, or boolean. When the attribute already exists, its value is overwritten. If it doesn't exist, it is created. Read ^^^^ 1. *read* reads out basic information about a queried element, such as its type and the source and target (if it is an edge):: >>> instantiate("my_pn", "Place") p1 >>> read("my_pn", "p1") ("Place, None) >>> instantiate("my_pn", "Transition") t1 >>> instantiate("my_pn", "P2T", edge=("p1", "t1")) p2t1 >>> read("my_pn", "p2t1") ("P2T", ("p1", "t1")) 2. *read_attrs* reads out the attributes of a specific element, in a dictionary form. This operation can be used to read out, for example, the number of tokens of a specific place:: >>> instantiate("my_pn", "Place") p1 >>> attr_assign("my_pn", "p1", "name", "place 1") >>> attr_assign("my_pn", "p1", "tokens", 2) >>> read_attrs("my_pn", "p1") {"name": "place 1", "tokens": 2} types element_list_nice read_outgoing read_incoming read_association_source read_association_destination connections_between all_instances Delete ^^^^^^ delete_element attr_delete