فهرست منبع

Documentation on transformations

Yentl Van Tendeloo 8 سال پیش
والد
کامیت
ceb71bf688
1فایلهای تغییر یافته به همراه154 افزوده شده و 5 حذف شده
  1. 154 5
      doc/transformations.rst

+ 154 - 5
doc/transformations.rst

@@ -38,18 +38,130 @@ We will now continue on how to specify a model transformation through modelling.
 RAMification
 ^^^^^^^^^^^^
 
-Explain how RAMification works and what it does.
-Specifically, which attributes does it add etc.
+To support model transformation, the Modelverse makes use of RAMification.
+In RAMification, the original metamodel is Relaxed, Augmented, and Modified.
+As such, the new metamodel can be used to define model transformation rules.
+
+This consists of the following three phases:
+1. The metamodel is **Relaxed**, such that lower cardinalities are no longer applied.
+   Similarly, constraints are removed, and abstract entities can be instantiated.
+   This is done because in model transformations, we only use a specific part of the metamodel.
+2. The metamodel is **Augmented**, such that new attributes and concepts are added.
+   These new attributes are *label* and *constraint* in the LHS, and *label* and *action* in the right hand side.
+   New concepts that are added, are the LHS and RHS entity.
+   These are the containers for all elements of the LHS and the RHS, respectively.
+3. The metamodel is **Modified**, such that existing attributes are renamed and their types are altered.
+   All attributes have to become constraints on that specific attribute in the LHS, and actions for the new value in the RHS.
+   For example, the *tokens* attribute of a place becomes a constraint function (returning True or False), instead of an attribute of type integer.
+
+RAMification happens in the background in the Modelverse.
+Users can, of course, open the RAMified metamodel just like any other metamodel.
+
+As RAMification makes a distinction between the LHS and RHS, all entities in the metamodel are effectively duplicated: the LHS entities are prefixed with *Pre_*, and the RHS entities are prefixed with *Post_*.
+Similarly, the names of all attributes are prefixed with *constraint_* and *value_*, respectively.
+
+Implicit merge
+^^^^^^^^^^^^^^
+
+As a model transformation considers multiple languages, both for its input and output, it must be possible somewhere to join them.
+For example, a transformation from PetriNets to a ReachabilityGraph formalism, makes use of entities from both metamodels, in the same model.
+To allow for this, all used metamodels are implicitly merged before RAMification.
+Therefore, the metamodel becomes a combination of all metamodels that were originally specified, making it possible to use all of them in a single model.
+
+Note, however, that the metamodels might use similar concepts: both a PetriNet and a ReachabilityGraph have the notion of a *Place*, but it means something different in both cases.
+Therefore, the elemens are prepended with the tag that was used to define them.
+As such, the model transformation has no notion of *Place*, but only of *PetriNets/Place* and *ReachabilityGraph/Place*.
+In all operations in the transformation, it is necessary to use this notation.
+
+As the same metamodel might be used multiple times, but in different contexts (i.e., with different tags), the metamodels are sometimes added multiple times.
+Each time, however, a different tag is prepended.
+This allows model transformations that combine, or alter, models of the same type, while still distinguishing between the two of them.
+Recall the *master/Place* discussion from the beginning of this section.
 
 Rule specification
 ^^^^^^^^^^^^^^^^^^
 
