|
@@ -103,6 +103,43 @@ For associations, we have the same three attributes, augmented with:
|
|
|
6. *target_lower_cardinality* specifies the number (integer) of outgoing edges that are at least required for the source.
|
|
|
7. *target_upper_cardinality* specifies the number (integer) of outgoing edges that are at most required for the source.
|
|
|
|
|
|
+Constraints
|
|
|
+^^^^^^^^^^^
|
|
|
+
|
|
|
+A constraint specifies additional constraints on the instances of this model, which could not be expressed before.
|
|
|
+We distinguish between two types of constraints: local and global constraints.
|
|
|
+
|
|
|
+Local constraints are defined at the level of a single class or association.
|
|
|
+For example, if the number of tokens must always be non-negative, this can be specified as follows::
|
|
|
+
|
|
|
+ >>> attr_assign_code("PetriNets", "Place", "constraints", \
|
|
|
+ ... """
|
|
|
+ ... String function constraint(model : Element, name : String):
|
|
|
+ ... if (integer_gte(read_attribute(model, name, "tokens"), 0)):
|
|
|
+ ... return "OK"!
|
|
|
+ ... else:
|
|
|
+ ... return "Negative number of tokens specified"!
|
|
|
+
|
|
|
+Global constraints operate over the complete model, and are therefore not attached to a single element.
|
|
|
+Instead, a specific *GlobalConstraint* element must be instantiated.
|
|
|
+This element has a *constraint* attribute, which specifies the constraint to evaluate in the global context.
|
|
|
+For example, when, for some reason, the number of places must always be larger than the number of transitions::
|
|
|
+
|
|
|
+ >>> constraint = instantiate("PetriNets", "GlobalConstraint")
|
|
|
+ >>> attr_assign_code("PetriNets", constraint, "constraint", \
|
|
|
+ ... """
|
|
|
+ ... String function constraint(model : Element):
|
|
|
+ ... if (set_len(allInstances(model, "Place")) > set_len(allInstances(model, "Transition"))):
|
|
|
+ ... return "OK"!
|
|
|
+ ... else:
|
|
|
+ ... return "Needs more places than transitions"!
|
|
|
+
|
|
|
+While all constraints can be specified as global constraints, using local constraints is preferred.
|
|
|
+
|
|
|
+.. note::
|
|
|
+ Currently, all constraints are only evaluated upon explicit user request.
|
|
|
+ More specifically: during the *verify* operation.
|
|
|
+
|
|
|
Defining attributes
|
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
@@ -145,9 +182,3 @@ This can be easily done as follows::
|
|
|
>>> define_attribute("PetriNets", "Place", "tokens", "Natural")
|
|
|
|
|
|
For the name, *String* can be defined similarly (using *is_physical_string*).
|
|
|
-
|
|
|
-Constraints
|
|
|
-^^^^^^^^^^^
|
|
|
-
|
|
|
-A constraint specifies additional constraints on the instances of this model, which could not be expressed before.
|
|
|
-We distinguish between two types of constraints:
|