-How to specify a rule
+Now we actually get to define a rule.
+Rules are themselves just models of the RAMified (and merged) metamodel.
+As such, they are created just like any other model.
+This is the code parameter of the *transformation_add_MT* operation, which takes a Modelverse model.
+An example specification is shown below, which will copy the highest number of tokens between places that have the same name, assuming that only one has a non-zero number of tokens::
+
+    LHS {
+        Pre_PetriNets/Place {
+            label = "pn_place_master"
+            constraint_tokens = $
+                    Boolean function constraint(value : Integer):
+                        return value > 0!
+                $
+        }
+
+        Pre_PetriNets/Place {
+            label = "pn_place_slave"
+            constraint_tokens = $
+                    Boolean function constraint(value : Integer):
+                        return value == 0!
+                $
+
+        constraint = $
+            Boolean function constraint(host_model : Element, mapping : Element):
+                return value_eq(read_attribute(host_model, mapping["pn_place_master"], "name"), 
+                                read_attribute(host_model, mapping["pn_place_slave"], "name"))!
+                $
+    }
+    RHS {
+        Pre_PetriNets/Place {
+            label = "pn_place_master"
+        }
+        Pre_PetriNets/Place {
+            label = "pn_place_slave"
+            value_tokens = $
+                Integer function value(host_model : Element, name : Element, mapping : Element):
+                $
+        }
+    }
+
+Some remarks, specifically in relation to users of AToMPM:
+1. Unspecified attributes in the LHS are always fulfilled (i.e., *result = True* in AToMPM notation).
+2. Unspecified attributes in the RHS are always copied as-is (i.e., *result = get_attr()* in AToMPM notation).
+3. Just like in AToMPM, labels are strings and can be used as such.
+4. While *mapping* contains a mapping for the labels to their elements in the host model, all elements of the host model an technically be used, even those not occuring in the LHS.
+5. During rewriting, it is possible to access the values of all elements of the host model, including those matched before in the LHS.
+   Newly created elements in the RHS can of course not be referenced.
+   Elements removed in the RHS can no longer be referenced either, though this will likely be updated in future versions.
 
 Schedule
 ^^^^^^^^
 
-Scheduling constructs
+The rule we have previously applied, does not yet do much in itself: it needs to be scheduled.
+Scheduling consists of defining in which order rules are executed, but also defining how the rule is to be executed: as a query (*Query*), for one match (*Atomic*), or for all matches (*ForAll*).
+For scheduling purposes, each rule has a *onSuccess* and *onFailure* association.
+*onSuccess* associations are followed when the rule has been applied successfully (i.e., at least one match was found), and the *onFailure* association is followed otherwise.
+Rules can also be composites, in which case they define a schedule themselves.
+
+Each schedule, including the main schedule, has exactly one *Initial* element, and possibly (some) *Success* and *Failure* elements.
+When the *Success* (*Failure*) node is reached, the composite rule is said to succeed (fail).
+On the topmost schedule, success indicates that the model transformation is to be applied.
+When the topmost schedule ends in a failure node, the model transformation as a whole is deemed to fail, and all changes are reverted.
+As such, users are guarenteed that an intermediate model will never be visible, or corrupt previous models.
+
+An example schedule, which applies the previous rule for as long as it matches, is shown below::
+
+    Composite composite {
+        ForAll copy_tokens {
+            LHS {
+                ...
+            }
+            RHS {
+                ...
+            }
+        }
+        Success success {}
+    }
+
+    Initial (composite, copy_tokens) {}
+    OnSuccess (copy_tokens, copy_tokens) {}
+    OnFailure (copy_tokens, success) {}
 
 Invocation
 ----------
@@ -69,7 +181,44 @@ Also, model transformations always happen on a copy of the original model.
 As such, it is also possible to restore the model to before the transformation.
 When a model transformation fails (i.e., the schedule ends in a *Failure*), no output models are written and the models are left untouched.
 
+Signature
+^^^^^^^^^
+
+After a model transformation is defined, it is easy to forget exactly which parameters it takes, and what were the types of these parameters.
+Therefore, the *transformation_read_signature* function can be used to read out the signature of model transformations::
+
+    >>> transformation_read_signature("pn_simulate")
+    ({"pn": "PetriNets"}, {"pn": "PetriNets"})
+    >>> transformation_read_signature("pn_merge")
+    ({"master": "PetriNets", "slave": "Petrinets"}, {"result": "PetriNets"})
+
+Querying
+^^^^^^^^
+
+Similarly, it is often easy to forget which transformations are supported between a source and target metamodel.
+Therefore the *transformation_between* function can be used to query for all transformations that take a certain metamodel as input, and generate another metamodel as output::
+
+    >>> transformation_between("PetriNets", "PetriNets")
+    ["pn_optimize", "pn_simulate", "pn_rename", "pn_combine"]
+
+    >>> transformation_between("PetriNets", "ReachabilityGraph")
+    ["pn_analyze"]
+
+Note that this operation does not take into account other input or output metamodels::
+
+    >>> transformation_between("PetriNets", "Boolean")
+    ["analyze_query", "is_safe", "conforms"]
+
 Tracability links
 -----------------
 
-How do tracability links work?
+As the metamodels are merged together into a single metamodel, models can contain elements from both.
+It is often useful to create some kind of link between these different metamodels.
+However, a simple merge does not allow for this, as the different metamodels form their own "islands".
+To create links between them, for example for matching, or for tracability, we need tracability links.
+
+Definition
+^^^^^^^^^^
+
+Use
+^^^